[media] rename most media/video pci drivers to media/pci
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 14 Aug 2012 15:13:30 +0000 (12:13 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 19:36:22 +0000 (16:36 -0300)
Rename all PCI drivers with their own directory under
drivers/media/video into drivers/media/pci and update the
building system.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
428 files changed:
drivers/media/pci/Kconfig
drivers/media/pci/Makefile
drivers/media/pci/cx18/Kconfig [new file with mode: 0644]
drivers/media/pci/cx18/Makefile [new file with mode: 0644]
drivers/media/pci/cx18/cx18-alsa-main.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-alsa-mixer.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-alsa-mixer.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-alsa-pcm.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-alsa-pcm.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-alsa.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-audio.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-audio.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-av-audio.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-av-core.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-av-core.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-av-firmware.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-av-vbi.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-cards.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-cards.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-controls.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-controls.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-driver.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-driver.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-dvb.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-dvb.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-fileops.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-fileops.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-firmware.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-firmware.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-gpio.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-gpio.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-i2c.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-i2c.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-io.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-io.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-ioctl.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-ioctl.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-irq.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-irq.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-mailbox.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-mailbox.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-queue.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-queue.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-scb.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-scb.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-streams.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-streams.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-vbi.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-vbi.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-version.h [new file with mode: 0644]
drivers/media/pci/cx18/cx18-video.c [new file with mode: 0644]
drivers/media/pci/cx18/cx18-video.h [new file with mode: 0644]
drivers/media/pci/cx18/cx23418.h [new file with mode: 0644]
drivers/media/pci/cx23885/Kconfig [new file with mode: 0644]
drivers/media/pci/cx23885/Makefile [new file with mode: 0644]
drivers/media/pci/cx23885/altera-ci.c [new file with mode: 0644]
drivers/media/pci/cx23885/altera-ci.h [new file with mode: 0644]
drivers/media/pci/cx23885/cimax2.c [new file with mode: 0644]
drivers/media/pci/cx23885/cimax2.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-417.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-alsa.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-av.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-av.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-cards.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-core.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-dvb.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-f300.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-f300.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-i2c.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-input.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-input.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-ioctl.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-ioctl.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-ir.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-ir.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-reg.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-vbi.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885-video.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23885.h [new file with mode: 0644]
drivers/media/pci/cx23885/cx23888-ir.c [new file with mode: 0644]
drivers/media/pci/cx23885/cx23888-ir.h [new file with mode: 0644]
drivers/media/pci/cx23885/netup-eeprom.c [new file with mode: 0644]
drivers/media/pci/cx23885/netup-eeprom.h [new file with mode: 0644]
drivers/media/pci/cx23885/netup-init.c [new file with mode: 0644]
drivers/media/pci/cx23885/netup-init.h [new file with mode: 0644]
drivers/media/pci/cx25821/Kconfig [new file with mode: 0644]
drivers/media/pci/cx25821/Makefile [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-alsa.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-audio-upstream.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-audio-upstream.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-audio.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-biffuncs.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-cards.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-core.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-gpio.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-i2c.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-medusa-defines.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-medusa-reg.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-medusa-video.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-medusa-video.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-reg.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-sram.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-video-upstream.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-video-upstream.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-video.c [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821-video.h [new file with mode: 0644]
drivers/media/pci/cx25821/cx25821.h [new file with mode: 0644]
drivers/media/pci/cx88/Kconfig [new file with mode: 0644]
drivers/media/pci/cx88/Makefile [new file with mode: 0644]
drivers/media/pci/cx88/cx88-alsa.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-blackbird.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-cards.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-core.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-dsp.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-dvb.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-i2c.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-input.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-mpeg.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-reg.h [new file with mode: 0644]
drivers/media/pci/cx88/cx88-tvaudio.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-vbi.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-video.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-vp3054-i2c.c [new file with mode: 0644]
drivers/media/pci/cx88/cx88-vp3054-i2c.h [new file with mode: 0644]
drivers/media/pci/cx88/cx88.h [new file with mode: 0644]
drivers/media/pci/ivtv/Kconfig [new file with mode: 0644]
drivers/media/pci/ivtv/Makefile [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-cards.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-cards.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-controls.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-controls.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-driver.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-driver.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-fileops.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-fileops.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-firmware.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-firmware.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-gpio.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-gpio.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-i2c.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-i2c.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-ioctl.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-ioctl.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-irq.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-irq.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-mailbox.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-mailbox.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-queue.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-queue.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-routing.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-routing.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-streams.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-streams.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-udma.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-udma.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-vbi.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-vbi.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-version.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-yuv.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-yuv.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtvfb.c [new file with mode: 0644]
drivers/media/pci/saa7134/Kconfig [new file with mode: 0644]
drivers/media/pci/saa7134/Makefile [new file with mode: 0644]
drivers/media/pci/saa7134/saa6752hs.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-alsa.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-cards.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-core.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-dvb.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-empress.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-i2c.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-input.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-reg.h [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-ts.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-tvaudio.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-vbi.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134-video.c [new file with mode: 0644]
drivers/media/pci/saa7134/saa7134.h [new file with mode: 0644]
drivers/media/pci/saa7164/Kconfig [new file with mode: 0644]
drivers/media/pci/saa7164/Makefile [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-api.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-buffer.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-bus.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-cards.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-cmd.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-core.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-dvb.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-encoder.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-fw.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-i2c.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-reg.h [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-types.h [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164-vbi.c [new file with mode: 0644]
drivers/media/pci/saa7164/saa7164.h [new file with mode: 0644]
drivers/media/pci/zoran/Kconfig [new file with mode: 0644]
drivers/media/pci/zoran/Makefile [new file with mode: 0644]
drivers/media/pci/zoran/videocodec.c [new file with mode: 0644]
drivers/media/pci/zoran/videocodec.h [new file with mode: 0644]
drivers/media/pci/zoran/zoran.h [new file with mode: 0644]
drivers/media/pci/zoran/zoran_card.c [new file with mode: 0644]
drivers/media/pci/zoran/zoran_card.h [new file with mode: 0644]
drivers/media/pci/zoran/zoran_device.c [new file with mode: 0644]
drivers/media/pci/zoran/zoran_device.h [new file with mode: 0644]
drivers/media/pci/zoran/zoran_driver.c [new file with mode: 0644]
drivers/media/pci/zoran/zoran_procfs.c [new file with mode: 0644]
drivers/media/pci/zoran/zoran_procfs.h [new file with mode: 0644]
drivers/media/pci/zoran/zr36016.c [new file with mode: 0644]
drivers/media/pci/zoran/zr36016.h [new file with mode: 0644]
drivers/media/pci/zoran/zr36050.c [new file with mode: 0644]
drivers/media/pci/zoran/zr36050.h [new file with mode: 0644]
drivers/media/pci/zoran/zr36057.h [new file with mode: 0644]
drivers/media/pci/zoran/zr36060.c [new file with mode: 0644]
drivers/media/pci/zoran/zr36060.h [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/cx18/Kconfig [deleted file]
drivers/media/video/cx18/Makefile [deleted file]
drivers/media/video/cx18/cx18-alsa-main.c [deleted file]
drivers/media/video/cx18/cx18-alsa-mixer.c [deleted file]
drivers/media/video/cx18/cx18-alsa-mixer.h [deleted file]
drivers/media/video/cx18/cx18-alsa-pcm.c [deleted file]
drivers/media/video/cx18/cx18-alsa-pcm.h [deleted file]
drivers/media/video/cx18/cx18-alsa.h [deleted file]
drivers/media/video/cx18/cx18-audio.c [deleted file]
drivers/media/video/cx18/cx18-audio.h [deleted file]
drivers/media/video/cx18/cx18-av-audio.c [deleted file]
drivers/media/video/cx18/cx18-av-core.c [deleted file]
drivers/media/video/cx18/cx18-av-core.h [deleted file]
drivers/media/video/cx18/cx18-av-firmware.c [deleted file]
drivers/media/video/cx18/cx18-av-vbi.c [deleted file]
drivers/media/video/cx18/cx18-cards.c [deleted file]
drivers/media/video/cx18/cx18-cards.h [deleted file]
drivers/media/video/cx18/cx18-controls.c [deleted file]
drivers/media/video/cx18/cx18-controls.h [deleted file]
drivers/media/video/cx18/cx18-driver.c [deleted file]
drivers/media/video/cx18/cx18-driver.h [deleted file]
drivers/media/video/cx18/cx18-dvb.c [deleted file]
drivers/media/video/cx18/cx18-dvb.h [deleted file]
drivers/media/video/cx18/cx18-fileops.c [deleted file]
drivers/media/video/cx18/cx18-fileops.h [deleted file]
drivers/media/video/cx18/cx18-firmware.c [deleted file]
drivers/media/video/cx18/cx18-firmware.h [deleted file]
drivers/media/video/cx18/cx18-gpio.c [deleted file]
drivers/media/video/cx18/cx18-gpio.h [deleted file]
drivers/media/video/cx18/cx18-i2c.c [deleted file]
drivers/media/video/cx18/cx18-i2c.h [deleted file]
drivers/media/video/cx18/cx18-io.c [deleted file]
drivers/media/video/cx18/cx18-io.h [deleted file]
drivers/media/video/cx18/cx18-ioctl.c [deleted file]
drivers/media/video/cx18/cx18-ioctl.h [deleted file]
drivers/media/video/cx18/cx18-irq.c [deleted file]
drivers/media/video/cx18/cx18-irq.h [deleted file]
drivers/media/video/cx18/cx18-mailbox.c [deleted file]
drivers/media/video/cx18/cx18-mailbox.h [deleted file]
drivers/media/video/cx18/cx18-queue.c [deleted file]
drivers/media/video/cx18/cx18-queue.h [deleted file]
drivers/media/video/cx18/cx18-scb.c [deleted file]
drivers/media/video/cx18/cx18-scb.h [deleted file]
drivers/media/video/cx18/cx18-streams.c [deleted file]
drivers/media/video/cx18/cx18-streams.h [deleted file]
drivers/media/video/cx18/cx18-vbi.c [deleted file]
drivers/media/video/cx18/cx18-vbi.h [deleted file]
drivers/media/video/cx18/cx18-version.h [deleted file]
drivers/media/video/cx18/cx18-video.c [deleted file]
drivers/media/video/cx18/cx18-video.h [deleted file]
drivers/media/video/cx18/cx23418.h [deleted file]
drivers/media/video/cx23885/Kconfig [deleted file]
drivers/media/video/cx23885/Makefile [deleted file]
drivers/media/video/cx23885/altera-ci.c [deleted file]
drivers/media/video/cx23885/altera-ci.h [deleted file]
drivers/media/video/cx23885/cimax2.c [deleted file]
drivers/media/video/cx23885/cimax2.h [deleted file]
drivers/media/video/cx23885/cx23885-417.c [deleted file]
drivers/media/video/cx23885/cx23885-alsa.c [deleted file]
drivers/media/video/cx23885/cx23885-av.c [deleted file]
drivers/media/video/cx23885/cx23885-av.h [deleted file]
drivers/media/video/cx23885/cx23885-cards.c [deleted file]
drivers/media/video/cx23885/cx23885-core.c [deleted file]
drivers/media/video/cx23885/cx23885-dvb.c [deleted file]
drivers/media/video/cx23885/cx23885-f300.c [deleted file]
drivers/media/video/cx23885/cx23885-f300.h [deleted file]
drivers/media/video/cx23885/cx23885-i2c.c [deleted file]
drivers/media/video/cx23885/cx23885-input.c [deleted file]
drivers/media/video/cx23885/cx23885-input.h [deleted file]
drivers/media/video/cx23885/cx23885-ioctl.c [deleted file]
drivers/media/video/cx23885/cx23885-ioctl.h [deleted file]
drivers/media/video/cx23885/cx23885-ir.c [deleted file]
drivers/media/video/cx23885/cx23885-ir.h [deleted file]
drivers/media/video/cx23885/cx23885-reg.h [deleted file]
drivers/media/video/cx23885/cx23885-vbi.c [deleted file]
drivers/media/video/cx23885/cx23885-video.c [deleted file]
drivers/media/video/cx23885/cx23885.h [deleted file]
drivers/media/video/cx23885/cx23888-ir.c [deleted file]
drivers/media/video/cx23885/cx23888-ir.h [deleted file]
drivers/media/video/cx23885/netup-eeprom.c [deleted file]
drivers/media/video/cx23885/netup-eeprom.h [deleted file]
drivers/media/video/cx23885/netup-init.c [deleted file]
drivers/media/video/cx23885/netup-init.h [deleted file]
drivers/media/video/cx25821/Kconfig [deleted file]
drivers/media/video/cx25821/Makefile [deleted file]
drivers/media/video/cx25821/cx25821-alsa.c [deleted file]
drivers/media/video/cx25821/cx25821-audio-upstream.c [deleted file]
drivers/media/video/cx25821/cx25821-audio-upstream.h [deleted file]
drivers/media/video/cx25821/cx25821-audio.h [deleted file]
drivers/media/video/cx25821/cx25821-biffuncs.h [deleted file]
drivers/media/video/cx25821/cx25821-cards.c [deleted file]
drivers/media/video/cx25821/cx25821-core.c [deleted file]
drivers/media/video/cx25821/cx25821-gpio.c [deleted file]
drivers/media/video/cx25821/cx25821-i2c.c [deleted file]
drivers/media/video/cx25821/cx25821-medusa-defines.h [deleted file]
drivers/media/video/cx25821/cx25821-medusa-reg.h [deleted file]
drivers/media/video/cx25821/cx25821-medusa-video.c [deleted file]
drivers/media/video/cx25821/cx25821-medusa-video.h [deleted file]
drivers/media/video/cx25821/cx25821-reg.h [deleted file]
drivers/media/video/cx25821/cx25821-sram.h [deleted file]
drivers/media/video/cx25821/cx25821-video-upstream-ch2.c [deleted file]
drivers/media/video/cx25821/cx25821-video-upstream-ch2.h [deleted file]
drivers/media/video/cx25821/cx25821-video-upstream.c [deleted file]
drivers/media/video/cx25821/cx25821-video-upstream.h [deleted file]
drivers/media/video/cx25821/cx25821-video.c [deleted file]
drivers/media/video/cx25821/cx25821-video.h [deleted file]
drivers/media/video/cx25821/cx25821.h [deleted file]
drivers/media/video/cx88/Kconfig [deleted file]
drivers/media/video/cx88/Makefile [deleted file]
drivers/media/video/cx88/cx88-alsa.c [deleted file]
drivers/media/video/cx88/cx88-blackbird.c [deleted file]
drivers/media/video/cx88/cx88-cards.c [deleted file]
drivers/media/video/cx88/cx88-core.c [deleted file]
drivers/media/video/cx88/cx88-dsp.c [deleted file]
drivers/media/video/cx88/cx88-dvb.c [deleted file]
drivers/media/video/cx88/cx88-i2c.c [deleted file]
drivers/media/video/cx88/cx88-input.c [deleted file]
drivers/media/video/cx88/cx88-mpeg.c [deleted file]
drivers/media/video/cx88/cx88-reg.h [deleted file]
drivers/media/video/cx88/cx88-tvaudio.c [deleted file]
drivers/media/video/cx88/cx88-vbi.c [deleted file]
drivers/media/video/cx88/cx88-video.c [deleted file]
drivers/media/video/cx88/cx88-vp3054-i2c.c [deleted file]
drivers/media/video/cx88/cx88-vp3054-i2c.h [deleted file]
drivers/media/video/cx88/cx88.h [deleted file]
drivers/media/video/ivtv/Kconfig [deleted file]
drivers/media/video/ivtv/Makefile [deleted file]
drivers/media/video/ivtv/ivtv-cards.c [deleted file]
drivers/media/video/ivtv/ivtv-cards.h [deleted file]
drivers/media/video/ivtv/ivtv-controls.c [deleted file]
drivers/media/video/ivtv/ivtv-controls.h [deleted file]
drivers/media/video/ivtv/ivtv-driver.c [deleted file]
drivers/media/video/ivtv/ivtv-driver.h [deleted file]
drivers/media/video/ivtv/ivtv-fileops.c [deleted file]
drivers/media/video/ivtv/ivtv-fileops.h [deleted file]
drivers/media/video/ivtv/ivtv-firmware.c [deleted file]
drivers/media/video/ivtv/ivtv-firmware.h [deleted file]
drivers/media/video/ivtv/ivtv-gpio.c [deleted file]
drivers/media/video/ivtv/ivtv-gpio.h [deleted file]
drivers/media/video/ivtv/ivtv-i2c.c [deleted file]
drivers/media/video/ivtv/ivtv-i2c.h [deleted file]
drivers/media/video/ivtv/ivtv-ioctl.c [deleted file]
drivers/media/video/ivtv/ivtv-ioctl.h [deleted file]
drivers/media/video/ivtv/ivtv-irq.c [deleted file]
drivers/media/video/ivtv/ivtv-irq.h [deleted file]
drivers/media/video/ivtv/ivtv-mailbox.c [deleted file]
drivers/media/video/ivtv/ivtv-mailbox.h [deleted file]
drivers/media/video/ivtv/ivtv-queue.c [deleted file]
drivers/media/video/ivtv/ivtv-queue.h [deleted file]
drivers/media/video/ivtv/ivtv-routing.c [deleted file]
drivers/media/video/ivtv/ivtv-routing.h [deleted file]
drivers/media/video/ivtv/ivtv-streams.c [deleted file]
drivers/media/video/ivtv/ivtv-streams.h [deleted file]
drivers/media/video/ivtv/ivtv-udma.c [deleted file]
drivers/media/video/ivtv/ivtv-udma.h [deleted file]
drivers/media/video/ivtv/ivtv-vbi.c [deleted file]
drivers/media/video/ivtv/ivtv-vbi.h [deleted file]
drivers/media/video/ivtv/ivtv-version.h [deleted file]
drivers/media/video/ivtv/ivtv-yuv.c [deleted file]
drivers/media/video/ivtv/ivtv-yuv.h [deleted file]
drivers/media/video/ivtv/ivtvfb.c [deleted file]
drivers/media/video/saa7134/Kconfig [deleted file]
drivers/media/video/saa7134/Makefile [deleted file]
drivers/media/video/saa7134/saa6752hs.c [deleted file]
drivers/media/video/saa7134/saa7134-alsa.c [deleted file]
drivers/media/video/saa7134/saa7134-cards.c [deleted file]
drivers/media/video/saa7134/saa7134-core.c [deleted file]
drivers/media/video/saa7134/saa7134-dvb.c [deleted file]
drivers/media/video/saa7134/saa7134-empress.c [deleted file]
drivers/media/video/saa7134/saa7134-i2c.c [deleted file]
drivers/media/video/saa7134/saa7134-input.c [deleted file]
drivers/media/video/saa7134/saa7134-reg.h [deleted file]
drivers/media/video/saa7134/saa7134-ts.c [deleted file]
drivers/media/video/saa7134/saa7134-tvaudio.c [deleted file]
drivers/media/video/saa7134/saa7134-vbi.c [deleted file]
drivers/media/video/saa7134/saa7134-video.c [deleted file]
drivers/media/video/saa7134/saa7134.h [deleted file]
drivers/media/video/saa7164/Kconfig [deleted file]
drivers/media/video/saa7164/Makefile [deleted file]
drivers/media/video/saa7164/saa7164-api.c [deleted file]
drivers/media/video/saa7164/saa7164-buffer.c [deleted file]
drivers/media/video/saa7164/saa7164-bus.c [deleted file]
drivers/media/video/saa7164/saa7164-cards.c [deleted file]
drivers/media/video/saa7164/saa7164-cmd.c [deleted file]
drivers/media/video/saa7164/saa7164-core.c [deleted file]
drivers/media/video/saa7164/saa7164-dvb.c [deleted file]
drivers/media/video/saa7164/saa7164-encoder.c [deleted file]
drivers/media/video/saa7164/saa7164-fw.c [deleted file]
drivers/media/video/saa7164/saa7164-i2c.c [deleted file]
drivers/media/video/saa7164/saa7164-reg.h [deleted file]
drivers/media/video/saa7164/saa7164-types.h [deleted file]
drivers/media/video/saa7164/saa7164-vbi.c [deleted file]
drivers/media/video/saa7164/saa7164.h [deleted file]
drivers/media/video/zoran/Kconfig [deleted file]
drivers/media/video/zoran/Makefile [deleted file]
drivers/media/video/zoran/videocodec.c [deleted file]
drivers/media/video/zoran/videocodec.h [deleted file]
drivers/media/video/zoran/zoran.h [deleted file]
drivers/media/video/zoran/zoran_card.c [deleted file]
drivers/media/video/zoran/zoran_card.h [deleted file]
drivers/media/video/zoran/zoran_device.c [deleted file]
drivers/media/video/zoran/zoran_device.h [deleted file]
drivers/media/video/zoran/zoran_driver.c [deleted file]
drivers/media/video/zoran/zoran_procfs.c [deleted file]
drivers/media/video/zoran/zoran_procfs.h [deleted file]
drivers/media/video/zoran/zr36016.c [deleted file]
drivers/media/video/zoran/zr36016.h [deleted file]
drivers/media/video/zoran/zr36050.c [deleted file]
drivers/media/video/zoran/zr36050.h [deleted file]
drivers/media/video/zoran/zr36057.h [deleted file]
drivers/media/video/zoran/zr36060.c [deleted file]
drivers/media/video/zoran/zr36060.h [deleted file]

index b16529b..b69cb12 100644 (file)
@@ -2,40 +2,36 @@
 # DVB device configuration
 #
 
-menuconfig DVB_CAPTURE_DRIVERS
-       bool "DVB/ATSC PCI adapters"
-       depends on DVB_CORE
-       default y
-       ---help---
-         Say Y to select Digital TV adapters
-
-if DVB_CAPTURE_DRIVERS && DVB_CORE && PCI && I2C
+menu "Media PCI Adapters"
+       visible if PCI && MEDIA_SUPPORT
+
+if MEDIA_ANALOG_TV_SUPPORT
+       comment "Media capture/analog TV support"
+source "drivers/media/pci/ivtv/Kconfig"
+source "drivers/media/pci/zoran/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
+       comment "Media capture/analog/hybrid TV support"
+source "drivers/media/pci/cx18/Kconfig"
+source "drivers/media/pci/cx23885/Kconfig"
+source "drivers/media/pci/cx25821/Kconfig"
+source "drivers/media/pci/cx88/Kconfig"
+source "drivers/media/pci/bt8xx/Kconfig"
+source "drivers/media/pci/saa7134/Kconfig"
+source "drivers/media/pci/saa7164/Kconfig"
+endif
 
-comment "Supported SAA7146 based PCI Adapters"
+if MEDIA_DIGITAL_TV_SUPPORT
+       comment "Media digital TV PCI Adapters"
 source "drivers/media/pci/ttpci/Kconfig"
-
-comment "Supported FlexCopII (B2C2) PCI Adapters"
 source "drivers/media/pci/b2c2/Kconfig"
-
-comment "Supported BT878 Adapters"
-source "drivers/media/pci/bt8xx/Kconfig"
-
-comment "Supported Pluto2 Adapters"
 source "drivers/media/pci/pluto2/Kconfig"
-
-comment "Supported SDMC DM1105 Adapters"
 source "drivers/media/pci/dm1105/Kconfig"
-
-comment "Supported Earthsoft PT1 Adapters"
 source "drivers/media/pci/pt1/Kconfig"
-
-comment "Supported Mantis Adapters"
 source "drivers/media/pci/mantis/Kconfig"
-
-comment "Supported nGene Adapters"
 source "drivers/media/pci/ngene/Kconfig"
-
-comment "Supported ddbridge ('Octopus') Adapters"
 source "drivers/media/pci/ddbridge/Kconfig"
+endif
 
-endif # DVB_CAPTURE_DRIVERS
+endmenu
index 1d44fbd..d47c222 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-y        :=        ttpci/          \
                b2c2/           \
-               bt8xx/          \
                pluto2/         \
                dm1105/         \
                pt1/            \
@@ -12,3 +11,13 @@ obj-y        :=      ttpci/          \
                ngene/          \
                ddbridge/       \
                b2c2/
+
+obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_VIDEO_CX18) += cx18/
+obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
+obj-$(CONFIG_VIDEO_CX88) += cx88/
+obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
+obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
diff --git a/drivers/media/pci/cx18/Kconfig b/drivers/media/pci/cx18/Kconfig
new file mode 100644 (file)
index 0000000..53b3c77
--- /dev/null
@@ -0,0 +1,35 @@
+config VIDEO_CX18
+       tristate "Conexant cx23418 MPEG encoder support"
+       depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
+       select I2C_ALGOBIT
+       select VIDEOBUF_VMALLOC
+       depends on RC_CORE
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_CX2341X
+       select VIDEO_CS5345
+       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+       ---help---
+         This is a video4linux driver for Conexant cx23418 based
+         PCI combo video recorder devices.
+
+         This is used in devices such as the Hauppauge HVR-1600
+         cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx18.
+
+config VIDEO_CX18_ALSA
+       tristate "Conexant 23418 DMA audio support"
+       depends on VIDEO_CX18 && SND && EXPERIMENTAL
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio on
+         Conexant 23418 based TV cards using ALSA.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx18-alsa.
diff --git a/drivers/media/pci/cx18/Makefile b/drivers/media/pci/cx18/Makefile
new file mode 100644 (file)
index 0000000..d3ff154
--- /dev/null
@@ -0,0 +1,13 @@
+cx18-objs    := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.o \
+       cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
+       cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
+       cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
+       cx18-dvb.o cx18-io.o
+cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
+
+obj-$(CONFIG_VIDEO_CX18) += cx18.o
+obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c
new file mode 100644 (file)
index 0000000..6d2a982
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "cx18-driver.h"
+#include "cx18-version.h"
+#include "cx18-alsa.h"
+#include "cx18-alsa-mixer.h"
+#include "cx18-alsa-pcm.h"
+
+int cx18_alsa_debug;
+
+#define CX18_DEBUG_ALSA_INFO(fmt, arg...) \
+       do { \
+               if (cx18_alsa_debug & 2) \
+                       printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \
+       } while (0);
+
+module_param_named(debug, cx18_alsa_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+                "Debug level (bitmask). Default: 0\n"
+                "\t\t\t  1/0x0001: warning\n"
+                "\t\t\t  2/0x0002: info\n");
+
+MODULE_AUTHOR("Andy Walls");
+MODULE_DESCRIPTION("CX23418 ALSA Interface");
+MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(CX18_VERSION);
+
+static inline
+struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev)
+{
+       return to_cx18(v4l2_dev)->alsa;
+}
+
+static inline
+struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev)
+{
+       return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev);
+}
+
+static void snd_cx18_card_free(struct snd_cx18_card *cxsc)
+{
+       if (cxsc == NULL)
+               return;
+
+       if (cxsc->v4l2_dev != NULL)
+               to_cx18(cxsc->v4l2_dev)->alsa = NULL;
+
+       /* FIXME - take any other stopping actions needed */
+
+       kfree(cxsc);
+}
+
+static void snd_cx18_card_private_free(struct snd_card *sc)
+{
+       if (sc == NULL)
+               return;
+       snd_cx18_card_free(sc->private_data);
+       sc->private_data = NULL;
+       sc->private_free = NULL;
+}
+
+static int snd_cx18_card_create(struct v4l2_device *v4l2_dev,
+                                      struct snd_card *sc,
+                                      struct snd_cx18_card **cxsc)
+{
+       *cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL);
+       if (*cxsc == NULL)
+               return -ENOMEM;
+
+       (*cxsc)->v4l2_dev = v4l2_dev;
+       (*cxsc)->sc = sc;
+
+       sc->private_data = *cxsc;
+       sc->private_free = snd_cx18_card_private_free;
+
+       return 0;
+}
+
+static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc)
+{
+       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+       struct snd_card *sc = cxsc->sc;
+
+       /* sc->driver is used by alsa-lib's configurator: simple, unique */
+       strlcpy(sc->driver, "CX23418", sizeof(sc->driver));
+
+       /* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */
+       snprintf(sc->shortname,  sizeof(sc->shortname), "CX18-%d",
+                cx->instance);
+
+       /* sc->longname is read from /proc/asound/cards */
+       snprintf(sc->longname, sizeof(sc->longname),
+                "CX23418 #%d %s TV/FM Radio/Line-In Capture",
+                cx->instance, cx->card_name);
+
+       return 0;
+}
+
+static int snd_cx18_init(struct v4l2_device *v4l2_dev)
+{
+       struct cx18 *cx = to_cx18(v4l2_dev);
+       struct snd_card *sc = NULL;
+       struct snd_cx18_card *cxsc;
+       int ret;
+
+       /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
+
+       /* (1) Check and increment the device index */
+       /* This is a no-op for us.  We'll use the cx->instance */
+
+       /* (2) Create a card instance */
+       ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
+                             SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
+                             THIS_MODULE, 0, &sc);
+       if (ret) {
+               CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit;
+       }
+
+       /* (3) Create a main component */
+       ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc);
+       if (ret) {
+               CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit_free;
+       }
+
+       /* (4) Set the driver ID and name strings */
+       snd_cx18_card_set_names(cxsc);
+
+
+       ret = snd_cx18_pcm_create(cxsc);
+       if (ret) {
+               CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit_free;
+       }
+       /* FIXME - proc files */
+
+       /* (7) Set the driver data and return 0 */
+       /* We do this out of normal order for PCI drivers to avoid races */
+       cx->alsa = cxsc;
+
+       /* (6) Register the card instance */
+       ret = snd_card_register(sc);
+       if (ret) {
+               cx->alsa = NULL;
+               CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit_free;
+       }
+
+       return 0;
+
+err_exit_free:
+       if (sc != NULL)
+               snd_card_free(sc);
+       kfree(cxsc);
+err_exit:
+       return ret;
+}
+
+int cx18_alsa_load(struct cx18 *cx)
+{
+       struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
+       struct cx18_stream *s;
+
+       if (v4l2_dev == NULL) {
+               printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
+                      __func__);
+               return 0;
+       }
+
+       cx = to_cx18(v4l2_dev);
+       if (cx == NULL) {
+               printk(KERN_ERR "cx18-alsa cx is NULL\n");
+               return 0;
+       }
+
+       s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
+       if (s->video_dev == NULL) {
+               CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
+                                    "skipping\n", __func__);
+               return 0;
+       }
+
+       if (cx->alsa != NULL) {
+               CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n",
+                             __func__);
+               return 0;
+       }
+
+       if (snd_cx18_init(v4l2_dev)) {
+               CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n",
+                             __func__);
+       } else {
+               CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance "
+                                    "\n", __func__);
+       }
+       return 0;
+}
+
+static int __init cx18_alsa_init(void)
+{
+       printk(KERN_INFO "cx18-alsa: module loading...\n");
+       cx18_ext_init = &cx18_alsa_load;
+       return 0;
+}
+
+static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc)
+{
+       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+
+       /* FIXME - pointer checks & shutdown cxsc */
+
+       snd_card_free(cxsc->sc);
+       cx->alsa = NULL;
+}
+
+static int __exit cx18_alsa_exit_callback(struct device *dev, void *data)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+       struct snd_cx18_card *cxsc;
+
+       if (v4l2_dev == NULL) {
+               printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
+                      __func__);
+               return 0;
+       }
+
+       cxsc = to_snd_cx18_card(v4l2_dev);
+       if (cxsc == NULL) {
+               CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n",
+                              __func__);
+               return 0;
+       }
+
+       snd_cx18_exit(cxsc);
+       return 0;
+}
+
+static void __exit cx18_alsa_exit(void)
+{
+       struct device_driver *drv;
+       int ret;
+
+       printk(KERN_INFO "cx18-alsa: module unloading...\n");
+
+       drv = driver_find("cx18", &pci_bus_type);
+       ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
+       (void)ret;      /* suppress compiler warning */
+
+       cx18_ext_init = NULL;
+       printk(KERN_INFO "cx18-alsa: module unload complete\n");
+}
+
+module_init(cx18_alsa_init);
+module_exit(cx18_alsa_exit);
diff --git a/drivers/media/pci/cx18/cx18-alsa-mixer.c b/drivers/media/pci/cx18/cx18-alsa-mixer.c
new file mode 100644 (file)
index 0000000..341bddc
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+
+#include "cx18-alsa.h"
+#include "cx18-driver.h"
+
+/*
+ * Note the cx18-av-core volume scale is funny, due to the alignment of the
+ * scale with another chip's range:
+ *
+ * v4l2_control value  /512    indicated dB    actual dB       reg 0x8d4
+ * 0x0000 - 0x01ff       0     -119            -96             228
+ * 0x0200 - 0x02ff       1     -118            -96             228
+ * ...
+ * 0x2c00 - 0x2dff      22      -97            -96             228
+ * 0x2e00 - 0x2fff      23      -96            -96             228
+ * 0x3000 - 0x31ff      24      -95            -95             226
+ * ...
+ * 0xee00 - 0xefff     119        0              0              36
+ * ...
+ * 0xfe00 - 0xffff     127       +8             +8              20
+ */
+static inline int dB_to_cx18_av_vol(int dB)
+{
+       if (dB < -96)
+               dB = -96;
+       else if (dB > 8)
+               dB = 8;
+       return (dB + 119) << 9;
+}
+
+static inline int cx18_av_vol_to_dB(int v)
+{
+       if (v < (23 << 9))
+               v = (23 << 9);
+       else if (v > (127 << 9))
+               v = (127 << 9);
+       return (v >> 9) - 119;
+}
+
+static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       /* We're already translating values, just keep this control in dB */
+       uinfo->value.integer.min  = -96;
+       uinfo->value.integer.max  =   8;
+       uinfo->value.integer.step =   1;
+       return 0;
+}
+
+static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl,
+                                    struct snd_ctl_elem_value *uctl)
+{
+       struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
+       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+       struct v4l2_control vctrl;
+       int ret;
+
+       vctrl.id = V4L2_CID_AUDIO_VOLUME;
+       vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
+
+       snd_cx18_lock(cxsc);
+       ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
+       snd_cx18_unlock(cxsc);
+
+       if (!ret)
+               uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value);
+       return ret;
+}
+
+static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl,
+                                    struct snd_ctl_elem_value *uctl)
+{
+       struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
+       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+       struct v4l2_control vctrl;
+       int ret;
+
+       vctrl.id = V4L2_CID_AUDIO_VOLUME;
+       vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
+
+       snd_cx18_lock(cxsc);
+
+       /* Fetch current state */
+       ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
+
+       if (ret ||
+           (cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
+
+               /* Set, if needed */
+               vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
+               ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl);
+               if (!ret)
+                       ret = 1; /* Indicate control was changed w/o error */
+       }
+       snd_cx18_unlock(cxsc);
+
+       return ret;
+}
+
+
+/* This is a bit of overkill, the slider is already in dB internally */
+static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0);
+
+static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Analog TV Capture Volume",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+       .info = snd_cx18_mixer_tv_volume_info,
+       .get = snd_cx18_mixer_tv_volume_get,
+       .put = snd_cx18_mixer_tv_volume_put,
+       .tlv.p = snd_cx18_mixer_tv_vol_db_scale
+};
+
+/* FIXME - add mute switch and balance, bass, treble sliders:
+       V4L2_CID_AUDIO_MUTE
+
+       V4L2_CID_AUDIO_BALANCE
+
+       V4L2_CID_AUDIO_BASS
+       V4L2_CID_AUDIO_TREBLE
+*/
+
+/* FIXME - add stereo, lang1, lang2, mono menu */
+/* FIXME - add CS5345 I2S volume for HVR-1600 */
+
+int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc)
+{
+       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+       struct snd_card *sc = cxsc->sc;
+       int ret;
+
+       strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername));
+
+       ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc));
+       if (ret) {
+               CX18_ALSA_WARN("%s: failed to add %s control, err %d\n",
+                               __func__, snd_cx18_mixer_tv_vol.name, ret);
+       }
+       return ret;
+}
diff --git a/drivers/media/pci/cx18/cx18-alsa-mixer.h b/drivers/media/pci/cx18/cx18-alsa-mixer.h
new file mode 100644 (file)
index 0000000..ec92387
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc);
diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.c b/drivers/media/pci/cx18/cx18-alsa-pcm.c
new file mode 100644 (file)
index 0000000..7a5b84a
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "cx18-driver.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-fileops.h"
+#include "cx18-alsa.h"
+
+static unsigned int pcm_debug;
+module_param(pcm_debug, int, 0644);
+MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
+
+#define dprintk(fmt, arg...) do {                                      \
+           if (pcm_debug)                                              \
+               printk(KERN_INFO "cx18-alsa-pcm %s: " fmt,              \
+                                 __func__, ##arg);                     \
+       } while (0)
+
+static struct snd_pcm_hardware snd_cx18_hw_capture = {
+       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP           |
+               SNDRV_PCM_INFO_INTERLEAVED    |
+               SNDRV_PCM_INFO_MMAP_VALID,
+
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_48000,
+
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
+       .period_bytes_min = 64,         /* 12544/2, */
+       .period_bytes_max = 12544,
+       .periods_min = 2,
+       .periods_max = 98,              /* 12544, */
+};
+
+void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data,
+                                size_t num_bytes)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime *runtime;
+       unsigned int oldptr;
+       unsigned int stride;
+       int period_elapsed = 0;
+       int length;
+
+       dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc,
+               pcm_data, num_bytes);
+
+       substream = cxsc->capture_pcm_substream;
+       if (substream == NULL) {
+               dprintk("substream was NULL\n");
+               return;
+       }
+
+       runtime = substream->runtime;
+       if (runtime == NULL) {
+               dprintk("runtime was NULL\n");
+               return;
+       }
+
+       stride = runtime->frame_bits >> 3;
+       if (stride == 0) {
+               dprintk("stride is zero\n");
+               return;
+       }
+
+       length = num_bytes / stride;
+       if (length == 0) {
+               dprintk("%s: length was zero\n", __func__);
+               return;
+       }
+
+       if (runtime->dma_area == NULL) {
+               dprintk("dma area was NULL - ignoring\n");
+               return;
+       }
+
+       oldptr = cxsc->hwptr_done_capture;
+       if (oldptr + length >= runtime->buffer_size) {
+               unsigned int cnt =
+                       runtime->buffer_size - oldptr;
+               memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+                      cnt * stride);
+               memcpy(runtime->dma_area, pcm_data + cnt * stride,
+                      length * stride - cnt * stride);
+       } else {
+               memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+                      length * stride);
+       }
+       snd_pcm_stream_lock(substream);
+
+       cxsc->hwptr_done_capture += length;
+       if (cxsc->hwptr_done_capture >=
+           runtime->buffer_size)
+               cxsc->hwptr_done_capture -=
+                       runtime->buffer_size;
+
+       cxsc->capture_transfer_done += length;
+       if (cxsc->capture_transfer_done >=
+           runtime->period_size) {
+               cxsc->capture_transfer_done -=
+                       runtime->period_size;
+               period_elapsed = 1;
+       }
+
+       snd_pcm_stream_unlock(substream);
+
+       if (period_elapsed)
+               snd_pcm_period_elapsed(substream);
+}
+
+static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+       struct cx18 *cx = to_cx18(v4l2_dev);
+       struct cx18_stream *s;
+       struct cx18_open_id item;
+       int ret;
+
+       /* Instruct the cx18 to start sending packets */
+       snd_cx18_lock(cxsc);
+       s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
+
+       item.cx = cx;
+       item.type = s->type;
+       item.open_id = cx->open_id++;
+
+       /* See if the stream is available */
+       if (cx18_claim_stream(&item, item.type)) {
+               /* No, it's already in use */
+               snd_cx18_unlock(cxsc);
+               return -EBUSY;
+       }
+
+       if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
+           test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               /* We're already streaming.  No additional action required */
+               snd_cx18_unlock(cxsc);
+               return 0;
+       }
+
+
+       runtime->hw = snd_cx18_hw_capture;
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       cxsc->capture_pcm_substream = substream;
+       runtime->private_data = cx;
+
+       cx->pcm_announce_callback = cx18_alsa_announce_pcm_data;
+
+       /* Not currently streaming, so start it up */
+       set_bit(CX18_F_S_STREAMING, &s->s_flags);
+       ret = cx18_start_v4l2_encode_stream(s);
+       snd_cx18_unlock(cxsc);
+
+       return ret;
+}
+
+static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+       struct cx18 *cx = to_cx18(v4l2_dev);
+       struct cx18_stream *s;
+
+       /* Instruct the cx18 to stop sending packets */
+       snd_cx18_lock(cxsc);
+       s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
+       cx18_stop_v4l2_encode_stream(s, 0);
+       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+
+       cx18_release_stream(s);
+
+       cx->pcm_announce_callback = NULL;
+       snd_cx18_unlock(cxsc);
+
+       return 0;
+}
+
+static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
+                    unsigned int cmd, void *arg)
+{
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       int ret;
+
+       snd_cx18_lock(cxsc);
+       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+       snd_cx18_unlock(cxsc);
+       return ret;
+}
+
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+                                       size_t size)
+{
+       struct snd_pcm_runtime *runtime = subs->runtime;
+
+       dprintk("Allocating vbuffer\n");
+       if (runtime->dma_area) {
+               if (runtime->dma_bytes > size)
+                       return 0;
+
+               vfree(runtime->dma_area);
+       }
+       runtime->dma_area = vmalloc(size);
+       if (!runtime->dma_area)
+               return -ENOMEM;
+
+       runtime->dma_bytes = size;
+
+       return 0;
+}
+
+static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *params)
+{
+       dprintk("%s called\n", __func__);
+
+       return snd_pcm_alloc_vmalloc_buffer(substream,
+                                          params_buffer_bytes(params));
+}
+
+static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       unsigned long flags;
+
+       spin_lock_irqsave(&cxsc->slock, flags);
+       if (substream->runtime->dma_area) {
+               dprintk("freeing pcm capture region\n");
+               vfree(substream->runtime->dma_area);
+               substream->runtime->dma_area = NULL;
+       }
+       spin_unlock_irqrestore(&cxsc->slock, flags);
+
+       return 0;
+}
+
+static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+
+       cxsc->hwptr_done_capture = 0;
+       cxsc->capture_transfer_done = 0;
+
+       return 0;
+}
+
+static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       return 0;
+}
+
+static
+snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       unsigned long flags;
+       snd_pcm_uframes_t hwptr_done;
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+
+       spin_lock_irqsave(&cxsc->slock, flags);
+       hwptr_done = cxsc->hwptr_done_capture;
+       spin_unlock_irqrestore(&cxsc->slock, flags);
+
+       return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+                                            unsigned long offset)
+{
+       void *pageptr = subs->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops snd_cx18_pcm_capture_ops = {
+       .open           = snd_cx18_pcm_capture_open,
+       .close          = snd_cx18_pcm_capture_close,
+       .ioctl          = snd_cx18_pcm_ioctl,
+       .hw_params      = snd_cx18_pcm_hw_params,
+       .hw_free        = snd_cx18_pcm_hw_free,
+       .prepare        = snd_cx18_pcm_prepare,
+       .trigger        = snd_cx18_pcm_trigger,
+       .pointer        = snd_cx18_pcm_pointer,
+       .page           = snd_pcm_get_vmalloc_page,
+};
+
+int snd_cx18_pcm_create(struct snd_cx18_card *cxsc)
+{
+       struct snd_pcm *sp;
+       struct snd_card *sc = cxsc->sc;
+       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+       struct cx18 *cx = to_cx18(v4l2_dev);
+       int ret;
+
+       ret = snd_pcm_new(sc, "CX23418 PCM",
+                         0, /* PCM device 0, the only one for this card */
+                         0, /* 0 playback substreams */
+                         1, /* 1 capture substream */
+                         &sp);
+       if (ret) {
+               CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit;
+       }
+
+       spin_lock_init(&cxsc->slock);
+
+       snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_cx18_pcm_capture_ops);
+       sp->info_flags = 0;
+       sp->private_data = cxsc;
+       strlcpy(sp->name, cx->card_name, sizeof(sp->name));
+
+       return 0;
+
+err_exit:
+       return ret;
+}
diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.h b/drivers/media/pci/cx18/cx18-alsa-pcm.h
new file mode 100644 (file)
index 0000000..d26e51f
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc);
+
+/* Used by cx18-mailbox to announce the PCM data to the module */
+void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data,
+                                size_t num_bytes);
diff --git a/drivers/media/pci/cx18/cx18-alsa.h b/drivers/media/pci/cx18/cx18-alsa.h
new file mode 100644 (file)
index 0000000..447da37
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+struct snd_card;
+
+struct snd_cx18_card {
+       struct v4l2_device *v4l2_dev;
+       struct snd_card *sc;
+       unsigned int capture_transfer_done;
+       unsigned int hwptr_done_capture;
+       struct snd_pcm_substream *capture_pcm_substream;
+       spinlock_t slock;
+};
+
+extern int cx18_alsa_debug;
+
+/*
+ * File operations that manipulate the encoder or video or audio subdevices
+ * need to be serialized.  Use the same lock we use for v4l2 file ops.
+ */
+static inline void snd_cx18_lock(struct snd_cx18_card *cxsc)
+{
+       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+       mutex_lock(&cx->serialize_lock);
+}
+
+static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
+{
+       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+       mutex_unlock(&cx->serialize_lock);
+}
+
+#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
+#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
+#define CX18_ALSA_DBGFLG_INFO  (1 << 1)
+
+#define CX18_ALSA_DEBUG(x, type, fmt, args...) \
+       do { \
+               if ((x) & cx18_alsa_debug) \
+                       printk(KERN_INFO "%s-alsa: " type ": " fmt, \
+                               v4l2_dev->name , ## args); \
+       } while (0)
+
+#define CX18_ALSA_DEBUG_WARN(fmt, args...) \
+       CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_WARN, "warning", fmt , ## args)
+
+#define CX18_ALSA_DEBUG_INFO(fmt, args...) \
+       CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_INFO, "info", fmt , ## args)
+
+#define CX18_ALSA_ERR(fmt, args...) \
+       printk(KERN_ERR "%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define CX18_ALSA_WARN(fmt, args...) \
+       printk(KERN_WARNING "%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define CX18_ALSA_INFO(fmt, args...) \
+       printk(KERN_INFO "%s-alsa: " fmt, v4l2_dev->name , ## args)
diff --git a/drivers/media/pci/cx18/cx18-audio.c b/drivers/media/pci/cx18/cx18-audio.c
new file mode 100644 (file)
index 0000000..3526892
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  cx18 audio-related functions
+ *
+ *  Derived from ivtv-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+#include "cx18-audio.h"
+
+#define CX18_AUDIO_ENABLE    0xc72014
+#define CX18_AI1_MUX_MASK    0x30
+#define CX18_AI1_MUX_I2S1    0x00
+#define CX18_AI1_MUX_I2S2    0x10
+#define CX18_AI1_MUX_843_I2S 0x20
+
+/* Selects the audio input and output according to the current
+   settings. */
+int cx18_audio_set_io(struct cx18 *cx)
+{
+       const struct cx18_card_audio_input *in;
+       u32 u, v;
+       int err;
+
+       /* Determine which input to use */
+       if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
+               in = &cx->card->radio_input;
+       else
+               in = &cx->card->audio_inputs[cx->audio_input];
+
+       /* handle muxer chips */
+       v4l2_subdev_call(cx->sd_extmux, audio, s_routing,
+                        (u32) in->muxer_input, 0, 0);
+
+       err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl,
+                              audio, s_routing, in->audio_input, 0, 0);
+       if (err)
+               return err;
+
+       /* FIXME - this internal mux should be abstracted to a subdev */
+       u = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+       v = u & ~CX18_AI1_MUX_MASK;
+       switch (in->audio_input) {
+       case CX18_AV_AUDIO_SERIAL1:
+               v |= CX18_AI1_MUX_I2S1;
+               break;
+       case CX18_AV_AUDIO_SERIAL2:
+               v |= CX18_AI1_MUX_I2S2;
+               break;
+       default:
+               v |= CX18_AI1_MUX_843_I2S;
+               break;
+       }
+       if (v == u) {
+               /* force a toggle of some AI1 MUX control bits */
+               u &= ~CX18_AI1_MUX_MASK;
+               switch (in->audio_input) {
+               case CX18_AV_AUDIO_SERIAL1:
+                       u |= CX18_AI1_MUX_843_I2S;
+                       break;
+               case CX18_AV_AUDIO_SERIAL2:
+                       u |= CX18_AI1_MUX_843_I2S;
+                       break;
+               default:
+                       u |= CX18_AI1_MUX_I2S1;
+                       break;
+               }
+               cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE,
+                                     u, CX18_AI1_MUX_MASK);
+       }
+       cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+                             v, CX18_AI1_MUX_MASK);
+       return 0;
+}
diff --git a/drivers/media/pci/cx18/cx18-audio.h b/drivers/media/pci/cx18/cx18-audio.h
new file mode 100644 (file)
index 0000000..2731d29
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  cx18 audio-related functions
+ *
+ *  Derived from ivtv-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+int cx18_audio_set_io(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx18-av-audio.c b/drivers/media/pci/cx18/cx18-av-audio.c
new file mode 100644 (file)
index 0000000..4a24ffb
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ *  cx18 ADEC audio functions
+ *
+ *  Derived from cx25840-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+
+static int set_audclk_freq(struct cx18 *cx, u32 freq)
+{
+       struct cx18_av_state *state = &cx->av_state;
+
+       if (freq != 32000 && freq != 44100 && freq != 48000)
+               return -EINVAL;
+
+       /*
+        * The PLL parameters are based on the external crystal frequency that
+        * would ideally be:
+        *
+        * NTSC Color subcarrier freq * 8 =
+        *      4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
+        *
+        * The accidents of history and rationale that explain from where this
+        * combination of magic numbers originate can be found in:
+        *
+        * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
+        * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
+        *
+        * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
+        * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
+        *
+        * As Mike Bradley has rightly pointed out, it's not the exact crystal
+        * frequency that matters, only that all parts of the driver and
+        * firmware are using the same value (close to the ideal value).
+        *
+        * Since I have a strong suspicion that, if the firmware ever assumes a
+        * crystal value at all, it will assume 28.636360 MHz, the crystal
+        * freq used in calculations in this driver will be:
+        *
+        *      xtal_freq = 28.636360 MHz
+        *
+        * an error of less than 0.13 ppm which is way, way better than any off
+        * the shelf crystal will have for accuracy anyway.
+        *
+        * Below I aim to run the PLLs' VCOs near 400 MHz to minimze error.
+        *
+        * Many thanks to Jeff Campbell and Mike Bradley for their extensive
+        * investigation, experimentation, testing, and suggested solutions of
+        * of audio/video sync problems with SVideo and CVBS captures.
+        */
+
+       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+               switch (freq) {
+               case 32000:
+                       /*
+                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+                        * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
+                        */
+                       cx18_av_write4(cx, 0x108, 0x200d040f);
+
+                       /* VID_PLL Fraction = 0x2be2fe */
+                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+                       /* AUX_PLL Fraction = 0x176740c */
+                       /* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/
+                       cx18_av_write4(cx, 0x110, 0x0176740c);
+
+                       /* src3/4/6_ctl */
+                       /* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */
+                       cx18_av_write4(cx, 0x900, 0x0801f77f);
+                       cx18_av_write4(cx, 0x904, 0x0801f77f);
+                       cx18_av_write4(cx, 0x90c, 0x0801f77f);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
+                       cx18_av_write(cx, 0x127, 0x60);
+
+                       /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11202fff);
+
+                       /*
+                        * EN_AV_LOCK = 0
+                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa00d2ef8);
+                       break;
+
+               case 44100:
+                       /*
+                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+                        * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x18
+                        */
+                       cx18_av_write4(cx, 0x108, 0x180e040f);
+
+                       /* VID_PLL Fraction = 0x2be2fe */
+                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+                       /* AUX_PLL Fraction = 0x062a1f2 */
+                       /* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/
+                       cx18_av_write4(cx, 0x110, 0x0062a1f2);
+
+                       /* src3/4/6_ctl */
+                       /* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */
+                       cx18_av_write4(cx, 0x900, 0x08016d59);
+                       cx18_av_write4(cx, 0x904, 0x08016d59);
+                       cx18_av_write4(cx, 0x90c, 0x08016d59);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */
+                       cx18_av_write(cx, 0x127, 0x58);
+
+                       /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x112092ff);
+
+                       /*
+                        * EN_AV_LOCK = 0
+                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa01d4bf8);
+                       break;
+
+               case 48000:
+                       /*
+                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+                        * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16
+                        */
+                       cx18_av_write4(cx, 0x108, 0x160e040f);
+
+                       /* VID_PLL Fraction = 0x2be2fe */
+                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+                       /* AUX_PLL Fraction = 0x05227ad */
+                       /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/
+                       cx18_av_write4(cx, 0x110, 0x005227ad);
+
+                       /* src3/4/6_ctl */
+                       /* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */
+                       cx18_av_write4(cx, 0x900, 0x08014faa);
+                       cx18_av_write4(cx, 0x904, 0x08014faa);
+                       cx18_av_write4(cx, 0x90c, 0x08014faa);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
+                       cx18_av_write(cx, 0x127, 0x56);
+
+                       /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11205fff);
+
+                       /*
+                        * EN_AV_LOCK = 0
+                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa01193f8);
+                       break;
+               }
+       } else {
+               switch (freq) {
+               case 32000:
+                       /*
+                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+                        * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30
+                        */
+                       cx18_av_write4(cx, 0x108, 0x300d040f);
+
+                       /* VID_PLL Fraction = 0x2be2fe */
+                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+                       /* AUX_PLL Fraction = 0x176740c */
+                       /* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/
+                       cx18_av_write4(cx, 0x110, 0x0176740c);
+
+                       /* src1_ctl */
+                       /* 0x1.0000 = 32000/32000 */
+                       cx18_av_write4(cx, 0x8f8, 0x08010000);
+
+                       /* src3/4/6_ctl */
+                       /* 0x2.0000 = 2 * (32000/32000) */
+                       cx18_av_write4(cx, 0x900, 0x08020000);
+                       cx18_av_write4(cx, 0x904, 0x08020000);
+                       cx18_av_write4(cx, 0x90c, 0x08020000);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */
+                       cx18_av_write(cx, 0x127, 0x70);
+
+                       /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11201fff);
+
+                       /*
+                        * EN_AV_LOCK = 0
+                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa00d2ef8);
+                       break;
+
+               case 44100:
+                       /*
+                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+                        * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24
+                        */
+                       cx18_av_write4(cx, 0x108, 0x240e040f);
+
+                       /* VID_PLL Fraction = 0x2be2fe */
+                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+                       /* AUX_PLL Fraction = 0x062a1f2 */
+                       /* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/
+                       cx18_av_write4(cx, 0x110, 0x0062a1f2);
+
+                       /* src1_ctl */
+                       /* 0x1.60cd = 44100/32000 */
+                       cx18_av_write4(cx, 0x8f8, 0x080160cd);
+
+                       /* src3/4/6_ctl */
+                       /* 0x1.7385 = 2 * (32000/44100) */
+                       cx18_av_write4(cx, 0x900, 0x08017385);
+                       cx18_av_write4(cx, 0x904, 0x08017385);
+                       cx18_av_write4(cx, 0x90c, 0x08017385);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */
+                       cx18_av_write(cx, 0x127, 0x64);
+
+                       /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x112061ff);
+
+                       /*
+                        * EN_AV_LOCK = 0
+                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa01d4bf8);
+                       break;
+
+               case 48000:
+                       /*
+                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+                        * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
+                        */
+                       cx18_av_write4(cx, 0x108, 0x200d040f);
+
+                       /* VID_PLL Fraction = 0x2be2fe */
+                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+                       /* AUX_PLL Fraction = 0x176740c */
+                       /* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/
+                       cx18_av_write4(cx, 0x110, 0x0176740c);
+
+                       /* src1_ctl */
+                       /* 0x1.8000 = 48000/32000 */
+                       cx18_av_write4(cx, 0x8f8, 0x08018000);
+
+                       /* src3/4/6_ctl */
+                       /* 0x1.5555 = 2 * (32000/48000) */
+                       cx18_av_write4(cx, 0x900, 0x08015555);
+                       cx18_av_write4(cx, 0x904, 0x08015555);
+                       cx18_av_write4(cx, 0x90c, 0x08015555);
+
+                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
+                       cx18_av_write(cx, 0x127, 0x60);
+
+                       /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
+                       cx18_av_write4(cx, 0x12c, 0x11203fff);
+
+                       /*
+                        * EN_AV_LOCK = 0
+                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+                        */
+                       cx18_av_write4(cx, 0x128, 0xa01193f8);
+                       break;
+               }
+       }
+
+       state->audclk_freq = freq;
+
+       return 0;
+}
+
+void cx18_av_audio_set_path(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       u8 v;
+
+       /* stop microcontroller */
+       v = cx18_av_read(cx, 0x803) & ~0x10;
+       cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+
+       /* assert soft reset */
+       v = cx18_av_read(cx, 0x810) | 0x01;
+       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
+       /* Mute everything to prevent the PFFT! */
+       cx18_av_write(cx, 0x8d3, 0x1f);
+
+       if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
+               /* Set Path1 to Serial Audio Input */
+               cx18_av_write4(cx, 0x8d0, 0x01011012);
+
+               /* The microcontroller should not be started for the
+                * non-tuner inputs: autodetection is specific for
+                * TV audio. */
+       } else {
+               /* Set Path1 to Analog Demod Main Channel */
+               cx18_av_write4(cx, 0x8d0, 0x1f063870);
+       }
+
+       set_audclk_freq(cx, state->audclk_freq);
+
+       /* deassert soft reset */
+       v = cx18_av_read(cx, 0x810) & ~0x01;
+       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
+       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+               /* When the microcontroller detects the
+                * audio format, it will unmute the lines */
+               v = cx18_av_read(cx, 0x803) | 0x10;
+               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+       }
+}
+
+static void set_volume(struct cx18 *cx, int volume)
+{
+       /* First convert the volume to msp3400 values (0-127) */
+       int vol = volume >> 9;
+       /* now scale it up to cx18_av values
+        * -114dB to -96dB maps to 0
+        * this should be 19, but in my testing that was 4dB too loud */
+       if (vol <= 23)
+               vol = 0;
+       else
+               vol -= 23;
+
+       /* PATH1_VOLUME */
+       cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
+}
+
+static void set_bass(struct cx18 *cx, int bass)
+{
+       /* PATH1_EQ_BASS_VOL */
+       cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
+}
+
+static void set_treble(struct cx18 *cx, int treble)
+{
+       /* PATH1_EQ_TREBLE_VOL */
+       cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
+}
+
+static void set_balance(struct cx18 *cx, int balance)
+{
+       int bal = balance >> 8;
+       if (bal > 0x80) {
+               /* PATH1_BAL_LEFT */
+               cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
+               /* PATH1_BAL_LEVEL */
+               cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
+       } else {
+               /* PATH1_BAL_LEFT */
+               cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
+               /* PATH1_BAL_LEVEL */
+               cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
+       }
+}
+
+static void set_mute(struct cx18 *cx, int mute)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       u8 v;
+
+       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+               /* Must turn off microcontroller in order to mute sound.
+                * Not sure if this is the best method, but it does work.
+                * If the microcontroller is running, then it will undo any
+                * changes to the mute register. */
+               v = cx18_av_read(cx, 0x803);
+               if (mute) {
+                       /* disable microcontroller */
+                       v &= ~0x10;
+                       cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+                       cx18_av_write(cx, 0x8d3, 0x1f);
+               } else {
+                       /* enable microcontroller */
+                       v |= 0x10;
+                       cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+               }
+       } else {
+               /* SRC1_MUTE_EN */
+               cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
+       }
+}
+
+int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       struct cx18_av_state *state = &cx->av_state;
+       int retval;
+       u8 v;
+
+       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+               v = cx18_av_read(cx, 0x803) & ~0x10;
+               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+               cx18_av_write(cx, 0x8d3, 0x1f);
+       }
+       v = cx18_av_read(cx, 0x810) | 0x1;
+       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
+       retval = set_audclk_freq(cx, freq);
+
+       v = cx18_av_read(cx, 0x810) & ~0x1;
+       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+               v = cx18_av_read(cx, 0x803) | 0x10;
+               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+       }
+       return retval;
+}
+
+static int cx18_av_audio_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = to_sd(ctrl);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_VOLUME:
+               set_volume(cx, ctrl->val);
+               break;
+       case V4L2_CID_AUDIO_BASS:
+               set_bass(cx, ctrl->val);
+               break;
+       case V4L2_CID_AUDIO_TREBLE:
+               set_treble(cx, ctrl->val);
+               break;
+       case V4L2_CID_AUDIO_BALANCE:
+               set_balance(cx, ctrl->val);
+               break;
+       case V4L2_CID_AUDIO_MUTE:
+               set_mute(cx, ctrl->val);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops = {
+       .s_ctrl = cx18_av_audio_s_ctrl,
+};
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
new file mode 100644 (file)
index 0000000..f164b7f
--- /dev/null
@@ -0,0 +1,1401 @@
+/*
+ *  cx18 ADEC audio functions
+ *
+ *  Derived from cx25840-core.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include <media/v4l2-chip-ident.h>
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
+{
+       u32 reg = 0xc40000 + (addr & ~3);
+       u32 mask = 0xff;
+       int shift = (addr & 3) * 8;
+       u32 x = cx18_read_reg(cx, reg);
+
+       x = (x & ~(mask << shift)) | ((u32)value << shift);
+       cx18_write_reg(cx, x, reg);
+       return 0;
+}
+
+int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
+{
+       u32 reg = 0xc40000 + (addr & ~3);
+       int shift = (addr & 3) * 8;
+       u32 x = cx18_read_reg(cx, reg);
+
+       x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
+       cx18_write_reg_expect(cx, x, reg,
+                               ((u32)eval << shift), ((u32)mask << shift));
+       return 0;
+}
+
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
+{
+       cx18_write_reg(cx, value, 0xc40000 + addr);
+       return 0;
+}
+
+int
+cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
+{
+       cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
+       return 0;
+}
+
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
+{
+       cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
+       return 0;
+}
+
+u8 cx18_av_read(struct cx18 *cx, u16 addr)
+{
+       u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
+       int shift = (addr & 3) * 8;
+
+       return (x >> shift) & 0xff;
+}
+
+u32 cx18_av_read4(struct cx18 *cx, u16 addr)
+{
+       return cx18_read_reg(cx, 0xc40000 + addr);
+}
+
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
+                  u8 or_value)
+{
+       return cx18_av_write(cx, addr,
+                            (cx18_av_read(cx, addr) & and_mask) |
+                            or_value);
+}
+
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
+                  u32 or_value)
+{
+       return cx18_av_write4(cx, addr,
+                            (cx18_av_read4(cx, addr) & and_mask) |
+                            or_value);
+}
+
+static void cx18_av_init(struct cx18 *cx)
+{
+       /*
+        * The crystal freq used in calculations in this driver will be
+        * 28.636360 MHz.
+        * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
+        */
+
+       /*
+        * VDCLK  Integer = 0x0f, Post Divider = 0x04
+        * AIMCLK Integer = 0x0e, Post Divider = 0x16
+        */
+       cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
+
+       /* VDCLK Fraction = 0x2be2fe */
+       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
+       cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
+
+       /* AIMCLK Fraction = 0x05227ad */
+       /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
+       cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
+
+       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
+       cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
+}
+
+static void cx18_av_initialize(struct v4l2_subdev *sd)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       int default_volume;
+       u32 v;
+
+       cx18_av_loadfw(cx);
+       /* Stop 8051 code execution */
+       cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
+                                                0x03000000, 0x13000000);
+
+       /* initallize the PLL by toggling sleep bit */
+       v = cx18_av_read4(cx, CXADEC_HOST_REG1);
+       /* enable sleep mode - register appears to be read only... */
+       cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
+       /* disable sleep mode */
+       cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
+                                                   v & 0xfffe, 0xffff);
+
+       /* initialize DLLs */
+       v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
+       /* disable FLD */
+       cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
+       /* enable FLD */
+       cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
+
+       v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
+       /* disable FLD */
+       cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
+       /* enable FLD */
+       cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
+
+       /* set analog bias currents. Set Vreg to 1.20V. */
+       cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
+
+       v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
+       /* enable TUNE_FIL_RST */
+       cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
+       /* disable TUNE_FIL_RST */
+       cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
+                             v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);
+
+       /* enable 656 output */
+       cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
+
+       /* video output drive strength */
+       cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
+
+       /* reset video */
+       cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
+       cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
+
+       /*
+        * Disable Video Auto-config of the Analog Front End and Video PLL.
+        *
+        * Since we only use BT.656 pixel mode, which works for both 525 and 625
+        * line systems, it's just easier for us to set registers
+        * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL),
+        * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC)
+        * ourselves, than to run around cleaning up after the auto-config.
+        *
+        * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit
+        * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL
+        * autoconfig either.)
+        *
+        * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3.
+        */
+       cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
+
+       /* Setup the Video and and Aux/Audio PLLs */
+       cx18_av_init(cx);
+
+       /* set video to auto-detect */
+       /* Clear bits 11-12 to enable slow locking mode.  Set autodetect mode */
+       /* set the comb notch = 1 */
+       cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
+
+       /* Enable wtw_en in CRUSH_CTRL (Set bit 22) */
+       /* Enable maj_sel in CRUSH_CTRL (Set bit 20) */
+       cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
+
+       /* Set VGA_TRACK_RANGE to 0x20 */
+       cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
+
+       /*
+        * Initial VBI setup
+        * VIP-1.1, 10 bit mode, enable Raw, disable sliced,
+        * don't clamp raw samples when codes are in use, 1 byte user D-words,
+        * IDID0 has line #, RP code V bit transition on VBLANK, data during
+        * blanking intervals
+        */
+       cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e);
+
+       /* Set the video input.
+          The setting in MODE_CTRL gets lost when we do the above setup */
+       /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
+       /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
+
+       /*
+        * Analog Front End (AFE)
+        * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2
+        *  bypass_ch[1-3]     use filter
+        *  droop_comp_ch[1-3] disable
+        *  clamp_en_ch[1-3]   disable
+        *  aud_in_sel         ADC2
+        *  luma_in_sel        ADC1
+        *  chroma_in_sel      ADC2
+        *  clamp_sel_ch[2-3]  midcode
+        *  clamp_sel_ch1      video decoder
+        *  vga_sel_ch3        audio decoder
+        *  vga_sel_ch[1-2]    video decoder
+        *  half_bw_ch[1-3]    disable
+        *  +12db_ch[1-3]      disable
+        */
+       cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
+
+/*     if(dwEnable && dw3DCombAvailable) { */
+/*             CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
+/*    } else { */
+/*             CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
+/*    } */
+       cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
+       default_volume = cx18_av_read(cx, 0x8d4);
+       /*
+        * Enforce the legacy volume scale mapping limits to avoid
+        * -ERANGE errors when initializing the volume control
+        */
+       if (default_volume > 228) {
+               /* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+               default_volume = 228;
+               cx18_av_write(cx, 0x8d4, 228);
+       } else if (default_volume < 20) {
+               /* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+               default_volume = 20;
+               cx18_av_write(cx, 0x8d4, 20);
+       }
+       default_volume = (((228 - default_volume) >> 1) + 23) << 9;
+       state->volume->cur.val = state->volume->default_value = default_volume;
+       v4l2_ctrl_handler_setup(&state->hdl);
+}
+
+static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
+{
+       cx18_av_initialize(sd);
+       return 0;
+}
+
+static int cx18_av_load_fw(struct v4l2_subdev *sd)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+
+       if (!state->is_initialized) {
+               /* initialize on first use */
+               state->is_initialized = 1;
+               cx18_av_initialize(sd);
+       }
+       return 0;
+}
+
+void cx18_av_std_setup(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_subdev *sd = &state->sd;
+       v4l2_std_id std = state->std;
+
+       /*
+        * Video ADC crystal clock to pixel clock SRC decimation ratio
+        * 28.636360 MHz/13.5 Mpps * 256 = 0x21f.07b
+        */
+       const int src_decimation = 0x21f;
+
+       int hblank, hactive, burst, vblank, vactive, sc;
+       int vblank656;
+       int luma_lpf, uv_lpf, comb;
+       u32 pll_int, pll_frac, pll_post;
+
+       /* datasheet startup, step 8d */
+       if (std & ~V4L2_STD_NTSC)
+               cx18_av_write(cx, 0x49f, 0x11);
+       else
+               cx18_av_write(cx, 0x49f, 0x14);
+
+       /*
+        * Note: At the end of a field, there are 3 sets of half line duration
+        * (double horizontal rate) pulses:
+        *
+        * 5 (625) or 6 (525) half-lines to blank for the vertical retrace
+        * 5 (625) or 6 (525) vertical sync pulses of half line duration
+        * 5 (625) or 6 (525) half-lines of equalization pulses
+        */
+       if (std & V4L2_STD_625_50) {
+               /*
+                * The following relationships of half line counts should hold:
+                * 625 = vblank656 + vactive
+                * 10 = vblank656 - vblank = vsync pulses + equalization pulses
+                *
+                * vblank656: half lines after line 625/mid-313 of blanked video
+                * vblank:    half lines, after line 5/317, of blanked video
+                * vactive:   half lines of active video +
+                *              5 half lines after the end of active video
+                *
+                * As far as I can tell:
+                * vblank656 starts counting from the falling edge of the first
+                *      vsync pulse (start of line 1 or mid-313)
+                * vblank starts counting from the after the 5 vsync pulses and
+                *      5 or 4 equalization pulses (start of line 6 or 318)
+                *
+                * For 625 line systems the driver will extract VBI information
+                * from lines 6-23 and lines 318-335 (but the slicer can only
+                * handle 17 lines, not the 18 in the vblank region).
+                * In addition, we need vblank656 and vblank to be one whole
+                * line longer, to cover line 24 and 336, so the SAV/EAV RP
+                * codes get generated such that the encoder can actually
+                * extract line 23 & 335 (WSS).  We'll lose 1 line in each field
+                * at the top of the screen.
+                *
+                * It appears the 5 half lines that happen after active
+                * video must be included in vactive (579 instead of 574),
+                * otherwise the colors get badly displayed in various regions
+                * of the screen.  I guess the chroma comb filter gets confused
+                * without them (at least when a PVR-350 is the PAL source).
+                */
+               vblank656 = 48; /* lines  1 -  24  &  313 - 336 */
+               vblank = 38;    /* lines  6 -  24  &  318 - 336 */
+               vactive = 579;  /* lines 24 - 313  &  337 - 626 */
+
+               /*
+                * For a 13.5 Mpps clock and 15,625 Hz line rate, a line is
+                * is 864 pixels = 720 active + 144 blanking.  ITU-R BT.601
+                * specifies 12 luma clock periods or ~ 0.9 * 13.5 Mpps after
+                * the end of active video to start a horizontal line, so that
+                * leaves 132 pixels of hblank to ignore.
+                */
+               hblank = 132;
+               hactive = 720;
+
+               /*
+                * Burst gate delay (for 625 line systems)
+                * Hsync leading edge to color burst rise = 5.6 us
+                * Color burst width = 2.25 us
+                * Gate width = 4 pixel clocks
+                * (5.6 us + 2.25/2 us) * 13.5 Mpps + 4/2 clocks = 92.79 clocks
+                */
+               burst = 93;
+               luma_lpf = 2;
+               if (std & V4L2_STD_PAL) {
+                       uv_lpf = 1;
+                       comb = 0x20;
+                       /* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
+                       sc = 688700;
+               } else if (std == V4L2_STD_PAL_Nc) {
+                       uv_lpf = 1;
+                       comb = 0x20;
+                       /* sc = 3582056.25 * src_decimation/28636360 * 2^13 */
+                       sc = 556422;
+               } else { /* SECAM */
+                       uv_lpf = 0;
+                       comb = 0;
+                       /* (fr + fb)/2 = (4406260 + 4250000)/2 = 4328130 */
+                       /* sc = 4328130 * src_decimation/28636360 * 2^13 */
+                       sc = 672314;
+               }
+       } else {
+               /*
+                * The following relationships of half line counts should hold:
+                * 525 = prevsync + vblank656 + vactive
+                * 12 = vblank656 - vblank = vsync pulses + equalization pulses
+                *
+                * prevsync:  6 half-lines before the vsync pulses
+                * vblank656: half lines, after line 3/mid-266, of blanked video
+                * vblank:    half lines, after line 9/272, of blanked video
+                * vactive:   half lines of active video
+                *
+                * As far as I can tell:
+                * vblank656 starts counting from the falling edge of the first
+                *      vsync pulse (start of line 4 or mid-266)
+                * vblank starts counting from the after the 6 vsync pulses and
+                *      6 or 5 equalization pulses (start of line 10 or 272)
+                *
+                * For 525 line systems the driver will extract VBI information
+                * from lines 10-21 and lines 273-284.
+                */
+               vblank656 = 38; /* lines  4 -  22  &  266 - 284 */
+               vblank = 26;    /* lines 10 -  22  &  272 - 284 */
+               vactive = 481;  /* lines 23 - 263  &  285 - 525 */
+
+               /*
+                * For a 13.5 Mpps clock and 15,734.26 Hz line rate, a line is
+                * is 858 pixels = 720 active + 138 blanking.  The Hsync leading
+                * edge should happen 1.2 us * 13.5 Mpps ~= 16 pixels after the
+                * end of active video, leaving 122 pixels of hblank to ignore
+                * before active video starts.
+                */
+               hactive = 720;
+               hblank = 122;
+               luma_lpf = 1;
+               uv_lpf = 1;
+
+               /*
+                * Burst gate delay (for 525 line systems)
+                * Hsync leading edge to color burst rise = 5.3 us
+                * Color burst width = 2.5 us
+                * Gate width = 4 pixel clocks
+                * (5.3 us + 2.5/2 us) * 13.5 Mpps + 4/2 clocks = 90.425 clocks
+                */
+               if (std == V4L2_STD_PAL_60) {
+                       burst = 90;
+                       luma_lpf = 2;
+                       comb = 0x20;
+                       /* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
+                       sc = 688700;
+               } else if (std == V4L2_STD_PAL_M) {
+                       /* The 97 needs to be verified against PAL-M timings */
+                       burst = 97;
+                       comb = 0x20;
+                       /* sc = 3575611.49 * src_decimation/28636360 * 2^13 */
+                       sc = 555421;
+               } else {
+                       burst = 90;
+                       comb = 0x66;
+                       /* sc = 3579545.45.. * src_decimation/28636360 * 2^13 */
+                       sc = 556032;
+               }
+       }
+
+       /* DEBUG: Displays configured PLL frequency */
+       pll_int = cx18_av_read(cx, 0x108);
+       pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
+       pll_post = cx18_av_read(cx, 0x109);
+       CX18_DEBUG_INFO_DEV(sd, "PLL regs = int: %u, frac: %u, post: %u\n",
+                           pll_int, pll_frac, pll_post);
+
+       if (pll_post) {
+               int fsc, pll;
+               u64 tmp;
+
+               pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
+               pll /= pll_post;
+               CX18_DEBUG_INFO_DEV(sd, "Video PLL = %d.%06d MHz\n",
+                                   pll / 1000000, pll % 1000000);
+               CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n",
+                                   pll / 8000000, (pll / 8) % 1000000);
+
+               CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio "
+                                   "= %d.%03d\n", src_decimation / 256,
+                                   ((src_decimation % 256) * 1000) / 256);
+
+               tmp = 28636360 * (u64) sc;
+               do_div(tmp, src_decimation);
+               fsc = tmp >> 13;
+               CX18_DEBUG_INFO_DEV(sd,
+                                   "Chroma sub-carrier initial freq = %d.%06d "
+                                   "MHz\n", fsc / 1000000, fsc % 1000000);
+
+               CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, "
+                                   "vactive %i, vblank656 %i, src_dec %i, "
+                                   "burst 0x%02x, luma_lpf %i, uv_lpf %i, "
+                                   "comb 0x%02x, sc 0x%06x\n",
+                                   hblank, hactive, vblank, vactive, vblank656,
+                                   src_decimation, burst, luma_lpf, uv_lpf,
+                                   comb, sc);
+       }
+
+       /* Sets horizontal blanking delay and active lines */
+       cx18_av_write(cx, 0x470, hblank);
+       cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+                                               (hactive << 4)));
+       cx18_av_write(cx, 0x472, hactive >> 4);
+
+       /* Sets burst gate delay */
+       cx18_av_write(cx, 0x473, burst);
+
+       /* Sets vertical blanking delay and active duration */
+       cx18_av_write(cx, 0x474, vblank);
+       cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+                                               (vactive << 4)));
+       cx18_av_write(cx, 0x476, vactive >> 4);
+       cx18_av_write(cx, 0x477, vblank656);
+
+       /* Sets src decimation rate */
+       cx18_av_write(cx, 0x478, 0xff & src_decimation);
+       cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
+
+       /* Sets Luma and UV Low pass filters */
+       cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+       /* Enables comb filters */
+       cx18_av_write(cx, 0x47b, comb);
+
+       /* Sets SC Step*/
+       cx18_av_write(cx, 0x47c, sc);
+       cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+       cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
+
+       if (std & V4L2_STD_625_50) {
+               state->slicer_line_delay = 1;
+               state->slicer_line_offset = (6 + state->slicer_line_delay - 2);
+       } else {
+               state->slicer_line_delay = 0;
+               state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
+       }
+       cx18_av_write(cx, 0x47f, state->slicer_line_delay);
+}
+
+static void input_change(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       v4l2_std_id std = state->std;
+       u8 v;
+
+       /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
+       cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+       cx18_av_and_or(cx, 0x401, ~0x60, 0);
+       cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
+
+       if (std & V4L2_STD_525_60) {
+               if (std == V4L2_STD_NTSC_M_JP) {
+                       /* Japan uses EIAJ audio standard */
+                       cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
+                       cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
+               } else if (std == V4L2_STD_NTSC_M_KR) {
+                       /* South Korea uses A2 audio standard */
+                       cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
+                       cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
+               } else {
+                       /* Others use the BTSC audio standard */
+                       cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
+                       cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
+               }
+       } else if (std & V4L2_STD_PAL) {
+               /* Follow tuner change procedure for PAL */
+               cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
+               cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
+       } else if (std & V4L2_STD_SECAM) {
+               /* Select autodetect for SECAM */
+               cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
+               cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
+       }
+
+       v = cx18_av_read(cx, 0x803);
+       if (v & 0x10) {
+               /* restart audio decoder microcontroller */
+               v &= ~0x10;
+               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+               v |= 0x10;
+               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+       }
+}
+
+static int cx18_av_s_frequency(struct v4l2_subdev *sd,
+                              struct v4l2_frequency *freq)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       input_change(cx);
+       return 0;
+}
+
+static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
+                                       enum cx18_av_audio_input aud_input)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_subdev *sd = &state->sd;
+
+       enum analog_signal_type {
+               NONE, CVBS, Y, C, SIF, Pb, Pr
+       } ch[3] = {NONE, NONE, NONE};
+
+       u8 afe_mux_cfg;
+       u8 adc2_cfg;
+       u8 input_mode;
+       u32 afe_cfg;
+       int i;
+
+       CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
+                           vid_input, aud_input);
+
+       if (vid_input >= CX18_AV_COMPOSITE1 &&
+           vid_input <= CX18_AV_COMPOSITE8) {
+               afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+               ch[0] = CVBS;
+               input_mode = 0x0;
+       } else if (vid_input >= CX18_AV_COMPONENT_LUMA1) {
+               int luma = vid_input & 0xf000;
+               int r_chroma = vid_input & 0xf0000;
+               int b_chroma = vid_input & 0xf00000;
+
+               if ((vid_input & ~0xfff000) ||
+                   luma < CX18_AV_COMPONENT_LUMA1 ||
+                   luma > CX18_AV_COMPONENT_LUMA8 ||
+                   r_chroma < CX18_AV_COMPONENT_R_CHROMA4 ||
+                   r_chroma > CX18_AV_COMPONENT_R_CHROMA6 ||
+                   b_chroma < CX18_AV_COMPONENT_B_CHROMA7 ||
+                   b_chroma > CX18_AV_COMPONENT_B_CHROMA8) {
+                       CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
+                                    vid_input);
+                       return -EINVAL;
+               }
+               afe_mux_cfg = (luma - CX18_AV_COMPONENT_LUMA1) >> 12;
+               ch[0] = Y;
+               afe_mux_cfg |= (r_chroma - CX18_AV_COMPONENT_R_CHROMA4) >> 12;
+               ch[1] = Pr;
+               afe_mux_cfg |= (b_chroma - CX18_AV_COMPONENT_B_CHROMA7) >> 14;
+               ch[2] = Pb;
+               input_mode = 0x6;
+       } else {
+               int luma = vid_input & 0xf0;
+               int chroma = vid_input & 0xf00;
+
+               if ((vid_input & ~0xff0) ||
+                   luma < CX18_AV_SVIDEO_LUMA1 ||
+                   luma > CX18_AV_SVIDEO_LUMA8 ||
+                   chroma < CX18_AV_SVIDEO_CHROMA4 ||
+                   chroma > CX18_AV_SVIDEO_CHROMA8) {
+                       CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
+                                    vid_input);
+                       return -EINVAL;
+               }
+               afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+               ch[0] = Y;
+               if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
+                       afe_mux_cfg &= 0x3f;
+                       afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+                       ch[2] = C;
+               } else {
+                       afe_mux_cfg &= 0xcf;
+                       afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+                       ch[1] = C;
+               }
+               input_mode = 0x2;
+       }
+
+       switch (aud_input) {
+       case CX18_AV_AUDIO_SERIAL1:
+       case CX18_AV_AUDIO_SERIAL2:
+               /* do nothing, use serial audio input */
+               break;
+       case CX18_AV_AUDIO4:
+               afe_mux_cfg &= ~0x30;
+               ch[1] = SIF;
+               break;
+       case CX18_AV_AUDIO5:
+               afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
+               ch[1] = SIF;
+               break;
+       case CX18_AV_AUDIO6:
+               afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
+               ch[1] = SIF;
+               break;
+       case CX18_AV_AUDIO7:
+               afe_mux_cfg &= ~0xc0;
+               ch[2] = SIF;
+               break;
+       case CX18_AV_AUDIO8:
+               afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
+               ch[2] = SIF;
+               break;
+
+       default:
+               CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
+                            aud_input);
+               return -EINVAL;
+       }
+
+       /* Set up analog front end multiplexers */
+       cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
+       /* Set INPUT_MODE to Composite, S-Video, or Component */
+       cx18_av_and_or(cx, 0x401, ~0x6, input_mode);
+
+       /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+       adc2_cfg = cx18_av_read(cx, 0x102);
+       if (ch[2] == NONE)
+               adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */
+       else
+               adc2_cfg |= 0x2;  /* Signal on CH3, set ADC2 to CH3 for input */
+
+       /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+       if (ch[1] != NONE && ch[2] != NONE)
+               adc2_cfg |= 0x4; /* Set dual mode */
+       else
+               adc2_cfg &= ~0x4; /* Clear dual mode */
+       cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
+
+       /* Configure the analog front end */
+       afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+       afe_cfg &= 0xff000000;
+       afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */
+       if (ch[1] != NONE && ch[2] != NONE)
+               afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */
+
+       for (i = 0; i < 3; i++) {
+               switch (ch[i]) {
+               default:
+               case NONE:
+                       /* CLAMP_SEL = Fixed to midcode clamp level */
+                       afe_cfg |= (0x00000200 << i);
+                       break;
+               case CVBS:
+               case Y:
+                       if (i > 0)
+                               afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */
+                       break;
+               case C:
+               case Pb:
+               case Pr:
+                       /* CLAMP_SEL = Fixed to midcode clamp level */
+                       afe_cfg |= (0x00000200 << i);
+                       if (i == 0 && ch[i] == C)
+                               afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */
+                       break;
+               case SIF:
+                       /*
+                        * VGA_GAIN_SEL = Audio Decoder
+                        * CLAMP_SEL = Fixed to midcode clamp level
+                        */
+                       afe_cfg |= (0x00000240 << i);
+                       if (i == 0)
+                               afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */
+                       break;
+               }
+       }
+
+       cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
+
+       state->vid_input = vid_input;
+       state->aud_input = aud_input;
+       cx18_av_audio_set_path(cx);
+       input_change(cx);
+       return 0;
+}
+
+static int cx18_av_s_video_routing(struct v4l2_subdev *sd,
+                                  u32 input, u32 output, u32 config)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       return set_input(cx, input, state->aud_input);
+}
+
+static int cx18_av_s_audio_routing(struct v4l2_subdev *sd,
+                                  u32 input, u32 output, u32 config)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       return set_input(cx, state->vid_input, input);
+}
+
+static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       u8 vpres;
+       u8 mode;
+       int val = 0;
+
+       if (state->radio)
+               return 0;
+
+       vpres = cx18_av_read(cx, 0x40e) & 0x20;
+       vt->signal = vpres ? 0xffff : 0x0;
+
+       vt->capability |=
+                   V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+                   V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+       mode = cx18_av_read(cx, 0x804);
+
+       /* get rxsubchans and audmode */
+       if ((mode & 0xf) == 1)
+               val |= V4L2_TUNER_SUB_STEREO;
+       else
+               val |= V4L2_TUNER_SUB_MONO;
+
+       if (mode == 2 || mode == 4)
+               val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+       if (mode & 0x10)
+               val |= V4L2_TUNER_SUB_SAP;
+
+       vt->rxsubchans = val;
+       vt->audmode = state->audmode;
+       return 0;
+}
+
+static int cx18_av_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       u8 v;
+
+       if (state->radio)
+               return 0;
+
+       v = cx18_av_read(cx, 0x809);
+       v &= ~0xf;
+
+       switch (vt->audmode) {
+       case V4L2_TUNER_MODE_MONO:
+               /* mono      -> mono
+                  stereo    -> mono
+                  bilingual -> lang1 */
+               break;
+       case V4L2_TUNER_MODE_STEREO:
+       case V4L2_TUNER_MODE_LANG1:
+               /* mono      -> mono
+                  stereo    -> stereo
+                  bilingual -> lang1 */
+               v |= 0x4;
+               break;
+       case V4L2_TUNER_MODE_LANG1_LANG2:
+               /* mono      -> mono
+                  stereo    -> stereo
+                  bilingual -> lang1/lang2 */
+               v |= 0x7;
+               break;
+       case V4L2_TUNER_MODE_LANG2:
+               /* mono      -> mono
+                  stereo    -> stereo
+                  bilingual -> lang2 */
+               v |= 0x1;
+               break;
+       default:
+               return -EINVAL;
+       }
+       cx18_av_write_expect(cx, 0x809, v, v, 0xff);
+       state->audmode = vt->audmode;
+       return 0;
+}
+
+static int cx18_av_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       u8 fmt = 0;     /* zero is autodetect */
+       u8 pal_m = 0;
+
+       if (state->radio == 0 && state->std == norm)
+               return 0;
+
+       state->radio = 0;
+       state->std = norm;
+
+       /* First tests should be against specific std */
+       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 (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;
+       }
+
+       CX18_DEBUG_INFO_DEV(sd, "changing video std to fmt %i\n", fmt);
+
+       /* Follow step 9 of section 3.16 in the cx18_av datasheet.
+          Without this PAL may display a vertical ghosting effect.
+          This happens for example with the Yuan MPC622. */
+       if (fmt >= 4 && fmt < 8) {
+               /* Set format to NTSC-M */
+               cx18_av_and_or(cx, 0x400, ~0xf, 1);
+               /* Turn off LCOMB */
+               cx18_av_and_or(cx, 0x47b, ~6, 0);
+       }
+       cx18_av_and_or(cx, 0x400, ~0x2f, fmt | 0x20);
+       cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
+       cx18_av_std_setup(cx);
+       input_change(cx);
+       return 0;
+}
+
+static int cx18_av_s_radio(struct v4l2_subdev *sd)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       state->radio = 1;
+       return 0;
+}
+
+static int cx18_av_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = to_sd(ctrl);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               cx18_av_write(cx, 0x414, ctrl->val - 128);
+               break;
+
+       case V4L2_CID_CONTRAST:
+               cx18_av_write(cx, 0x415, ctrl->val << 1);
+               break;
+
+       case V4L2_CID_SATURATION:
+               cx18_av_write(cx, 0x420, ctrl->val << 1);
+               cx18_av_write(cx, 0x421, ctrl->val << 1);
+               break;
+
+       case V4L2_CID_HUE:
+               cx18_av_write(cx, 0x422, ctrl->val);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+       int is_50Hz = !(state->std & V4L2_STD_525_60);
+
+       if (fmt->code != V4L2_MBUS_FMT_FIXED)
+               return -EINVAL;
+
+       fmt->field = V4L2_FIELD_INTERLACED;
+       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
+       Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
+
+       Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
+       Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
+
+       /*
+        * This adjustment reflects the excess of vactive, set in
+        * cx18_av_std_setup(), above standard values:
+        *
+        * 480 + 1 for 60 Hz systems
+        * 576 + 3 for 50 Hz systems
+        */
+       Vlines = fmt->height + (is_50Hz ? 3 : 1);
+
+       /*
+        * Invalid height and width scaling requests are:
+        * 1. width less than 1/16 of the source width
+        * 2. width greater than the source width
+        * 3. height less than 1/8 of the source height
+        * 4. height greater than the source height
+        */
+       if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+           (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+               CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
+                            fmt->width, fmt->height);
+               return -ERANGE;
+       }
+
+       HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+       VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+       VSC &= 0x1fff;
+
+       if (fmt->width >= 385)
+               filter = 0;
+       else if (fmt->width > 192)
+               filter = 1;
+       else if (fmt->width > 96)
+               filter = 2;
+       else
+               filter = 3;
+
+       CX18_DEBUG_INFO_DEV(sd,
+                           "decoder set size %dx%d -> scale  %ux%u\n",
+                           fmt->width, fmt->height, HSC, VSC);
+
+       /* HSCALE=HSC */
+       cx18_av_write(cx, 0x418, HSC & 0xff);
+       cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
+       cx18_av_write(cx, 0x41a, HSC >> 16);
+       /* VSCALE=VSC */
+       cx18_av_write(cx, 0x41c, VSC & 0xff);
+       cx18_av_write(cx, 0x41d, VSC >> 8);
+       /* VS_INTRLACE=1 VFILT=filter */
+       cx18_av_write(cx, 0x41e, 0x8 | filter);
+       return 0;
+}
+
+static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       CX18_DEBUG_INFO_DEV(sd, "%s output\n", enable ? "enable" : "disable");
+       if (enable) {
+               cx18_av_write(cx, 0x115, 0x8c);
+               cx18_av_write(cx, 0x116, 0x07);
+       } else {
+               cx18_av_write(cx, 0x115, 0x00);
+               cx18_av_write(cx, 0x116, 0x00);
+       }
+       return 0;
+}
+
+static void log_video_status(struct cx18 *cx)
+{
+       static const char *const fmt_strs[] = {
+               "0x0",
+               "NTSC-M", "NTSC-J", "NTSC-4.43",
+               "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
+               "0x9", "0xA", "0xB",
+               "SECAM",
+               "0xD", "0xE", "0xF"
+       };
+
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_subdev *sd = &state->sd;
+       u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
+       u8 gen_stat1 = cx18_av_read(cx, 0x40d);
+       u8 gen_stat2 = cx18_av_read(cx, 0x40e);
+       int vid_input = state->vid_input;
+
+       CX18_INFO_DEV(sd, "Video signal:              %spresent\n",
+                     (gen_stat2 & 0x20) ? "" : "not ");
+       CX18_INFO_DEV(sd, "Detected format:           %s\n",
+                     fmt_strs[gen_stat1 & 0xf]);
+
+       CX18_INFO_DEV(sd, "Specified standard:        %s\n",
+                     vidfmt_sel ? fmt_strs[vidfmt_sel]
+                                : "automatic detection");
+
+       if (vid_input >= CX18_AV_COMPOSITE1 &&
+           vid_input <= CX18_AV_COMPOSITE8) {
+               CX18_INFO_DEV(sd, "Specified video input:     Composite %d\n",
+                             vid_input - CX18_AV_COMPOSITE1 + 1);
+       } else {
+               CX18_INFO_DEV(sd, "Specified video input:     "
+                             "S-Video (Luma In%d, Chroma In%d)\n",
+                             (vid_input & 0xf0) >> 4,
+                             (vid_input & 0xf00) >> 8);
+       }
+
+       CX18_INFO_DEV(sd, "Specified audioclock freq: %d Hz\n",
+                     state->audclk_freq);
+}
+
+static void log_audio_status(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_subdev *sd = &state->sd;
+       u8 download_ctl = cx18_av_read(cx, 0x803);
+       u8 mod_det_stat0 = cx18_av_read(cx, 0x804);
+       u8 mod_det_stat1 = cx18_av_read(cx, 0x805);
+       u8 audio_config = cx18_av_read(cx, 0x808);
+       u8 pref_mode = cx18_av_read(cx, 0x809);
+       u8 afc0 = cx18_av_read(cx, 0x80b);
+       u8 mute_ctl = cx18_av_read(cx, 0x8d3);
+       int aud_input = state->aud_input;
+       char *p;
+
+       switch (mod_det_stat0) {
+       case 0x00: p = "mono"; break;
+       case 0x01: p = "stereo"; break;
+       case 0x02: p = "dual"; break;
+       case 0x04: p = "tri"; break;
+       case 0x10: p = "mono with SAP"; break;
+       case 0x11: p = "stereo with SAP"; break;
+       case 0x12: p = "dual with SAP"; break;
+       case 0x14: p = "tri with SAP"; break;
+       case 0xfe: p = "forced mode"; break;
+       default: p = "not defined"; break;
+       }
+       CX18_INFO_DEV(sd, "Detected audio mode:       %s\n", p);
+
+       switch (mod_det_stat1) {
+       case 0x00: p = "not defined"; break;
+       case 0x01: p = "EIAJ"; break;
+       case 0x02: p = "A2-M"; break;
+       case 0x03: p = "A2-BG"; break;
+       case 0x04: p = "A2-DK1"; break;
+       case 0x05: p = "A2-DK2"; break;
+       case 0x06: p = "A2-DK3"; break;
+       case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+       case 0x08: p = "AM-L"; break;
+       case 0x09: p = "NICAM-BG"; break;
+       case 0x0a: p = "NICAM-DK"; break;
+       case 0x0b: p = "NICAM-I"; break;
+       case 0x0c: p = "NICAM-L"; break;
+       case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+       case 0x0e: p = "IF FM Radio"; break;
+       case 0x0f: p = "BTSC"; break;
+       case 0x10: p = "detected chrominance"; break;
+       case 0xfd: p = "unknown audio standard"; break;
+       case 0xfe: p = "forced audio standard"; break;
+       case 0xff: p = "no detected audio standard"; break;
+       default: p = "not defined"; break;
+       }
+       CX18_INFO_DEV(sd, "Detected audio standard:   %s\n", p);
+       CX18_INFO_DEV(sd, "Audio muted:               %s\n",
+                     (mute_ctl & 0x2) ? "yes" : "no");
+       CX18_INFO_DEV(sd, "Audio microcontroller:     %s\n",
+                     (download_ctl & 0x10) ? "running" : "stopped");
+
+       switch (audio_config >> 4) {
+       case 0x00: p = "undefined"; break;
+       case 0x01: p = "BTSC"; break;
+       case 0x02: p = "EIAJ"; break;
+       case 0x03: p = "A2-M"; break;
+       case 0x04: p = "A2-BG"; break;
+       case 0x05: p = "A2-DK1"; break;
+       case 0x06: p = "A2-DK2"; break;
+       case 0x07: p = "A2-DK3"; break;
+       case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
+       case 0x09: p = "AM-L"; break;
+       case 0x0a: p = "NICAM-BG"; break;
+       case 0x0b: p = "NICAM-DK"; break;
+       case 0x0c: p = "NICAM-I"; break;
+       case 0x0d: p = "NICAM-L"; break;
+       case 0x0e: p = "FM radio"; break;
+       case 0x0f: p = "automatic detection"; break;
+       default: p = "undefined"; break;
+       }
+       CX18_INFO_DEV(sd, "Configured audio standard: %s\n", p);
+
+       if ((audio_config >> 4) < 0xF) {
+               switch (audio_config & 0xF) {
+               case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
+               case 0x01: p = "MONO2 (LANGUAGE B)"; break;
+               case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
+               case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
+               case 0x04: p = "STEREO"; break;
+               case 0x05: p = "DUAL1 (AC)"; break;
+               case 0x06: p = "DUAL2 (BC)"; break;
+               case 0x07: p = "DUAL3 (AB)"; break;
+               default: p = "undefined";
+               }
+               CX18_INFO_DEV(sd, "Configured audio mode:     %s\n", p);
+       } else {
+               switch (audio_config & 0xF) {
+               case 0x00: p = "BG"; break;
+               case 0x01: p = "DK1"; break;
+               case 0x02: p = "DK2"; break;
+               case 0x03: p = "DK3"; break;
+               case 0x04: p = "I"; break;
+               case 0x05: p = "L"; break;
+               case 0x06: p = "BTSC"; break;
+               case 0x07: p = "EIAJ"; break;
+               case 0x08: p = "A2-M"; break;
+               case 0x09: p = "FM Radio (4.5 MHz)"; break;
+               case 0x0a: p = "FM Radio (5.5 MHz)"; break;
+               case 0x0b: p = "S-Video"; break;
+               case 0x0f: p = "automatic standard and mode detection"; break;
+               default: p = "undefined"; break;
+               }
+               CX18_INFO_DEV(sd, "Configured audio system:   %s\n", p);
+       }
+
+       if (aud_input)
+               CX18_INFO_DEV(sd, "Specified audio input:     Tuner (In%d)\n",
+                             aud_input);
+       else
+               CX18_INFO_DEV(sd, "Specified audio input:     External\n");
+
+       switch (pref_mode & 0xf) {
+       case 0: p = "mono/language A"; break;
+       case 1: p = "language B"; break;
+       case 2: p = "language C"; break;
+       case 3: p = "analog fallback"; break;
+       case 4: p = "stereo"; break;
+       case 5: p = "language AC"; break;
+       case 6: p = "language BC"; break;
+       case 7: p = "language AB"; break;
+       default: p = "undefined"; break;
+       }
+       CX18_INFO_DEV(sd, "Preferred audio mode:      %s\n", p);
+
+       if ((audio_config & 0xf) == 0xf) {
+               switch ((afc0 >> 3) & 0x1) {
+               case 0: p = "system DK"; break;
+               case 1: p = "system L"; break;
+               }
+               CX18_INFO_DEV(sd, "Selected 65 MHz format:    %s\n", p);
+
+               switch (afc0 & 0x7) {
+               case 0: p = "Chroma"; break;
+               case 1: p = "BTSC"; break;
+               case 2: p = "EIAJ"; break;
+               case 3: p = "A2-M"; break;
+               case 4: p = "autodetect"; break;
+               default: p = "undefined"; break;
+               }
+               CX18_INFO_DEV(sd, "Selected 45 MHz format:    %s\n", p);
+       }
+}
+
+static int cx18_av_log_status(struct v4l2_subdev *sd)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       log_video_status(cx);
+       log_audio_status(cx);
+       return 0;
+}
+
+static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match)
+{
+       return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1;
+}
+
+static int cx18_av_g_chip_ident(struct v4l2_subdev *sd,
+                               struct v4l2_dbg_chip_ident *chip)
+{
+       struct cx18_av_state *state = to_cx18_av_state(sd);
+
+       if (cx18_av_dbg_match(&chip->match)) {
+               chip->ident = state->id;
+               chip->revision = state->rev;
+       }
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx18_av_g_register(struct v4l2_subdev *sd,
+                             struct v4l2_dbg_register *reg)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       if (!cx18_av_dbg_match(&reg->match))
+               return -EINVAL;
+       if ((reg->reg & 0x3) != 0)
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       reg->size = 4;
+       reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc);
+       return 0;
+}
+
+static int cx18_av_s_register(struct v4l2_subdev *sd,
+                             struct v4l2_dbg_register *reg)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       if (!cx18_av_dbg_match(&reg->match))
+               return -EINVAL;
+       if ((reg->reg & 0x3) != 0)
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val);
+       return 0;
+}
+#endif
+
+static const struct v4l2_ctrl_ops cx18_av_ctrl_ops = {
+       .s_ctrl = cx18_av_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops cx18_av_general_ops = {
+       .g_chip_ident = cx18_av_g_chip_ident,
+       .log_status = cx18_av_log_status,
+       .load_fw = cx18_av_load_fw,
+       .reset = cx18_av_reset,
+       .g_ctrl = v4l2_subdev_g_ctrl,
+       .s_ctrl = v4l2_subdev_s_ctrl,
+       .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+       .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+       .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+       .queryctrl = v4l2_subdev_queryctrl,
+       .querymenu = v4l2_subdev_querymenu,
+       .s_std = cx18_av_s_std,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = cx18_av_g_register,
+       .s_register = cx18_av_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops cx18_av_tuner_ops = {
+       .s_radio = cx18_av_s_radio,
+       .s_frequency = cx18_av_s_frequency,
+       .g_tuner = cx18_av_g_tuner,
+       .s_tuner = cx18_av_s_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
+       .s_clock_freq = cx18_av_s_clock_freq,
+       .s_routing = cx18_av_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
+       .s_routing = cx18_av_s_video_routing,
+       .s_stream = cx18_av_s_stream,
+       .s_mbus_fmt = cx18_av_s_mbus_fmt,
+};
+
+static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
+       .decode_vbi_line = cx18_av_decode_vbi_line,
+       .g_sliced_fmt = cx18_av_g_sliced_fmt,
+       .s_sliced_fmt = cx18_av_s_sliced_fmt,
+       .s_raw_fmt = cx18_av_s_raw_fmt,
+};
+
+static const struct v4l2_subdev_ops cx18_av_ops = {
+       .core = &cx18_av_general_ops,
+       .tuner = &cx18_av_tuner_ops,
+       .audio = &cx18_av_audio_ops,
+       .video = &cx18_av_video_ops,
+       .vbi = &cx18_av_vbi_ops,
+};
+
+int cx18_av_probe(struct cx18 *cx)
+{
+       struct cx18_av_state *state = &cx->av_state;
+       struct v4l2_subdev *sd;
+       int err;
+
+       state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff;
+       state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO)
+                   ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN;
+
+       state->vid_input = CX18_AV_COMPOSITE7;
+       state->aud_input = CX18_AV_AUDIO8;
+       state->audclk_freq = 48000;
+       state->audmode = V4L2_TUNER_MODE_LANG1;
+       state->slicer_line_delay = 0;
+       state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
+
+       sd = &state->sd;
+       v4l2_subdev_init(sd, &cx18_av_ops);
+       v4l2_set_subdevdata(sd, cx);
+       snprintf(sd->name, sizeof(sd->name),
+                "%s %03x", cx->v4l2_dev.name, (state->rev >> 4));
+       sd->grp_id = CX18_HW_418_AV;
+       v4l2_ctrl_handler_init(&state->hdl, 9);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 127, 1, 64);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 127, 1, 64);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+                       V4L2_CID_HUE, -128, 127, 1, 0);
+
+       state->volume = v4l2_ctrl_new_std(&state->hdl,
+                       &cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
+                       0, 65535, 65535 / 100, 0);
+       v4l2_ctrl_new_std(&state->hdl,
+                       &cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
+                       0, 1, 1, 0);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+                       V4L2_CID_AUDIO_BALANCE,
+                       0, 65535, 65535 / 100, 32768);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+                       V4L2_CID_AUDIO_BASS,
+                       0, 65535, 65535 / 100, 32768);
+       v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+                       V4L2_CID_AUDIO_TREBLE,
+                       0, 65535, 65535 / 100, 32768);
+       sd->ctrl_handler = &state->hdl;
+       if (state->hdl.error) {
+               int err = state->hdl.error;
+
+               v4l2_ctrl_handler_free(&state->hdl);
+               return err;
+       }
+       err = v4l2_device_register_subdev(&cx->v4l2_dev, sd);
+       if (err)
+               v4l2_ctrl_handler_free(&state->hdl);
+       else
+               cx18_av_init(cx);
+       return err;
+}
diff --git a/drivers/media/pci/cx18/cx18-av-core.h b/drivers/media/pci/cx18/cx18-av-core.h
new file mode 100644 (file)
index 0000000..e9c69d9
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ *  cx18 ADEC header
+ *
+ *  Derived from cx25840-core.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX18_AV_CORE_H_
+#define _CX18_AV_CORE_H_
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+struct cx18;
+
+enum cx18_av_video_input {
+       /* Composite video inputs In1-In8 */
+       CX18_AV_COMPOSITE1 = 1,
+       CX18_AV_COMPOSITE2,
+       CX18_AV_COMPOSITE3,
+       CX18_AV_COMPOSITE4,
+       CX18_AV_COMPOSITE5,
+       CX18_AV_COMPOSITE6,
+       CX18_AV_COMPOSITE7,
+       CX18_AV_COMPOSITE8,
+
+       /* S-Video inputs consist of one luma input (In1-In8) ORed with one
+          chroma input (In5-In8) */
+       CX18_AV_SVIDEO_LUMA1 = 0x10,
+       CX18_AV_SVIDEO_LUMA2 = 0x20,
+       CX18_AV_SVIDEO_LUMA3 = 0x30,
+       CX18_AV_SVIDEO_LUMA4 = 0x40,
+       CX18_AV_SVIDEO_LUMA5 = 0x50,
+       CX18_AV_SVIDEO_LUMA6 = 0x60,
+       CX18_AV_SVIDEO_LUMA7 = 0x70,
+       CX18_AV_SVIDEO_LUMA8 = 0x80,
+       CX18_AV_SVIDEO_CHROMA4 = 0x400,
+       CX18_AV_SVIDEO_CHROMA5 = 0x500,
+       CX18_AV_SVIDEO_CHROMA6 = 0x600,
+       CX18_AV_SVIDEO_CHROMA7 = 0x700,
+       CX18_AV_SVIDEO_CHROMA8 = 0x800,
+
+       /* S-Video aliases for common luma/chroma combinations */
+       CX18_AV_SVIDEO1 = 0x510,
+       CX18_AV_SVIDEO2 = 0x620,
+       CX18_AV_SVIDEO3 = 0x730,
+       CX18_AV_SVIDEO4 = 0x840,
+
+       /* Component Video inputs consist of one luma input (In1-In8) ORed
+          with a red chroma (In4-In6) and blue chroma input (In7-In8) */
+       CX18_AV_COMPONENT_LUMA1 = 0x1000,
+       CX18_AV_COMPONENT_LUMA2 = 0x2000,
+       CX18_AV_COMPONENT_LUMA3 = 0x3000,
+       CX18_AV_COMPONENT_LUMA4 = 0x4000,
+       CX18_AV_COMPONENT_LUMA5 = 0x5000,
+       CX18_AV_COMPONENT_LUMA6 = 0x6000,
+       CX18_AV_COMPONENT_LUMA7 = 0x7000,
+       CX18_AV_COMPONENT_LUMA8 = 0x8000,
+       CX18_AV_COMPONENT_R_CHROMA4 = 0x40000,
+       CX18_AV_COMPONENT_R_CHROMA5 = 0x50000,
+       CX18_AV_COMPONENT_R_CHROMA6 = 0x60000,
+       CX18_AV_COMPONENT_B_CHROMA7 = 0x700000,
+       CX18_AV_COMPONENT_B_CHROMA8 = 0x800000,
+
+       /* Component Video aliases for common combinations */
+       CX18_AV_COMPONENT1 = 0x861000,
+};
+
+enum cx18_av_audio_input {
+       /* Audio inputs: serial or In4-In8 */
+       CX18_AV_AUDIO_SERIAL1,
+       CX18_AV_AUDIO_SERIAL2,
+       CX18_AV_AUDIO4 = 4,
+       CX18_AV_AUDIO5,
+       CX18_AV_AUDIO6,
+       CX18_AV_AUDIO7,
+       CX18_AV_AUDIO8,
+};
+
+struct cx18_av_state {
+       struct v4l2_subdev sd;
+       struct v4l2_ctrl_handler hdl;
+       struct v4l2_ctrl *volume;
+       int radio;
+       v4l2_std_id std;
+       enum cx18_av_video_input vid_input;
+       enum cx18_av_audio_input aud_input;
+       u32 audclk_freq;
+       int audmode;
+       u32 id;
+       u32 rev;
+       int is_initialized;
+
+       /*
+        * The VBI slicer starts operating and counting lines, beginning at
+        * slicer line count of 1, at D lines after the deassertion of VRESET.
+        * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525
+        * line systems respectively.  Sliced ancillary data captured on VBI
+        * slicer line M is inserted after the VBI slicer is done with line M,
+        * when VBI slicer line count is N = M+1.  Thus when the VBI slicer
+        * reports a VBI slicer line number with ancillary data, the IDID0 byte
+        * indicates VBI slicer line N.  The actual field line that the captured
+        * data comes from is
+        *
+        * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2).
+        *
+        * L is the line in the field, not frame, from which the VBI data came.
+        * N is the line reported by the slicer in the ancillary data.
+        * D is the slicer_line_delay value programmed into register 0x47f.
+        * S is 6 for 625 line systems or 10 for 525 line systems
+        * (S+D-2) is the slicer_line_offset used to convert slicer reported
+        * line counts to actual field lines.
+        */
+       int slicer_line_delay;
+       int slicer_line_offset;
+};
+
+
+/* Registers */
+#define CXADEC_CHIP_TYPE_TIGER     0x837
+#define CXADEC_CHIP_TYPE_MAKO      0x843
+
+#define CXADEC_HOST_REG1           0x000
+#define CXADEC_HOST_REG2           0x001
+
+#define CXADEC_CHIP_CTRL           0x100
+#define CXADEC_AFE_CTRL            0x104
+#define CXADEC_PLL_CTRL1           0x108
+#define CXADEC_VID_PLL_FRAC        0x10C
+#define CXADEC_AUX_PLL_FRAC        0x110
+#define CXADEC_PIN_CTRL1           0x114
+#define CXADEC_PIN_CTRL2           0x118
+#define CXADEC_PIN_CFG1            0x11C
+#define CXADEC_PIN_CFG2            0x120
+
+#define CXADEC_PIN_CFG3            0x124
+#define CXADEC_I2S_MCLK            0x127
+
+#define CXADEC_AUD_LOCK1           0x128
+#define CXADEC_AUD_LOCK2           0x12C
+#define CXADEC_POWER_CTRL          0x130
+#define CXADEC_AFE_DIAG_CTRL1      0x134
+#define CXADEC_AFE_DIAG_CTRL2      0x138
+#define CXADEC_AFE_DIAG_CTRL3      0x13C
+#define CXADEC_PLL_DIAG_CTRL       0x140
+#define CXADEC_TEST_CTRL1          0x144
+#define CXADEC_TEST_CTRL2          0x148
+#define CXADEC_BIST_STAT           0x14C
+#define CXADEC_DLL1_DIAG_CTRL      0x158
+#define CXADEC_DLL2_DIAG_CTRL      0x15C
+
+/* IR registers */
+#define CXADEC_IR_CTRL_REG         0x200
+#define CXADEC_IR_TXCLK_REG        0x204
+#define CXADEC_IR_RXCLK_REG        0x208
+#define CXADEC_IR_CDUTY_REG        0x20C
+#define CXADEC_IR_STAT_REG         0x210
+#define CXADEC_IR_IRQEN_REG        0x214
+#define CXADEC_IR_FILTER_REG       0x218
+#define CXADEC_IR_FIFO_REG         0x21C
+
+/* Video Registers */
+#define CXADEC_MODE_CTRL           0x400
+#define CXADEC_OUT_CTRL1           0x404
+#define CXADEC_OUT_CTRL2           0x408
+#define CXADEC_GEN_STAT            0x40C
+#define CXADEC_INT_STAT_MASK       0x410
+#define CXADEC_LUMA_CTRL           0x414
+
+#define CXADEC_BRIGHTNESS_CTRL_BYTE 0x414
+#define CXADEC_CONTRAST_CTRL_BYTE  0x415
+#define CXADEC_LUMA_CTRL_BYTE_3    0x416
+
+#define CXADEC_HSCALE_CTRL         0x418
+#define CXADEC_VSCALE_CTRL         0x41C
+
+#define CXADEC_CHROMA_CTRL         0x420
+
+#define CXADEC_USAT_CTRL_BYTE      0x420
+#define CXADEC_VSAT_CTRL_BYTE      0x421
+#define CXADEC_HUE_CTRL_BYTE       0x422
+
+#define CXADEC_VBI_LINE_CTRL1      0x424
+#define CXADEC_VBI_LINE_CTRL2      0x428
+#define CXADEC_VBI_LINE_CTRL3      0x42C
+#define CXADEC_VBI_LINE_CTRL4      0x430
+#define CXADEC_VBI_LINE_CTRL5      0x434
+#define CXADEC_VBI_FC_CFG          0x438
+#define CXADEC_VBI_MISC_CFG1       0x43C
+#define CXADEC_VBI_MISC_CFG2       0x440
+#define CXADEC_VBI_PAY1            0x444
+#define CXADEC_VBI_PAY2            0x448
+#define CXADEC_VBI_CUST1_CFG1      0x44C
+#define CXADEC_VBI_CUST1_CFG2      0x450
+#define CXADEC_VBI_CUST1_CFG3      0x454
+#define CXADEC_VBI_CUST2_CFG1      0x458
+#define CXADEC_VBI_CUST2_CFG2      0x45C
+#define CXADEC_VBI_CUST2_CFG3      0x460
+#define CXADEC_VBI_CUST3_CFG1      0x464
+#define CXADEC_VBI_CUST3_CFG2      0x468
+#define CXADEC_VBI_CUST3_CFG3      0x46C
+#define CXADEC_HORIZ_TIM_CTRL      0x470
+#define CXADEC_VERT_TIM_CTRL       0x474
+#define CXADEC_SRC_COMB_CFG        0x478
+#define CXADEC_CHROMA_VBIOFF_CFG   0x47C
+#define CXADEC_FIELD_COUNT         0x480
+#define CXADEC_MISC_TIM_CTRL       0x484
+#define CXADEC_DFE_CTRL1           0x488
+#define CXADEC_DFE_CTRL2           0x48C
+#define CXADEC_DFE_CTRL3           0x490
+#define CXADEC_PLL_CTRL2           0x494
+#define CXADEC_HTL_CTRL            0x498
+#define CXADEC_COMB_CTRL           0x49C
+#define CXADEC_CRUSH_CTRL          0x4A0
+#define CXADEC_SOFT_RST_CTRL       0x4A4
+#define CXADEC_MV_DT_CTRL2         0x4A8
+#define CXADEC_MV_DT_CTRL3         0x4AC
+#define CXADEC_MISC_DIAG_CTRL      0x4B8
+
+#define CXADEC_DL_CTL              0x800
+#define CXADEC_DL_CTL_ADDRESS_LOW  0x800   /* Byte 1 in DL_CTL */
+#define CXADEC_DL_CTL_ADDRESS_HIGH 0x801   /* Byte 2 in DL_CTL */
+#define CXADEC_DL_CTL_DATA         0x802   /* Byte 3 in DL_CTL */
+#define CXADEC_DL_CTL_CONTROL      0x803   /* Byte 4 in DL_CTL */
+
+#define CXADEC_STD_DET_STATUS      0x804
+
+#define CXADEC_STD_DET_CTL         0x808
+#define CXADEC_STD_DET_CTL_AUD_CTL   0x808 /* Byte 1 in STD_DET_CTL */
+#define CXADEC_STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */
+
+#define CXADEC_DW8051_INT          0x80C
+#define CXADEC_GENERAL_CTL         0x810
+#define CXADEC_AAGC_CTL            0x814
+#define CXADEC_IF_SRC_CTL          0x818
+#define CXADEC_ANLOG_DEMOD_CTL     0x81C
+#define CXADEC_ROT_FREQ_CTL        0x820
+#define CXADEC_FM1_CTL             0x824
+#define CXADEC_PDF_CTL             0x828
+#define CXADEC_DFT1_CTL1           0x82C
+#define CXADEC_DFT1_CTL2           0x830
+#define CXADEC_DFT_STATUS          0x834
+#define CXADEC_DFT2_CTL1           0x838
+#define CXADEC_DFT2_CTL2           0x83C
+#define CXADEC_DFT2_STATUS         0x840
+#define CXADEC_DFT3_CTL1           0x844
+#define CXADEC_DFT3_CTL2           0x848
+#define CXADEC_DFT3_STATUS         0x84C
+#define CXADEC_DFT4_CTL1           0x850
+#define CXADEC_DFT4_CTL2           0x854
+#define CXADEC_DFT4_STATUS         0x858
+#define CXADEC_AM_MTS_DET          0x85C
+#define CXADEC_ANALOG_MUX_CTL      0x860
+#define CXADEC_DIG_PLL_CTL1        0x864
+#define CXADEC_DIG_PLL_CTL2        0x868
+#define CXADEC_DIG_PLL_CTL3        0x86C
+#define CXADEC_DIG_PLL_CTL4        0x870
+#define CXADEC_DIG_PLL_CTL5        0x874
+#define CXADEC_DEEMPH_GAIN_CTL     0x878
+#define CXADEC_DEEMPH_COEF1        0x87C
+#define CXADEC_DEEMPH_COEF2        0x880
+#define CXADEC_DBX1_CTL1           0x884
+#define CXADEC_DBX1_CTL2           0x888
+#define CXADEC_DBX1_STATUS         0x88C
+#define CXADEC_DBX2_CTL1           0x890
+#define CXADEC_DBX2_CTL2           0x894
+#define CXADEC_DBX2_STATUS         0x898
+#define CXADEC_AM_FM_DIFF          0x89C
+
+/* NICAM registers go here */
+#define CXADEC_NICAM_STATUS        0x8C8
+#define CXADEC_DEMATRIX_CTL        0x8CC
+
+#define CXADEC_PATH1_CTL1          0x8D0
+#define CXADEC_PATH1_VOL_CTL       0x8D4
+#define CXADEC_PATH1_EQ_CTL        0x8D8
+#define CXADEC_PATH1_SC_CTL        0x8DC
+
+#define CXADEC_PATH2_CTL1          0x8E0
+#define CXADEC_PATH2_VOL_CTL       0x8E4
+#define CXADEC_PATH2_EQ_CTL        0x8E8
+#define CXADEC_PATH2_SC_CTL        0x8EC
+
+#define CXADEC_SRC_CTL             0x8F0
+#define CXADEC_SRC_LF_COEF         0x8F4
+#define CXADEC_SRC1_CTL            0x8F8
+#define CXADEC_SRC2_CTL            0x8FC
+#define CXADEC_SRC3_CTL            0x900
+#define CXADEC_SRC4_CTL            0x904
+#define CXADEC_SRC5_CTL            0x908
+#define CXADEC_SRC6_CTL            0x90C
+
+#define CXADEC_BASEBAND_OUT_SEL    0x910
+#define CXADEC_I2S_IN_CTL          0x914
+#define CXADEC_I2S_OUT_CTL         0x918
+#define CXADEC_AC97_CTL            0x91C
+#define CXADEC_QAM_PDF             0x920
+#define CXADEC_QAM_CONST_DEC       0x924
+#define CXADEC_QAM_ROTATOR_FREQ    0x948
+
+/* Bit definitions / settings used in Mako Audio */
+#define CXADEC_PREF_MODE_MONO_LANGA        0
+#define CXADEC_PREF_MODE_MONO_LANGB        1
+#define CXADEC_PREF_MODE_MONO_LANGC        2
+#define CXADEC_PREF_MODE_FALLBACK          3
+#define CXADEC_PREF_MODE_STEREO            4
+#define CXADEC_PREF_MODE_DUAL_LANG_AC      5
+#define CXADEC_PREF_MODE_DUAL_LANG_BC      6
+#define CXADEC_PREF_MODE_DUAL_LANG_AB      7
+
+
+#define CXADEC_DETECT_STEREO               1
+#define CXADEC_DETECT_DUAL                 2
+#define CXADEC_DETECT_TRI                  4
+#define CXADEC_DETECT_SAP                  0x10
+#define CXADEC_DETECT_NO_SIGNAL            0xFF
+
+#define CXADEC_SELECT_AUDIO_STANDARD_BG    0xF0  /* NICAM BG and A2 BG */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK1   0xF1  /* NICAM DK and A2 DK */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK2   0xF2
+#define CXADEC_SELECT_AUDIO_STANDARD_DK3   0xF3
+#define CXADEC_SELECT_AUDIO_STANDARD_I     0xF4  /* NICAM I and A1 */
+#define CXADEC_SELECT_AUDIO_STANDARD_L     0xF5  /* NICAM L and System L AM */
+#define CXADEC_SELECT_AUDIO_STANDARD_BTSC  0xF6
+#define CXADEC_SELECT_AUDIO_STANDARD_EIAJ  0xF7
+#define CXADEC_SELECT_AUDIO_STANDARD_A2_M  0xF8  /* A2 M */
+#define CXADEC_SELECT_AUDIO_STANDARD_FM    0xF9  /* FM radio */
+#define CXADEC_SELECT_AUDIO_STANDARD_AUTO  0xFF  /* Auto detect */
+
+static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct cx18_av_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+       return &container_of(ctrl->handler, struct cx18_av_state, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-core.c                                                         */
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask);
+int cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval,
+                         u32 mask);
+u8 cx18_av_read(struct cx18 *cx, u16 addr);
+u32 cx18_av_read4(struct cx18 *cx, u16 addr);
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
+void cx18_av_std_setup(struct cx18 *cx);
+
+int cx18_av_probe(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-firmware.c                                                      */
+int cx18_av_loadfw(struct cx18 *cx);
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-audio.c                                                         */
+int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+void cx18_av_audio_set_path(struct cx18 *cx);
+extern const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops;
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-vbi.c                                                           */
+int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
+                          struct v4l2_decode_vbi_line *vbi);
+int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
+int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
+int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-av-firmware.c b/drivers/media/pci/cx18/cx18-av-firmware.c
new file mode 100644 (file)
index 0000000..a34fd08
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *  cx18 ADEC firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include <linux/firmware.h>
+
+#define CX18_AUDIO_ENABLE    0xc72014
+#define CX18_AI1_MUX_MASK    0x30
+#define CX18_AI1_MUX_I2S1    0x00
+#define CX18_AI1_MUX_I2S2    0x10
+#define CX18_AI1_MUX_843_I2S 0x20
+#define CX18_AI1_MUX_INVALID 0x30
+
+#define FWFILE "v4l-cx23418-dig.fw"
+
+static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
+{
+       struct v4l2_subdev *sd = &cx->av_state.sd;
+       int ret = 0;
+       const u8 *data;
+       u32 size;
+       int addr;
+       u32 expected, dl_control;
+
+       /* Ensure we put the 8051 in reset and enable firmware upload mode */
+       dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+       do {
+               dl_control &= 0x00ffffff;
+               dl_control |= 0x0f000000;
+               cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
+               dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+       } while ((dl_control & 0xff000000) != 0x0f000000);
+
+       /* Read and auto increment until at address 0x0000 */
+       while (dl_control & 0x3fff)
+               dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+
+       data = fw->data;
+       size = fw->size;
+       for (addr = 0; addr < size; addr++) {
+               dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
+               expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
+               if (expected != dl_control) {
+                       CX18_ERR_DEV(sd, "verification of %s firmware load "
+                                    "failed: expected %#010x got %#010x\n",
+                                    FWFILE, expected, dl_control);
+                       ret = -EIO;
+                       break;
+               }
+               dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+       }
+       if (ret == 0)
+               CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
+                             FWFILE, size);
+       return ret;
+}
+
+int cx18_av_loadfw(struct cx18 *cx)
+{
+       struct v4l2_subdev *sd = &cx->av_state.sd;
+       const struct firmware *fw = NULL;
+       u32 size;
+       u32 u, v;
+       const u8 *ptr;
+       int i;
+       int retries1 = 0;
+
+       if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) {
+               CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE);
+               return -EINVAL;
+       }
+
+       /* The firmware load often has byte errors, so allow for several
+          retries, both at byte level and at the firmware load level. */
+       while (retries1 < 5) {
+               cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000,
+                                         0x00008430, 0xffffffff); /* cx25843 */
+               cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff);
+
+               /* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */
+               cx18_av_write4_expect(cx, 0x8100, 0x00010000,
+                                         0x00008430, 0xffffffff); /* cx25843 */
+
+               /* Put the 8051 in reset and enable firmware upload */
+               cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
+
+               ptr = fw->data;
+               size = fw->size;
+
+               for (i = 0; i < size; i++) {
+                       u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
+                       u32 value = 0;
+                       int retries2;
+                       int unrec_err = 0;
+
+                       for (retries2 = 0; retries2 < CX18_MAX_MMIO_WR_RETRIES;
+                            retries2++) {
+                               cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
+                                                      dl_control);
+                               udelay(10);
+                               value = cx18_av_read4(cx, CXADEC_DL_CTL);
+                               if (value == dl_control)
+                                       break;
+                               /* Check if we can correct the byte by changing
+                                  the address.  We can only write the lower
+                                  address byte of the address. */
+                               if ((value & 0x3F00) != (dl_control & 0x3F00)) {
+                                       unrec_err = 1;
+                                       break;
+                               }
+                       }
+                       if (unrec_err || retries2 >= CX18_MAX_MMIO_WR_RETRIES)
+                               break;
+               }
+               if (i == size)
+                       break;
+               retries1++;
+       }
+       if (retries1 >= 5) {
+               CX18_ERR_DEV(sd, "unable to load firmware %s\n", FWFILE);
+               release_firmware(fw);
+               return -EIO;
+       }
+
+       cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+                               0x03000000 | fw->size, 0x03000000, 0x13000000);
+
+       CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
+
+       if (cx18_av_verifyfw(cx, fw) == 0)
+               cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+                               0x13000000 | fw->size, 0x13000000, 0x13000000);
+
+       /* Output to the 416 */
+       cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
+
+       /* Audio input control 1 set to Sony mode */
+       /* Audio output input 2 is 0 for slave operation input */
+       /* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+       /* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+          after WS transition for first bit of audio word. */
+       cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0);
+
+       /* Audio output control 1 is set to Sony mode */
+       /* Audio output control 2 is set to 1 for master mode */
+       /* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+       /* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+          after WS transition for first bit of audio word. */
+       /* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT
+          are generated) */
+       cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
+
+       /* set alt I2s master clock to /0x16 and enable alt divider i2s
+          passthrough */
+       cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5600B687);
+
+       cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
+                                                                 0x3F00FFFF);
+       /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
+
+       /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
+       /* Register 0x09CC is defined by the Merlin firmware, and doesn't
+          have a name in the spec. */
+       cx18_av_write4(cx, 0x09CC, 1);
+
+       v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+       /* If bit 11 is 1, clear bit 10 */
+       if (v & 0x800)
+               cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE,
+                                     0, 0x400);
+
+       /* Toggle the AI1 MUX */
+       v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+       u = v & CX18_AI1_MUX_MASK;
+       v &= ~CX18_AI1_MUX_MASK;
+       if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) {
+               /* Switch to I2S1 */
+               v |= CX18_AI1_MUX_I2S1;
+               cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+                                     v, CX18_AI1_MUX_MASK);
+               /* Switch back to the A/V decoder core I2S output */
+               v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S;
+       } else {
+               /* Switch to the A/V decoder core I2S output */
+               v |= CX18_AI1_MUX_843_I2S;
+               cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+                                     v, CX18_AI1_MUX_MASK);
+               /* Switch back to I2S1 or I2S2 */
+               v = (v & ~CX18_AI1_MUX_MASK) | u;
+       }
+       cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+                             v, CX18_AI1_MUX_MASK);
+
+       /* Enable WW auto audio standard detection */
+       v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
+       v |= 0xFF;   /* Auto by default */
+       v |= 0x400;  /* Stereo by default */
+       v |= 0x14000000;
+       cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
+
+       release_firmware(fw);
+       return 0;
+}
+
+MODULE_FIRMWARE(FWFILE);
diff --git a/drivers/media/pci/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c
new file mode 100644 (file)
index 0000000..baa36fb
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ *  cx18 ADEC VBI functions
+ *
+ *  Derived from cx25840-vbi.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#include "cx18-driver.h"
+
+/*
+ * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
+ * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
+ * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
+ * (should!) look like:
+ *     4 byte EAV code:          0xff 0x00 0x00 0xRP
+ *     unknown number of possible idle bytes
+ *     3 byte Anc data preamble: 0x00 0xff 0xff
+ *     1 byte data identifier:   ne010iii (parity bits, 010, DID bits)
+ *     1 byte secondary data id: nessssss (parity bits, SDID bits)
+ *     1 byte data word count:   necccccc (parity bits, NN Dword count)
+ *     2 byte Internal DID:      VBI-line-# 0x80
+ *     NN data bytes
+ *     1 byte checksum
+ *     Fill bytes needed to fil out to 4*NN bytes of payload
+ *
+ * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
+ * in the vertical blanking interval are:
+ *     0xb0 (Task         0 VerticalBlank HorizontalBlank 0 0 0 0)
+ *     0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
+ *
+ * Since the V bit is only allowed to toggle in the EAV RP code, just
+ * before the first active region line and for active lines, they are:
+ *     0x90 (Task         0 0 HorizontalBlank 0 0 0 0)
+ *     0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
+ *
+ * The user application DID bytes we care about are:
+ *     0x91 (1 0 010        0 !ActiveLine AncDataPresent)
+ *     0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
+ *
+ */
+static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
+
+struct vbi_anc_data {
+       /* u8 eav[4]; */
+       /* u8 idle[]; Variable number of idle bytes */
+       u8 preamble[3];
+       u8 did;
+       u8 sdid;
+       u8 data_count;
+       u8 idid[2];
+       u8 payload[1]; /* data_count of payload */
+       /* u8 checksum; */
+       /* u8 fill[]; Variable number of fill bytes */
+};
+
+static int odd_parity(u8 c)
+{
+       c ^= (c >> 4);
+       c ^= (c >> 2);
+       c ^= (c >> 1);
+
+       return c & 1;
+}
+
+static int decode_vps(u8 *dst, u8 *p)
+{
+       static const u8 biphase_tbl[] = {
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+               0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+               0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+               0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+               0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+               0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+               0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+               0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
+               0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
+               0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
+               0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
+               0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+               0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+               0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+               0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+               0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
+               0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
+               0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
+               0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
+               0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+               0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+               0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+               0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+               0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+               0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+       };
+
+       u8 c, err = 0;
+       int i;
+
+       for (i = 0; i < 2 * 13; i += 2) {
+               err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
+               c = (biphase_tbl[p[i + 1]] & 0xf) |
+                   ((biphase_tbl[p[i]] & 0xf) << 4);
+               dst[i / 2] = c;
+       }
+
+       return err & 0xf0;
+}
+
+int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       struct cx18_av_state *state = &cx->av_state;
+       static const u16 lcr2vbi[] = {
+               0, V4L2_SLICED_TELETEXT_B, 0,   /* 1 */
+               0, V4L2_SLICED_WSS_625, 0,      /* 4 */
+               V4L2_SLICED_CAPTION_525,        /* 6 */
+               0, 0, V4L2_SLICED_VPS, 0, 0,    /* 9 */
+               0, 0, 0, 0
+       };
+       int is_pal = !(state->std & V4L2_STD_525_60);
+       int i;
+
+       memset(svbi, 0, sizeof(*svbi));
+       /* we're done if raw VBI is active */
+       if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
+               return 0;
+
+       if (is_pal) {
+               for (i = 7; i <= 23; i++) {
+                       u8 v = cx18_av_read(cx, 0x424 + i - 7);
+
+                       svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+                       svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+                       svbi->service_set |= svbi->service_lines[0][i] |
+                               svbi->service_lines[1][i];
+               }
+       } else {
+               for (i = 10; i <= 21; i++) {
+                       u8 v = cx18_av_read(cx, 0x424 + i - 10);
+
+                       svbi->service_lines[0][i] = lcr2vbi[v >> 4];
+                       svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
+                       svbi->service_set |= svbi->service_lines[0][i] |
+                               svbi->service_lines[1][i];
+               }
+       }
+       return 0;
+}
+
+int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       struct cx18_av_state *state = &cx->av_state;
+
+       /* Setup standard */
+       cx18_av_std_setup(cx);
+
+       /* VBI Offset */
+       cx18_av_write(cx, 0x47f, state->slicer_line_delay);
+       cx18_av_write(cx, 0x404, 0x2e);
+       return 0;
+}
+
+int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       struct cx18_av_state *state = &cx->av_state;
+       int is_pal = !(state->std & V4L2_STD_525_60);
+       int i, x;
+       u8 lcr[24];
+
+       for (x = 0; x <= 23; x++)
+               lcr[x] = 0x00;
+
+       /* Setup standard */
+       cx18_av_std_setup(cx);
+
+       /* Sliced VBI */
+       cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
+       cx18_av_write(cx, 0x406, 0x13);
+       cx18_av_write(cx, 0x47f, state->slicer_line_delay);
+
+       /* Force impossible lines to 0 */
+       if (is_pal) {
+               for (i = 0; i <= 6; i++)
+                       svbi->service_lines[0][i] =
+                               svbi->service_lines[1][i] = 0;
+       } else {
+               for (i = 0; i <= 9; i++)
+                       svbi->service_lines[0][i] =
+                               svbi->service_lines[1][i] = 0;
+
+               for (i = 22; i <= 23; i++)
+                       svbi->service_lines[0][i] =
+                               svbi->service_lines[1][i] = 0;
+       }
+
+       /* Build register values for requested service lines */
+       for (i = 7; i <= 23; i++) {
+               for (x = 0; x <= 1; x++) {
+                       switch (svbi->service_lines[1-x][i]) {
+                       case V4L2_SLICED_TELETEXT_B:
+                               lcr[i] |= 1 << (4 * x);
+                               break;
+                       case V4L2_SLICED_WSS_625:
+                               lcr[i] |= 4 << (4 * x);
+                               break;
+                       case V4L2_SLICED_CAPTION_525:
+                               lcr[i] |= 6 << (4 * x);
+                               break;
+                       case V4L2_SLICED_VPS:
+                               lcr[i] |= 9 << (4 * x);
+                               break;
+                       }
+               }
+       }
+
+       if (is_pal) {
+               for (x = 1, i = 0x424; i <= 0x434; i++, x++)
+                       cx18_av_write(cx, i, lcr[6 + x]);
+       } else {
+               for (x = 1, i = 0x424; i <= 0x430; i++, x++)
+                       cx18_av_write(cx, i, lcr[9 + x]);
+               for (i = 0x431; i <= 0x434; i++)
+                       cx18_av_write(cx, i, 0);
+       }
+
+       cx18_av_write(cx, 0x43c, 0x16);
+       /* Should match vblank set in cx18_av_std_setup() */
+       cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
+       return 0;
+}
+
+int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
+                                  struct v4l2_decode_vbi_line *vbi)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       struct cx18_av_state *state = &cx->av_state;
+       struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
+       u8 *p;
+       int did, sdid, l, err = 0;
+
+       /*
+        * Check for the ancillary data header for sliced VBI
+        */
+       if (anc->preamble[0] ||
+                       anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
+                       (anc->did != sliced_vbi_did[0] &&
+                        anc->did != sliced_vbi_did[1])) {
+               vbi->line = vbi->type = 0;
+               return 0;
+       }
+
+       did = anc->did;
+       sdid = anc->sdid & 0xf;
+       l = anc->idid[0] & 0x3f;
+       l += state->slicer_line_offset;
+       p = anc->payload;
+
+       /* Decode the SDID set by the slicer */
+       switch (sdid) {
+       case 1:
+               sdid = V4L2_SLICED_TELETEXT_B;
+               break;
+       case 4:
+               sdid = V4L2_SLICED_WSS_625;
+               break;
+       case 6:
+               sdid = V4L2_SLICED_CAPTION_525;
+               err = !odd_parity(p[0]) || !odd_parity(p[1]);
+               break;
+       case 9:
+               sdid = V4L2_SLICED_VPS;
+               if (decode_vps(p, p) != 0)
+                       err = 1;
+               break;
+       default:
+               sdid = 0;
+               err = 1;
+               break;
+       }
+
+       vbi->type = err ? 0 : sdid;
+       vbi->line = err ? 0 : l;
+       vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
+       vbi->p = p;
+       return 0;
+}
diff --git a/drivers/media/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c
new file mode 100644 (file)
index 0000000..c07c849
--- /dev/null
@@ -0,0 +1,638 @@
+/*
+ *  cx18 functions to query card hardware
+ *
+ *  Derived from ivtv-cards.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include "cx18-i2c.h"
+#include <media/cs5345.h>
+
+#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
+
+/********************** card configuration *******************************/
+
+/* usual i2c tuner addresses to probe */
+static struct cx18_card_tuner_i2c cx18_i2c_std = {
+       .radio = { I2C_CLIENT_END },
+       .demod = { 0x43, I2C_CLIENT_END },
+       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/*
+ * usual i2c tuner addresses to probe with additional demod address for
+ * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too).
+ */
+static struct cx18_card_tuner_i2c cx18_i2c_nxp = {
+       .radio = { I2C_CLIENT_END },
+       .demod = { 0x42, 0x43, I2C_CLIENT_END },
+       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/
+   This keeps the PCI ID database up to date. Note that the entries
+   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
+   New vendor IDs should still be added to the vendor ID list. */
+
+/* Hauppauge HVR-1600 cards */
+
+/* Note: for Hauppauge cards the tveeprom information is used instead
+   of PCI IDs */
+static const struct cx18_card cx18_card_hvr1600_esmt = {
+       .type = CX18_CARD_HVR_1600_ESMT,
+       .name = "Hauppauge HVR-1600",
+       .comment = "Simultaneous Digital and Analog TV capture supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_CS5345,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+                 CX18_HW_Z8F0811_IR_HAUP,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+               { CX18_CARD_INPUT_LINE_IN2,
+                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+       .ddr = {
+               /* ESMT M13S128324A-5B memory */
+               .chip_config = 0x003,
+               .refresh = 0x30c,
+               .timing1 = 0x44220e82,
+               .timing2 = 0x08,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .gpio_init.initial_value = 0x3001,
+       .gpio_init.direction = 0x3001,
+       .gpio_i2c_slave_reset = {
+               .active_lo_mask = 0x3001,
+               .msecs_asserted = 10,
+               .msecs_recovery = 40,
+               .ir_reset_mask  = 0x0001,
+       },
+       .i2c = &cx18_i2c_std,
+};
+
+static const struct cx18_card cx18_card_hvr1600_s5h1411 = {
+       .type = CX18_CARD_HVR_1600_S5H1411,
+       .name = "Hauppauge HVR-1600",
+       .comment = "Simultaneous Digital and Analog TV capture supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_CS5345,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+                 CX18_HW_Z8F0811_IR_HAUP,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+               { CX18_CARD_INPUT_LINE_IN2,
+                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+       .ddr = {
+               /* ESMT M13S128324A-5B memory */
+               .chip_config = 0x003,
+               .refresh = 0x30c,
+               .timing1 = 0x44220e82,
+               .timing2 = 0x08,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .gpio_init.initial_value = 0x3801,
+       .gpio_init.direction = 0x3801,
+       .gpio_i2c_slave_reset = {
+               .active_lo_mask = 0x3801,
+               .msecs_asserted = 10,
+               .msecs_recovery = 40,
+               .ir_reset_mask  = 0x0001,
+       },
+       .i2c = &cx18_i2c_nxp,
+};
+
+static const struct cx18_card cx18_card_hvr1600_samsung = {
+       .type = CX18_CARD_HVR_1600_SAMSUNG,
+       .name = "Hauppauge HVR-1600 (Preproduction)",
+       .comment = "Simultaneous Digital and Analog TV capture supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_CS5345,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+                 CX18_HW_Z8F0811_IR_HAUP,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+               { CX18_CARD_INPUT_LINE_IN2,
+                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+       .ddr = {
+               /* Samsung K4D263238G-VC33 memory */
+               .chip_config = 0x003,
+               .refresh = 0x30c,
+               .timing1 = 0x23230b73,
+               .timing2 = 0x08,
+               .tune_lane = 0,
+               .initial_emrs = 2,
+       },
+       .gpio_init.initial_value = 0x3001,
+       .gpio_init.direction = 0x3001,
+       .gpio_i2c_slave_reset = {
+               .active_lo_mask = 0x3001,
+               .msecs_asserted = 10,
+               .msecs_recovery = 40,
+               .ir_reset_mask  = 0x0001,
+       },
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Compro VideoMate H900: note that this card is analog only! */
+
+static const struct cx18_card_pci_info cx18_pci_h900[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_h900 = {
+       .type = CX18_CARD_COMPRO_H900,
+       .name = "Compro VideoMate H900",
+       .comment = "Analog TV capture supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER,
+                 CX18_AV_AUDIO5, 0 },
+               { CX18_CARD_INPUT_LINE_IN1,
+                 CX18_AV_AUDIO_SERIAL1, 0 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+                        CX18_AV_AUDIO_SERIAL1, 0 },
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .ddr = {
+               /* EtronTech EM6A9160TS-5G memory */
+               .chip_config = 0x50003,
+               .refresh = 0x753,
+               .timing1 = 0x24330e84,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .xceive_pin = 15,
+       .pci_list = cx18_pci_h900,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPC718: not working at the moment! */
+
+static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_YUAN, 0x0718 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_mpc718 = {
+       .type = CX18_CARD_YUAN_MPC718,
+       .name = "Yuan MPC718 MiniPCI DVB-T/Analog",
+       .comment = "Experimenters needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+                 CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                               CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+               { CX18_CARD_INPUT_SVIDEO2,    2,
+                               CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+       },
+       .tuners = {
+               /* XC3028 tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       /* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+       .ddr = {
+               /* Hynix HY5DU283222B DDR RAM */
+               .chip_config = 0x303,
+               .refresh = 0x3bd,
+               .timing1 = 0x36320966,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 2,
+       },
+       .gpio_init.initial_value = 0x1,
+       .gpio_init.direction = 0x3,
+       /* FIXME - these GPIO's are just guesses */
+       .gpio_audio_input = { .mask   = 0x3,
+                             .tuner  = 0x1,
+                             .linein = 0x3,
+                             .radio  = 0x1 },
+       .xceive_pin = 0,
+       .pci_list = cx18_pci_mpc718,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* GoTView PCI */
+
+static const struct cx18_card_pci_info cx18_pci_gotview_dvd3[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_GOTVIEW, 0x3343 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_gotview_dvd3 = {
+       .type = CX18_CARD_GOTVIEW_PCI_DVD3,
+       .name = "GoTView PCI DVD3 Hybrid",
+       .comment = "Experimenters needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+                 CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                               CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+               { CX18_CARD_INPUT_SVIDEO2,    2,
+                               CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+       },
+       .tuners = {
+               /* XC3028 tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       /* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+       .ddr = {
+               /* Hynix HY5DU283222B DDR RAM */
+               .chip_config = 0x303,
+               .refresh = 0x3bd,
+               .timing1 = 0x36320966,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 2,
+       },
+       .gpio_init.initial_value = 0x1,
+       .gpio_init.direction = 0x3,
+
+       .gpio_audio_input = { .mask   = 0x3,
+                             .tuner  = 0x1,
+                             .linein = 0x2,
+                             .radio  = 0x1 },
+       .xceive_pin = 0,
+       .pci_list = cx18_pci_gotview_dvd3,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Conexant Raptor PAL/SECAM: note that this card is analog only! */
+
+static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_CONEXANT, 0x0009 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_cnxt_raptor_pal = {
+       .type = CX18_CARD_CNXT_RAPTOR_PAL,
+       .name = "Conexant Raptor PAL/SECAM",
+       .comment = "Analog TV capture supported\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+               { CX18_CARD_INPUT_SVIDEO2,    2,
+                       CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+       },
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 2 },
+       .ddr = {
+               /* MT 46V16M16 memory */
+               .chip_config = 0x50306,
+               .refresh = 0x753,
+               .timing1 = 0x33220953,
+               .timing2 = 0x09,
+               .tune_lane = 0,
+               .initial_emrs = 0,
+       },
+       .gpio_init.initial_value = 0x1002,
+       .gpio_init.direction = 0xf002,
+       .gpio_audio_input = { .mask   = 0xf002,
+                             .tuner  = 0x1002,   /* LED D1  Tuner AF  */
+                             .linein = 0x2000,   /* LED D2  Line In 1 */
+                             .radio  = 0x4002 }, /* LED D3  Tuner AF  */
+       .pci_list = cx18_pci_cnxt_raptor_pal,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */
+
+static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 },
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
+       .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT,
+       .name = "Toshiba Qosmio DVB-T/Analog",
+       .comment = "Experimenters and photos needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE6 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+       },
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .ddr = {
+               .chip_config = 0x202,
+               .refresh = 0x3bb,
+               .timing1 = 0x33320a63,
+               .timing2 = 0x0a,
+               .tune_lane = 0,
+               .initial_emrs = 0x42,
+       },
+       .xceive_pin = 15,
+       .pci_list = cx18_pci_toshiba_qosmio_dvbt,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Leadtek WinFast PVR2100 */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100   */
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_pvr2100 = {
+       .type = CX18_CARD_LEADTEK_PVR2100,
+       .name = "Leadtek WinFast PVR2100",
+       .comment = "Experimenters and photos needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
+                 CX18_HW_GPIO_RESET_CTRL,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+       },
+       .tuners = {
+               /* XC2028 tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+       .ddr = {
+               /* Pointer to proper DDR config values provided by Terry Wu */
+               .chip_config = 0x303,
+               .refresh = 0x3bb,
+               .timing1 = 0x24220e83,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 0x2,
+       },
+       .gpio_init.initial_value = 0x6,
+       .gpio_init.direction = 0x7,
+       .gpio_audio_input = { .mask   = 0x7,
+                             .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
+       .xceive_pin = 1,
+       .pci_list = cx18_pci_leadtek_pvr2100,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Leadtek WinFast DVR3100 H */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = {
+       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
+       { 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_dvr3100h = {
+       .type = CX18_CARD_LEADTEK_DVR3100H,
+       .name = "Leadtek WinFast DVR3100 H",
+       .comment = "Simultaneous DVB-T and Analog capture supported,\n"
+                 "\texcept when capturing Analog from the antenna input.\n",
+       .v4l2_capabilities = CX18_CAP_ENCODER,
+       .hw_audio_ctrl = CX18_HW_418_AV,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
+                 CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+       .video_inputs = {
+               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+               { CX18_CARD_INPUT_SVIDEO1,    1,
+                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+               { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 },
+       },
+       .audio_inputs = {
+               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+       },
+       .tuners = {
+               /* XC3028 tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+       .ddr = {
+               /* Pointer to proper DDR config values provided by Terry Wu */
+               .chip_config = 0x303,
+               .refresh = 0x3bb,
+               .timing1 = 0x24220e83,
+               .timing2 = 0x1f,
+               .tune_lane = 0,
+               .initial_emrs = 0x2,
+       },
+       .gpio_init.initial_value = 0x6,
+       .gpio_init.direction = 0x7,
+       .gpio_audio_input = { .mask   = 0x7,
+                             .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
+       .xceive_pin = 1,
+       .pci_list = cx18_pci_leadtek_dvr3100h,
+       .i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static const struct cx18_card *cx18_card_list[] = {
+       &cx18_card_hvr1600_esmt,
+       &cx18_card_hvr1600_samsung,
+       &cx18_card_h900,
+       &cx18_card_mpc718,
+       &cx18_card_cnxt_raptor_pal,
+       &cx18_card_toshiba_qosmio_dvbt,
+       &cx18_card_leadtek_pvr2100,
+       &cx18_card_leadtek_dvr3100h,
+       &cx18_card_gotview_dvd3,
+       &cx18_card_hvr1600_s5h1411
+};
+
+const struct cx18_card *cx18_get_card(u16 index)
+{
+       if (index >= ARRAY_SIZE(cx18_card_list))
+               return NULL;
+       return cx18_card_list[index];
+}
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
+{
+       const struct cx18_card_video_input *card_input =
+               cx->card->video_inputs + index;
+       static const char * const input_strs[] = {
+               "Tuner 1",
+               "S-Video 1",
+               "S-Video 2",
+               "Composite 1",
+               "Composite 2",
+               "Component 1"
+       };
+
+       if (index >= cx->nof_inputs)
+               return -EINVAL;
+       input->index = index;
+       strlcpy(input->name, input_strs[card_input->video_type - 1],
+                       sizeof(input->name));
+       input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
+                       V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+       input->audioset = (1 << cx->nof_audio_inputs) - 1;
+       input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
+                               cx->tuner_std : V4L2_STD_ALL;
+       return 0;
+}
+
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
+{
+       const struct cx18_card_audio_input *aud_input =
+               cx->card->audio_inputs + index;
+       static const char * const input_strs[] = {
+               "Tuner 1",
+               "Line In 1",
+               "Line In 2"
+       };
+
+       memset(audio, 0, sizeof(*audio));
+       if (index >= cx->nof_audio_inputs)
+               return -EINVAL;
+       strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+                       sizeof(audio->name));
+       audio->index = index;
+       audio->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
diff --git a/drivers/media/pci/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h
new file mode 100644 (file)
index 0000000..add7391
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  cx18 functions to query card hardware
+ *
+ *  Derived from ivtv-cards.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* hardware flags */
+#define CX18_HW_TUNER                  (1 << 0)
+#define CX18_HW_TVEEPROM               (1 << 1)
+#define CX18_HW_CS5345                 (1 << 2)
+#define CX18_HW_DVB                    (1 << 3)
+#define CX18_HW_418_AV                 (1 << 4)
+#define CX18_HW_GPIO_MUX               (1 << 5)
+#define CX18_HW_GPIO_RESET_CTRL                (1 << 6)
+#define CX18_HW_Z8F0811_IR_TX_HAUP     (1 << 7)
+#define CX18_HW_Z8F0811_IR_RX_HAUP     (1 << 8)
+#define CX18_HW_Z8F0811_IR_HAUP        (CX18_HW_Z8F0811_IR_RX_HAUP | \
+                                CX18_HW_Z8F0811_IR_TX_HAUP)
+
+#define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \
+                       CX18_HW_Z8F0811_IR_TX_HAUP)
+
+/* video inputs */
+#define        CX18_CARD_INPUT_VID_TUNER       1
+#define        CX18_CARD_INPUT_SVIDEO1         2
+#define        CX18_CARD_INPUT_SVIDEO2         3
+#define        CX18_CARD_INPUT_COMPOSITE1      4
+#define        CX18_CARD_INPUT_COMPOSITE2      5
+#define        CX18_CARD_INPUT_COMPONENT1      6
+
+/* audio inputs */
+#define        CX18_CARD_INPUT_AUD_TUNER       1
+#define        CX18_CARD_INPUT_LINE_IN1        2
+#define        CX18_CARD_INPUT_LINE_IN2        3
+
+#define CX18_CARD_MAX_VIDEO_INPUTS 6
+#define CX18_CARD_MAX_AUDIO_INPUTS 3
+#define CX18_CARD_MAX_TUNERS      2
+
+/* V4L2 capability aliases */
+#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
+                         V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \
+                         V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)
+
+struct cx18_card_video_input {
+       u8  video_type;         /* video input type */
+       u8  audio_index;        /* index in cx18_card_audio_input array */
+       u32 video_input;        /* hardware video input */
+};
+
+struct cx18_card_audio_input {
+       u8  audio_type;         /* audio input type */
+       u32 audio_input;        /* hardware audio input */
+       u16 muxer_input;        /* hardware muxer input for boards with a
+                                  multiplexer chip */
+};
+
+struct cx18_card_pci_info {
+       u16 device;
+       u16 subsystem_vendor;
+       u16 subsystem_device;
+};
+
+/* GPIO definitions */
+
+/* The mask is the set of bits used by the operation */
+
+struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
+       u32 direction;  /* DIR setting. Leave to 0 if no init is needed */
+       u32 initial_value;
+};
+
+struct cx18_gpio_i2c_slave_reset {
+       u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */
+       u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
+       int msecs_asserted; /* time period reset must remain asserted */
+       int msecs_recovery; /* time after deassert for chips to be ready */
+       u32 ir_reset_mask;  /* GPIO to reset the Zilog Z8F0811 IR contoller */
+};
+
+struct cx18_gpio_audio_input {         /* select tuner/line in input */
+       u32 mask;               /* leave to 0 if not supported */
+       u32 tuner;
+       u32 linein;
+       u32 radio;
+};
+
+struct cx18_card_tuner {
+       v4l2_std_id std;        /* standard for which the tuner is suitable */
+       int         tuner;      /* tuner ID (from tuner.h) */
+};
+
+struct cx18_card_tuner_i2c {
+       unsigned short radio[2];/* radio tuner i2c address to probe */
+       unsigned short demod[3];/* demodulator i2c address to probe */
+       unsigned short tv[4];   /* tv tuner i2c addresses to probe */
+};
+
+struct cx18_ddr {              /* DDR config data */
+       u32 chip_config;
+       u32 refresh;
+       u32 timing1;
+       u32 timing2;
+       u32 tune_lane;
+       u32 initial_emrs;
+};
+
+/* for card information/parameters */
+struct cx18_card {
+       int type;
+       char *name;
+       char *comment;
+       u32 v4l2_capabilities;
+       u32 hw_audio_ctrl;      /* hardware used for the V4L2 controls (only
+                                  1 dev allowed currently) */
+       u32 hw_muxer;           /* hardware used to multiplex audio input */
+       u32 hw_all;             /* all hardware used by the board */
+       struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS];
+       struct cx18_card_audio_input audio_inputs[CX18_CARD_MAX_AUDIO_INPUTS];
+       struct cx18_card_audio_input radio_input;
+
+       /* GPIO card-specific settings */
+       u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
+       struct cx18_gpio_init            gpio_init;
+       struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
+       struct cx18_gpio_audio_input    gpio_audio_input;
+
+       struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
+       struct cx18_card_tuner_i2c *i2c;
+
+       struct cx18_ddr ddr;
+
+       /* list of device and subsystem vendor/devices that
+          correspond to this card type. */
+       const struct cx18_card_pci_info *pci_list;
+};
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input);
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *input);
+const struct cx18_card *cx18_get_card(u16 index);
diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c
new file mode 100644 (file)
index 0000000..282a3d2
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *  cx18 ioctl control functions
+ *
+ *  Derived from ivtv-controls.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-ioctl.h"
+#include "cx18-audio.h"
+#include "cx18-mailbox.h"
+#include "cx18-controls.h"
+
+static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
+{
+       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+       int type = cxhdl->stream_type->val;
+
+       if (atomic_read(&cx->ana_capturing) > 0)
+               return -EBUSY;
+
+       if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV ||
+           !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS ||
+             type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD ||
+             type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) {
+               /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */
+               cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE;
+               CX18_DEBUG_INFO("disabled insertion of sliced VBI data into "
+                               "the MPEG stream\n");
+               return 0;
+       }
+
+       /* Allocate sliced VBI buffers if needed. */
+       if (cx->vbi.sliced_mpeg_data[0] == NULL) {
+               int i;
+
+               for (i = 0; i < CX18_VBI_FRAMES; i++) {
+                       cx->vbi.sliced_mpeg_data[i] =
+                              kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL);
+                       if (cx->vbi.sliced_mpeg_data[i] == NULL) {
+                               while (--i >= 0) {
+                                       kfree(cx->vbi.sliced_mpeg_data[i]);
+                                       cx->vbi.sliced_mpeg_data[i] = NULL;
+                               }
+                               cx->vbi.insert_mpeg =
+                                                 V4L2_MPEG_STREAM_VBI_FMT_NONE;
+                               CX18_WARN("Unable to allocate buffers for "
+                                         "sliced VBI data insertion\n");
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       cx->vbi.insert_mpeg = fmt;
+       CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS,"
+                       "when sliced VBI is enabled\n");
+
+       /*
+        * If our current settings have no lines set for capture, store a valid,
+        * default set of service lines to capture, in our current settings.
+        */
+       if (cx18_get_service_set(cx->vbi.sliced_in) == 0) {
+               if (cx->is_60hz)
+                       cx->vbi.sliced_in->service_set =
+                                                       V4L2_SLICED_CAPTION_525;
+               else
+                       cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
+               cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
+       }
+       return 0;
+}
+
+static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
+{
+       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+       int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+       struct v4l2_mbus_framefmt fmt;
+
+       /* fix videodecoder resolution */
+       fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+       fmt.height = cxhdl->height;
+       fmt.code = V4L2_MBUS_FMT_FIXED;
+       v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
+       return 0;
+}
+
+static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
+{
+       static const u32 freqs[3] = { 44100, 48000, 32000 };
+       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+
+       /* The audio clock of the digitizer must match the codec sample
+          rate otherwise you get some very strange effects. */
+       if (idx < ARRAY_SIZE(freqs))
+               cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
+       return 0;
+}
+
+static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
+{
+       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+
+       cx->dualwatch_stereo_mode = val;
+       return 0;
+}
+
+struct cx2341x_handler_ops cx18_cxhdl_ops = {
+       .s_audio_mode = cx18_s_audio_mode,
+       .s_audio_sampling_freq = cx18_s_audio_sampling_freq,
+       .s_video_encoding = cx18_s_video_encoding,
+       .s_stream_vbi_fmt = cx18_s_stream_vbi_fmt,
+};
diff --git a/drivers/media/pci/cx18/cx18-controls.h b/drivers/media/pci/cx18/cx18-controls.h
new file mode 100644 (file)
index 0000000..cb5dfc7
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  cx18 ioctl control functions
+ *
+ *  Derived from ivtv-controls.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+ *  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
+ */
+
+extern struct cx2341x_handler_ops cx18_cxhdl_ops;
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
new file mode 100644 (file)
index 0000000..c67733d
--- /dev/null
@@ -0,0 +1,1360 @@
+/*
+ *  cx18 driver initialization and card probing
+ *
+ *  Derived from ivtv-driver.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-version.h"
+#include "cx18-cards.h"
+#include "cx18-i2c.h"
+#include "cx18-irq.h"
+#include "cx18-gpio.h"
+#include "cx18-firmware.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-av-core.h"
+#include "cx18-scb.h"
+#include "cx18-mailbox.h"
+#include "cx18-ioctl.h"
+#include "cx18-controls.h"
+#include "tuner-xc2028.h"
+#include <linux/dma-mapping.h>
+#include <media/tveeprom.h>
+
+/* If you have already X v4l cards, then set this to X. This way
+   the device numbers stay matched. Example: you have a WinTV card
+   without radio and a Compro H900 with. Normally this would give a
+   video1 device together with a radio0 device for the Compro. By
+   setting this to 1 you ensure that radio0 is now also radio1. */
+int cx18_first_minor;
+
+/* Callback for registering extensions */
+int (*cx18_ext_init)(struct cx18 *);
+EXPORT_SYMBOL(cx18_ext_init);
+
+/* add your revision and whatnot here */
+static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
+       {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
+
+static atomic_t cx18_instance = ATOMIC_INIT(0);
+
+/* Parameter declarations */
+static int cardtype[CX18_MAX_CARDS];
+static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1 };
+static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1 };
+static unsigned cardtype_c = 1;
+static unsigned tuner_c = 1;
+static unsigned radio_c = 1;
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+/* Buffers */
+static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
+static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS;
+static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
+static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
+static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
+
+static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE;
+static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE;
+static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE;
+static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE;
+static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE;
+
+static int enc_ts_bufs = -1;
+static int enc_mpg_bufs = -1;
+static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM;
+static int enc_yuv_bufs = -1;
+static int enc_vbi_bufs = -1;
+static int enc_pcm_bufs = -1;
+
+
+static int cx18_pci_latency = 1;
+
+static int mmio_ndelay;
+static int retry_mmio = 1;
+
+int cx18_debug;
+
+module_param_array(tuner, int, &tuner_c, 0644);
+module_param_array(radio, int, &radio_c, 0644);
+module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+module_param_named(debug, cx18_debug, int, 0644);
+module_param(mmio_ndelay, int, 0644);
+module_param(retry_mmio, int, 0644);
+module_param(cx18_pci_latency, int, 0644);
+module_param(cx18_first_minor, int, 0644);
+
+module_param(enc_ts_buffers, int, 0644);
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_idx_buffers, int, 0644);
+module_param(enc_yuv_buffers, int, 0644);
+module_param(enc_vbi_buffers, int, 0644);
+module_param(enc_pcm_buffers, int, 0644);
+
+module_param(enc_ts_bufsize, int, 0644);
+module_param(enc_mpg_bufsize, int, 0644);
+module_param(enc_idx_bufsize, int, 0644);
+module_param(enc_yuv_bufsize, int, 0644);
+module_param(enc_pcm_bufsize, int, 0644);
+
+module_param(enc_ts_bufs, int, 0644);
+module_param(enc_mpg_bufs, int, 0644);
+module_param(enc_idx_bufs, int, 0644);
+module_param(enc_yuv_bufs, int, 0644);
+module_param(enc_vbi_bufs, int, 0644);
+module_param(enc_pcm_bufs, int, 0644);
+
+MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+                       "\t\t\tsee tuner.h for values");
+MODULE_PARM_DESC(radio,
+                "Enable or disable the radio. Use only if autodetection\n"
+                "\t\t\tfails. 0 = disable, 1 = enable");
+MODULE_PARM_DESC(cardtype,
+                "Only use this option if your card is not detected properly.\n"
+                "\t\tSpecify card type:\n"
+                "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
+                "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
+                "\t\t\t 3 = Compro VideoMate H900\n"
+                "\t\t\t 4 = Yuan MPC718\n"
+                "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
+                "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
+                "\t\t\t 7 = Leadtek WinFast PVR2100\n"
+                "\t\t\t 8 = Leadtek WinFast DVR3100 H\n"
+                "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n"
+                "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\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(debug,
+                "Debug level (bitmask). Default: 0\n"
+                "\t\t\t  1/0x0001: warning\n"
+                "\t\t\t  2/0x0002: info\n"
+                "\t\t\t  4/0x0004: mailbox\n"
+                "\t\t\t  8/0x0008: dma\n"
+                "\t\t\t 16/0x0010: ioctl\n"
+                "\t\t\t 32/0x0020: file\n"
+                "\t\t\t 64/0x0040: i2c\n"
+                "\t\t\t128/0x0080: irq\n"
+                "\t\t\t256/0x0100: high volume\n");
+MODULE_PARM_DESC(cx18_pci_latency,
+                "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
+                "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(retry_mmio,
+                "(Deprecated) MMIO writes are now always checked and retried\n"
+                "\t\t\tEffectively: 1 [Yes]");
+MODULE_PARM_DESC(mmio_ndelay,
+                "(Deprecated) MMIO accesses are now never purposely delayed\n"
+                "\t\t\tEffectively: 0 ns");
+MODULE_PARM_DESC(enc_ts_buffers,
+                "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
+MODULE_PARM_DESC(enc_ts_bufsize,
+                "Size of an encoder TS buffer (kB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE));
+MODULE_PARM_DESC(enc_ts_bufs,
+                "Number of encoder TS buffers\n"
+                "\t\t\tDefault is computed from other enc_ts_* parameters");
+MODULE_PARM_DESC(enc_mpg_buffers,
+                "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_mpg_bufsize,
+                "Size of an encoder MPG buffer (kB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE));
+MODULE_PARM_DESC(enc_mpg_bufs,
+                "Number of encoder MPG buffers\n"
+                "\t\t\tDefault is computed from other enc_mpg_* parameters");
+MODULE_PARM_DESC(enc_idx_buffers,
+                "(Deprecated) Encoder IDX buffer memory (MB)\n"
+                "\t\t\tIgnored, except 0 disables IDX buffer allocations\n"
+                "\t\t\tDefault: 1 [Enabled]");
+MODULE_PARM_DESC(enc_idx_bufsize,
+                "Size of an encoder IDX buffer (kB)\n"
+                "\t\t\tAllowed values are multiples of 1.5 kB rounded up\n"
+                "\t\t\t(multiples of size required for 64 index entries)\n"
+                "\t\t\tDefault: 2");
+MODULE_PARM_DESC(enc_idx_bufs,
+                "Number of encoder IDX buffers\n"
+                "\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM));
+MODULE_PARM_DESC(enc_yuv_buffers,
+                "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_bufsize,
+                "Size of an encoder YUV buffer (kB)\n"
+                "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n"
+                "\t\t\t(multiples of size required for 32 screen lines)\n"
+                "\t\t\tDefault: 102");
+MODULE_PARM_DESC(enc_yuv_bufs,
+                "Number of encoder YUV buffers\n"
+                "\t\t\tDefault is computed from other enc_yuv_* parameters");
+MODULE_PARM_DESC(enc_vbi_buffers,
+                "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_bufs,
+                "Number of encoder VBI buffers\n"
+                "\t\t\tDefault is computed from enc_vbi_buffers");
+MODULE_PARM_DESC(enc_pcm_buffers,
+                "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_bufsize,
+                "Size of an encoder PCM buffer (kB)\n"
+                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE));
+MODULE_PARM_DESC(enc_pcm_bufs,
+                "Number of encoder PCM buffers\n"
+                "\t\t\tDefault is computed from other enc_pcm_* parameters");
+
+MODULE_PARM_DESC(cx18_first_minor,
+                "Set device node number assigned to first card");
+
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_DESCRIPTION("CX23418 driver");
+MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(CX18_VERSION);
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct cx18 *dev = container_of(work, struct cx18, request_module_wk);
+
+       /* Make sure cx18-alsa module is loaded */
+       request_module("cx18-alsa");
+
+       /* Initialize cx18-alsa for this instance of the cx18 device */
+       if (cx18_ext_init != NULL)
+               cx18_ext_init(dev);
+}
+
+static void request_modules(struct cx18 *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct cx18 *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+/* Generic utility functions */
+int cx18_msleep_timeout(unsigned int msecs, int intr)
+{
+       long int timeout = msecs_to_jiffies(msecs);
+       int sig;
+
+       do {
+               set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+               timeout = schedule_timeout(timeout);
+               sig = intr ? signal_pending(current) : 0;
+       } while (!sig && timeout);
+       return sig;
+}
+
+/* Release ioremapped memory */
+static void cx18_iounmap(struct cx18 *cx)
+{
+       if (cx == NULL)
+               return;
+
+       /* Release io memory */
+       if (cx->enc_mem != NULL) {
+               CX18_DEBUG_INFO("releasing enc_mem\n");
+               iounmap(cx->enc_mem);
+               cx->enc_mem = NULL;
+       }
+}
+
+static void cx18_eeprom_dump(struct cx18 *cx, unsigned char *eedata, int len)
+{
+       int i;
+
+       CX18_INFO("eeprom dump:\n");
+       for (i = 0; i < len; i++) {
+               if (0 == (i % 16))
+                       CX18_INFO("eeprom %02x:", i);
+               printk(KERN_CONT " %02x", eedata[i]);
+               if (15 == (i % 16))
+                       printk(KERN_CONT "\n");
+       }
+}
+
+/* Hauppauge card? get values from tveeprom */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
+{
+       struct i2c_client c;
+       u8 eedata[256];
+
+       memset(&c, 0, sizeof(c));
+       strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name));
+       c.adapter = &cx->i2c_adap[0];
+       c.addr = 0xA0 >> 1;
+
+       memset(tv, 0, sizeof(*tv));
+       if (tveeprom_read(&c, eedata, sizeof(eedata)))
+               return;
+
+       switch (cx->card->type) {
+       case CX18_CARD_HVR_1600_ESMT:
+       case CX18_CARD_HVR_1600_SAMSUNG:
+       case CX18_CARD_HVR_1600_S5H1411:
+               tveeprom_hauppauge_analog(&c, tv, eedata);
+               break;
+       case CX18_CARD_YUAN_MPC718:
+       case CX18_CARD_GOTVIEW_PCI_DVD3:
+               tv->model = 0x718;
+               cx18_eeprom_dump(cx, eedata, sizeof(eedata));
+               CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n",
+                         eedata[2], eedata[1], eedata[4], eedata[3]);
+               break;
+       default:
+               tv->model = 0xffffffff;
+               cx18_eeprom_dump(cx, eedata, sizeof(eedata));
+               break;
+       }
+}
+
+static void cx18_process_eeprom(struct cx18 *cx)
+{
+       struct tveeprom tv;
+
+       cx18_read_eeprom(cx, &tv);
+
+       /* Many thanks to Steven Toth from Hauppauge for providing the
+          model numbers */
+       /* Note: the Samsung memory models cannot be reliably determined
+          from the model number. Use the cardtype module option if you
+          have one of these preproduction models. */
+       switch (tv.model) {
+       case 74301: /* Retail models */
+       case 74321:
+       case 74351: /* OEM models */
+       case 74361:
+               /* Digital side is s5h1411/tda18271 */
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411);
+               break;
+       case 74021: /* Retail models */
+       case 74031:
+       case 74041:
+       case 74141:
+       case 74541: /* OEM models */
+       case 74551:
+       case 74591:
+       case 74651:
+       case 74691:
+       case 74751:
+       case 74891:
+               /* Digital side is s5h1409/mxl5005s */
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+               break;
+       case 0x718:
+               return;
+       case 0xffffffff:
+               CX18_INFO("Unknown EEPROM encoding\n");
+               return;
+       case 0:
+               CX18_ERR("Invalid EEPROM\n");
+               return;
+       default:
+               CX18_ERR("Unknown model %d, defaulting to original HVR-1600 "
+                        "(cardtype=1)\n", tv.model);
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+               break;
+       }
+
+       cx->v4l2_cap = cx->card->v4l2_capabilities;
+       cx->card_name = cx->card->name;
+       cx->card_i2c = cx->card->i2c;
+
+       CX18_INFO("Autodetected %s\n", cx->card_name);
+
+       if (tv.tuner_type == TUNER_ABSENT)
+               CX18_ERR("tveeprom cannot autodetect tuner!\n");
+
+       if (cx->options.tuner == -1)
+               cx->options.tuner = tv.tuner_type;
+       if (cx->options.radio == -1)
+               cx->options.radio = (tv.has_radio != 0);
+
+       if (cx->std != 0)
+               /* user specified tuner standard */
+               return;
+
+       /* autodetect tuner standard */
+#define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B  | V4L2_STD_GH | \
+                                  V4L2_STD_MN | \
+                                  V4L2_STD_PAL_I | \
+                                  V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \
+                                  V4L2_STD_DK)
+       if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL)
+                                       == TVEEPROM_TUNER_FORMAT_ALL) {
+               CX18_DEBUG_INFO("Worldwide tuner detected\n");
+               cx->std = V4L2_STD_ALL;
+       } else if (tv.tuner_formats & V4L2_STD_PAL) {
+               CX18_DEBUG_INFO("PAL tuner detected\n");
+               cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+       } else if (tv.tuner_formats & V4L2_STD_NTSC) {
+               CX18_DEBUG_INFO("NTSC tuner detected\n");
+               cx->std |= V4L2_STD_NTSC_M;
+       } else if (tv.tuner_formats & V4L2_STD_SECAM) {
+               CX18_DEBUG_INFO("SECAM tuner detected\n");
+               cx->std |= V4L2_STD_SECAM_L;
+       } else {
+               CX18_INFO("No tuner detected, default to NTSC-M\n");
+               cx->std |= V4L2_STD_NTSC_M;
+       }
+}
+
+static v4l2_std_id cx18_parse_std(struct cx18 *cx)
+{
+       switch (pal[0]) {
+       case '6':
+               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;
+       case 'n':
+       case 'N':
+               if (pal[1] == 'c' || pal[1] == 'C')
+                       return V4L2_STD_PAL_Nc;
+               return V4L2_STD_PAL_N;
+       case 'i':
+       case 'I':
+               return V4L2_STD_PAL_I;
+       case 'd':
+       case 'D':
+       case 'k':
+       case 'K':
+               return V4L2_STD_PAL_DK;
+       case 'M':
+       case 'm':
+               return V4L2_STD_PAL_M;
+       case '-':
+               break;
+       default:
+               CX18_WARN("pal= argument not recognised\n");
+               return 0;
+       }
+
+       switch (secam[0]) {
+       case 'b':
+       case 'B':
+       case 'g':
+       case 'G':
+       case 'h':
+       case 'H':
+               return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+       case 'd':
+       case 'D':
+       case 'k':
+       case 'K':
+               return V4L2_STD_SECAM_DK;
+       case 'l':
+       case 'L':
+               if (secam[1] == 'C' || secam[1] == 'c')
+                       return V4L2_STD_SECAM_LC;
+               return V4L2_STD_SECAM_L;
+       case '-':
+               break;
+       default:
+               CX18_WARN("secam= argument not recognised\n");
+               return 0;
+       }
+
+       switch (ntsc[0]) {
+       case 'm':
+       case 'M':
+               return V4L2_STD_NTSC_M;
+       case 'j':
+       case 'J':
+               return V4L2_STD_NTSC_M_JP;
+       case 'k':
+       case 'K':
+               return V4L2_STD_NTSC_M_KR;
+       case '-':
+               break;
+       default:
+               CX18_WARN("ntsc= argument not recognised\n");
+               return 0;
+       }
+
+       /* no match found */
+       return 0;
+}
+
+static void cx18_process_options(struct cx18 *cx)
+{
+       int i, j;
+
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+       cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */
+
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs;
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs;
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs;
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs;
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs;
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs;
+       cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */
+
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize;
+       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */
+
+       /* Ensure stream_buffers & stream_buf_size are valid */
+       for (i = 0; i < CX18_MAX_STREAMS; i++) {
+               if (cx->stream_buffers[i] == 0 ||     /* User said 0 buffers */
+                   cx->options.megabytes[i] <= 0 ||  /* User said 0 MB total */
+                   cx->stream_buf_size[i] <= 0) {    /* User said buf size 0 */
+                       cx->options.megabytes[i] = 0;
+                       cx->stream_buffers[i] = 0;
+                       cx->stream_buf_size[i] = 0;
+                       continue;
+               }
+               /*
+                * YUV is a special case where the stream_buf_size needs to be
+                * an integral multiple of 33.75 kB (storage for 32 screens
+                * lines to maintain alignment in case of lost buffers).
+                *
+                * IDX is a special case where the stream_buf_size should be
+                * an integral multiple of 1.5 kB (storage for 64 index entries
+                * to maintain alignment in case of lost buffers).
+                *
+                */
+               if (i == CX18_ENC_STREAM_TYPE_YUV) {
+                       cx->stream_buf_size[i] *= 1024;
+                       cx->stream_buf_size[i] -=
+                          (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE);
+
+                       if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE)
+                               cx->stream_buf_size[i] =
+                                               CX18_UNIT_ENC_YUV_BUFSIZE;
+               } else if (i == CX18_ENC_STREAM_TYPE_IDX) {
+                       cx->stream_buf_size[i] *= 1024;
+                       cx->stream_buf_size[i] -=
+                          (cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE);
+
+                       if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE)
+                               cx->stream_buf_size[i] =
+                                               CX18_UNIT_ENC_IDX_BUFSIZE;
+               }
+               /*
+                * YUV and IDX are special cases where the stream_buf_size is
+                * now in bytes.
+                * VBI is a special case where the stream_buf_size is fixed
+                * and already in bytes
+                */
+               if (i == CX18_ENC_STREAM_TYPE_VBI ||
+                   i == CX18_ENC_STREAM_TYPE_YUV ||
+                   i == CX18_ENC_STREAM_TYPE_IDX) {
+                       if (cx->stream_buffers[i] < 0) {
+                               cx->stream_buffers[i] =
+                                       cx->options.megabytes[i] * 1024 * 1024
+                                       / cx->stream_buf_size[i];
+                       } else {
+                               /* N.B. This might round down to 0 */
+                               cx->options.megabytes[i] =
+                                       cx->stream_buffers[i]
+                                       * cx->stream_buf_size[i]/(1024 * 1024);
+                       }
+               } else {
+                       /* All other streams have stream_buf_size in kB here */
+                       if (cx->stream_buffers[i] < 0) {
+                               cx->stream_buffers[i] =
+                                               cx->options.megabytes[i] * 1024
+                                               / cx->stream_buf_size[i];
+                       } else {
+                               /* N.B. This might round down to 0 */
+                               cx->options.megabytes[i] =
+                                               cx->stream_buffers[i]
+                                               * cx->stream_buf_size[i] / 1024;
+                       }
+                       /* convert from kB to bytes */
+                       cx->stream_buf_size[i] *= 1024;
+               }
+               CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, "
+                               "%d bytes\n", i, cx->options.megabytes[i],
+                               cx->stream_buffers[i], cx->stream_buf_size[i]);
+       }
+
+       cx->options.cardtype = cardtype[cx->instance];
+       cx->options.tuner = tuner[cx->instance];
+       cx->options.radio = radio[cx->instance];
+
+       cx->std = cx18_parse_std(cx);
+       if (cx->options.cardtype == -1) {
+               CX18_INFO("Ignore card\n");
+               return;
+       }
+       cx->card = cx18_get_card(cx->options.cardtype - 1);
+       if (cx->card)
+               CX18_INFO("User specified %s card\n", cx->card->name);
+       else if (cx->options.cardtype != 0)
+               CX18_ERR("Unknown user specified type, trying to autodetect card\n");
+       if (cx->card == NULL) {
+               if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
+                       cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+                       CX18_INFO("Autodetected Hauppauge card\n");
+               }
+       }
+       if (cx->card == NULL) {
+               for (i = 0; (cx->card = cx18_get_card(i)); i++) {
+                       if (cx->card->pci_list == NULL)
+                               continue;
+                       for (j = 0; cx->card->pci_list[j].device; j++) {
+                               if (cx->pci_dev->device !=
+                                   cx->card->pci_list[j].device)
+                                       continue;
+                               if (cx->pci_dev->subsystem_vendor !=
+                                   cx->card->pci_list[j].subsystem_vendor)
+                                       continue;
+                               if (cx->pci_dev->subsystem_device !=
+                                   cx->card->pci_list[j].subsystem_device)
+                                       continue;
+                               CX18_INFO("Autodetected %s card\n", cx->card->name);
+                               goto done;
+                       }
+               }
+       }
+done:
+
+       if (cx->card == NULL) {
+               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+               CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
+                        cx->pci_dev->vendor, cx->pci_dev->device);
+               CX18_ERR("              subsystem vendor/device: [%04x:%04x]\n",
+                        cx->pci_dev->subsystem_vendor,
+                        cx->pci_dev->subsystem_device);
+               CX18_ERR("Defaulting to %s card\n", cx->card->name);
+               CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
+               CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
+               CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
+       }
+       cx->v4l2_cap = cx->card->v4l2_capabilities;
+       cx->card_name = cx->card->name;
+       cx->card_i2c = cx->card->i2c;
+}
+
+static int __devinit cx18_create_in_workq(struct cx18 *cx)
+{
+       snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
+                cx->v4l2_dev.name);
+       cx->in_work_queue = alloc_ordered_workqueue(cx->in_workq_name, 0);
+       if (cx->in_work_queue == NULL) {
+               CX18_ERR("Unable to create incoming mailbox handler thread\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
+               cx->in_work_order[i].cx = cx;
+               cx->in_work_order[i].str = cx->epu_debug_str;
+               INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler);
+       }
+}
+
+/* Precondition: the cx18 structure has been memset to 0. Only
+   the dev and instance fields have been filled in.
+   No assumptions on the card type may be made here (see cx18_init_struct2
+   for that).
+ */
+static int __devinit cx18_init_struct1(struct cx18 *cx)
+{
+       int ret;
+
+       cx->base_addr = pci_resource_start(cx->pci_dev, 0);
+
+       mutex_init(&cx->serialize_lock);
+       mutex_init(&cx->gpio_lock);
+       mutex_init(&cx->epu2apu_mb_lock);
+       mutex_init(&cx->epu2cpu_mb_lock);
+
+       ret = cx18_create_in_workq(cx);
+       if (ret)
+               return ret;
+
+       cx18_init_in_work_orders(cx);
+
+       /* start counting open_id at 1 */
+       cx->open_id = 1;
+
+       /* Initial settings */
+       cx->cxhdl.port = CX2341X_PORT_MEMORY;
+       cx->cxhdl.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI;
+       cx->cxhdl.ops = &cx18_cxhdl_ops;
+       cx->cxhdl.func = cx18_api_func;
+       cx->cxhdl.priv = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+       ret = cx2341x_handler_init(&cx->cxhdl, 50);
+       if (ret)
+               return ret;
+       cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl;
+
+       cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val;
+       cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val;
+       cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val |
+               (cx->cxhdl.video_temporal_filter_mode->cur.val << 1) |
+               (cx->cxhdl.video_median_filter_type->cur.val << 2);
+
+       init_waitqueue_head(&cx->cap_w);
+       init_waitqueue_head(&cx->mb_apu_waitq);
+       init_waitqueue_head(&cx->mb_cpu_waitq);
+       init_waitqueue_head(&cx->dma_waitq);
+
+       /* VBI */
+       cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
+
+       /* IVTV style VBI insertion into MPEG streams */
+       INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list);
+       INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list);
+       INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list);
+       list_add(&cx->vbi.sliced_mpeg_buf.list,
+                &cx->vbi.sliced_mpeg_mdl.buf_list);
+       return 0;
+}
+
+/* Second initialization part. Here the card type has been
+   autodetected. */
+static void __devinit cx18_init_struct2(struct cx18 *cx)
+{
+       int i;
+
+       for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
+               if (cx->card->video_inputs[i].video_type == 0)
+                       break;
+       cx->nof_inputs = i;
+       for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
+               if (cx->card->audio_inputs[i].audio_type == 0)
+                       break;
+       cx->nof_audio_inputs = i;
+
+       /* Find tuner input */
+       for (i = 0; i < cx->nof_inputs; i++) {
+               if (cx->card->video_inputs[i].video_type ==
+                               CX18_CARD_INPUT_VID_TUNER)
+                       break;
+       }
+       if (i == cx->nof_inputs)
+               i = 0;
+       cx->active_input = i;
+       cx->audio_input = cx->card->video_inputs[i].audio_index;
+}
+
+static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
+                         const struct pci_device_id *pci_id)
+{
+       u16 cmd;
+       unsigned char pci_latency;
+
+       CX18_DEBUG_INFO("Enabling pci device\n");
+
+       if (pci_enable_device(pci_dev)) {
+               CX18_ERR("Can't enable device %d!\n", cx->instance);
+               return -EIO;
+       }
+       if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
+               CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
+               return -EIO;
+       }
+       if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
+               CX18_ERR("Cannot request encoder memory region, card %d\n",
+                        cx->instance);
+               return -EIO;
+       }
+
+       /* Enable bus mastering and memory mapped IO for the CX23418 */
+       pci_read_config_word(pci_dev, PCI_COMMAND, &cmd);
+       cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+       pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
+
+       cx->card_rev = pci_dev->revision;
+       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
+
+       if (pci_latency < 64 && cx18_pci_latency) {
+               CX18_INFO("Unreasonably low latency timer, "
+                              "setting to 64 (was %d)\n", pci_latency);
+               pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 64);
+               pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
+       }
+
+       CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
+                  "irq: %d, latency: %d, memory: 0x%llx\n",
+                  cx->pci_dev->device, cx->card_rev, pci_dev->bus->number,
+                  PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn),
+                  cx->pci_dev->irq, pci_latency, (u64)cx->base_addr);
+
+       return 0;
+}
+
+static void cx18_init_subdevs(struct cx18 *cx)
+{
+       u32 hw = cx->card->hw_all;
+       u32 device;
+       int i;
+
+       for (i = 0, device = 1; i < 32; i++, device <<= 1) {
+
+               if (!(device & hw))
+                       continue;
+
+               switch (device) {
+               case CX18_HW_DVB:
+               case CX18_HW_TVEEPROM:
+                       /* These subordinate devices do not use probing */
+                       cx->hw_flags |= device;
+                       break;
+               case CX18_HW_418_AV:
+                       /* The A/V decoder gets probed earlier to set PLLs */
+                       /* Just note that the card uses it (i.e. has analog) */
+                       cx->hw_flags |= device;
+                       break;
+               case CX18_HW_GPIO_RESET_CTRL:
+                       /*
+                        * The Reset Controller gets probed and added to
+                        * hw_flags earlier for i2c adapter/bus initialization
+                        */
+                       break;
+               case CX18_HW_GPIO_MUX:
+                       if (cx18_gpio_register(cx, device) == 0)
+                               cx->hw_flags |= device;
+                       break;
+               default:
+                       if (cx18_i2c_register(cx, i) == 0)
+                               cx->hw_flags |= device;
+                       break;
+               }
+       }
+
+       if (cx->hw_flags & CX18_HW_418_AV)
+               cx->sd_av = cx18_find_hw(cx, CX18_HW_418_AV);
+
+       if (cx->card->hw_muxer != 0)
+               cx->sd_extmux = cx18_find_hw(cx, cx->card->hw_muxer);
+}
+
+static int __devinit cx18_probe(struct pci_dev *pci_dev,
+                               const struct pci_device_id *pci_id)
+{
+       int retval = 0;
+       int i;
+       u32 devtype;
+       struct cx18 *cx;
+
+       /* FIXME - module parameter arrays constrain max instances */
+       i = atomic_inc_return(&cx18_instance) - 1;
+       if (i >= CX18_MAX_CARDS) {
+               printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
+                      "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
+               return -ENOMEM;
+       }
+
+       cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
+       if (cx == NULL) {
+               printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
+                      i);
+               return -ENOMEM;
+       }
+       cx->pci_dev = pci_dev;
+       cx->instance = i;
+
+       retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
+       if (retval) {
+               printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
+                      "\n", cx->instance);
+               kfree(cx);
+               return retval;
+       }
+       snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d",
+                cx->instance);
+       CX18_INFO("Initializing card %d\n", cx->instance);
+
+       cx18_process_options(cx);
+       if (cx->options.cardtype == -1) {
+               retval = -ENODEV;
+               goto err;
+       }
+
+       retval = cx18_init_struct1(cx);
+       if (retval)
+               goto err;
+
+       CX18_DEBUG_INFO("base addr: 0x%llx\n", (u64)cx->base_addr);
+
+       /* PCI Device Setup */
+       retval = cx18_setup_pci(cx, pci_dev, pci_id);
+       if (retval != 0)
+               goto free_workqueues;
+
+       /* map io memory */
+       CX18_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+                  (u64)cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
+       cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
+                                      CX18_MEM_SIZE);
+       if (!cx->enc_mem) {
+               CX18_ERR("ioremap failed. Can't get a window into CX23418 "
+                        "memory and register space\n");
+               CX18_ERR("Each capture card with a CX23418 needs 64 MB of "
+                        "vmalloc address space for the window\n");
+               CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+               CX18_ERR("Use the vmalloc= kernel command line option to set "
+                        "VmallocTotal to a larger value\n");
+               retval = -ENOMEM;
+               goto free_mem;
+       }
+       cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
+       devtype = cx18_read_reg(cx, 0xC72028);
+       switch (devtype & 0xff000000) {
+       case 0xff000000:
+               CX18_INFO("cx23418 revision %08x (A)\n", devtype);
+               break;
+       case 0x01000000:
+               CX18_INFO("cx23418 revision %08x (B)\n", devtype);
+               break;
+       default:
+               CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
+               break;
+       }
+
+       cx18_init_power(cx, 1);
+       cx18_init_memory(cx);
+
+       cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
+       cx18_init_scb(cx);
+
+       cx18_gpio_init(cx);
+
+       /* Initialize integrated A/V decoder early to set PLLs, just in case */
+       retval = cx18_av_probe(cx);
+       if (retval) {
+               CX18_ERR("Could not register A/V decoder subdevice\n");
+               goto free_map;
+       }
+
+       /* Initialize GPIO Reset Controller to do chip resets during i2c init */
+       if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
+               if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0)
+                       CX18_WARN("Could not register GPIO reset controller"
+                                 "subdevice; proceeding anyway.\n");
+               else
+                       cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL;
+       }
+
+       /* active i2c  */
+       CX18_DEBUG_INFO("activating i2c...\n");
+       retval = init_cx18_i2c(cx);
+       if (retval) {
+               CX18_ERR("Could not initialize i2c\n");
+               goto free_map;
+       }
+
+       if (cx->card->hw_all & CX18_HW_TVEEPROM) {
+               /* Based on the model number the cardtype may be changed.
+                  The PCI IDs are not always reliable. */
+               const struct cx18_card *orig_card = cx->card;
+               cx18_process_eeprom(cx);
+
+               if (cx->card != orig_card) {
+                       /* Changed the cardtype; re-reset the I2C chips */
+                       cx18_gpio_init(cx);
+                       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+                                       core, reset, (u32) CX18_GPIO_RESET_I2C);
+               }
+       }
+       if (cx->card->comment)
+               CX18_INFO("%s", cx->card->comment);
+       if (cx->card->v4l2_capabilities == 0) {
+               retval = -ENODEV;
+               goto free_i2c;
+       }
+       cx18_init_memory(cx);
+       cx18_init_scb(cx);
+
+       /* Register IRQ */
+       retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
+                            IRQF_SHARED | IRQF_DISABLED,
+                            cx->v4l2_dev.name, (void *)cx);
+       if (retval) {
+               CX18_ERR("Failed to register irq %d\n", retval);
+               goto free_i2c;
+       }
+
+       if (cx->std == 0)
+               cx->std = V4L2_STD_NTSC_M;
+
+       if (cx->options.tuner == -1) {
+               for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
+                       if ((cx->std & cx->card->tuners[i].std) == 0)
+                               continue;
+                       cx->options.tuner = cx->card->tuners[i].tuner;
+                       break;
+               }
+       }
+       /* if no tuner was found, then pick the first tuner in the card list */
+       if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
+               cx->std = cx->card->tuners[0].std;
+               if (cx->std & V4L2_STD_PAL)
+                       cx->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+               else if (cx->std & V4L2_STD_NTSC)
+                       cx->std = V4L2_STD_NTSC_M;
+               else if (cx->std & V4L2_STD_SECAM)
+                       cx->std = V4L2_STD_SECAM_L;
+               cx->options.tuner = cx->card->tuners[0].tuner;
+       }
+       if (cx->options.radio == -1)
+               cx->options.radio = (cx->card->radio_input.audio_type != 0);
+
+       /* The card is now fully identified, continue with card-specific
+          initialization. */
+       cx18_init_struct2(cx);
+
+       cx18_init_subdevs(cx);
+
+       if (cx->std & V4L2_STD_525_60)
+               cx->is_60hz = 1;
+       else
+               cx->is_50hz = 1;
+
+       cx2341x_handler_set_50hz(&cx->cxhdl, !cx->is_60hz);
+
+       if (cx->options.radio > 0)
+               cx->v4l2_cap |= V4L2_CAP_RADIO;
+
+       if (cx->options.tuner > -1) {
+               struct tuner_setup setup;
+
+               setup.addr = ADDR_UNSET;
+               setup.type = cx->options.tuner;
+               setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+               if (cx->options.radio > 0)
+                       setup.mode_mask |= T_RADIO;
+               setup.tuner_callback = (setup.type == TUNER_XC2028) ?
+                       cx18_reset_tuner_gpio : NULL;
+               cx18_call_all(cx, tuner, s_type_addr, &setup);
+               if (setup.type == TUNER_XC2028) {
+                       static struct xc2028_ctrl ctrl = {
+                               .fname = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                       };
+                       struct v4l2_priv_tun_config cfg = {
+                               .tuner = cx->options.tuner,
+                               .priv = &ctrl,
+                       };
+                       cx18_call_all(cx, tuner, s_config, &cfg);
+               }
+       }
+
+       /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
+          are not. */
+       cx->tuner_std = cx->std;
+       if (cx->std == V4L2_STD_ALL)
+               cx->std = V4L2_STD_NTSC_M;
+
+       retval = cx18_streams_setup(cx);
+       if (retval) {
+               CX18_ERR("Error %d setting up streams\n", retval);
+               goto free_irq;
+       }
+       retval = cx18_streams_register(cx);
+       if (retval) {
+               CX18_ERR("Error %d registering devices\n", retval);
+               goto free_streams;
+       }
+
+       CX18_INFO("Initialized card: %s\n", cx->card_name);
+
+       /* Load cx18 submodules (cx18-alsa) */
+       request_modules(cx);
+       return 0;
+
+free_streams:
+       cx18_streams_cleanup(cx, 1);
+free_irq:
+       free_irq(cx->pci_dev->irq, (void *)cx);
+free_i2c:
+       exit_cx18_i2c(cx);
+free_map:
+       cx18_iounmap(cx);
+free_mem:
+       release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+free_workqueues:
+       destroy_workqueue(cx->in_work_queue);
+err:
+       if (retval == 0)
+               retval = -ENODEV;
+       CX18_ERR("Error %d on initialization\n", retval);
+
+       v4l2_device_unregister(&cx->v4l2_dev);
+       kfree(cx);
+       return retval;
+}
+
+int cx18_init_on_first_open(struct cx18 *cx)
+{
+       int video_input;
+       int fw_retry_count = 3;
+       struct v4l2_frequency vf;
+       struct cx18_open_id fh;
+       v4l2_std_id std;
+
+       fh.cx = cx;
+
+       if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
+               return -ENXIO;
+
+       if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
+               return 0;
+
+       while (--fw_retry_count > 0) {
+               /* load firmware */
+               if (cx18_firmware_init(cx) == 0)
+                       break;
+               if (fw_retry_count > 1)
+                       CX18_WARN("Retry loading firmware\n");
+       }
+
+       if (fw_retry_count == 0) {
+               set_bit(CX18_F_I_FAILED, &cx->i_flags);
+               return -ENXIO;
+       }
+       set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
+
+       /*
+        * Init the firmware twice to work around a silicon bug
+        * with the digital TS.
+        *
+        * The second firmware load requires us to normalize the APU state,
+        * or the audio for the first analog capture will be badly incorrect.
+        *
+        * I can't seem to call APU_RESETAI and have it succeed without the
+        * APU capturing audio, so we start and stop it here to do the reset
+        */
+
+       /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */
+       cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0);
+       cx18_vapi(cx, CX18_APU_RESETAI, 0);
+       cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);
+
+       fw_retry_count = 3;
+       while (--fw_retry_count > 0) {
+               /* load firmware */
+               if (cx18_firmware_init(cx) == 0)
+                       break;
+               if (fw_retry_count > 1)
+                       CX18_WARN("Retry loading firmware\n");
+       }
+
+       if (fw_retry_count == 0) {
+               set_bit(CX18_F_I_FAILED, &cx->i_flags);
+               return -ENXIO;
+       }
+
+       /*
+        * The second firmware load requires us to normalize the APU state,
+        * or the audio for the first analog capture will be badly incorrect.
+        *
+        * I can't seem to call APU_RESETAI and have it succeed without the
+        * APU capturing audio, so we start and stop it here to do the reset
+        */
+
+       /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */
+       cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0);
+       cx18_vapi(cx, CX18_APU_RESETAI, 0);
+       cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);
+
+       /* Init the A/V decoder, if it hasn't been already */
+       v4l2_subdev_call(cx->sd_av, core, load_fw);
+
+       vf.tuner = 0;
+       vf.type = V4L2_TUNER_ANALOG_TV;
+       vf.frequency = 6400; /* the tuner 'baseline' frequency */
+
+       /* Set initial frequency. For PAL/SECAM broadcasts no
+          'default' channel exists AFAIK. */
+       if (cx->std == V4L2_STD_NTSC_M_JP)
+               vf.frequency = 1460;    /* ch. 1 91250*16/1000 */
+       else if (cx->std & V4L2_STD_NTSC_M)
+               vf.frequency = 1076;    /* ch. 4 67250*16/1000 */
+
+       video_input = cx->active_input;
+       cx->active_input++;     /* Force update of input */
+       cx18_s_input(NULL, &fh, video_input);
+
+       /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
+          in one place. */
+       cx->std++;              /* Force full standard initialization */
+       std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std;
+       cx18_s_std(NULL, &fh, &std);
+       cx18_s_frequency(NULL, &fh, &vf);
+       return 0;
+}
+
+static void cx18_cancel_in_work_orders(struct cx18 *cx)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++)
+               cancel_work_sync(&cx->in_work_order[i].work);
+}
+
+static void cx18_cancel_out_work_orders(struct cx18 *cx)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_STREAMS; i++)
+               if (&cx->streams[i].video_dev != NULL)
+                       cancel_work_sync(&cx->streams[i].out_work_order);
+}
+
+static void cx18_remove(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct cx18 *cx = to_cx18(v4l2_dev);
+       int i;
+
+       CX18_DEBUG_INFO("Removing Card\n");
+
+       flush_request_modules(cx);
+
+       /* Stop all captures */
+       CX18_DEBUG_INFO("Stopping all streams\n");
+       if (atomic_read(&cx->tot_capturing) > 0)
+               cx18_stop_all_captures(cx);
+
+       /* Stop interrupts that cause incoming work to be queued */
+       cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+
+       /* Incoming work can cause outgoing work, so clean up incoming first */
+       cx18_cancel_in_work_orders(cx);
+       cx18_cancel_out_work_orders(cx);
+
+       /* Stop ack interrupts that may have been needed for work to finish */
+       cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+       cx18_halt_firmware(cx);
+
+       destroy_workqueue(cx->in_work_queue);
+
+       cx18_streams_cleanup(cx, 1);
+
+       exit_cx18_i2c(cx);
+
+       free_irq(cx->pci_dev->irq, (void *)cx);
+
+       cx18_iounmap(cx);
+
+       release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+
+       pci_disable_device(cx->pci_dev);
+
+       if (cx->vbi.sliced_mpeg_data[0] != NULL)
+               for (i = 0; i < CX18_VBI_FRAMES; i++)
+                       kfree(cx->vbi.sliced_mpeg_data[i]);
+
+       v4l2_ctrl_handler_free(&cx->av_state.hdl);
+
+       CX18_INFO("Removed %s\n", cx->card_name);
+
+       v4l2_device_unregister(v4l2_dev);
+       kfree(cx);
+}
+
+
+/* define a pci_driver for card detection */
+static struct pci_driver cx18_pci_driver = {
+      .name =     "cx18",
+      .id_table = cx18_pci_tbl,
+      .probe =    cx18_probe,
+      .remove =   cx18_remove,
+};
+
+static int __init module_start(void)
+{
+       printk(KERN_INFO "cx18:  Start initialization, version %s\n",
+              CX18_VERSION);
+
+       /* Validate parameters */
+       if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
+               printk(KERN_ERR "cx18:  Exiting, cx18_first_minor must be between 0 and %d\n",
+                    CX18_MAX_CARDS - 1);
+               return -1;
+       }
+
+       if (cx18_debug < 0 || cx18_debug > 511) {
+               cx18_debug = 0;
+               printk(KERN_INFO "cx18:   Debug value must be >= 0 and <= 511!\n");
+       }
+
+       if (pci_register_driver(&cx18_pci_driver)) {
+               printk(KERN_ERR "cx18:   Error detecting PCI card\n");
+               return -ENODEV;
+       }
+       printk(KERN_INFO "cx18:  End initialization\n");
+       return 0;
+}
+
+static void __exit module_cleanup(void)
+{
+       pci_unregister_driver(&cx18_pci_driver);
+}
+
+module_init(module_start);
+module_exit(module_cleanup);
+MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h
new file mode 100644 (file)
index 0000000..2767c64
--- /dev/null
@@ -0,0 +1,730 @@
+/*
+ *  cx18 driver internal defines and structures
+ *
+ *  Derived from ivtv-driver.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX18_DRIVER_H
+#define CX18_DRIVER_H
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/pagemap.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/tuner.h>
+#include <media/ir-kbd-i2c.h>
+#include "cx18-mailbox.h"
+#include "cx18-av-core.h"
+#include "cx23418.h"
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+/* Videobuf / YUV support */
+#include <media/videobuf-core.h>
+#include <media/videobuf-vmalloc.h>
+
+#ifndef CONFIG_PCI
+#  error "This driver requires kernel PCI support."
+#endif
+
+#define CX18_MEM_OFFSET        0x00000000
+#define CX18_MEM_SIZE  0x04000000
+#define CX18_REG_OFFSET        0x02000000
+
+/* Maximum cx18 driver instances. */
+#define CX18_MAX_CARDS 32
+
+/* Supported cards */
+#define CX18_CARD_HVR_1600_ESMT              0 /* Hauppauge HVR 1600 (ESMT memory) */
+#define CX18_CARD_HVR_1600_SAMSUNG    1        /* Hauppauge HVR 1600 (Samsung memory) */
+#define CX18_CARD_COMPRO_H900        2 /* Compro VideoMate H900 */
+#define CX18_CARD_YUAN_MPC718        3 /* Yuan MPC718 */
+#define CX18_CARD_CNXT_RAPTOR_PAL     4        /* Conexant Raptor PAL */
+#define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
+#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100 */
+#define CX18_CARD_LEADTEK_DVR3100H    7 /* Leadtek WinFast DVR3100 H */
+#define CX18_CARD_GOTVIEW_PCI_DVD3    8 /* GoTView PCI DVD3 Hybrid */
+#define CX18_CARD_HVR_1600_S5H1411    9 /* Hauppauge HVR 1600 s5h1411/tda18271*/
+#define CX18_CARD_LAST               9
+
+#define CX18_ENC_STREAM_TYPE_MPG  0
+#define CX18_ENC_STREAM_TYPE_TS   1
+#define CX18_ENC_STREAM_TYPE_YUV  2
+#define CX18_ENC_STREAM_TYPE_VBI  3
+#define CX18_ENC_STREAM_TYPE_PCM  4
+#define CX18_ENC_STREAM_TYPE_IDX  5
+#define CX18_ENC_STREAM_TYPE_RAD  6
+#define CX18_MAX_STREAMS         7
+
+/* system vendor and device IDs */
+#define PCI_VENDOR_ID_CX      0x14f1
+#define PCI_DEVICE_ID_CX23418 0x5b7a
+
+/* subsystem vendor ID */
+#define CX18_PCI_ID_HAUPPAUGE          0x0070
+#define CX18_PCI_ID_COMPRO             0x185b
+#define CX18_PCI_ID_YUAN               0x12ab
+#define CX18_PCI_ID_CONEXANT           0x14f1
+#define CX18_PCI_ID_TOSHIBA            0x1179
+#define CX18_PCI_ID_LEADTEK            0x107D
+#define CX18_PCI_ID_GOTVIEW            0x5854
+
+/* ======================================================================== */
+/* ========================== START USER SETTABLE DMA VARIABLES =========== */
+/* ======================================================================== */
+
+/* DMA Buffers, Default size in MB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFFERS  1
+#define CX18_DEFAULT_ENC_MPG_BUFFERS 2
+#define CX18_DEFAULT_ENC_IDX_BUFFERS 1
+#define CX18_DEFAULT_ENC_YUV_BUFFERS 2
+#define CX18_DEFAULT_ENC_VBI_BUFFERS 1
+#define CX18_DEFAULT_ENC_PCM_BUFFERS 1
+
+/* Maximum firmware DMA buffers per stream */
+#define CX18_MAX_FW_MDLS_PER_STREAM 63
+
+/* YUV buffer sizes in bytes to ensure integer # of frames per buffer */
+#define CX18_UNIT_ENC_YUV_BUFSIZE      (720 *  32 * 3 / 2) /* bytes */
+#define CX18_625_LINE_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32)
+#define CX18_525_LINE_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32)
+
+/* IDX buffer size should be a multiple of the index entry size from the chip */
+struct cx18_enc_idx_entry {
+       __le32 length;
+       __le32 offset_low;
+       __le32 offset_high;
+       __le32 flags;
+       __le32 pts_low;
+       __le32 pts_high;
+} __attribute__ ((packed));
+#define CX18_UNIT_ENC_IDX_BUFSIZE \
+       (sizeof(struct cx18_enc_idx_entry) * V4L2_ENC_IDX_ENTRIES)
+
+/* DMA buffer, default size in kB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFSIZE   32
+#define CX18_DEFAULT_ENC_MPG_BUFSIZE  32
+#define CX18_DEFAULT_ENC_IDX_BUFSIZE  (CX18_UNIT_ENC_IDX_BUFSIZE * 1 / 1024 + 1)
+#define CX18_DEFAULT_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1)
+#define CX18_DEFAULT_ENC_PCM_BUFSIZE   4
+
+/* i2c stuff */
+#define I2C_CLIENTS_MAX 16
+
+/* debugging */
+
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_WARN  (1 << 0)
+#define CX18_DBGFLG_INFO  (1 << 1)
+#define CX18_DBGFLG_API   (1 << 2)
+#define CX18_DBGFLG_DMA   (1 << 3)
+#define CX18_DBGFLG_IOCTL (1 << 4)
+#define CX18_DBGFLG_FILE  (1 << 5)
+#define CX18_DBGFLG_I2C   (1 << 6)
+#define CX18_DBGFLG_IRQ   (1 << 7)
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_HIGHVOL (1 << 8)
+
+/* NOTE: extra space before comma in 'fmt , ## args' is required for
+   gcc-2.95, otherwise it won't compile. */
+#define CX18_DEBUG(x, type, fmt, args...) \
+       do { \
+               if ((x) & cx18_debug) \
+                       v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
+       } while (0)
+#define CX18_DEBUG_WARN(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
+#define CX18_DEBUG_INFO(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
+#define CX18_DEBUG_API(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_DMA(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_IOCTL(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_FILE(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_I2C(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_IRQ(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
+       do { \
+               if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
+                       v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
+       } while (0)
+#define CX18_DEBUG_HI_WARN(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
+#define CX18_DEBUG_HI_INFO(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
+#define CX18_DEBUG_HI_API(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_HI_DMA(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_HI_IOCTL(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_HI_FILE(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_HI_I2C(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_HI_IRQ(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+/* Standard kernel messages */
+#define CX18_ERR(fmt, args...)      v4l2_err(&cx->v4l2_dev, fmt , ## args)
+#define CX18_WARN(fmt, args...)     v4l2_warn(&cx->v4l2_dev, fmt , ## args)
+#define CX18_INFO(fmt, args...)     v4l2_info(&cx->v4l2_dev, fmt , ## args)
+
+/* Messages for internal subdevs to use */
+#define CX18_DEBUG_DEV(x, dev, type, fmt, args...) \
+       do { \
+               if ((x) & cx18_debug) \
+                       v4l2_info(dev, " " type ": " fmt , ## args); \
+       } while (0)
+#define CX18_DEBUG_WARN_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args)
+#define CX18_DEBUG_INFO_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args)
+#define CX18_DEBUG_API_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args)
+#define CX18_DEBUG_DMA_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args)
+#define CX18_DEBUG_IOCTL_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args)
+#define CX18_DEBUG_FILE_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args)
+#define CX18_DEBUG_I2C_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args)
+#define CX18_DEBUG_IRQ_DEV(dev, fmt, args...) \
+               CX18_DEBUG_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args)
+
+#define CX18_DEBUG_HIGH_VOL_DEV(x, dev, type, fmt, args...) \
+       do { \
+               if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
+                       v4l2_info(dev, " " type ": " fmt , ## args); \
+       } while (0)
+#define CX18_DEBUG_HI_WARN_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args)
+#define CX18_DEBUG_HI_INFO_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args)
+#define CX18_DEBUG_HI_API_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args)
+#define CX18_DEBUG_HI_DMA_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args)
+#define CX18_DEBUG_HI_IOCTL_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args)
+#define CX18_DEBUG_HI_FILE_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args)
+#define CX18_DEBUG_HI_I2C_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args)
+#define CX18_DEBUG_HI_IRQ_DEV(dev, fmt, args...) \
+       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args)
+
+#define CX18_ERR_DEV(dev, fmt, args...)      v4l2_err(dev, fmt , ## args)
+#define CX18_WARN_DEV(dev, fmt, args...)     v4l2_warn(dev, fmt , ## args)
+#define CX18_INFO_DEV(dev, fmt, args...)     v4l2_info(dev, fmt , ## args)
+
+extern int cx18_debug;
+
+struct cx18_options {
+       int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
+       int cardtype;           /* force card type on load */
+       int tuner;              /* set tuner on load */
+       int radio;              /* enable/disable radio */
+};
+
+/* per-mdl bit flags */
+#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianess swapped */
+
+/* per-stream, s_flags */
+#define CX18_F_S_CLAIMED       3       /* this stream is claimed */
+#define CX18_F_S_STREAMING      4      /* the fw is decoding/encoding this stream */
+#define CX18_F_S_INTERNAL_USE  5       /* this stream is used internally (sliced VBI processing) */
+#define CX18_F_S_STREAMOFF     7       /* signal end of stream EOS */
+#define CX18_F_S_APPL_IO        8      /* this stream is used read/written by an application */
+#define CX18_F_S_STOPPING      9       /* telling the fw to stop capturing */
+
+/* per-cx18, i_flags */
+#define CX18_F_I_LOADED_FW             0       /* Loaded firmware 1st time */
+#define CX18_F_I_EOS                   4       /* End of encoder stream */
+#define CX18_F_I_RADIO_USER            5       /* radio tuner is selected */
+#define CX18_F_I_ENC_PAUSED            13      /* the encoder is paused */
+#define CX18_F_I_INITED                        21      /* set after first open */
+#define CX18_F_I_FAILED                        22      /* set if first open failed */
+
+/* These are the VBI types as they appear in the embedded VBI private packets. */
+#define CX18_SLICED_TYPE_TELETEXT_B     (1)
+#define CX18_SLICED_TYPE_CAPTION_525    (4)
+#define CX18_SLICED_TYPE_WSS_625        (5)
+#define CX18_SLICED_TYPE_VPS            (7)
+
+/**
+ * list_entry_is_past_end - check if a previous loop cursor is off list end
+ * @pos:       the type * previously used as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ *
+ * Check if the entry's list_head is the head of the list, thus it's not a
+ * real entry but was the loop cursor that walked past the end
+ */
+#define list_entry_is_past_end(pos, head, member) \
+       (&pos->member == (head))
+
+struct cx18_buffer {
+       struct list_head list;
+       dma_addr_t dma_handle;
+       char *buf;
+
+       u32 bytesused;
+       u32 readpos;
+};
+
+struct cx18_mdl {
+       struct list_head list;
+       u32 id;         /* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */
+
+       unsigned int skipped;
+       unsigned long m_flags;
+
+       struct list_head buf_list;
+       struct cx18_buffer *curr_buf; /* current buffer in list for reading */
+
+       u32 bytesused;
+       u32 readpos;
+};
+
+struct cx18_queue {
+       struct list_head list;
+       atomic_t depth;
+       u32 bytesused;
+       spinlock_t lock;
+};
+
+struct cx18_stream; /* forward reference */
+
+struct cx18_dvb {
+       struct cx18_stream *stream;
+       struct dmx_frontend hw_frontend;
+       struct dmx_frontend mem_frontend;
+       struct dmxdev dmxdev;
+       struct dvb_adapter dvb_adapter;
+       struct dvb_demux demux;
+       struct dvb_frontend *fe;
+       struct dvb_net dvbnet;
+       int enabled;
+       int feeding;
+       struct mutex feedlock;
+};
+
+struct cx18;    /* forward reference */
+struct cx18_scb; /* forward reference */
+
+
+#define CX18_MAX_MDL_ACKS 2
+#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
+/* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */
+
+#define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1
+#define CX18_F_EWO_MB_STALE_WHILE_PROC   0x2
+#define CX18_F_EWO_MB_STALE \
+            (CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC)
+
+struct cx18_in_work_order {
+       struct work_struct work;
+       atomic_t pending;
+       struct cx18 *cx;
+       unsigned long flags;
+       int rpu;
+       struct cx18_mailbox mb;
+       struct cx18_mdl_ack mdl_ack[CX18_MAX_MDL_ACKS];
+       char *str;
+};
+
+#define CX18_INVALID_TASK_HANDLE 0xffffffff
+
+struct cx18_stream {
+       /* These first five fields are always set, even if the stream
+          is not actually created. */
+       struct video_device *video_dev; /* NULL when stream not created */
+       struct cx18_dvb *dvb;           /* DVB / Digital Transport */
+       struct cx18 *cx;                /* for ease of use */
+       const char *name;               /* name of the stream */
+       int type;                       /* stream type */
+       u32 handle;                     /* task handle */
+       unsigned int mdl_base_idx;
+
+       u32 id;
+       unsigned long s_flags;  /* status flags, see above */
+       int dma;                /* can be PCI_DMA_TODEVICE,
+                                  PCI_DMA_FROMDEVICE or
+                                  PCI_DMA_NONE */
+       wait_queue_head_t waitq;
+
+       /* Buffers */
+       struct list_head buf_pool;      /* buffers not attached to an MDL */
+       u32 buffers;                    /* total buffers owned by this stream */
+       u32 buf_size;                   /* size in bytes of a single buffer */
+
+       /* MDL sizes - all stream MDLs are the same size */
+       u32 bufs_per_mdl;
+       u32 mdl_size;           /* total bytes in all buffers in a mdl */
+
+       /* MDL Queues */
+       struct cx18_queue q_free;       /* free - in rotation, not committed */
+       struct cx18_queue q_busy;       /* busy - in use by firmware */
+       struct cx18_queue q_full;       /* full - data for user apps */
+       struct cx18_queue q_idle;       /* idle - not in rotation */
+
+       struct work_struct out_work_order;
+
+       /* Videobuf for YUV video */
+       u32 pixelformat;
+       u32 vb_bytes_per_frame;
+       struct list_head vb_capture;    /* video capture queue */
+       spinlock_t vb_lock;
+       struct timer_list vb_timeout;
+
+       struct videobuf_queue vbuf_q;
+       spinlock_t vbuf_q_lock; /* Protect vbuf_q */
+       enum v4l2_buf_type vb_type;
+};
+
+struct cx18_videobuf_buffer {
+       /* Common video buffer sub-system struct */
+       struct videobuf_buffer vb;
+       v4l2_std_id tvnorm; /* selected tv norm */
+       u32 bytes_used;
+};
+
+struct cx18_open_id {
+       struct v4l2_fh fh;
+       u32 open_id;
+       int type;
+       struct cx18 *cx;
+};
+
+static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
+{
+       return container_of(fh, struct cx18_open_id, fh);
+}
+
+static inline struct cx18_open_id *file2id(struct file *file)
+{
+       return fh2id(file->private_data);
+}
+
+/* forward declaration of struct defined in cx18-cards.h */
+struct cx18_card;
+
+/*
+ * A note about "sliced" VBI data as implemented in this driver:
+ *
+ * Currently we collect the sliced VBI in the form of Ancillary Data
+ * packets, inserted by the AV core decoder/digitizer/slicer in the
+ * horizontal blanking region of the VBI lines, in "raw" mode as far as
+ * the Encoder is concerned.  We don't ever tell the Encoder itself
+ * to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode)
+ *
+ * We then process the ancillary data ourselves to send the sliced data
+ * to the user application directly or build up MPEG-2 private stream 1
+ * packets to splice into (only!) MPEG-2 PS streams for the user app.
+ *
+ * (That's how ivtv essentially does it.)
+ *
+ * The Encoder should be able to extract certain sliced VBI data for
+ * us and provide it in a separate stream or splice it into any type of
+ * MPEG PS or TS stream, but this isn't implemented yet.
+ */
+
+/*
+ * Number of "raw" VBI samples per horizontal line we tell the Encoder to
+ * grab from the decoder/digitizer/slicer output for raw or sliced VBI.
+ * It depends on the pixel clock and the horiz rate:
+ *
+ * (1/Fh)*(2*Fp) = Samples/line
+ *     = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples
+ *
+ *  Sliced VBI data is sent as ancillary data during horizontal blanking
+ *  Raw VBI is sent as active video samples during vertcal blanking
+ *
+ *  We use a  BT.656 pxiel clock of 13.5 MHz and a BT.656 active line
+ *  length of 720 pixels @ 4:2:2 sampling.  Thus...
+ *
+ *  For systems that use a 15.734 kHz horizontal rate, such as
+ *  NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have:
+ *
+ *  (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line =
+ *  4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples
+ *
+ *  For systems that use a 15.625 kHz horizontal rate, such as
+ *  PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have:
+ *
+ *  (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
+ *  4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
+ */
+static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */
+static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */
+static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */
+
+#define CX18_VBI_FRAMES 32
+
+struct vbi_info {
+       /* Current state of v4l2 VBI settings for this device */
+       struct v4l2_format in;
+       struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */
+       u32 count;    /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */
+       u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */
+
+       u32 frame; /* Count of VBI buffers/frames received from Encoder */
+
+       /*
+        * Vars for creation and insertion of MPEG Private Stream 1 packets
+        * of sliced VBI data into an MPEG PS
+        */
+
+       /* Boolean: create and insert Private Stream 1 packets into the PS */
+       int insert_mpeg;
+
+       /*
+        * Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
+        * Used in cx18-vbi.c only for collecting sliced data, and as a source
+        * during conversion of sliced VBI data into MPEG Priv Stream 1 packets.
+        * We don't need to save state here, but the array may have been a bit
+        * too big (2304 bytes) to alloc from the stack.
+        */
+       struct v4l2_sliced_vbi_data sliced_data[36];
+
+       /*
+        * A ring buffer of driver-generated MPEG-2 PS
+        * Program Pack/Private Stream 1 packets for sliced VBI data insertion
+        * into the MPEG PS stream.
+        *
+        * In each sliced_mpeg_data[] buffer is:
+        *      16 byte MPEG-2 PS Program Pack Header
+        *      16 byte MPEG-2 Private Stream 1 PES Header
+        *       4 byte magic number: "itv0" or "ITV0"
+        *       4 byte first  field line mask, if "itv0"
+        *       4 byte second field line mask, if "itv0"
+        *      36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data
+        *
+        *      Each line in the payload is
+        *       1 byte line header derived from the SDID (WSS, CC, VPS, etc.)
+        *      42 bytes of line data
+        *
+        * That's a maximum 1552 bytes of payload in the Private Stream 1 packet
+        * which is the payload size a PVR-350 (CX23415) MPEG decoder will
+        * accept for VBI data. So, including the headers, it's a maximum 1584
+        * bytes total.
+        */
+#define CX18_SLICED_MPEG_DATA_MAXSZ    1584
+       /* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */
+#define CX18_SLICED_MPEG_DATA_BUFSZ    (CX18_SLICED_MPEG_DATA_MAXSZ+8)
+       u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
+       u32 sliced_mpeg_size[CX18_VBI_FRAMES];
+
+       /* Count of Program Pack/Program Stream 1 packets inserted into PS */
+       u32 inserted_frame;
+
+       /*
+        * A dummy driver stream transfer mdl & buffer with a copy of the next
+        * sliced_mpeg_data[] buffer for output to userland apps.
+        * Only used in cx18-fileops.c, but its state needs to persist at times.
+        */
+       struct cx18_mdl sliced_mpeg_mdl;
+       struct cx18_buffer sliced_mpeg_buf;
+};
+
+/* Per cx23418, per I2C bus private algo callback data */
+struct cx18_i2c_algo_callback_data {
+       struct cx18 *cx;
+       int bus_index;   /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
+};
+
+#define CX18_MAX_MMIO_WR_RETRIES 10
+
+/* Struct to hold info about cx18 cards */
+struct cx18 {
+       int instance;
+       struct pci_dev *pci_dev;
+       struct v4l2_device v4l2_dev;
+       struct v4l2_subdev *sd_av;     /* A/V decoder/digitizer sub-device */
+       struct v4l2_subdev *sd_extmux; /* External multiplexer sub-dev */
+
+       const struct cx18_card *card;   /* card information */
+       const char *card_name;  /* full name of the card */
+       const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
+       u8 is_50hz;
+       u8 is_60hz;
+       u8 nof_inputs;          /* number of video inputs */
+       u8 nof_audio_inputs;    /* number of audio inputs */
+       u32 v4l2_cap;           /* V4L2 capabilities of card */
+       u32 hw_flags;           /* Hardware description of the board */
+       unsigned int free_mdl_idx;
+       struct cx18_scb __iomem *scb; /* pointer to SCB */
+       struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/
+       struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/
+
+       struct cx18_av_state av_state;
+
+       /* codec settings */
+       struct cx2341x_handler cxhdl;
+       u32 filter_mode;
+       u32 temporal_strength;
+       u32 spatial_strength;
+
+       /* dualwatch */
+       unsigned long dualwatch_jiffies;
+       u32 dualwatch_stereo_mode;
+
+       struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
+       struct cx18_options options;    /* User options */
+       int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */
+       int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
+       struct cx18_stream streams[CX18_MAX_STREAMS];   /* Stream data */
+       struct snd_cx18_card *alsa; /* ALSA interface for PCM capture stream */
+       void (*pcm_announce_callback)(struct snd_cx18_card *card, u8 *pcm_data,
+                                     size_t num_bytes);
+
+       unsigned long i_flags;  /* global cx18 flags */
+       atomic_t ana_capturing; /* count number of active analog capture streams */
+       atomic_t tot_capturing; /* total count number of active capture streams */
+       int search_pack_header;
+
+       int open_id;            /* incremented each time an open occurs, used as
+                                  unique ID. Starts at 1, so 0 can be used as
+                                  uninitialized value in the stream->id. */
+
+       resource_size_t base_addr;
+
+       u8 card_rev;
+       void __iomem *enc_mem, *reg_mem;
+
+       struct vbi_info vbi;
+
+       u64 mpg_data_received;
+       u64 vbi_data_inserted;
+
+       wait_queue_head_t mb_apu_waitq;
+       wait_queue_head_t mb_cpu_waitq;
+       wait_queue_head_t cap_w;
+       /* when the current DMA is finished this queue is woken up */
+       wait_queue_head_t dma_waitq;
+
+       u32 sw1_irq_mask;
+       u32 sw2_irq_mask;
+       u32 hw2_irq_mask;
+
+       struct workqueue_struct *in_work_queue;
+       char in_workq_name[11]; /* "cx18-NN-in" */
+       struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS];
+       char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
+
+       /* i2c */
+       struct i2c_adapter i2c_adap[2];
+       struct i2c_algo_bit_data i2c_algo[2];
+       struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
+
+       struct IR_i2c_init_data ir_i2c_init_data;
+
+       /* gpio */
+       u32 gpio_dir;
+       u32 gpio_val;
+       struct mutex gpio_lock;
+       struct v4l2_subdev sd_gpiomux;
+       struct v4l2_subdev sd_resetctrl;
+
+       /* v4l2 and User settings */
+
+       /* codec settings */
+       u32 audio_input;
+       u32 active_input;
+       v4l2_std_id std;
+       v4l2_std_id tuner_std;  /* The norm of the tuner (fixed) */
+
+       /* Used for cx18-alsa module loading */
+       struct work_struct request_module_wk;
+};
+
+static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct cx18, v4l2_dev);
+}
+
+/* cx18 extensions to be loaded */
+extern int (*cx18_ext_init)(struct cx18 *);
+
+/* Globals */
+extern int cx18_first_minor;
+
+/*==============Prototypes==================*/
+
+/* Return non-zero if a signal is pending */
+int cx18_msleep_timeout(unsigned int msecs, int intr);
+
+/* Read Hauppauge eeprom */
+struct tveeprom; /* forward reference */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
+
+/* First-open initialization: load firmware, etc. */
+int cx18_init_on_first_open(struct cx18 *cx);
+
+/* Test if the current VBI mode is raw (1) or sliced (0) */
+static inline int cx18_raw_vbi(const struct cx18 *cx)
+{
+       return cx->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
+}
+
+/* Call the specified callback for all subdevs with a grp_id bit matching the
+ * mask in hw (if 0, then match them all). Ignore any errors. */
+#define cx18_call_hw(cx, hw, o, f, args...)                            \
+       do {                                                            \
+               struct v4l2_subdev *__sd;                               \
+               __v4l2_device_call_subdevs_p(&(cx)->v4l2_dev, __sd,     \
+                       !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
+       } while (0)
+
+#define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args)
+
+/* Call the specified callback for all subdevs with a grp_id bit matching the
+ * mask in hw (if 0, then match them all). If the callback returns an error
+ * other than 0 or -ENOIOCTLCMD, then return with that error code. */
+#define cx18_call_hw_err(cx, hw, o, f, args...)                                \
+({                                                                     \
+       struct v4l2_subdev *__sd;                                       \
+       __v4l2_device_call_subdevs_until_err_p(&(cx)->v4l2_dev,         \
+                       __sd, !(hw) || (__sd->grp_id & (hw)), o, f,     \
+                       ##args);                                        \
+})
+
+#define cx18_call_all_err(cx, o, f, args...) \
+       cx18_call_hw_err(cx, 0, o, f , ##args)
+
+#endif /* CX18_DRIVER_H */
diff --git a/drivers/media/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c
new file mode 100644 (file)
index 0000000..3eac59c
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ *  cx18 functions for DVB support
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 "cx18-version.h"
+#include "cx18-dvb.h"
+#include "cx18-io.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "s5h1409.h"
+#include "mxl5005s.h"
+#include "s5h1411.h"
+#include "tda18271.h"
+#include "zl10353.h"
+
+#include <linux/firmware.h>
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "tuner-xc2028.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define FWFILE "dvb-cx18-mpc718-mt352.fw"
+
+#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
+#define CX18_CLOCK_ENABLE2              0xc71024
+#define CX18_DMUX_CLK_MASK              0x0080
+
+/*
+ * CX18_CARD_HVR_1600_ESMT
+ * CX18_CARD_HVR_1600_SAMSUNG
+ */
+
+static struct mxl5005s_config hauppauge_hvr1600_tuner = {
+       .i2c_address     = 0xC6 >> 1,
+       .if_freq         = IF_FREQ_5380000HZ,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_C_H,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .qam_gain        = 0x02,
+       .AgcMasterByte   = 0x00,
+};
+
+static struct s5h1409_config hauppauge_hvr1600_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+       .hvr1600_opt   = S5H1409_HVR1600_OPTIMIZE
+};
+
+/*
+ * CX18_CARD_HVR_1600_S5H1411
+ */
+static struct s5h1411_config hcw_s5h1411_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_44000,
+       .qam_if        = S5H1411_IF_4000,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+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_DIGITAL,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+/*
+ * CX18_CARD_LEADTEK_DVR3100H
+ */
+/* Information/confirmation of proper config values provided by Terry Wu */
+static struct zl10353_config leadtek_dvr3100h_demod = {
+       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+       .parallel_ts           = 1,         /* Not a serial TS */
+       .no_tuner              = 1,         /* XC3028 is not behind the gate */
+       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+/*
+ * CX18_CARD_YUAN_MPC718
+ */
+/*
+ * Due to
+ *
+ * 1. an absence of information on how to prgram the MT352
+ * 2. the Linux mt352 module pushing MT352 initialzation off onto us here
+ *
+ * We have to use an init sequence that *you* must extract from the Windows
+ * driver (yuanrap.sys) and which we load as a firmware.
+ *
+ * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual
+ * with chip programming details, then I can remove this annoyance.
+ */
+static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
+                                  const struct firmware **fw)
+{
+       struct cx18 *cx = stream->cx;
+       const char *fn = FWFILE;
+       int ret;
+
+       ret = request_firmware(fw, fn, &cx->pci_dev->dev);
+       if (ret)
+               CX18_ERR("Unable to open firmware file %s\n", fn);
+       else {
+               size_t sz = (*fw)->size;
+               if (sz < 2 || sz > 64 || (sz % 2) != 0) {
+                       CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
+                                fn, (unsigned long) sz);
+                       ret = -EILSEQ;
+                       release_firmware(*fw);
+                       *fw = NULL;
+               }
+       }
+
+       if (ret) {
+               CX18_ERR("The MPC718 board variant with the MT352 DVB-T"
+                         "demodualtor will not work without it\n");
+               CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware "
+                         "mpc718' if you need the firmware\n");
+       }
+       return ret;
+}
+
+static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
+{
+       struct cx18_dvb *dvb = container_of(fe->dvb,
+                                           struct cx18_dvb, dvb_adapter);
+       struct cx18_stream *stream = dvb->stream;
+       const struct firmware *fw = NULL;
+       int ret;
+       int i;
+       u8 buf[3];
+
+       ret = yuan_mpc718_mt352_reqfw(stream, &fw);
+       if (ret)
+               return ret;
+
+       /* Loop through all the register-value pairs in the firmware file */
+       for (i = 0; i < fw->size; i += 2) {
+               buf[0] = fw->data[i];
+               /* Intercept a few registers we want to set ourselves */
+               switch (buf[0]) {
+               case TRL_NOMINAL_RATE_0:
+                       /* Set our custom OFDM bandwidth in the case below */
+                       break;
+               case TRL_NOMINAL_RATE_1:
+                       /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
+                       /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
+                       /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
+                       buf[1] = 0x72;
+                       buf[2] = 0x49;
+                       mt352_write(fe, buf, 3);
+                       break;
+               case INPUT_FREQ_0:
+                       /* Set our custom IF in the case below */
+                       break;
+               case INPUT_FREQ_1:
+                       /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
+                       buf[1] = 0x31;
+                       buf[2] = 0xc0;
+                       mt352_write(fe, buf, 3);
+                       break;
+               default:
+                       /* Pass through the register-value pair from the fw */
+                       buf[1] = fw->data[i+1];
+                       mt352_write(fe, buf, 2);
+                       break;
+               }
+       }
+
+       buf[0] = (u8) TUNER_GO;
+       buf[1] = 0x01; /* Go */
+       mt352_write(fe, buf, 2);
+       release_firmware(fw);
+       return 0;
+}
+
+static struct mt352_config yuan_mpc718_mt352_demod = {
+       .demod_address = 0x1e >> 1,
+       .adc_clock     = 20480,     /* 20.480 MHz */
+       .if2           =  4560,     /*  4.560 MHz */
+       .no_tuner      = 1,         /* XC3028 is not behind the gate */
+       .demod_init    = yuan_mpc718_mt352_init,
+};
+
+static struct zl10353_config yuan_mpc718_zl10353_demod = {
+       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+       .parallel_ts           = 1,         /* Not a serial TS */
+       .no_tuner              = 1,         /* XC3028 is not behind the gate */
+       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+static struct zl10353_config gotview_dvd3_zl10353_demod = {
+       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+       .parallel_ts           = 1,         /* Not a serial TS */
+       .no_tuner              = 1,         /* XC3028 is not behind the gate */
+       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+static int dvb_register(struct cx18_stream *stream);
+
+/* Kernel DVB framework calls this when the feed needs to start.
+ * The CX18 framework should enable the transport DMA handling
+ * and queue processing.
+ */
+static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
+       struct cx18 *cx;
+       int ret;
+       u32 v;
+
+       if (!stream)
+               return -EINVAL;
+
+       cx = stream->cx;
+       CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
+                       feed->pid, feed->index);
+
+       mutex_lock(&cx->serialize_lock);
+       ret = cx18_init_on_first_open(cx);
+       mutex_unlock(&cx->serialize_lock);
+       if (ret) {
+               CX18_ERR("Failed to initialize firmware starting DVB feed\n");
+               return ret;
+       }
+       ret = -EINVAL;
+
+       switch (cx->card->type) {
+       case CX18_CARD_HVR_1600_ESMT:
+       case CX18_CARD_HVR_1600_SAMSUNG:
+       case CX18_CARD_HVR_1600_S5H1411:
+               v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+               v |= 0x00400000; /* Serial Mode */
+               v |= 0x00002000; /* Data Length - Byte */
+               v |= 0x00010000; /* Error - Polarity */
+               v |= 0x00020000; /* Error - Passthru */
+               v |= 0x000c0000; /* Error - Ignore */
+               cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+               break;
+
+       case CX18_CARD_LEADTEK_DVR3100H:
+       case CX18_CARD_YUAN_MPC718:
+       case CX18_CARD_GOTVIEW_PCI_DVD3:
+       default:
+               /* Assumption - Parallel transport - Signalling
+                * undefined or default.
+                */
+               break;
+       }
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       mutex_lock(&stream->dvb->feedlock);
+       if (stream->dvb->feeding++ == 0) {
+               CX18_DEBUG_INFO("Starting Transport DMA\n");
+               mutex_lock(&cx->serialize_lock);
+               set_bit(CX18_F_S_STREAMING, &stream->s_flags);
+               ret = cx18_start_v4l2_encode_stream(stream);
+               if (ret < 0) {
+                       CX18_DEBUG_INFO("Failed to start Transport DMA\n");
+                       stream->dvb->feeding--;
+                       if (stream->dvb->feeding == 0)
+                               clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
+               }
+               mutex_unlock(&cx->serialize_lock);
+       } else
+               ret = 0;
+       mutex_unlock(&stream->dvb->feedlock);
+
+       return ret;
+}
+
+/* Kernel DVB framework calls this when the feed needs to stop. */
+static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
+       struct cx18 *cx;
+       int ret = -EINVAL;
+
+       if (stream) {
+               cx = stream->cx;
+               CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
+                               feed->pid, feed->index);
+
+               mutex_lock(&stream->dvb->feedlock);
+               if (--stream->dvb->feeding == 0) {
+                       CX18_DEBUG_INFO("Stopping Transport DMA\n");
+                       mutex_lock(&cx->serialize_lock);
+                       ret = cx18_stop_v4l2_encode_stream(stream, 0);
+                       mutex_unlock(&cx->serialize_lock);
+               } else
+                       ret = 0;
+               mutex_unlock(&stream->dvb->feedlock);
+       }
+
+       return ret;
+}
+
+int cx18_dvb_register(struct cx18_stream *stream)
+{
+       struct cx18 *cx = stream->cx;
+       struct cx18_dvb *dvb = stream->dvb;
+       struct dvb_adapter *dvb_adapter;
+       struct dvb_demux *dvbdemux;
+       struct dmx_demux *dmx;
+       int ret;
+
+       if (!dvb)
+               return -EINVAL;
+
+       dvb->enabled = 0;
+       dvb->stream = stream;
+
+       ret = dvb_register_adapter(&dvb->dvb_adapter,
+                       CX18_DRIVER_NAME,
+                       THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
+       if (ret < 0)
+               goto err_out;
+
+       dvb_adapter = &dvb->dvb_adapter;
+
+       dvbdemux = &dvb->demux;
+
+       dvbdemux->priv = (void *)stream;
+
+       dvbdemux->filternum = 256;
+       dvbdemux->feednum = 256;
+       dvbdemux->start_feed = cx18_dvb_start_feed;
+       dvbdemux->stop_feed = cx18_dvb_stop_feed;
+       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+               DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+       ret = dvb_dmx_init(dvbdemux);
+       if (ret < 0)
+               goto err_dvb_unregister_adapter;
+
+       dmx = &dvbdemux->dmx;
+
+       dvb->hw_frontend.source = DMX_FRONTEND_0;
+       dvb->mem_frontend.source = DMX_MEMORY_FE;
+       dvb->dmxdev.filternum = 256;
+       dvb->dmxdev.demux = dmx;
+
+       ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
+       if (ret < 0)
+               goto err_dvb_dmx_release;
+
+       ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
+       if (ret < 0)
+               goto err_dvb_dmxdev_release;
+
+       ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
+       if (ret < 0)
+               goto err_remove_hw_frontend;
+
+       ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
+       if (ret < 0)
+               goto err_remove_mem_frontend;
+
+       ret = dvb_register(stream);
+       if (ret < 0)
+               goto err_disconnect_frontend;
+
+       dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
+
+       CX18_INFO("DVB Frontend registered\n");
+       CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
+                 stream->dvb->dvb_adapter.num, stream->name,
+                 stream->buffers, stream->buf_size/1024,
+                 (stream->buf_size * 100 / 1024) % 100);
+
+       mutex_init(&dvb->feedlock);
+       dvb->enabled = 1;
+       return ret;
+
+err_disconnect_frontend:
+       dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+       dmx->remove_frontend(dmx, &dvb->mem_frontend);
+err_remove_hw_frontend:
+       dmx->remove_frontend(dmx, &dvb->hw_frontend);
+err_dvb_dmxdev_release:
+       dvb_dmxdev_release(&dvb->dmxdev);
+err_dvb_dmx_release:
+       dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+       dvb_unregister_adapter(dvb_adapter);
+err_out:
+       return ret;
+}
+
+void cx18_dvb_unregister(struct cx18_stream *stream)
+{
+       struct cx18 *cx = stream->cx;
+       struct cx18_dvb *dvb = stream->dvb;
+       struct dvb_adapter *dvb_adapter;
+       struct dvb_demux *dvbdemux;
+       struct dmx_demux *dmx;
+
+       CX18_INFO("unregister DVB\n");
+
+       if (dvb == NULL || !dvb->enabled)
+               return;
+
+       dvb_adapter = &dvb->dvb_adapter;
+       dvbdemux = &dvb->demux;
+       dmx = &dvbdemux->dmx;
+
+       dmx->close(dmx);
+       dvb_net_release(&dvb->dvbnet);
+       dmx->remove_frontend(dmx, &dvb->mem_frontend);
+       dmx->remove_frontend(dmx, &dvb->hw_frontend);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(dvbdemux);
+       dvb_unregister_frontend(dvb->fe);
+       dvb_frontend_detach(dvb->fe);
+       dvb_unregister_adapter(dvb_adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. cx18_dvb_start_feed() will also need changes.
+ */
+static int dvb_register(struct cx18_stream *stream)
+{
+       struct cx18_dvb *dvb = stream->dvb;
+       struct cx18 *cx = stream->cx;
+       int ret = 0;
+
+       switch (cx->card->type) {
+       case CX18_CARD_HVR_1600_ESMT:
+       case CX18_CARD_HVR_1600_SAMSUNG:
+               dvb->fe = dvb_attach(s5h1409_attach,
+                       &hauppauge_hvr1600_config,
+                       &cx->i2c_adap[0]);
+               if (dvb->fe != NULL) {
+                       dvb_attach(mxl5005s_attach, dvb->fe,
+                               &cx->i2c_adap[0],
+                               &hauppauge_hvr1600_tuner);
+                       ret = 0;
+               }
+               break;
+       case CX18_CARD_HVR_1600_S5H1411:
+               dvb->fe = dvb_attach(s5h1411_attach,
+                                    &hcw_s5h1411_config,
+                                    &cx->i2c_adap[0]);
+               if (dvb->fe != NULL)
+                       dvb_attach(tda18271_attach, dvb->fe,
+                                  0x60, &cx->i2c_adap[0],
+                                  &hauppauge_tda18271_config);
+               break;
+       case CX18_CARD_LEADTEK_DVR3100H:
+               dvb->fe = dvb_attach(zl10353_attach,
+                                    &leadtek_dvr3100h_demod,
+                                    &cx->i2c_adap[1]);
+               if (dvb->fe != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &cx->i2c_adap[1],
+                               .i2c_addr = 0xc2 >> 1,
+                               .ctrl = NULL,
+                       };
+                       static struct xc2028_ctrl ctrl = {
+                               .fname   = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                               .demod   = XC3028_FE_ZARLINK456,
+                               .type    = XC2028_AUTO,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctrl);
+               }
+               break;
+       case CX18_CARD_YUAN_MPC718:
+               /*
+                * TODO
+                * Apparently, these cards also could instead have a
+                * DiBcom demod supported by one of the db7000 drivers
+                */
+               dvb->fe = dvb_attach(mt352_attach,
+                                    &yuan_mpc718_mt352_demod,
+                                    &cx->i2c_adap[1]);
+               if (dvb->fe == NULL)
+                       dvb->fe = dvb_attach(zl10353_attach,
+                                            &yuan_mpc718_zl10353_demod,
+                                            &cx->i2c_adap[1]);
+               if (dvb->fe != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &cx->i2c_adap[1],
+                               .i2c_addr = 0xc2 >> 1,
+                               .ctrl = NULL,
+                       };
+                       static struct xc2028_ctrl ctrl = {
+                               .fname   = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                               .demod   = XC3028_FE_ZARLINK456,
+                               .type    = XC2028_AUTO,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctrl);
+               }
+               break;
+       case CX18_CARD_GOTVIEW_PCI_DVD3:
+                       dvb->fe = dvb_attach(zl10353_attach,
+                                            &gotview_dvd3_zl10353_demod,
+                                            &cx->i2c_adap[1]);
+               if (dvb->fe != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &cx->i2c_adap[1],
+                               .i2c_addr = 0xc2 >> 1,
+                               .ctrl = NULL,
+                       };
+                       static struct xc2028_ctrl ctrl = {
+                               .fname   = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                               .demod   = XC3028_FE_ZARLINK456,
+                               .type    = XC2028_AUTO,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctrl);
+               }
+               break;
+       default:
+               /* No Digital Tv Support */
+               break;
+       }
+
+       if (dvb->fe == NULL) {
+               CX18_ERR("frontend initialization failed\n");
+               return -1;
+       }
+
+       dvb->fe->callback = cx18_reset_tuner_gpio;
+
+       ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
+       if (ret < 0) {
+               if (dvb->fe->ops.release)
+                       dvb->fe->ops.release(dvb->fe);
+               return ret;
+       }
+
+       /*
+        * The firmware seems to enable the TS DMUX clock
+        * under various circumstances.  However, since we know we
+        * might use it, let's just turn it on ourselves here.
+        */
+       cx18_write_reg_expect(cx,
+                             (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK,
+                             CX18_CLOCK_ENABLE2,
+                             CX18_DMUX_CLK_MASK,
+                             (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK);
+
+       return ret;
+}
+
+MODULE_FIRMWARE(FWFILE);
diff --git a/drivers/media/pci/cx18/cx18-dvb.h b/drivers/media/pci/cx18/cx18-dvb.h
new file mode 100644 (file)
index 0000000..bf8d8f6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  cx18 functions for DVB support
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@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 "cx18-driver.h"
+
+int cx18_dvb_register(struct cx18_stream *stream);
+void cx18_dvb_unregister(struct cx18_stream *stream);
diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c
new file mode 100644 (file)
index 0000000..4bfd865
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ *  cx18 file operation functions
+ *
+ *  Derived from ivtv-fileops.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-fileops.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-mailbox.h"
+#include "cx18-scb.h"
+#include "cx18-streams.h"
+#include "cx18-controls.h"
+#include "cx18-ioctl.h"
+#include "cx18-cards.h"
+
+/* This function tries to claim the stream for a specific file descriptor.
+   If no one else is using this stream then the stream is claimed and
+   associated VBI and IDX streams are also automatically claimed.
+   Possible error returns: -EBUSY if someone else has claimed
+   the stream or 0 on success. */
+int cx18_claim_stream(struct cx18_open_id *id, int type)
+{
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[type];
+       struct cx18_stream *s_assoc;
+
+       /* Nothing should ever try to directly claim the IDX stream */
+       if (type == CX18_ENC_STREAM_TYPE_IDX) {
+               CX18_WARN("MPEG Index stream cannot be claimed "
+                         "directly, but something tried.\n");
+               return -EINVAL;
+       }
+
+       if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+               /* someone already claimed this stream */
+               if (s->id == id->open_id) {
+                       /* yes, this file descriptor did. So that's OK. */
+                       return 0;
+               }
+               if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
+                       /* VBI is handled already internally, now also assign
+                          the file descriptor to this stream for external
+                          reading of the stream. */
+                       s->id = id->open_id;
+                       CX18_DEBUG_INFO("Start Read VBI\n");
+                       return 0;
+               }
+               /* someone else is using this stream already */
+               CX18_DEBUG_INFO("Stream %d is busy\n", type);
+               return -EBUSY;
+       }
+       s->id = id->open_id;
+
+       /*
+        * CX18_ENC_STREAM_TYPE_MPG needs to claim:
+        * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
+        * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
+        * (We don't yet fix up MPEG Index entries for our inserted packets).
+        *
+        * For all other streams we're done.
+        */
+       if (type != CX18_ENC_STREAM_TYPE_MPG)
+               return 0;
+
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
+               s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       else if (!cx18_stream_enabled(s_assoc))
+               return 0;
+
+       set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+
+       /* mark that it is used internally */
+       set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
+       return 0;
+}
+EXPORT_SYMBOL(cx18_claim_stream);
+
+/* This function releases a previously claimed stream. It will take into
+   account associated VBI streams. */
+void cx18_release_stream(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_stream *s_assoc;
+
+       s->id = -1;
+       if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
+               /*
+                * The IDX stream is only used internally, and can
+                * only be indirectly unclaimed by unclaiming the MPG stream.
+                */
+               return;
+       }
+
+       if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
+               test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
+               /* this stream is still in use internally */
+               return;
+       }
+       if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+               CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
+               return;
+       }
+
+       cx18_flush_queues(s);
+
+       /*
+        * CX18_ENC_STREAM_TYPE_MPG needs to release the
+        * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
+        *
+        * For all other streams we're done.
+        */
+       if (s->type != CX18_ENC_STREAM_TYPE_MPG)
+               return;
+
+       /* Unclaim the associated MPEG Index stream */
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+               clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+               cx18_flush_queues(s_assoc);
+       }
+
+       /* Unclaim the associated VBI stream */
+       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+               if (s_assoc->id == -1) {
+                       /*
+                        * The VBI stream is not still claimed by a file
+                        * descriptor, so completely unclaim it.
+                        */
+                       clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+                       cx18_flush_queues(s_assoc);
+               }
+       }
+}
+EXPORT_SYMBOL(cx18_release_stream);
+
+static void cx18_dualwatch(struct cx18 *cx)
+{
+       struct v4l2_tuner vt;
+       u32 new_stereo_mode;
+       const u32 dual = 0x0200;
+
+       new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
+       memset(&vt, 0, sizeof(vt));
+       cx18_call_all(cx, tuner, g_tuner, &vt);
+       if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
+                       (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
+               new_stereo_mode = dual;
+
+       if (new_stereo_mode == cx->dualwatch_stereo_mode)
+               return;
+
+       CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
+                          cx->dualwatch_stereo_mode, new_stereo_mode);
+       if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
+               CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+}
+
+
+static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
+                                    int *err)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       struct cx18_mdl *mdl;
+       DEFINE_WAIT(wait);
+
+       *err = 0;
+       while (1) {
+               if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+                       /* Process pending program updates and VBI data */
+                       if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
+                               cx->dualwatch_jiffies = jiffies;
+                               cx18_dualwatch(cx);
+                       }
+                       if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                               while ((mdl = cx18_dequeue(s_vbi,
+                                                          &s_vbi->q_full))) {
+                                       /* byteswap and process VBI data */
+                                       cx18_process_vbi_data(cx, mdl,
+                                                             s_vbi->type);
+                                       cx18_stream_put_mdl_fw(s_vbi, mdl);
+                               }
+                       }
+                       mdl = &cx->vbi.sliced_mpeg_mdl;
+                       if (mdl->readpos != mdl->bytesused)
+                               return mdl;
+               }
+
+               /* do we have new data? */
+               mdl = cx18_dequeue(s, &s->q_full);
+               if (mdl) {
+                       if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
+                                               &mdl->m_flags))
+                               return mdl;
+                       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+                               /* byteswap MPG data */
+                               cx18_mdl_swap(mdl);
+                       else {
+                               /* byteswap and process VBI data */
+                               cx18_process_vbi_data(cx, mdl, s->type);
+                       }
+                       return mdl;
+               }
+
+               /* return if end of stream */
+               if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+                       CX18_DEBUG_INFO("EOS %s\n", s->name);
+                       return NULL;
+               }
+
+               /* return if file was opened with O_NONBLOCK */
+               if (non_block) {
+                       *err = -EAGAIN;
+                       return NULL;
+               }
+
+               /* wait for more data to arrive */
+               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+               /* New buffers might have become available before we were added
+                  to the waitqueue */
+               if (!atomic_read(&s->q_full.depth))
+                       schedule();
+               finish_wait(&s->waitq, &wait);
+               if (signal_pending(current)) {
+                       /* return if a signal was received */
+                       CX18_DEBUG_INFO("User stopped %s\n", s->name);
+                       *err = -EINTR;
+                       return NULL;
+               }
+       }
+}
+
+static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
+{
+       struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
+       struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
+       int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+       buf->buf = cx->vbi.sliced_mpeg_data[idx];
+       buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
+       buf->readpos = 0;
+
+       mdl->curr_buf = NULL;
+       mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
+       mdl->readpos = 0;
+}
+
+static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
+       struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
+{
+       struct cx18 *cx = s->cx;
+       size_t len = buf->bytesused - buf->readpos;
+
+       *stop = false;
+       if (len > ucount)
+               len = ucount;
+       if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
+           !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
+               /*
+                * Try to find a good splice point in the PS, just before
+                * an MPEG-2 Program Pack start code, and provide only
+                * up to that point to the user, so it's easy to insert VBI data
+                * the next time around.
+                *
+                * This will not work for an MPEG-2 TS and has only been
+                * verified by analysis to work for an MPEG-2 PS.  Helen Buus
+                * pointed out this works for the CX23416 MPEG-2 DVD compatible
+                * stream, and research indicates both the MPEG 2 SVCD and DVD
+                * stream types use an MPEG-2 PS container.
+                */
+               /*
+                * An MPEG-2 Program Stream (PS) is a series of
+                * MPEG-2 Program Packs terminated by an
+                * MPEG Program End Code after the last Program Pack.
+                * A Program Pack may hold a PS System Header packet and any
+                * number of Program Elementary Stream (PES) Packets
+                */
+               const char *start = buf->buf + buf->readpos;
+               const char *p = start + 1;
+               const u8 *q;
+               u8 ch = cx->search_pack_header ? 0xba : 0xe0;
+               int stuffing, i;
+
+               while (start + len > p) {
+                       /* Scan for a 0 to find a potential MPEG-2 start code */
+                       q = memchr(p, 0, start + len - p);
+                       if (q == NULL)
+                               break;
+                       p = q + 1;
+                       /*
+                        * Keep looking if not a
+                        * MPEG-2 Pack header start code:  0x00 0x00 0x01 0xba
+                        * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
+                        */
+                       if ((char *)q + 15 >= buf->buf + buf->bytesused ||
+                           q[1] != 0 || q[2] != 1 || q[3] != ch)
+                               continue;
+
+                       /* If expecting the primary video PES */
+                       if (!cx->search_pack_header) {
+                               /* Continue if it couldn't be a PES packet */
+                               if ((q[6] & 0xc0) != 0x80)
+                                       continue;
+                               /* Check if a PTS or PTS & DTS follow */
+                               if (((q[7] & 0xc0) == 0x80 &&  /* PTS only */
+                                    (q[9] & 0xf0) == 0x20) || /* PTS only */
+                                   ((q[7] & 0xc0) == 0xc0 &&  /* PTS & DTS */
+                                    (q[9] & 0xf0) == 0x30)) { /* DTS follows */
+                                       /* Assume we found the video PES hdr */
+                                       ch = 0xba; /* next want a Program Pack*/
+                                       cx->search_pack_header = 1;
+                                       p = q + 9; /* Skip this video PES hdr */
+                               }
+                               continue;
+                       }
+
+                       /* We may have found a Program Pack start code */
+
+                       /* Get the count of stuffing bytes & verify them */
+                       stuffing = q[13] & 7;
+                       /* all stuffing bytes must be 0xff */
+                       for (i = 0; i < stuffing; i++)
+                               if (q[14 + i] != 0xff)
+                                       break;
+                       if (i == stuffing && /* right number of stuffing bytes*/
+                           (q[4] & 0xc4) == 0x44 && /* marker check */
+                           (q[12] & 3) == 3 &&  /* marker check */
+                           q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
+                           q[15 + stuffing] == 0 &&
+                           q[16 + stuffing] == 1) {
+                               /* We declare we actually found a Program Pack*/
+                               cx->search_pack_header = 0; /* expect vid PES */
+                               len = (char *)q - start;
+                               cx18_setup_sliced_vbi_mdl(cx);
+                               *stop = true;
+                               break;
+                       }
+               }
+       }
+       if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
+               CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
+                               len, s->name);
+               return -EFAULT;
+       }
+       buf->readpos += len;
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+           buf != &cx->vbi.sliced_mpeg_buf)
+               cx->mpg_data_received += len;
+       return len;
+}
+
+static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
+               struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
+{
+       size_t tot_written = 0;
+       int rc;
+       bool stop = false;
+
+       if (mdl->curr_buf == NULL)
+               mdl->curr_buf = list_first_entry(&mdl->buf_list,
+                                                struct cx18_buffer, list);
+
+       if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
+               /*
+                * For some reason we've exhausted the buffers, but the MDL
+                * object still said some data was unread.
+                * Fix that and bail out.
+                */
+               mdl->readpos = mdl->bytesused;
+               return 0;
+       }
+
+       list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
+
+               if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
+                       continue;
+
+               rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
+                                          ucount - tot_written, &stop);
+               if (rc < 0)
+                       return rc;
+               mdl->readpos += rc;
+               tot_written += rc;
+
+               if (stop ||     /* Forced stopping point for VBI insertion */
+                   tot_written >= ucount ||    /* Reader request statisfied */
+                   mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
+                   mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
+                       break;
+       }
+       return tot_written;
+}
+
+static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
+               size_t tot_count, int non_block)
+{
+       struct cx18 *cx = s->cx;
+       size_t tot_written = 0;
+       int single_frame = 0;
+
+       if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
+               /* shouldn't happen */
+               CX18_DEBUG_WARN("Stream %s not initialized before read\n",
+                               s->name);
+               return -EIO;
+       }
+
+       /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
+          frames should arrive one-by-one, so make sure we never output more
+          than one VBI frame at a time */
+       if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
+               single_frame = 1;
+
+       for (;;) {
+               struct cx18_mdl *mdl;
+               int rc;
+
+               mdl = cx18_get_mdl(s, non_block, &rc);
+               /* if there is no data available... */
+               if (mdl == NULL) {
+                       /* if we got data, then return that regardless */
+                       if (tot_written)
+                               break;
+                       /* EOS condition */
+                       if (rc == 0) {
+                               clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+                               clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+                               cx18_release_stream(s);
+                       }
+                       /* set errno */
+                       return rc;
+               }
+
+               rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
+                               tot_count - tot_written);
+
+               if (mdl != &cx->vbi.sliced_mpeg_mdl) {
+                       if (mdl->readpos == mdl->bytesused)
+                               cx18_stream_put_mdl_fw(s, mdl);
+                       else
+                               cx18_push(s, mdl, &s->q_full);
+               } else if (mdl->readpos == mdl->bytesused) {
+                       int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+                       cx->vbi.sliced_mpeg_size[idx] = 0;
+                       cx->vbi.inserted_frame++;
+                       cx->vbi_data_inserted += mdl->bytesused;
+               }
+               if (rc < 0)
+                       return rc;
+               tot_written += rc;
+
+               if (tot_written == tot_count || single_frame)
+                       break;
+       }
+       return tot_written;
+}
+
+static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
+               size_t count, loff_t *pos, int non_block)
+{
+       ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
+       struct cx18 *cx = s->cx;
+
+       CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
+       if (rc > 0)
+               pos += rc;
+       return rc;
+}
+
+int cx18_start_capture(struct cx18_open_id *id)
+{
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       struct cx18_stream *s_vbi;
+       struct cx18_stream *s_idx;
+
+       if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
+               /* you cannot read from these stream types. */
+               return -EPERM;
+       }
+
+       /* Try to claim this stream. */
+       if (cx18_claim_stream(id, s->type))
+               return -EBUSY;
+
+       /* If capture is already in progress, then we also have to
+          do nothing extra. */
+       if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
+           test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+               return 0;
+       }
+
+       /* Start associated VBI or IDX stream capture if required */
+       s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+               /*
+                * The VBI and IDX streams should have been claimed
+                * automatically, if for internal use, when the MPG stream was
+                * claimed.  We only need to start these streams capturing.
+                */
+               if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
+                   !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                       if (cx18_start_v4l2_encode_stream(s_idx)) {
+                               CX18_DEBUG_WARN("IDX capture start failed\n");
+                               clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+                               goto start_failed;
+                       }
+                       CX18_DEBUG_INFO("IDX capture started\n");
+               }
+               if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+                   !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+                       if (cx18_start_v4l2_encode_stream(s_vbi)) {
+                               CX18_DEBUG_WARN("VBI capture start failed\n");
+                               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+                               goto start_failed;
+                       }
+                       CX18_DEBUG_INFO("VBI insertion started\n");
+               }
+       }
+
+       /* Tell the card to start capturing */
+       if (!cx18_start_v4l2_encode_stream(s)) {
+               /* We're done */
+               set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+               /* Resume a possibly paused encoder */
+               if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
+               return 0;
+       }
+
+start_failed:
+       CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
+
+       /*
+        * The associated VBI and IDX streams for internal use are released
+        * automatically when the MPG stream is released.  We only need to stop
+        * the associated stream.
+        */
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+               /* Stop the IDX stream which is always for internal use */
+               if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                       cx18_stop_v4l2_encode_stream(s_idx, 0);
+                       clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+               }
+               /* Stop the VBI stream, if only running for internal use */
+               if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
+                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+               }
+       }
+       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+       cx18_release_stream(s); /* Also releases associated streams */
+       return -EIO;
+}
+
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+               loff_t *pos)
+{
+       struct cx18_open_id *id = file2id(filp);
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       int rc;
+
+       CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+
+       mutex_lock(&cx->serialize_lock);
+       rc = cx18_start_capture(id);
+       mutex_unlock(&cx->serialize_lock);
+       if (rc)
+               return rc;
+
+       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
+               return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
+                       filp->f_flags & O_NONBLOCK);
+       }
+
+       return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+}
+
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
+{
+       struct cx18_open_id *id = file2id(filp);
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+       /* Start a capture if there is none */
+       if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               int rc;
+
+               mutex_lock(&cx->serialize_lock);
+               rc = cx18_start_capture(id);
+               mutex_unlock(&cx->serialize_lock);
+               if (rc) {
+                       CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
+                                       s->name, rc);
+                       return POLLERR;
+               }
+               CX18_DEBUG_FILE("Encoder poll started capture\n");
+       }
+
+       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
+               int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
+                if (eof && videobuf_poll == POLLERR)
+                        return POLLHUP;
+                else
+                        return videobuf_poll;
+       }
+
+       /* add stream's waitq to the poll list */
+       CX18_DEBUG_HI_FILE("Encoder poll\n");
+       poll_wait(filp, &s->waitq, wait);
+
+       if (atomic_read(&s->q_full.depth))
+               return POLLIN | POLLRDNORM;
+       if (eof)
+               return POLLHUP;
+       return 0;
+}
+
+int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
+
+               /* Start a capture if there is none */
+               if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+                       int rc;
+
+                       mutex_lock(&cx->serialize_lock);
+                       rc = cx18_start_capture(id);
+                       mutex_unlock(&cx->serialize_lock);
+                       if (rc) {
+                               CX18_DEBUG_INFO(
+                                       "Could not start capture for %s (%d)\n",
+                                       s->name, rc);
+                               return -EINVAL;
+                       }
+                       CX18_DEBUG_FILE("Encoder mmap started capture\n");
+               }
+
+               return videobuf_mmap_mapper(&s->vbuf_q, vma);
+       }
+
+       return -EINVAL;
+}
+
+void cx18_vb_timeout(unsigned long data)
+{
+       struct cx18_stream *s = (struct cx18_stream *)data;
+       struct cx18_videobuf_buffer *buf;
+       unsigned long flags;
+
+       /* Return all of the buffers in error state, so the vbi/vid inode
+        * can return from blocking.
+        */
+       spin_lock_irqsave(&s->vb_lock, flags);
+       while (!list_empty(&s->vb_capture)) {
+               buf = list_entry(s->vb_capture.next,
+                       struct cx18_videobuf_buffer, vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+       }
+       spin_unlock_irqrestore(&s->vb_lock, flags);
+}
+
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
+{
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+       struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+
+       CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+       /* 'Unclaim' this stream */
+
+       /* Stop capturing */
+       if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+               CX18_DEBUG_INFO("close stopping capture\n");
+               if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
+                       /* Stop internal use associated VBI and IDX streams */
+                       if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+                               CX18_DEBUG_INFO("close stopping embedded VBI "
+                                               "capture\n");
+                               cx18_stop_v4l2_encode_stream(s_vbi, 0);
+                       }
+                       if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+                               CX18_DEBUG_INFO("close stopping IDX capture\n");
+                               cx18_stop_v4l2_encode_stream(s_idx, 0);
+                       }
+               }
+               if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
+                   test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
+                       /* Also used internally, don't stop capturing */
+                       s->id = -1;
+               else
+                       cx18_stop_v4l2_encode_stream(s, gop_end);
+       }
+       if (!gop_end) {
+               clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+               clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+               cx18_release_stream(s);
+       }
+}
+
+int cx18_v4l2_close(struct file *filp)
+{
+       struct v4l2_fh *fh = filp->private_data;
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+       mutex_lock(&cx->serialize_lock);
+       /* Stop radio */
+       if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
+               /* Closing radio device, return to TV mode */
+               cx18_mute(cx);
+               /* Mark that the radio is no longer in use */
+               clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+               /* Switch tuner to TV */
+               cx18_call_all(cx, core, s_std, cx->std);
+               /* Select correct audio input (i.e. TV tuner or Line in) */
+               cx18_audio_set_io(cx);
+               if (atomic_read(&cx->ana_capturing) > 0) {
+                       /* Undo video mute */
+                       cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+                           (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
+                           (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
+               }
+               /* Done! Unmute and continue. */
+               cx18_unmute(cx);
+       }
+
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
+
+       /* 'Unclaim' this stream */
+       if (s->id == id->open_id)
+               cx18_stop_capture(id, 0);
+       kfree(id);
+       mutex_unlock(&cx->serialize_lock);
+       return 0;
+}
+
+static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_open_id *item;
+
+       CX18_DEBUG_FILE("open %s\n", s->name);
+
+       /* Allocate memory */
+       item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
+       if (NULL == item) {
+               CX18_DEBUG_WARN("nomem on v4l2 open\n");
+               return -ENOMEM;
+       }
+       v4l2_fh_init(&item->fh, s->video_dev);
+
+       item->cx = cx;
+       item->type = s->type;
+
+       item->open_id = cx->open_id++;
+       filp->private_data = &item->fh;
+       v4l2_fh_add(&item->fh);
+
+       if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
+               if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+                       if (atomic_read(&cx->ana_capturing) > 0) {
+                               /* switching to radio while capture is
+                                  in progress is not polite */
+                               v4l2_fh_del(&item->fh);
+                               v4l2_fh_exit(&item->fh);
+                               kfree(item);
+                               return -EBUSY;
+                       }
+               }
+
+               /* Mark that the radio is being used. */
+               set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+               /* We have the radio */
+               cx18_mute(cx);
+               /* Switch tuner to radio */
+               cx18_call_all(cx, tuner, s_radio);
+               /* Select the correct audio input (i.e. radio tuner) */
+               cx18_audio_set_io(cx);
+               /* Done! Unmute and continue. */
+               cx18_unmute(cx);
+       }
+       return 0;
+}
+
+int cx18_v4l2_open(struct file *filp)
+{
+       int res;
+       struct video_device *video_dev = video_devdata(filp);
+       struct cx18_stream *s = video_get_drvdata(video_dev);
+       struct cx18 *cx = s->cx;
+
+       mutex_lock(&cx->serialize_lock);
+       if (cx18_init_on_first_open(cx)) {
+               CX18_ERR("Failed to initialize on %s\n",
+                        video_device_node_name(video_dev));
+               mutex_unlock(&cx->serialize_lock);
+               return -ENXIO;
+       }
+       res = cx18_serialized_open(s, filp);
+       mutex_unlock(&cx->serialize_lock);
+       return res;
+}
+
+void cx18_mute(struct cx18 *cx)
+{
+       u32 h;
+       if (atomic_read(&cx->ana_capturing)) {
+               h = cx18_find_handle(cx);
+               if (h != CX18_INVALID_TASK_HANDLE)
+                       cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
+               else
+                       CX18_ERR("Can't find valid task handle for mute\n");
+       }
+       CX18_DEBUG_INFO("Mute\n");
+}
+
+void cx18_unmute(struct cx18 *cx)
+{
+       u32 h;
+       if (atomic_read(&cx->ana_capturing)) {
+               h = cx18_find_handle(cx);
+               if (h != CX18_INVALID_TASK_HANDLE) {
+                       cx18_msleep_timeout(100, 0);
+                       cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
+                       cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
+               } else
+                       CX18_ERR("Can't find valid task handle for unmute\n");
+       }
+       CX18_DEBUG_INFO("Unmute\n");
+}
diff --git a/drivers/media/pci/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h
new file mode 100644 (file)
index 0000000..b9e5110
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  cx18 file operation functions
+ *
+ *  Derived from ivtv-fileops.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+/* Testing/Debugging */
+int cx18_v4l2_open(struct file *filp);
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                     loff_t *pos);
+ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
+                      loff_t *pos);
+int cx18_v4l2_close(struct file *filp);
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
+int cx18_start_capture(struct cx18_open_id *id);
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
+void cx18_mute(struct cx18 *cx);
+void cx18_unmute(struct cx18 *cx);
+int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
+void cx18_vb_timeout(unsigned long data);
+
+/* Shared with cx18-alsa module */
+int cx18_claim_stream(struct cx18_open_id *id, int type);
+void cx18_release_stream(struct cx18_stream *s);
diff --git a/drivers/media/pci/cx18/cx18-firmware.c b/drivers/media/pci/cx18/cx18-firmware.c
new file mode 100644 (file)
index 0000000..a1c1cec
--- /dev/null
@@ -0,0 +1,459 @@
+/*
+ *  cx18 firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-firmware.h"
+#include "cx18-cards.h"
+#include <linux/firmware.h>
+
+#define CX18_PROC_SOFT_RESET           0xc70010
+#define CX18_DDR_SOFT_RESET            0xc70014
+#define CX18_CLOCK_SELECT1             0xc71000
+#define CX18_CLOCK_SELECT2             0xc71004
+#define CX18_HALF_CLOCK_SELECT1        0xc71008
+#define CX18_HALF_CLOCK_SELECT2        0xc7100C
+#define CX18_CLOCK_POLARITY1           0xc71010
+#define CX18_CLOCK_POLARITY2           0xc71014
+#define CX18_ADD_DELAY_ENABLE1         0xc71018
+#define CX18_ADD_DELAY_ENABLE2         0xc7101C
+#define CX18_CLOCK_ENABLE1             0xc71020
+#define CX18_CLOCK_ENABLE2             0xc71024
+
+#define CX18_REG_BUS_TIMEOUT_EN        0xc72024
+
+#define CX18_FAST_CLOCK_PLL_INT        0xc78000
+#define CX18_FAST_CLOCK_PLL_FRAC       0xc78004
+#define CX18_FAST_CLOCK_PLL_POST       0xc78008
+#define CX18_FAST_CLOCK_PLL_PRESCALE   0xc7800C
+#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
+
+#define CX18_SLOW_CLOCK_PLL_INT        0xc78014
+#define CX18_SLOW_CLOCK_PLL_FRAC       0xc78018
+#define CX18_SLOW_CLOCK_PLL_POST       0xc7801C
+#define CX18_MPEG_CLOCK_PLL_INT                0xc78040
+#define CX18_MPEG_CLOCK_PLL_FRAC       0xc78044
+#define CX18_MPEG_CLOCK_PLL_POST       0xc78048
+#define CX18_PLL_POWER_DOWN            0xc78088
+#define CX18_SW1_INT_STATUS             0xc73104
+#define CX18_SW1_INT_ENABLE_PCI         0xc7311C
+#define CX18_SW2_INT_SET                0xc73140
+#define CX18_SW2_INT_STATUS             0xc73144
+#define CX18_ADEC_CONTROL              0xc78120
+
+#define CX18_DDR_REQUEST_ENABLE        0xc80000
+#define CX18_DDR_CHIP_CONFIG           0xc80004
+#define CX18_DDR_REFRESH               0xc80008
+#define CX18_DDR_TIMING1               0xc8000C
+#define CX18_DDR_TIMING2               0xc80010
+#define CX18_DDR_POWER_REG             0xc8001C
+
+#define CX18_DDR_TUNE_LANE             0xc80048
+#define CX18_DDR_INITIAL_EMRS          0xc80054
+#define CX18_DDR_MB_PER_ROW_7          0xc8009C
+#define CX18_DDR_BASE_63_ADDR          0xc804FC
+
+#define CX18_WMB_CLIENT02              0xc90108
+#define CX18_WMB_CLIENT05              0xc90114
+#define CX18_WMB_CLIENT06              0xc90118
+#define CX18_WMB_CLIENT07              0xc9011C
+#define CX18_WMB_CLIENT08              0xc90120
+#define CX18_WMB_CLIENT09              0xc90124
+#define CX18_WMB_CLIENT10              0xc90128
+#define CX18_WMB_CLIENT11              0xc9012C
+#define CX18_WMB_CLIENT12              0xc90130
+#define CX18_WMB_CLIENT13              0xc90134
+#define CX18_WMB_CLIENT14              0xc90138
+
+#define CX18_DSP0_INTERRUPT_MASK       0xd0004C
+
+#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
+#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
+
+struct cx18_apu_rom_seghdr {
+       u32 sync1;
+       u32 sync2;
+       u32 addr;
+       u32 size;
+};
+
+static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
+{
+       const struct firmware *fw = NULL;
+       int i, j;
+       unsigned size;
+       u32 __iomem *dst = (u32 __iomem *)mem;
+       const u32 *src;
+
+       if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
+               CX18_ERR("Unable to open firmware %s\n", fn);
+               CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
+               return -ENOMEM;
+       }
+
+       src = (const u32 *)fw->data;
+
+       for (i = 0; i < fw->size; i += 4096) {
+               cx18_setup_page(cx, i);
+               for (j = i; j < fw->size && j < i + 4096; j += 4) {
+                       /* no need for endianness conversion on the ppc */
+                       cx18_raw_writel(cx, *src, dst);
+                       if (cx18_raw_readl(cx, dst) != *src) {
+                               CX18_ERR("Mismatch at offset %x\n", i);
+                               release_firmware(fw);
+                               cx18_setup_page(cx, 0);
+                               return -EIO;
+                       }
+                       dst++;
+                       src++;
+               }
+       }
+       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+               CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
+       size = fw->size;
+       release_firmware(fw);
+       cx18_setup_page(cx, SCB_OFFSET);
+       return size;
+}
+
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
+                               u32 *entry_addr)
+{
+       const struct firmware *fw = NULL;
+       int i, j;
+       unsigned size;
+       const u32 *src;
+       struct cx18_apu_rom_seghdr seghdr;
+       const u8 *vers;
+       u32 offset = 0;
+       u32 apu_version = 0;
+       int sz;
+
+       if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
+               CX18_ERR("unable to open firmware %s\n", fn);
+               CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
+               cx18_setup_page(cx, 0);
+               return -ENOMEM;
+       }
+
+       *entry_addr = 0;
+       src = (const u32 *)fw->data;
+       vers = fw->data + sizeof(seghdr);
+       sz = fw->size;
+
+       apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
+       while (offset + sizeof(seghdr) < fw->size) {
+               const u32 *shptr = src + offset / 4;
+
+               seghdr.sync1 = le32_to_cpu(shptr[0]);
+               seghdr.sync2 = le32_to_cpu(shptr[1]);
+               seghdr.addr = le32_to_cpu(shptr[2]);
+               seghdr.size = le32_to_cpu(shptr[3]);
+
+               offset += sizeof(seghdr);
+               if (seghdr.sync1 != APU_ROM_SYNC1 ||
+                   seghdr.sync2 != APU_ROM_SYNC2) {
+                       offset += seghdr.size;
+                       continue;
+               }
+               CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
+                               seghdr.addr + seghdr.size - 1);
+               if (*entry_addr == 0)
+                       *entry_addr = seghdr.addr;
+               if (offset + seghdr.size > sz)
+                       break;
+               for (i = 0; i < seghdr.size; i += 4096) {
+                       cx18_setup_page(cx, seghdr.addr + i);
+                       for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
+                               /* no need for endianness conversion on the ppc */
+                               cx18_raw_writel(cx, src[(offset + j) / 4],
+                                               dst + seghdr.addr + j);
+                               if (cx18_raw_readl(cx, dst + seghdr.addr + j)
+                                   != src[(offset + j) / 4]) {
+                                       CX18_ERR("Mismatch at offset %x\n",
+                                                offset + j);
+                                       release_firmware(fw);
+                                       cx18_setup_page(cx, 0);
+                                       return -EIO;
+                               }
+                       }
+               }
+               offset += seghdr.size;
+       }
+       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+               CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
+                               fn, apu_version, fw->size);
+       size = fw->size;
+       release_firmware(fw);
+       cx18_setup_page(cx, 0);
+       return size;
+}
+
+void cx18_halt_firmware(struct cx18 *cx)
+{
+       CX18_DEBUG_INFO("Preparing for firmware halt.\n");
+       cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
+                                 0x0000000F, 0x000F000F);
+       cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
+                                 0x00000002, 0x00020002);
+}
+
+void cx18_init_power(struct cx18 *cx, int lowpwr)
+{
+       /* power-down Spare and AOM PLLs */
+       /* power-up fast, slow and mpeg PLLs */
+       cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
+
+       /* ADEC out of sleep */
+       cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
+                                 0x00000000, 0x00020002);
+
+       /*
+        * The PLL parameters are based on the external crystal frequency that
+        * would ideally be:
+        *
+        * NTSC Color subcarrier freq * 8 =
+        *      4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
+        *
+        * The accidents of history and rationale that explain from where this
+        * combination of magic numbers originate can be found in:
+        *
+        * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
+        * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
+        *
+        * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
+        * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
+        *
+        * As Mike Bradley has rightly pointed out, it's not the exact crystal
+        * frequency that matters, only that all parts of the driver and
+        * firmware are using the same value (close to the ideal value).
+        *
+        * Since I have a strong suspicion that, if the firmware ever assumes a
+        * crystal value at all, it will assume 28.636360 MHz, the crystal
+        * freq used in calculations in this driver will be:
+        *
+        *      xtal_freq = 28.636360 MHz
+        *
+        * an error of less than 0.13 ppm which is way, way better than any off
+        * the shelf crystal will have for accuracy anyway.
+        *
+        * Below I aim to run the PLLs' VCOs near 400 MHz to minimze errors.
+        *
+        * Many thanks to Jeff Campbell and Mike Bradley for their extensive
+        * investigation, experimentation, testing, and suggested solutions of
+        * of audio/video sync problems with SVideo and CVBS captures.
+        */
+
+       /* the fast clock is at 200/245 MHz */
+       /* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/
+       /* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/
+       cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
+       cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
+                                               CX18_FAST_CLOCK_PLL_FRAC);
+
+       cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
+       cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
+       cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
+
+       /* set slow clock to 125/120 MHz */
+       /* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */
+       /* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */
+       cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);
+       cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,
+                                               CX18_SLOW_CLOCK_PLL_FRAC);
+       cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);
+
+       /* mpeg clock pll 54MHz */
+       /* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */
+       cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
+       cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
+       cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
+
+       /* Defaults */
+       /* APU = SC or SC/2 = 125/62.5 */
+       /* EPU = SC = 125 */
+       /* DDR = FC = 180 */
+       /* ENC = SC = 125 */
+       /* AI1 = SC = 125 */
+       /* VIM2 = disabled */
+       /* PCI = FC/2 = 90 */
+       /* AI2 = disabled */
+       /* DEMUX = disabled */
+       /* AO = SC/2 = 62.5 */
+       /* SER = 54MHz */
+       /* VFC = disabled */
+       /* USB = disabled */
+
+       if (lowpwr) {
+               cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
+                                         0x00000020, 0xFFFFFFFF);
+               cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
+                                         0x00000004, 0xFFFFFFFF);
+       } else {
+               /* This doesn't explicitly set every clock select */
+               cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
+                                         0x00000004, 0x00060006);
+               cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
+                                         0x00000006, 0x00060006);
+       }
+
+       cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
+                                 0x00000002, 0xFFFFFFFF);
+       cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
+                                 0x00000104, 0xFFFFFFFF);
+       cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
+                                 0x00009026, 0xFFFFFFFF);
+       cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
+                                 0x00003105, 0xFFFFFFFF);
+}
+
+void cx18_init_memory(struct cx18 *cx)
+{
+       cx18_msleep_timeout(10, 0);
+       cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
+                                 0x00000000, 0x00010001);
+       cx18_msleep_timeout(10, 0);
+
+       cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
+
+       cx18_msleep_timeout(10, 0);
+
+       cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
+       cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
+       cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
+
+       cx18_msleep_timeout(10, 0);
+
+       /* Initialize DQS pad time */
+       cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
+       cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
+
+       cx18_msleep_timeout(10, 0);
+
+       cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
+                                 0x00000000, 0x00020002);
+       cx18_msleep_timeout(10, 0);
+
+       /* use power-down mode when idle */
+       cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
+
+       cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
+                                 0x00000001, 0x00010001);
+
+       cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
+       cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
+
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);  /* AO */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);  /* AI2 */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);  /* AI1 */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);  /* ME */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);  /* ENC */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);  /* PK */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);  /* RC */
+       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);  /* AVO */
+}
+
+#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"
+#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"
+
+int cx18_firmware_init(struct cx18 *cx)
+{
+       u32 fw_entry_addr;
+       int sz, retries;
+       u32 api_args[MAX_MB_ARGUMENTS];
+
+       /* Allow chip to control CLKRUN */
+       cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
+
+       /* Stop the firmware */
+       cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
+                                 0x0000000F, 0x000F000F);
+
+       cx18_msleep_timeout(1, 0);
+
+       /* If the CPU is still running */
+       if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
+               CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
+               return -EIO;
+       }
+
+       cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+       cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+       sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);
+       if (sz <= 0)
+               return sz;
+
+       /* The SCB & IPC area *must* be correct before starting the firmwares */
+       cx18_init_scb(cx);
+
+       fw_entry_addr = 0;
+       sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,
+                               &fw_entry_addr);
+       if (sz <= 0)
+               return sz;
+
+       /* Start the CPU. The CPU will take care of the APU for us. */
+       cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
+                                 0x00000000, 0x00080008);
+
+       /* Wait up to 500 ms for the APU to come out of reset */
+       for (retries = 0;
+            retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
+            retries++)
+               cx18_msleep_timeout(10, 0);
+
+       cx18_msleep_timeout(200, 0);
+
+       if (retries == 50 &&
+           (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
+               CX18_ERR("Could not start the CPU\n");
+               return -EIO;
+       }
+
+       /*
+        * The CPU had once before set up to receive an interrupt for it's
+        * outgoing IRQ_CPU_TO_EPU_ACK to us.  If it ever does this, we get an
+        * interrupt when it sends us an ack, but by the time we process it,
+        * that flag in the SW2 status register has been cleared by the CPU
+        * firmware.  We'll prevent that not so useful condition from happening
+        * by clearing the CPU's interrupt enables for Ack IRQ's we want to
+        * process.
+        */
+       cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+       /* Try a benign command to see if the CPU is alive and well */
+       sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
+       if (sz < 0)
+               return sz;
+
+       /* initialize GPIO */
+       cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
+       return 0;
+}
+
+MODULE_FIRMWARE(CX18_CPU_FIRMWARE);
+MODULE_FIRMWARE(CX18_APU_FIRMWARE);
diff --git a/drivers/media/pci/cx18/cx18-firmware.h b/drivers/media/pci/cx18/cx18-firmware.h
new file mode 100644 (file)
index 0000000..38d4c05
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  cx18 firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+int cx18_firmware_init(struct cx18 *cx);
+void cx18_halt_firmware(struct cx18 *cx);
+void cx18_init_memory(struct cx18 *cx);
+void cx18_init_power(struct cx18 *cx, int lowpwr);
diff --git a/drivers/media/pci/cx18/cx18-gpio.c b/drivers/media/pci/cx18/cx18-gpio.c
new file mode 100644 (file)
index 0000000..5374aeb
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ *  cx18 gpio functions
+ *
+ *  Derived from ivtv-gpio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "tuner-xc2028.h"
+
+/********************* GPIO stuffs *********************/
+
+/* GPIO registers */
+#define CX18_REG_GPIO_IN     0xc72010
+#define CX18_REG_GPIO_OUT1   0xc78100
+#define CX18_REG_GPIO_DIR1   0xc78108
+#define CX18_REG_GPIO_OUT2   0xc78104
+#define CX18_REG_GPIO_DIR2   0xc7810c
+
+/*
+ * HVR-1600 GPIO pins, courtesy of Hauppauge:
+ *
+ * gpio0: zilog ir process reset pin
+ * gpio1: zilog programming pin (you should never use this)
+ * gpio12: cx24227 reset pin
+ * gpio13: cs5345 reset pin
+*/
+
+/*
+ * File scope utility functions
+ */
+static void gpio_write(struct cx18 *cx)
+{
+       u32 dir_lo = cx->gpio_dir & 0xffff;
+       u32 val_lo = cx->gpio_val & 0xffff;
+       u32 dir_hi = cx->gpio_dir >> 16;
+       u32 val_hi = cx->gpio_val >> 16;
+
+       cx18_write_reg_expect(cx, dir_lo << 16,
+                                       CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo);
+       cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo,
+                                       CX18_REG_GPIO_OUT1, val_lo, dir_lo);
+       cx18_write_reg_expect(cx, dir_hi << 16,
+                                       CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi);
+       cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi,
+                                       CX18_REG_GPIO_OUT2, val_hi, dir_hi);
+}
+
+static void gpio_update(struct cx18 *cx, u32 mask, u32 data)
+{
+       if (mask == 0)
+               return;
+
+       mutex_lock(&cx->gpio_lock);
+       cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
+       gpio_write(cx);
+       mutex_unlock(&cx->gpio_lock);
+}
+
+static void gpio_reset_seq(struct cx18 *cx, u32 active_lo, u32 active_hi,
+                          unsigned int assert_msecs,
+                          unsigned int recovery_msecs)
+{
+       u32 mask;
+
+       mask = active_lo | active_hi;
+       if (mask == 0)
+               return;
+
+       /*
+        * Assuming that active_hi and active_lo are a subsets of the bits in
+        * gpio_dir.  Also assumes that active_lo and active_hi don't overlap
+        * in any bit position
+        */
+
+       /* Assert */
+       gpio_update(cx, mask, ~active_lo);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(assert_msecs));
+
+       /* Deassert */
+       gpio_update(cx, mask, ~active_hi);
+       schedule_timeout_uninterruptible(msecs_to_jiffies(recovery_msecs));
+}
+
+/*
+ * GPIO Multiplexer - logical device
+ */
+static int gpiomux_log_status(struct v4l2_subdev *sd)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       mutex_lock(&cx->gpio_lock);
+       CX18_INFO_DEV(sd, "GPIO:  direction 0x%08x, value 0x%08x\n",
+                     cx->gpio_dir, cx->gpio_val);
+       mutex_unlock(&cx->gpio_lock);
+       return 0;
+}
+
+static int gpiomux_s_radio(struct v4l2_subdev *sd)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       /*
+        * FIXME - work out the cx->active/audio_input mess - this is
+        * intended to handle the switch to radio mode and set the
+        * audio routing, but we need to update the state in cx
+        */
+       gpio_update(cx, cx->card->gpio_audio_input.mask,
+                       cx->card->gpio_audio_input.radio);
+       return 0;
+}
+
+static int gpiomux_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       u32 data;
+
+       switch (cx->card->audio_inputs[cx->audio_input].muxer_input) {
+       case 1:
+               data = cx->card->gpio_audio_input.linein;
+               break;
+       case 0:
+               data = cx->card->gpio_audio_input.tuner;
+               break;
+       default:
+               /*
+                * FIXME - work out the cx->active/audio_input mess - this is
+                * intended to handle the switch from radio mode and set the
+                * audio routing, but we need to update the state in cx
+                */
+               data = cx->card->gpio_audio_input.tuner;
+               break;
+       }
+       gpio_update(cx, cx->card->gpio_audio_input.mask, data);
+       return 0;
+}
+
+static int gpiomux_s_audio_routing(struct v4l2_subdev *sd,
+                                  u32 input, u32 output, u32 config)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       u32 data;
+
+       switch (input) {
+       case 0:
+               data = cx->card->gpio_audio_input.tuner;
+               break;
+       case 1:
+               data = cx->card->gpio_audio_input.linein;
+               break;
+       case 2:
+               data = cx->card->gpio_audio_input.radio;
+               break;
+       default:
+               return -EINVAL;
+       }
+       gpio_update(cx, cx->card->gpio_audio_input.mask, data);
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops gpiomux_core_ops = {
+       .log_status = gpiomux_log_status,
+       .s_std = gpiomux_s_std,
+};
+
+static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = {
+       .s_radio = gpiomux_s_radio,
+};
+
+static const struct v4l2_subdev_audio_ops gpiomux_audio_ops = {
+       .s_routing = gpiomux_s_audio_routing,
+};
+
+static const struct v4l2_subdev_ops gpiomux_ops = {
+       .core = &gpiomux_core_ops,
+       .tuner = &gpiomux_tuner_ops,
+       .audio = &gpiomux_audio_ops,
+};
+
+/*
+ * GPIO Reset Controller - logical device
+ */
+static int resetctrl_log_status(struct v4l2_subdev *sd)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+       mutex_lock(&cx->gpio_lock);
+       CX18_INFO_DEV(sd, "GPIO:  direction 0x%08x, value 0x%08x\n",
+                     cx->gpio_dir, cx->gpio_val);
+       mutex_unlock(&cx->gpio_lock);
+       return 0;
+}
+
+static int resetctrl_reset(struct v4l2_subdev *sd, u32 val)
+{
+       struct cx18 *cx = v4l2_get_subdevdata(sd);
+       const struct cx18_gpio_i2c_slave_reset *p;
+
+       p = &cx->card->gpio_i2c_slave_reset;
+       switch (val) {
+       case CX18_GPIO_RESET_I2C:
+               gpio_reset_seq(cx, p->active_lo_mask, p->active_hi_mask,
+                              p->msecs_asserted, p->msecs_recovery);
+               break;
+       case CX18_GPIO_RESET_Z8F0811:
+               /*
+                * Assert timing for the Z8F0811 on HVR-1600 boards:
+                * 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to
+                *    initiate
+                * 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock
+                *    cycles (6,601,085 nanoseconds ~= 7 milliseconds)
+                * 3. DBG pin must be high before chip exits reset for normal
+                *    operation.  DBG is open drain and hopefully pulled high
+                *    since we don't normally drive it (GPIO 1?) for the
+                *    HVR-1600
+                * 4. Z8F0811 won't exit reset until RESET is deasserted
+                * 5. Zilog comes out of reset, loads reset vector address and
+                *    executes from there. Required recovery delay unknown.
+                */
+               gpio_reset_seq(cx, p->ir_reset_mask, 0,
+                              p->msecs_asserted, p->msecs_recovery);
+               break;
+       case CX18_GPIO_RESET_XC2028:
+               if (cx->card->tuners[0].tuner == TUNER_XC2028)
+                       gpio_reset_seq(cx, (1 << cx->card->xceive_pin), 0,
+                                      1, 1);
+               break;
+       }
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops resetctrl_core_ops = {
+       .log_status = resetctrl_log_status,
+       .reset = resetctrl_reset,
+};
+
+static const struct v4l2_subdev_ops resetctrl_ops = {
+       .core = &resetctrl_core_ops,
+};
+
+/*
+ * External entry points
+ */
+void cx18_gpio_init(struct cx18 *cx)
+{
+       mutex_lock(&cx->gpio_lock);
+       cx->gpio_dir = cx->card->gpio_init.direction;
+       cx->gpio_val = cx->card->gpio_init.initial_value;
+
+       if (cx->card->tuners[0].tuner == TUNER_XC2028) {
+               cx->gpio_dir |= 1 << cx->card->xceive_pin;
+               cx->gpio_val |= 1 << cx->card->xceive_pin;
+       }
+
+       if (cx->gpio_dir == 0) {
+               mutex_unlock(&cx->gpio_lock);
+               return;
+       }
+
+       CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
+                       cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
+                       cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
+                       cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
+                       cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
+
+       gpio_write(cx);
+       mutex_unlock(&cx->gpio_lock);
+}
+
+int cx18_gpio_register(struct cx18 *cx, u32 hw)
+{
+       struct v4l2_subdev *sd;
+       const struct v4l2_subdev_ops *ops;
+       char *str;
+
+       switch (hw) {
+       case CX18_HW_GPIO_MUX:
+               sd = &cx->sd_gpiomux;
+               ops = &gpiomux_ops;
+               str = "gpio-mux";
+               break;
+       case CX18_HW_GPIO_RESET_CTRL:
+               sd = &cx->sd_resetctrl;
+               ops = &resetctrl_ops;
+               str = "gpio-reset-ctrl";
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       v4l2_subdev_init(sd, ops);
+       v4l2_set_subdevdata(sd, cx);
+       snprintf(sd->name, sizeof(sd->name), "%s %s", cx->v4l2_dev.name, str);
+       sd->grp_id = hw;
+       return v4l2_device_register_subdev(&cx->v4l2_dev, sd);
+}
+
+void cx18_reset_ir_gpio(void *data)
+{
+       struct cx18 *cx = to_cx18((struct v4l2_device *)data);
+
+       if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0)
+               return;
+
+       CX18_DEBUG_INFO("Resetting IR microcontroller\n");
+
+       v4l2_subdev_call(&cx->sd_resetctrl,
+                        core, reset, CX18_GPIO_RESET_Z8F0811);
+}
+EXPORT_SYMBOL(cx18_reset_ir_gpio);
+/* This symbol is exported for use by lirc_pvr150 for the IR-blaster */
+
+/* Xceive tuner reset function */
+int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
+{
+       struct i2c_algo_bit_data *algo = dev;
+       struct cx18_i2c_algo_callback_data *cb_data = algo->data;
+       struct cx18 *cx = cb_data->cx;
+
+       if (cmd != XC2028_TUNER_RESET ||
+           cx->card->tuners[0].tuner != TUNER_XC2028)
+               return 0;
+
+       CX18_DEBUG_INFO("Resetting XCeive tuner\n");
+       return v4l2_subdev_call(&cx->sd_resetctrl,
+                               core, reset, CX18_GPIO_RESET_XC2028);
+}
diff --git a/drivers/media/pci/cx18/cx18-gpio.h b/drivers/media/pci/cx18/cx18-gpio.h
new file mode 100644 (file)
index 0000000..4aea2ef
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  cx18 gpio functions
+ *
+ *  Derived from ivtv-gpio.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+void cx18_gpio_init(struct cx18 *cx);
+int cx18_gpio_register(struct cx18 *cx, u32 hw);
+
+enum cx18_gpio_reset_type {
+       CX18_GPIO_RESET_I2C     = 0,
+       CX18_GPIO_RESET_Z8F0811 = 1,
+       CX18_GPIO_RESET_XC2028  = 2,
+};
+
+void cx18_reset_ir_gpio(void *data);
+int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);
diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
new file mode 100644 (file)
index 0000000..51609d5
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ *  cx18 I2C functions
+ *
+ *  Derived from ivtv-i2c.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "cx18-i2c.h"
+#include "cx18-irq.h"
+
+#define CX18_REG_I2C_1_WR   0xf15000
+#define CX18_REG_I2C_1_RD   0xf15008
+#define CX18_REG_I2C_2_WR   0xf25100
+#define CX18_REG_I2C_2_RD   0xf25108
+
+#define SETSCL_BIT      0x0001
+#define SETSDL_BIT      0x0002
+#define GETSCL_BIT      0x0004
+#define GETSDL_BIT      0x0008
+
+#define CX18_CS5345_I2C_ADDR           0x4c
+#define CX18_Z8F0811_IR_TX_I2C_ADDR    0x70
+#define CX18_Z8F0811_IR_RX_I2C_ADDR    0x71
+
+/* This array should match the CX18_HW_ defines */
+static const u8 hw_addrs[] = {
+       0,                              /* CX18_HW_TUNER */
+       0,                              /* CX18_HW_TVEEPROM */
+       CX18_CS5345_I2C_ADDR,           /* CX18_HW_CS5345 */
+       0,                              /* CX18_HW_DVB */
+       0,                              /* CX18_HW_418_AV */
+       0,                              /* CX18_HW_GPIO_MUX */
+       0,                              /* CX18_HW_GPIO_RESET_CTRL */
+       CX18_Z8F0811_IR_TX_I2C_ADDR,    /* CX18_HW_Z8F0811_IR_TX_HAUP */
+       CX18_Z8F0811_IR_RX_I2C_ADDR,    /* CX18_HW_Z8F0811_IR_RX_HAUP */
+};
+
+/* This array should match the CX18_HW_ defines */
+/* This might well become a card-specific array */
+static const u8 hw_bus[] = {
+       1,      /* CX18_HW_TUNER */
+       0,      /* CX18_HW_TVEEPROM */
+       0,      /* CX18_HW_CS5345 */
+       0,      /* CX18_HW_DVB */
+       0,      /* CX18_HW_418_AV */
+       0,      /* CX18_HW_GPIO_MUX */
+       0,      /* CX18_HW_GPIO_RESET_CTRL */
+       0,      /* CX18_HW_Z8F0811_IR_TX_HAUP */
+       0,      /* CX18_HW_Z8F0811_IR_RX_HAUP */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const char * const hw_devicenames[] = {
+       "tuner",
+       "tveeprom",
+       "cs5345",
+       "cx23418_DTV",
+       "cx23418_AV",
+       "gpio_mux",
+       "gpio_reset_ctrl",
+       "ir_tx_z8f0811_haup",
+       "ir_rx_z8f0811_haup",
+};
+
+static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
+                          const char *type, u8 addr)
+{
+       struct i2c_board_info info;
+       struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data;
+       unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       strlcpy(info.type, type, I2C_NAME_SIZE);
+
+       /* Our default information for ir-kbd-i2c.c to use */
+       switch (hw) {
+       case CX18_HW_Z8F0811_IR_RX_HAUP:
+               init_data->ir_codes = RC_MAP_HAUPPAUGE;
+               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+               init_data->type = RC_TYPE_RC5;
+               init_data->name = cx->card_name;
+               info.platform_data = init_data;
+               break;
+       }
+
+       return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
+              -1 : 0;
+}
+
+int cx18_i2c_register(struct cx18 *cx, unsigned idx)
+{
+       struct v4l2_subdev *sd;
+       int bus = hw_bus[idx];
+       struct i2c_adapter *adap = &cx->i2c_adap[bus];
+       const char *type = hw_devicenames[idx];
+       u32 hw = 1 << idx;
+
+       if (idx >= ARRAY_SIZE(hw_addrs))
+               return -1;
+
+       if (hw == CX18_HW_TUNER) {
+               /* special tuner group handling */
+               sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+                               adap, type, 0, cx->card_i2c->radio);
+               if (sd != NULL)
+                       sd->grp_id = hw;
+               sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+                               adap, type, 0, cx->card_i2c->demod);
+               if (sd != NULL)
+                       sd->grp_id = hw;
+               sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+                               adap, type, 0, cx->card_i2c->tv);
+               if (sd != NULL)
+                       sd->grp_id = hw;
+               return sd != NULL ? 0 : -1;
+       }
+
+       if (hw & CX18_HW_IR_ANY)
+               return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]);
+
+       /* Is it not an I2C device or one we do not wish to register? */
+       if (!hw_addrs[idx])
+               return -1;
+
+       /* It's an I2C device other than an analog tuner or IR chip */
+       sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx],
+                                NULL);
+       if (sd != NULL)
+               sd->grp_id = hw;
+       return sd != NULL ? 0 : -1;
+}
+
+/* Find the first member of the subdev group id in hw */
+struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw)
+{
+       struct v4l2_subdev *result = NULL;
+       struct v4l2_subdev *sd;
+
+       spin_lock(&cx->v4l2_dev.lock);
+       v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) {
+               if (sd->grp_id == hw) {
+                       result = sd;
+                       break;
+               }
+       }
+       spin_unlock(&cx->v4l2_dev.lock);
+       return result;
+}
+
+static void cx18_setscl(void *data, int state)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+       u32 r = cx18_read_reg(cx, addr);
+
+       if (state)
+               cx18_write_reg(cx, r | SETSCL_BIT, addr);
+       else
+               cx18_write_reg(cx, r & ~SETSCL_BIT, addr);
+}
+
+static void cx18_setsda(void *data, int state)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+       u32 r = cx18_read_reg(cx, addr);
+
+       if (state)
+               cx18_write_reg(cx, r | SETSDL_BIT, addr);
+       else
+               cx18_write_reg(cx, r & ~SETSDL_BIT, addr);
+}
+
+static int cx18_getscl(void *data)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+       return cx18_read_reg(cx, addr) & GETSCL_BIT;
+}
+
+static int cx18_getsda(void *data)
+{
+       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+       u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+       return cx18_read_reg(cx, addr) & GETSDL_BIT;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter cx18_i2c_adap_template = {
+       .name = "cx18 i2c driver",
+       .algo = NULL,                   /* set by i2c-algo-bit */
+       .algo_data = NULL,              /* filled from template */
+       .owner = THIS_MODULE,
+};
+
+#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
+#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
+
+static struct i2c_algo_bit_data cx18_i2c_algo_template = {
+       .setsda         = cx18_setsda,
+       .setscl         = cx18_setscl,
+       .getsda         = cx18_getsda,
+       .getscl         = cx18_getscl,
+       .udelay         = CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/
+       .timeout        = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
+};
+
+/* init + register i2c adapter */
+int init_cx18_i2c(struct cx18 *cx)
+{
+       int i, err;
+       CX18_DEBUG_I2C("i2c init\n");
+
+       for (i = 0; i < 2; i++) {
+               /* Setup algorithm for adapter */
+               memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
+                       sizeof(struct i2c_algo_bit_data));
+               cx->i2c_algo_cb_data[i].cx = cx;
+               cx->i2c_algo_cb_data[i].bus_index = i;
+               cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
+
+               /* Setup adapter */
+               memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
+                       sizeof(struct i2c_adapter));
+               cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
+               sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
+                               " #%d-%d", cx->instance, i);
+               i2c_set_adapdata(&cx->i2c_adap[i], &cx->v4l2_dev);
+               cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev;
+       }
+
+       if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
+               /* Reset/Unreset I2C hardware block */
+               /* Clock select 220MHz */
+               cx18_write_reg_expect(cx, 0x10000000, 0xc71004,
+                                         0x00000000, 0x10001000);
+               /* Clock Enable */
+               cx18_write_reg_expect(cx, 0x10001000, 0xc71024,
+                                         0x00001000, 0x10001000);
+       }
+       /* courtesy of Steven Toth <stoth@hauppauge.com> */
+       cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
+       mdelay(10);
+       cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);
+       mdelay(10);
+       cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
+       mdelay(10);
+
+       /* Set to edge-triggered intrs. */
+       cx18_write_reg(cx, 0x00c00000, 0xc730c8);
+       /* Clear any stale intrs */
+       cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,
+                      ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);
+
+       /* Hw I2C1 Clock Freq ~100kHz */
+       cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+       cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
+       cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
+
+       /* Hw I2C2 Clock Freq ~100kHz */
+       cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+       cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
+       cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
+
+       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+                    core, reset, (u32) CX18_GPIO_RESET_I2C);
+
+       err = i2c_bit_add_bus(&cx->i2c_adap[0]);
+       if (err)
+               goto err;
+       err = i2c_bit_add_bus(&cx->i2c_adap[1]);
+       if (err)
+               goto err_del_bus_0;
+       return 0;
+
+ err_del_bus_0:
+       i2c_del_adapter(&cx->i2c_adap[0]);
+ err:
+       return err;
+}
+
+void exit_cx18_i2c(struct cx18 *cx)
+{
+       int i;
+       CX18_DEBUG_I2C("i2c exit\n");
+       cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
+                                                       CX18_REG_I2C_1_WR);
+       cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
+                                                       CX18_REG_I2C_2_WR);
+
+       for (i = 0; i < 2; i++) {
+               i2c_del_adapter(&cx->i2c_adap[i]);
+       }
+}
+
+/*
+   Hauppauge HVR1600 should have:
+   32 cx24227
+   98 unknown
+   a0 eeprom
+   c2 tuner
+   e? zilog ir
+   */
diff --git a/drivers/media/pci/cx18/cx18-i2c.h b/drivers/media/pci/cx18/cx18-i2c.h
new file mode 100644 (file)
index 0000000..1180fdc
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  cx18 I2C functions
+ *
+ *  Derived from ivtv-i2c.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+int cx18_i2c_register(struct cx18 *cx, unsigned idx);
+struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw);
+
+/* init + register i2c adapter */
+int init_cx18_i2c(struct cx18 *cx);
+void exit_cx18_i2c(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx18-io.c b/drivers/media/pci/cx18/cx18-io.c
new file mode 100644 (file)
index 0000000..49b9dbd
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  cx18 driver PCI memory mapped IO access routines
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-irq.h"
+
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
+{
+       u8 __iomem *dst = addr;
+       u16 val2 = val | (val << 8);
+       u32 val4 = val2 | (val2 << 16);
+
+       /* Align writes on the CX23418's addresses */
+       if ((count > 0) && ((unsigned long)dst & 1)) {
+               cx18_writeb(cx, (u8) val, dst);
+               count--;
+               dst++;
+       }
+       if ((count > 1) && ((unsigned long)dst & 2)) {
+               cx18_writew(cx, val2, dst);
+               count -= 2;
+               dst += 2;
+       }
+       while (count > 3) {
+               cx18_writel(cx, val4, dst);
+               count -= 4;
+               dst += 4;
+       }
+       if (count > 1) {
+               cx18_writew(cx, val2, dst);
+               count -= 2;
+               dst += 2;
+       }
+       if (count > 0)
+               cx18_writeb(cx, (u8) val, dst);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
+{
+       cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val);
+       cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | val;
+       cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
+{
+       cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) & ~val;
+       cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
+{
+       cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val);
+       cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | val;
+       cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
+{
+       cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) & ~val;
+       cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val)
+{
+       u32 r;
+       r = cx18_read_reg(cx, SW2_INT_ENABLE_CPU);
+       cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_CPU);
+}
+
+void cx18_setup_page(struct cx18 *cx, u32 addr)
+{
+       u32 val;
+       val = cx18_read_reg(cx, 0xD000F8);
+       val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
+       cx18_write_reg(cx, val, 0xD000F8);
+}
diff --git a/drivers/media/pci/cx18/cx18-io.h b/drivers/media/pci/cx18/cx18-io.h
new file mode 100644 (file)
index 0000000..18974d8
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *  cx18 driver PCI memory mapped IO access routines
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX18_IO_H
+#define CX18_IO_H
+
+#include "cx18-driver.h"
+
+/*
+ * Readback and retry of MMIO access for reliability:
+ * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
+ * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
+ *
+ * *write* functions are implied to retry the mmio unless suffixed with _noretry
+ * *read* functions never retry the mmio (it never helps to do so)
+ */
+
+/* Non byteswapping memory mapped IO */
+static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
+{
+       return __raw_readl(addr);
+}
+
+static inline
+void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       __raw_writel(val, addr);
+}
+
+static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+               cx18_raw_writel_noretry(cx, val, addr);
+               if (val == cx18_raw_readl(cx, addr))
+                       break;
+       }
+}
+
+/* Normal memory mapped IO */
+static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
+{
+       return readl(addr);
+}
+
+static inline
+void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       writel(val, addr);
+}
+
+static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+               cx18_writel_noretry(cx, val, addr);
+               if (val == cx18_readl(cx, addr))
+                       break;
+       }
+}
+
+static inline
+void cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
+                       u32 eval, u32 mask)
+{
+       int i;
+       u32 r;
+       eval &= mask;
+       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+               cx18_writel_noretry(cx, val, addr);
+               r = cx18_readl(cx, addr);
+               if (r == 0xffffffff && eval != 0xffffffff)
+                       continue;
+               if (eval == (r & mask))
+                       break;
+       }
+}
+
+static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr)
+{
+       return readw(addr);
+}
+
+static inline
+void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+       writew(val, addr);
+}
+
+static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+               cx18_writew_noretry(cx, val, addr);
+               if (val == cx18_readw(cx, addr))
+                       break;
+       }
+}
+
+static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr)
+{
+       return readb(addr);
+}
+
+static inline
+void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+       writeb(val, addr);
+}
+
+static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+       int i;
+       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+               cx18_writeb_noretry(cx, val, addr);
+               if (val == cx18_readb(cx, addr))
+                       break;
+       }
+}
+
+static inline
+void cx18_memcpy_fromio(struct cx18 *cx, void *to,
+                       const void __iomem *from, unsigned int len)
+{
+       memcpy_fromio(to, from, len);
+}
+
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
+
+
+/* Access "register" region of CX23418 memory mapped I/O */
+static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg)
+{
+       cx18_writel_noretry(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
+{
+       cx18_writel(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
+                                        u32 eval, u32 mask)
+{
+       cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask);
+}
+
+static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg)
+{
+       return cx18_readl(cx, cx->reg_mem + reg);
+}
+
+
+/* Access "encoder memory" region of CX23418 memory mapped I/O */
+static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
+{
+       cx18_writel(cx, val, cx->enc_mem + addr);
+}
+
+static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr)
+{
+       return cx18_readl(cx, cx->enc_mem + addr);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val);
+void cx18_setup_page(struct cx18 *cx, u32 addr);
+
+#endif /* CX18_IO_H */
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
new file mode 100644 (file)
index 0000000..e9912db
--- /dev/null
@@ -0,0 +1,1194 @@
+/*
+ *  cx18 ioctl system call
+ *
+ *  Derived from ivtv-ioctl.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-version.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-fileops.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-video.h"
+#include "cx18-streams.h"
+#include "cx18-ioctl.h"
+#include "cx18-gpio.h"
+#include "cx18-controls.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include <media/tveeprom.h>
+#include <media/v4l2-chip-ident.h>
+
+u16 cx18_service2vbi(int type)
+{
+       switch (type) {
+       case V4L2_SLICED_TELETEXT_B:
+               return CX18_SLICED_TYPE_TELETEXT_B;
+       case V4L2_SLICED_CAPTION_525:
+               return CX18_SLICED_TYPE_CAPTION_525;
+       case V4L2_SLICED_WSS_625:
+               return CX18_SLICED_TYPE_WSS_625;
+       case V4L2_SLICED_VPS:
+               return CX18_SLICED_TYPE_VPS;
+       default:
+               return 0;
+       }
+}
+
+/* Check if VBI services are allowed on the (field, line) for the video std */
+static int valid_service_line(int field, int line, int is_pal)
+{
+       return (is_pal && line >= 6 &&
+               ((field == 0 && line <= 23) || (field == 1 && line <= 22))) ||
+              (!is_pal && line >= 10 && line < 22);
+}
+
+/*
+ * For a (field, line, std) and inbound potential set of services for that line,
+ * return the first valid service of those passed in the incoming set for that
+ * line in priority order:
+ * CC, VPS, or WSS over TELETEXT for well known lines
+ * TELETEXT, before VPS, before CC, before WSS, for other lines
+ */
+static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
+{
+       u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
+       int i;
+
+       set = set & valid_set;
+       if (set == 0 || !valid_service_line(field, line, is_pal))
+               return 0;
+       if (!is_pal) {
+               if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
+                       return V4L2_SLICED_CAPTION_525;
+       } else {
+               if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
+                       return V4L2_SLICED_VPS;
+               if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
+                       return V4L2_SLICED_WSS_625;
+               if (line == 23)
+                       return 0;
+       }
+       for (i = 0; i < 32; i++) {
+               if ((1 << i) & set)
+                       return 1 << i;
+       }
+       return 0;
+}
+
+/*
+ * Expand the service_set of *fmt into valid service_lines for the std,
+ * and clear the passed in fmt->service_set
+ */
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+       u16 set = fmt->service_set;
+       int f, l;
+
+       fmt->service_set = 0;
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++)
+                       fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
+       }
+}
+
+/*
+ * Sanitize the service_lines in *fmt per the video std, and return 1
+ * if any service_line is left as valid after santization
+ */
+static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+       int f, l;
+       u16 set = 0;
+
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++) {
+                       fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
+                       set |= fmt->service_lines[f][l];
+               }
+       }
+       return set != 0;
+}
+
+/* Compute the service_set from the assumed valid service_lines of *fmt */
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
+{
+       int f, l;
+       u16 set = 0;
+
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++)
+                       set |= fmt->service_lines[f][l];
+       }
+       return set;
+}
+
+static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+       pixfmt->width = cx->cxhdl.width;
+       pixfmt->height = cx->cxhdl.height;
+       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       pixfmt->field = V4L2_FIELD_INTERLACED;
+       pixfmt->priv = 0;
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+               pixfmt->pixelformat = s->pixelformat;
+               pixfmt->sizeimage = s->vb_bytes_per_frame;
+               pixfmt->bytesperline = 720;
+       } else {
+               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+               pixfmt->sizeimage = 128 * 1024;
+               pixfmt->bytesperline = 0;
+       }
+       return 0;
+}
+
+static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
+
+       vbifmt->sampling_rate = 27000000;
+       vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */
+       vbifmt->samples_per_line = vbi_active_samples - 4;
+       vbifmt->sample_format = V4L2_PIX_FMT_GREY;
+       vbifmt->start[0] = cx->vbi.start[0];
+       vbifmt->start[1] = cx->vbi.start[1];
+       vbifmt->count[0] = vbifmt->count[1] = cx->vbi.count;
+       vbifmt->flags = 0;
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+       return 0;
+}
+
+static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
+                                       struct v4l2_format *fmt)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+       /* sane, V4L2 spec compliant, defaults */
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
+       vbifmt->service_set = 0;
+
+       /*
+        * Fetch the configured service_lines and total service_set from the
+        * digitizer/slicer.  Note, cx18_av_vbi() wipes the passed in
+        * fmt->fmt.sliced under valid calling conditions
+        */
+       if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced))
+               return -EINVAL;
+
+       /* Ensure V4L2 spec compliant output */
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       vbifmt->service_set = cx18_get_service_set(vbifmt);
+       return 0;
+}
+
+static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       int w = fmt->fmt.pix.width;
+       int h = fmt->fmt.pix.height;
+       int min_h = 2;
+
+       w = min(w, 720);
+       w = max(w, 2);
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+               /* YUV height must be a multiple of 32 */
+               h &= ~0x1f;
+               min_h = 32;
+       }
+       h = min(h, cx->is_50hz ? 576 : 480);
+       h = max(h, min_h);
+
+       fmt->fmt.pix.width = w;
+       fmt->fmt.pix.height = h;
+       return 0;
+}
+
+static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       return cx18_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
+                                       struct v4l2_format *fmt)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+
+       /* If given a service set, expand it validly & clear passed in set */
+       if (vbifmt->service_set)
+               cx18_expand_service_set(vbifmt, cx->is_50hz);
+       /* Sanitize the service_lines, and compute the new set if any valid */
+       if (check_service_set(vbifmt, cx->is_50hz))
+               vbifmt->service_set = cx18_get_service_set(vbifmt);
+       return 0;
+}
+
+static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       struct cx18_stream *s = &cx->streams[id->type];
+       int ret;
+       int w, h;
+
+       ret = cx18_try_fmt_vid_cap(file, fh, fmt);
+       if (ret)
+               return ret;
+       w = fmt->fmt.pix.width;
+       h = fmt->fmt.pix.height;
+
+       if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
+           s->pixelformat == fmt->fmt.pix.pixelformat)
+               return 0;
+
+       if (atomic_read(&cx->ana_capturing) > 0)
+               return -EBUSY;
+
+       s->pixelformat = fmt->fmt.pix.pixelformat;
+       /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+          UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+       if (s->pixelformat == V4L2_PIX_FMT_HM12)
+               s->vb_bytes_per_frame = h * 720 * 3 / 2;
+       else
+               s->vb_bytes_per_frame = h * 720 * 2;
+
+       mbus_fmt.width = cx->cxhdl.width = w;
+       mbus_fmt.height = cx->cxhdl.height = h;
+       mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+       v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
+       return cx18_g_fmt_vid_cap(file, fh, fmt);
+}
+
+static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
+                               struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       int ret;
+
+       /*
+        * Changing the Encoder's Raw VBI parameters won't have any effect
+        * if any analog capture is ongoing
+        */
+       if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
+               return -EBUSY;
+
+       /*
+        * Set the digitizer registers for raw active VBI.
+        * Note cx18_av_vbi_wipes out a lot of the passed in fmt under valid
+        * calling conditions
+        */
+       ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi);
+       if (ret)
+               return ret;
+
+       /* Store our new v4l2 (non-)sliced VBI state */
+       cx->vbi.sliced_in->service_set = 0;
+       cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+
+       return cx18_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
+                                       struct v4l2_format *fmt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       int ret;
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+       cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
+
+       /*
+        * Changing the Encoder's Raw VBI parameters won't have any effect
+        * if any analog capture is ongoing
+        */
+       if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
+               return -EBUSY;
+
+       /*
+        * Set the service_lines requested in the digitizer/slicer registers.
+        * Note, cx18_av_vbi() wipes some "impossible" service lines in the
+        * passed in fmt->fmt.sliced under valid calling conditions
+        */
+       ret = v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &fmt->fmt.sliced);
+       if (ret)
+               return ret;
+       /* Store our current v4l2 sliced VBI settings */
+       cx->vbi.in.type =  V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+       memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
+       return 0;
+}
+
+static int cx18_g_chip_ident(struct file *file, void *fh,
+                               struct v4l2_dbg_chip_ident *chip)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       int err = 0;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               switch (chip->match.addr) {
+               case 0:
+                       chip->ident = V4L2_IDENT_CX23418;
+                       chip->revision = cx18_read_reg(cx, 0xC72028);
+                       break;
+               case 1:
+                       /*
+                        * The A/V decoder is always present, but in the rare
+                        * case that the card doesn't have analog, we don't
+                        * use it.  We find it w/o using the cx->sd_av pointer
+                        */
+                       cx18_call_hw(cx, CX18_HW_418_AV,
+                                    core, g_chip_ident, chip);
+                       break;
+               default:
+                       /*
+                        * Could return ident = V4L2_IDENT_UNKNOWN if we had
+                        * other host chips at higher addresses, but we don't
+                        */
+                       err = -EINVAL; /* per V4L2 spec */
+                       break;
+               }
+               break;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
+               cx18_call_all(cx, core, g_chip_ident, chip);
+               break;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /*
+                * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
+                * to look if a chip is at the address with no driver.  That's a
+                * dangerous thing to do with EEPROMs anyway.
+                */
+               cx18_call_all(cx, core, g_chip_ident, chip);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       return err;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
+{
+       struct v4l2_dbg_register *regs = arg;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+               return -EINVAL;
+
+       regs->size = 4;
+       if (cmd == VIDIOC_DBG_S_REGISTER)
+               cx18_write_enc(cx, regs->val, regs->reg);
+       else
+               regs->val = cx18_read_enc(cx, regs->reg);
+       return 0;
+}
+
+static int cx18_g_register(struct file *file, void *fh,
+                               struct v4l2_dbg_register *reg)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (v4l2_chip_match_host(&reg->match))
+               return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
+       /* FIXME - errors shouldn't be ignored */
+       cx18_call_all(cx, core, g_register, reg);
+       return 0;
+}
+
+static int cx18_s_register(struct file *file, void *fh,
+                               struct v4l2_dbg_register *reg)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (v4l2_chip_match_host(&reg->match))
+               return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
+       /* FIXME - errors shouldn't be ignored */
+       cx18_call_all(cx, core, s_register, reg);
+       return 0;
+}
+#endif
+
+static int cx18_querycap(struct file *file, void *fh,
+                               struct v4l2_capability *vcap)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+
+       strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
+       strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
+       snprintf(vcap->bus_info, sizeof(vcap->bus_info),
+                "PCI:%s", pci_name(cx->pci_dev));
+       vcap->capabilities = cx->v4l2_cap;          /* capabilities */
+       if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+               vcap->capabilities |= V4L2_CAP_STREAMING;
+       return 0;
+}
+
+static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       return cx18_get_audio_input(cx, vin->index, vin);
+}
+
+static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       vin->index = cx->audio_input;
+       return cx18_get_audio_input(cx, vin->index, vin);
+}
+
+static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (vout->index >= cx->nof_audio_inputs)
+               return -EINVAL;
+       cx->audio_input = vout->index;
+       cx18_audio_set_io(cx);
+       return 0;
+}
+
+static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       /* set it to defaults from our table */
+       return cx18_get_input(cx, vin->index, vin);
+}
+
+static int cx18_cropcap(struct file *file, void *fh,
+                       struct v4l2_cropcap *cropcap)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       cropcap->bounds.top = cropcap->bounds.left = 0;
+       cropcap->bounds.width = 720;
+       cropcap->bounds.height = cx->is_50hz ? 576 : 480;
+       cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
+       cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
+       cropcap->defrect = cropcap->bounds;
+       return 0;
+}
+
+static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n");
+       return -EINVAL;
+}
+
+static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
+       return -EINVAL;
+}
+
+static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
+                                       struct v4l2_fmtdesc *fmt)
+{
+       static const struct v4l2_fmtdesc formats[] = {
+               { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+                 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
+               },
+               { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
+                 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
+               },
+               { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+                 "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 }
+               },
+       };
+
+       if (fmt->index > ARRAY_SIZE(formats) - 1)
+               return -EINVAL;
+       *fmt = formats[fmt->index];
+       return 0;
+}
+
+static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       *i = cx->active_input;
+       return 0;
+}
+
+int cx18_s_input(struct file *file, void *fh, unsigned int inp)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+
+       if (inp >= cx->nof_inputs)
+               return -EINVAL;
+
+       if (inp == cx->active_input) {
+               CX18_DEBUG_INFO("Input unchanged\n");
+               return 0;
+       }
+
+       CX18_DEBUG_INFO("Changing input from %d to %d\n",
+                       cx->active_input, inp);
+
+       cx->active_input = inp;
+       /* Set the audio input to whatever is appropriate for the input type. */
+       cx->audio_input = cx->card->video_inputs[inp].audio_index;
+
+       /* prevent others from messing with the streams until
+          we're finished changing inputs. */
+       cx18_mute(cx);
+       cx18_video_set_io(cx);
+       cx18_audio_set_io(cx);
+       cx18_unmute(cx);
+       return 0;
+}
+
+static int cx18_g_frequency(struct file *file, void *fh,
+                               struct v4l2_frequency *vf)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (vf->tuner != 0)
+               return -EINVAL;
+
+       cx18_call_all(cx, tuner, g_frequency, vf);
+       return 0;
+}
+
+int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+
+       if (vf->tuner != 0)
+               return -EINVAL;
+
+       cx18_mute(cx);
+       CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
+       cx18_call_all(cx, tuner, s_frequency, vf);
+       cx18_unmute(cx);
+       return 0;
+}
+
+static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       *std = cx->std;
+       return 0;
+}
+
+int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+
+       if ((*std & V4L2_STD_ALL) == 0)
+               return -EINVAL;
+
+       if (*std == cx->std)
+               return 0;
+
+       if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
+           atomic_read(&cx->ana_capturing) > 0) {
+               /* Switching standard would turn off the radio or mess
+                  with already running streams, prevent that by
+                  returning EBUSY. */
+               return -EBUSY;
+       }
+
+       cx->std = *std;
+       cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+       cx->is_50hz = !cx->is_60hz;
+       cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
+       cx->cxhdl.width = 720;
+       cx->cxhdl.height = cx->is_50hz ? 576 : 480;
+       cx->vbi.count = cx->is_50hz ? 18 : 12;
+       cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
+       cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
+       CX18_DEBUG_INFO("Switching standard to %llx.\n",
+                       (unsigned long long) cx->std);
+
+       /* Tuner */
+       cx18_call_all(cx, core, s_std, cx->std);
+       return 0;
+}
+
+static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+
+       if (vt->index != 0)
+               return -EINVAL;
+
+       cx18_call_all(cx, tuner, s_tuner, vt);
+       return 0;
+}
+
+static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       if (vt->index != 0)
+               return -EINVAL;
+
+       cx18_call_all(cx, tuner, g_tuner, vt);
+
+       if (vt->type == V4L2_TUNER_RADIO)
+               strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
+       else
+               strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
+       return 0;
+}
+
+static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
+                                       struct v4l2_sliced_vbi_cap *cap)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
+       int f, l;
+
+       if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
+               return -EINVAL;
+
+       cap->service_set = 0;
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++) {
+                       if (valid_service_line(f, l, cx->is_50hz)) {
+                               /*
+                                * We can find all v4l2 supported vbi services
+                                * for the standard, on a valid line for the std
+                                */
+                               cap->service_lines[f][l] = set;
+                               cap->service_set |= set;
+                       } else
+                               cap->service_lines[f][l] = 0;
+               }
+       }
+       for (f = 0; f < 3; f++)
+               cap->reserved[f] = 0;
+       return 0;
+}
+
+static int _cx18_process_idx_data(struct cx18_buffer *buf,
+                                 struct v4l2_enc_idx *idx)
+{
+       int consumed, remaining;
+       struct v4l2_enc_idx_entry *e_idx;
+       struct cx18_enc_idx_entry *e_buf;
+
+       /* Frame type lookup: 1=I, 2=P, 4=B */
+       const int mapping[8] = {
+               -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P,
+               -1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1
+       };
+
+       /*
+        * Assumption here is that a buf holds an integral number of
+        * struct cx18_enc_idx_entry objects and is properly aligned.
+        * This is enforced by the module options on IDX buffer sizes.
+        */
+       remaining = buf->bytesused - buf->readpos;
+       consumed = 0;
+       e_idx = &idx->entry[idx->entries];
+       e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos];
+
+       while (remaining >= sizeof(struct cx18_enc_idx_entry) &&
+              idx->entries < V4L2_ENC_IDX_ENTRIES) {
+
+               e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32)
+                               | le32_to_cpu(e_buf->offset_low);
+
+               e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32)
+                            | le32_to_cpu(e_buf->pts_low);
+
+               e_idx->length = le32_to_cpu(e_buf->length);
+
+               e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7];
+
+               e_idx->reserved[0] = 0;
+               e_idx->reserved[1] = 0;
+
+               idx->entries++;
+               e_idx = &idx->entry[idx->entries];
+               e_buf++;
+
+               remaining -= sizeof(struct cx18_enc_idx_entry);
+               consumed += sizeof(struct cx18_enc_idx_entry);
+       }
+
+       /* Swallow any partial entries at the end, if there are any */
+       if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry))
+               consumed += remaining;
+
+       buf->readpos += consumed;
+       return consumed;
+}
+
+static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl,
+                                struct v4l2_enc_idx *idx)
+{
+       if (s->type != CX18_ENC_STREAM_TYPE_IDX)
+               return -EINVAL;
+
+       if (mdl->curr_buf == NULL)
+               mdl->curr_buf = list_first_entry(&mdl->buf_list,
+                                                struct cx18_buffer, list);
+
+       if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
+               /*
+                * For some reason we've exhausted the buffers, but the MDL
+                * object still said some data was unread.
+                * Fix that and bail out.
+                */
+               mdl->readpos = mdl->bytesused;
+               return 0;
+       }
+
+       list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
+
+               /* Skip any empty buffers in the MDL */
+               if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
+                       continue;
+
+               mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx);
+
+               /* exit when MDL drained or request satisfied */
+               if (idx->entries >= V4L2_ENC_IDX_ENTRIES ||
+                   mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
+                   mdl->readpos >= mdl->bytesused)
+                       break;
+       }
+       return 0;
+}
+
+static int cx18_g_enc_index(struct file *file, void *fh,
+                               struct v4l2_enc_idx *idx)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       s32 tmp;
+       struct cx18_mdl *mdl;
+
+       if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */
+               return -EINVAL;
+
+       /* Compute the best case number of entries we can buffer */
+       tmp = s->buffers -
+                         s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN;
+       if (tmp <= 0)
+               tmp = 1;
+       tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry);
+
+       /* Fill out the header of the return structure */
+       idx->entries = 0;
+       idx->entries_cap = tmp;
+       memset(idx->reserved, 0, sizeof(idx->reserved));
+
+       /* Pull IDX MDLs and buffers from q_full and populate the entries */
+       do {
+               mdl = cx18_dequeue(s, &s->q_full);
+               if (mdl == NULL) /* No more IDX data right now */
+                       break;
+
+               /* Extract the Index entry data from the MDL and buffers */
+               cx18_process_idx_data(s, mdl, idx);
+               if (mdl->readpos < mdl->bytesused) {
+                       /* We finished with data remaining, push the MDL back */
+                       cx18_push(s, mdl, &s->q_full);
+                       break;
+               }
+
+               /* We drained this MDL, schedule it to go to the firmware */
+               cx18_enqueue(s, mdl, &s->q_free);
+
+       } while (idx->entries < V4L2_ENC_IDX_ENTRIES);
+
+       /* Tell the work handler to send free IDX MDLs to the firmware */
+       cx18_stream_load_fw_queue(s);
+       return 0;
+}
+
+static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
+{
+       struct videobuf_queue *q = NULL;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       switch (s->vb_type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               q = &s->vbuf_q;
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               break;
+       default:
+               break;
+       }
+       return q;
+}
+
+static int cx18_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       /* Start the hardware only if we're the video device */
+       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       if (id->type != CX18_ENC_STREAM_TYPE_YUV)
+               return -EINVAL;
+
+       /* Establish a buffer timeout */
+       mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
+
+       return videobuf_streamon(cx18_vb_queue(id));
+}
+
+static int cx18_streamoff(struct file *file, void *priv,
+       enum v4l2_buf_type type)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       /* Start the hardware only if we're the video device */
+       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       if (id->type != CX18_ENC_STREAM_TYPE_YUV)
+               return -EINVAL;
+
+       return videobuf_streamoff(cx18_vb_queue(id));
+}
+
+static int cx18_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *rb)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       return videobuf_reqbufs(cx18_vb_queue(id), rb);
+}
+
+static int cx18_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *b)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       return videobuf_querybuf(cx18_vb_queue(id), b);
+}
+
+static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       return videobuf_qbuf(cx18_vb_queue(id), b);
+}
+
+static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx18_open_id *id = file->private_data;
+       struct cx18 *cx = id->cx;
+       struct cx18_stream *s = &cx->streams[id->type];
+
+       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
+}
+
+static int cx18_encoder_cmd(struct file *file, void *fh,
+                               struct v4l2_encoder_cmd *enc)
+{
+       struct cx18_open_id *id = fh2id(fh);
+       struct cx18 *cx = id->cx;
+       u32 h;
+
+       switch (enc->cmd) {
+       case V4L2_ENC_CMD_START:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+               enc->flags = 0;
+               return cx18_start_capture(id);
+
+       case V4L2_ENC_CMD_STOP:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+               cx18_stop_capture(id,
+                                 enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
+               break;
+
+       case V4L2_ENC_CMD_PAUSE:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+               enc->flags = 0;
+               if (!atomic_read(&cx->ana_capturing))
+                       return -EPERM;
+               if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+                       return 0;
+               h = cx18_find_handle(cx);
+               if (h == CX18_INVALID_TASK_HANDLE) {
+                       CX18_ERR("Can't find valid task handle for "
+                                "V4L2_ENC_CMD_PAUSE\n");
+                       return -EBADFD;
+               }
+               cx18_mute(cx);
+               cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
+               break;
+
+       case V4L2_ENC_CMD_RESUME:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+               enc->flags = 0;
+               if (!atomic_read(&cx->ana_capturing))
+                       return -EPERM;
+               if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+                       return 0;
+               h = cx18_find_handle(cx);
+               if (h == CX18_INVALID_TASK_HANDLE) {
+                       CX18_ERR("Can't find valid task handle for "
+                                "V4L2_ENC_CMD_RESUME\n");
+                       return -EBADFD;
+               }
+               cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
+               cx18_unmute(cx);
+               break;
+
+       default:
+               CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_try_encoder_cmd(struct file *file, void *fh,
+                               struct v4l2_encoder_cmd *enc)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       switch (enc->cmd) {
+       case V4L2_ENC_CMD_START:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+               enc->flags = 0;
+               break;
+
+       case V4L2_ENC_CMD_STOP:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+               break;
+
+       case V4L2_ENC_CMD_PAUSE:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+               enc->flags = 0;
+               break;
+
+       case V4L2_ENC_CMD_RESUME:
+               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+               enc->flags = 0;
+               break;
+
+       default:
+               CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int cx18_log_status(struct file *file, void *fh)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+       struct v4l2_input vidin;
+       struct v4l2_audio audin;
+       int i;
+
+       CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
+       if (cx->hw_flags & CX18_HW_TVEEPROM) {
+               struct tveeprom tv;
+
+               cx18_read_eeprom(cx, &tv);
+       }
+       cx18_call_all(cx, core, log_status);
+       cx18_get_input(cx, cx->active_input, &vidin);
+       cx18_get_audio_input(cx, cx->audio_input, &audin);
+       CX18_INFO("Video Input: %s\n", vidin.name);
+       CX18_INFO("Audio Input: %s\n", audin.name);
+       mutex_lock(&cx->gpio_lock);
+       CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
+               cx->gpio_dir, cx->gpio_val);
+       mutex_unlock(&cx->gpio_lock);
+       CX18_INFO("Tuner: %s\n",
+               test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
+       v4l2_ctrl_handler_log_status(&cx->cxhdl.hdl, cx->v4l2_dev.name);
+       CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
+       for (i = 0; i < CX18_MAX_STREAMS; i++) {
+               struct cx18_stream *s = &cx->streams[i];
+
+               if (s->video_dev == NULL || s->buffers == 0)
+                       continue;
+               CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
+                         s->name, s->s_flags,
+                         atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
+                          / s->buffers,
+                         (s->buffers * s->buf_size) / 1024, s->buffers);
+       }
+       CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
+                       (long long)cx->mpg_data_received,
+                       (long long)cx->vbi_data_inserted);
+       return 0;
+}
+
+static long cx18_default(struct file *file, void *fh, bool valid_prio,
+                                                       int cmd, void *arg)
+{
+       struct cx18 *cx = fh2id(fh)->cx;
+
+       switch (cmd) {
+       case VIDIOC_INT_RESET: {
+               u32 val = *(u32 *)arg;
+
+               if ((val == 0) || (val & 0x01))
+                       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
+                                    (u32) CX18_GPIO_RESET_Z8F0811);
+               break;
+       }
+
+       default:
+               return -ENOTTY;
+       }
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
+       .vidioc_querycap                = cx18_querycap,
+       .vidioc_s_audio                 = cx18_s_audio,
+       .vidioc_g_audio                 = cx18_g_audio,
+       .vidioc_enumaudio               = cx18_enumaudio,
+       .vidioc_enum_input              = cx18_enum_input,
+       .vidioc_cropcap                 = cx18_cropcap,
+       .vidioc_s_crop                  = cx18_s_crop,
+       .vidioc_g_crop                  = cx18_g_crop,
+       .vidioc_g_input                 = cx18_g_input,
+       .vidioc_s_input                 = cx18_s_input,
+       .vidioc_g_frequency             = cx18_g_frequency,
+       .vidioc_s_frequency             = cx18_s_frequency,
+       .vidioc_s_tuner                 = cx18_s_tuner,
+       .vidioc_g_tuner                 = cx18_g_tuner,
+       .vidioc_g_enc_index             = cx18_g_enc_index,
+       .vidioc_g_std                   = cx18_g_std,
+       .vidioc_s_std                   = cx18_s_std,
+       .vidioc_log_status              = cx18_log_status,
+       .vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap,
+       .vidioc_encoder_cmd             = cx18_encoder_cmd,
+       .vidioc_try_encoder_cmd         = cx18_try_encoder_cmd,
+       .vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap,
+       .vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap,
+       .vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap,
+       .vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap,
+       .vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap,
+       .vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap,
+       .vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap,
+       .vidioc_g_chip_ident            = cx18_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register              = cx18_g_register,
+       .vidioc_s_register              = cx18_s_register,
+#endif
+       .vidioc_default                 = cx18_default,
+       .vidioc_streamon                = cx18_streamon,
+       .vidioc_streamoff               = cx18_streamoff,
+       .vidioc_reqbufs                 = cx18_reqbufs,
+       .vidioc_querybuf                = cx18_querybuf,
+       .vidioc_qbuf                    = cx18_qbuf,
+       .vidioc_dqbuf                   = cx18_dqbuf,
+};
+
+void cx18_set_funcs(struct video_device *vdev)
+{
+       vdev->ioctl_ops = &cx18_ioctl_ops;
+}
diff --git a/drivers/media/pci/cx18/cx18-ioctl.h b/drivers/media/pci/cx18/cx18-ioctl.h
new file mode 100644 (file)
index 0000000..2f9dd59
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  cx18 ioctl system call
+ *
+ *  Derived from ivtv-ioctl.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+u16 cx18_service2vbi(int type);
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
+void cx18_set_funcs(struct video_device *vdev);
+int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
+int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
+int cx18_s_input(struct file *file, void *fh, unsigned int inp);
diff --git a/drivers/media/pci/cx18/cx18-irq.c b/drivers/media/pci/cx18/cx18-irq.c
new file mode 100644 (file)
index 0000000..80edfe9
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *  cx18 interrupt handling
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-irq.h"
+#include "cx18-mailbox.h"
+#include "cx18-scb.h"
+
+static void xpu_ack(struct cx18 *cx, u32 sw2)
+{
+       if (sw2 & IRQ_CPU_TO_EPU_ACK)
+               wake_up(&cx->mb_cpu_waitq);
+       if (sw2 & IRQ_APU_TO_EPU_ACK)
+               wake_up(&cx->mb_apu_waitq);
+}
+
+static void epu_cmd(struct cx18 *cx, u32 sw1)
+{
+       if (sw1 & IRQ_CPU_TO_EPU)
+               cx18_api_epu_cmd_irq(cx, CPU);
+       if (sw1 & IRQ_APU_TO_EPU)
+               cx18_api_epu_cmd_irq(cx, APU);
+}
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id)
+{
+       struct cx18 *cx = (struct cx18 *)dev_id;
+       u32 sw1, sw2, hw2;
+
+       sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;
+       sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask;
+       hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask;
+
+       if (sw1)
+               cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
+       if (sw2)
+               cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
+       if (hw2)
+               cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
+
+       if (sw1 || sw2 || hw2)
+               CX18_DEBUG_HI_IRQ("received interrupts "
+                                 "SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
+
+       /*
+        * SW1 responses have to happen first.  The sending XPU times out the
+        * incoming mailboxes on us rather rapidly.
+        */
+       if (sw1)
+               epu_cmd(cx, sw1);
+
+       /* To do: interrupt-based I2C handling
+       if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
+       }
+       */
+
+       if (sw2)
+               xpu_ack(cx, sw2);
+
+       return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
+}
diff --git a/drivers/media/pci/cx18/cx18-irq.h b/drivers/media/pci/cx18/cx18-irq.h
new file mode 100644 (file)
index 0000000..30e7eaf
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  cx18 interrupt handling
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#define HW2_I2C1_INT                   (1 << 22)
+#define HW2_I2C2_INT                   (1 << 23)
+#define HW2_INT_CLR_STATUS             0xc730c4
+#define HW2_INT_MASK5_PCI              0xc730e4
+#define SW1_INT_SET                     0xc73100
+#define SW1_INT_STATUS                  0xc73104
+#define SW1_INT_ENABLE_PCI              0xc7311c
+#define SW2_INT_SET                     0xc73140
+#define SW2_INT_STATUS                  0xc73144
+#define SW2_INT_ENABLE_CPU              0xc73158
+#define SW2_INT_ENABLE_PCI              0xc7315c
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id);
diff --git a/drivers/media/pci/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c
new file mode 100644 (file)
index 0000000..eabf00c
--- /dev/null
@@ -0,0 +1,870 @@
+/*
+ *  cx18 mailbox functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-mailbox.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-alsa-pcm.h" /* FIXME make configurable */
+
+static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" };
+
+#define API_FAST (1 << 2) /* Short timeout */
+#define API_SLOW (1 << 3) /* Additional 300ms timeout */
+
+struct cx18_api_info {
+       u32 cmd;
+       u8 flags;               /* Flags, see above */
+       u8 rpu;                 /* Processing unit */
+       const char *name;       /* The name of the command */
+};
+
+#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
+
+static const struct cx18_api_info api_info[] = {
+       /* MPEG encoder API */
+       API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
+       API_ENTRY(CPU, CX18_EPU_DEBUG,                          0),
+       API_ENTRY(CPU, CX18_CREATE_TASK,                        0),
+       API_ENTRY(CPU, CX18_DESTROY_TASK,                       0),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_START,                  API_SLOW),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP,                   API_SLOW),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE,                  0),
+       API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
+       API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE,         0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN,                   0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM,               0),
+       API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE,        0),
+       API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING,              0),
+       API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE,                 0),
+       API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS,            0),
+       API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM,              API_SLOW),
+       API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO,            0),
+       API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT,                  0),
+       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID,                  0),
+       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID,                  0),
+       API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE,              0),
+       API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE,              0),
+       API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION,     0),
+       API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO,               0),
+       API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM,           0),
+       API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER,      0),
+       API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS,                    0),
+       API_ENTRY(CPU, CX18_CPU_SET_VFC_PARAM,                  0),
+       API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,                 0),
+       API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,                     API_FAST),
+       API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL,                 API_SLOW),
+       API_ENTRY(APU, CX18_APU_START,                          0),
+       API_ENTRY(APU, CX18_APU_STOP,                           0),
+       API_ENTRY(APU, CX18_APU_RESETAI,                        0),
+       API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32,                   0),
+       API_ENTRY(0, 0,                                         0),
+};
+
+static const struct cx18_api_info *find_api_info(u32 cmd)
+{
+       int i;
+
+       for (i = 0; api_info[i].cmd; i++)
+               if (api_info[i].cmd == cmd)
+                       return &api_info[i];
+       return NULL;
+}
+
+/* Call with buf of n*11+1 bytes */
+static char *u32arr2hex(u32 data[], int n, char *buf)
+{
+       char *p;
+       int i;
+
+       for (i = 0, p = buf; i < n; i++, p += 11) {
+               /* kernel snprintf() appends '\0' always */
+               snprintf(p, 12, " %#010x", data[i]);
+       }
+       *p = '\0';
+       return buf;
+}
+
+static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name)
+{
+       char argstr[MAX_MB_ARGUMENTS*11+1];
+
+       if (!(cx18_debug & CX18_DBGFLG_API))
+               return;
+
+       CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s"
+                      "\n", name, mb->request, mb->ack, mb->cmd, mb->error,
+                      u32arr2hex(mb->args, MAX_MB_ARGUMENTS, argstr));
+}
+
+
+/*
+ * Functions that run in a work_queue work handling context
+ */
+
+static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
+{
+       struct cx18_buffer *buf;
+
+       if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0)
+               return;
+
+       /* We ignore mdl and buf readpos accounting here - it doesn't matter */
+
+       /* The likely case */
+       if (list_is_singular(&mdl->buf_list)) {
+               buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
+                                      list);
+               if (buf->bytesused)
+                       dvb_dmx_swfilter(&s->dvb->demux,
+                                        buf->buf, buf->bytesused);
+               return;
+       }
+
+       list_for_each_entry(buf, &mdl->buf_list, list) {
+               if (buf->bytesused == 0)
+                       break;
+               dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused);
+       }
+}
+
+static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
+       struct cx18_mdl *mdl)
+{
+       struct cx18_videobuf_buffer *vb_buf;
+       struct cx18_buffer *buf;
+       u8 *p;
+       u32 offset = 0;
+       int dispatch = 0;
+
+       if (mdl->bytesused == 0)
+               return;
+
+       /* Acquire a videobuf buffer, clone to and and release it */
+       spin_lock(&s->vb_lock);
+       if (list_empty(&s->vb_capture))
+               goto out;
+
+       vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer,
+               vb.queue);
+
+       p = videobuf_to_vmalloc(&vb_buf->vb);
+       if (!p)
+               goto out;
+
+       offset = vb_buf->bytes_used;
+       list_for_each_entry(buf, &mdl->buf_list, list) {
+               if (buf->bytesused == 0)
+                       break;
+
+               if ((offset + buf->bytesused) <= vb_buf->vb.bsize) {
+                       memcpy(p + offset, buf->buf, buf->bytesused);
+                       offset += buf->bytesused;
+                       vb_buf->bytes_used += buf->bytesused;
+               }
+       }
+
+       /* If we've filled the buffer as per the callers res then dispatch it */
+       if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
+               dispatch = 1;
+               vb_buf->bytes_used = 0;
+       }
+
+       if (dispatch) {
+               vb_buf->vb.ts = ktime_to_timeval(ktime_get());
+               list_del(&vb_buf->vb.queue);
+               vb_buf->vb.state = VIDEOBUF_DONE;
+               wake_up(&vb_buf->vb.done);
+       }
+
+       mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
+
+out:
+       spin_unlock(&s->vb_lock);
+}
+
+static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s,
+                                 struct cx18_mdl *mdl)
+{
+       struct cx18_buffer *buf;
+
+       if (mdl->bytesused == 0)
+               return;
+
+       /* We ignore mdl and buf readpos accounting here - it doesn't matter */
+
+       /* The likely case */
+       if (list_is_singular(&mdl->buf_list)) {
+               buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
+                                      list);
+               if (buf->bytesused)
+                       cx->pcm_announce_callback(cx->alsa, buf->buf,
+                                                 buf->bytesused);
+               return;
+       }
+
+       list_for_each_entry(buf, &mdl->buf_list, list) {
+               if (buf->bytesused == 0)
+                       break;
+               cx->pcm_announce_callback(cx->alsa, buf->buf, buf->bytesused);
+       }
+}
+
+static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       u32 handle, mdl_ack_count, id;
+       struct cx18_mailbox *mb;
+       struct cx18_mdl_ack *mdl_ack;
+       struct cx18_stream *s;
+       struct cx18_mdl *mdl;
+       int i;
+
+       mb = &order->mb;
+       handle = mb->args[0];
+       s = cx18_handle_to_stream(cx, handle);
+
+       if (s == NULL) {
+               CX18_WARN("Got DMA done notification for unknown/inactive"
+                         " handle %d, %s mailbox seq no %d\n", handle,
+                         (order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) ?
+                         "stale" : "good", mb->request);
+               return;
+       }
+
+       mdl_ack_count = mb->args[2];
+       mdl_ack = order->mdl_ack;
+       for (i = 0; i < mdl_ack_count; i++, mdl_ack++) {
+               id = mdl_ack->id;
+               /*
+                * Simple integrity check for processing a stale (and possibly
+                * inconsistent mailbox): make sure the MDL id is in the
+                * valid range for the stream.
+                *
+                * We go through the trouble of dealing with stale mailboxes
+                * because most of the time, the mailbox data is still valid and
+                * unchanged (and in practice the firmware ping-pongs the
+                * two mdl_ack buffers so mdl_acks are not stale).
+                *
+                * There are occasions when we get a half changed mailbox,
+                * which this check catches for a handle & id mismatch.  If the
+                * handle and id do correspond, the worst case is that we
+                * completely lost the old MDL, but pick up the new MDL
+                * early (but the new mdl_ack is guaranteed to be good in this
+                * case as the firmware wouldn't point us to a new mdl_ack until
+                * it's filled in).
+                *
+                * cx18_queue_get_mdl() will detect the lost MDLs
+                * and send them back to q_free for fw rotation eventually.
+                */
+               if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) &&
+                   !(id >= s->mdl_base_idx &&
+                     id < (s->mdl_base_idx + s->buffers))) {
+                       CX18_WARN("Fell behind! Ignoring stale mailbox with "
+                                 " inconsistent data. Lost MDL for mailbox "
+                                 "seq no %d\n", mb->request);
+                       break;
+               }
+               mdl = cx18_queue_get_mdl(s, id, mdl_ack->data_used);
+
+               CX18_DEBUG_HI_DMA("DMA DONE for %s (MDL %d)\n", s->name, id);
+               if (mdl == NULL) {
+                       CX18_WARN("Could not find MDL %d for stream %s\n",
+                                 id, s->name);
+                       continue;
+               }
+
+               CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
+                                 s->name, mdl->bytesused);
+
+               if (s->type == CX18_ENC_STREAM_TYPE_TS) {
+                       cx18_mdl_send_to_dvb(s, mdl);
+                       cx18_enqueue(s, mdl, &s->q_free);
+               } else if (s->type == CX18_ENC_STREAM_TYPE_PCM) {
+                       /* Pass the data to cx18-alsa */
+                       if (cx->pcm_announce_callback != NULL) {
+                               cx18_mdl_send_to_alsa(cx, s, mdl);
+                               cx18_enqueue(s, mdl, &s->q_free);
+                       } else {
+                               cx18_enqueue(s, mdl, &s->q_full);
+                       }
+               } else if (s->type == CX18_ENC_STREAM_TYPE_YUV) {
+                       cx18_mdl_send_to_videobuf(s, mdl);
+                       cx18_enqueue(s, mdl, &s->q_free);
+               } else {
+                       cx18_enqueue(s, mdl, &s->q_full);
+                       if (s->type == CX18_ENC_STREAM_TYPE_IDX)
+                               cx18_stream_rotate_idx_mdls(cx);
+               }
+       }
+       /* Put as many MDLs as possible back into fw use */
+       cx18_stream_load_fw_queue(s);
+
+       wake_up(&cx->dma_waitq);
+       if (s->id != -1)
+               wake_up(&s->waitq);
+}
+
+static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       char *p;
+       char *str = order->str;
+
+       CX18_DEBUG_INFO("%x %s\n", order->mb.args[0], str);
+       p = strchr(str, '.');
+       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
+               CX18_INFO("FW version: %s\n", p - 1);
+}
+
+static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       switch (order->rpu) {
+       case CPU:
+       {
+               switch (order->mb.cmd) {
+               case CX18_EPU_DMA_DONE:
+                       epu_dma_done(cx, order);
+                       break;
+               case CX18_EPU_DEBUG:
+                       epu_debug(cx, order);
+                       break;
+               default:
+                       CX18_WARN("Unknown CPU to EPU mailbox command %#0x\n",
+                                 order->mb.cmd);
+                       break;
+               }
+               break;
+       }
+       case APU:
+               CX18_WARN("Unknown APU to EPU mailbox command %#0x\n",
+                         order->mb.cmd);
+               break;
+       default:
+               break;
+       }
+}
+
+static
+void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       atomic_set(&order->pending, 0);
+}
+
+void cx18_in_work_handler(struct work_struct *work)
+{
+       struct cx18_in_work_order *order =
+                       container_of(work, struct cx18_in_work_order, work);
+       struct cx18 *cx = order->cx;
+       epu_cmd(cx, order);
+       free_in_work_order(cx, order);
+}
+
+
+/*
+ * Functions that run in an interrupt handling context
+ */
+
+static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       struct cx18_mailbox __iomem *ack_mb;
+       u32 ack_irq, req;
+
+       switch (order->rpu) {
+       case APU:
+               ack_irq = IRQ_EPU_TO_APU_ACK;
+               ack_mb = &cx->scb->apu2epu_mb;
+               break;
+       case CPU:
+               ack_irq = IRQ_EPU_TO_CPU_ACK;
+               ack_mb = &cx->scb->cpu2epu_mb;
+               break;
+       default:
+               CX18_WARN("Unhandled RPU (%d) for command %x ack\n",
+                         order->rpu, order->mb.cmd);
+               return;
+       }
+
+       req = order->mb.request;
+       /* Don't ack if the RPU has gotten impatient and timed us out */
+       if (req != cx18_readl(cx, &ack_mb->request) ||
+           req == cx18_readl(cx, &ack_mb->ack)) {
+               CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
+                               "incoming %s to EPU mailbox (sequence no. %u) "
+                               "while processing\n",
+                               rpu_str[order->rpu], rpu_str[order->rpu], req);
+               order->flags |= CX18_F_EWO_MB_STALE_WHILE_PROC;
+               return;
+       }
+       cx18_writel(cx, req, &ack_mb->ack);
+       cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq);
+       return;
+}
+
+static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       u32 handle, mdl_ack_offset, mdl_ack_count;
+       struct cx18_mailbox *mb;
+       int i;
+
+       mb = &order->mb;
+       handle = mb->args[0];
+       mdl_ack_offset = mb->args[1];
+       mdl_ack_count = mb->args[2];
+
+       if (handle == CX18_INVALID_TASK_HANDLE ||
+           mdl_ack_count == 0 || mdl_ack_count > CX18_MAX_MDL_ACKS) {
+               if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
+                       mb_ack_irq(cx, order);
+               return -1;
+       }
+
+       for (i = 0; i < sizeof(struct cx18_mdl_ack) * mdl_ack_count; i += sizeof(u32))
+               ((u32 *)order->mdl_ack)[i / sizeof(u32)] =
+                       cx18_readl(cx, cx->enc_mem + mdl_ack_offset + i);
+
+       if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
+               mb_ack_irq(cx, order);
+       return 1;
+}
+
+static
+int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       u32 str_offset;
+       char *str = order->str;
+
+       str[0] = '\0';
+       str_offset = order->mb.args[1];
+       if (str_offset) {
+               cx18_setup_page(cx, str_offset);
+               cx18_memcpy_fromio(cx, str, cx->enc_mem + str_offset, 252);
+               str[252] = '\0';
+               cx18_setup_page(cx, SCB_OFFSET);
+       }
+
+       if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
+               mb_ack_irq(cx, order);
+
+       return str_offset ? 1 : 0;
+}
+
+static inline
+int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+       int ret = -1;
+
+       switch (order->rpu) {
+       case CPU:
+       {
+               switch (order->mb.cmd) {
+               case CX18_EPU_DMA_DONE:
+                       ret = epu_dma_done_irq(cx, order);
+                       break;
+               case CX18_EPU_DEBUG:
+                       ret = epu_debug_irq(cx, order);
+                       break;
+               default:
+                       CX18_WARN("Unknown CPU to EPU mailbox command %#0x\n",
+                                 order->mb.cmd);
+                       break;
+               }
+               break;
+       }
+       case APU:
+               CX18_WARN("Unknown APU to EPU mailbox command %#0x\n",
+                         order->mb.cmd);
+               break;
+       default:
+               break;
+       }
+       return ret;
+}
+
+static inline
+struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx)
+{
+       int i;
+       struct cx18_in_work_order *order = NULL;
+
+       for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
+               /*
+                * We only need "pending" atomic to inspect its contents,
+                * and need not do a check and set because:
+                * 1. Any work handler thread only clears "pending" and only
+                * on one, particular work order at a time, per handler thread.
+                * 2. "pending" is only set here, and we're serialized because
+                * we're called in an IRQ handler context.
+                */
+               if (atomic_read(&cx->in_work_order[i].pending) == 0) {
+                       order = &cx->in_work_order[i];
+                       atomic_set(&order->pending, 1);
+                       break;
+               }
+       }
+       return order;
+}
+
+void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
+{
+       struct cx18_mailbox __iomem *mb;
+       struct cx18_mailbox *order_mb;
+       struct cx18_in_work_order *order;
+       int submit;
+       int i;
+
+       switch (rpu) {
+       case CPU:
+               mb = &cx->scb->cpu2epu_mb;
+               break;
+       case APU:
+               mb = &cx->scb->apu2epu_mb;
+               break;
+       default:
+               return;
+       }
+
+       order = alloc_in_work_order_irq(cx);
+       if (order == NULL) {
+               CX18_WARN("Unable to find blank work order form to schedule "
+                         "incoming mailbox command processing\n");
+               return;
+       }
+
+       order->flags = 0;
+       order->rpu = rpu;
+       order_mb = &order->mb;
+
+       /* mb->cmd and mb->args[0] through mb->args[2] */
+       for (i = 0; i < 4; i++)
+               (&order_mb->cmd)[i] = cx18_readl(cx, &mb->cmd + i);
+
+       /* mb->request and mb->ack.  N.B. we want to read mb->ack last */
+       for (i = 0; i < 2; i++)
+               (&order_mb->request)[i] = cx18_readl(cx, &mb->request + i);
+
+       if (order_mb->request == order_mb->ack) {
+               CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
+                               "incoming %s to EPU mailbox (sequence no. %u)"
+                               "\n",
+                               rpu_str[rpu], rpu_str[rpu], order_mb->request);
+               if (cx18_debug & CX18_DBGFLG_WARN)
+                       dump_mb(cx, order_mb, "incoming");
+               order->flags = CX18_F_EWO_MB_STALE_UPON_RECEIPT;
+       }
+
+       /*
+        * Individual EPU command processing is responsible for ack-ing
+        * a non-stale mailbox as soon as possible
+        */
+       submit = epu_cmd_irq(cx, order);
+       if (submit > 0) {
+               queue_work(cx->in_work_queue, &order->work);
+       }
+}
+
+
+/*
+ * Functions called from a non-interrupt, non work_queue context
+ */
+
+static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+       const struct cx18_api_info *info = find_api_info(cmd);
+       u32 irq, req, ack, err;
+       struct cx18_mailbox __iomem *mb;
+       wait_queue_head_t *waitq;
+       struct mutex *mb_lock;
+       unsigned long int t0, timeout, ret;
+       int i;
+       char argstr[MAX_MB_ARGUMENTS*11+1];
+       DEFINE_WAIT(w);
+
+       if (info == NULL) {
+               CX18_WARN("unknown cmd %x\n", cmd);
+               return -EINVAL;
+       }
+
+       if (cx18_debug & CX18_DBGFLG_API) { /* only call u32arr2hex if needed */
+               if (cmd == CX18_CPU_DE_SET_MDL) {
+                       if (cx18_debug & CX18_DBGFLG_HIGHVOL)
+                               CX18_DEBUG_HI_API("%s\tcmd %#010x args%s\n",
+                                               info->name, cmd,
+                                               u32arr2hex(data, args, argstr));
+               } else
+                       CX18_DEBUG_API("%s\tcmd %#010x args%s\n",
+                                      info->name, cmd,
+                                      u32arr2hex(data, args, argstr));
+       }
+
+       switch (info->rpu) {
+       case APU:
+               waitq = &cx->mb_apu_waitq;
+               mb_lock = &cx->epu2apu_mb_lock;
+               irq = IRQ_EPU_TO_APU;
+               mb = &cx->scb->epu2apu_mb;
+               break;
+       case CPU:
+               waitq = &cx->mb_cpu_waitq;
+               mb_lock = &cx->epu2cpu_mb_lock;
+               irq = IRQ_EPU_TO_CPU;
+               mb = &cx->scb->epu2cpu_mb;
+               break;
+       default:
+               CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu);
+               return -EINVAL;
+       }
+
+       mutex_lock(mb_lock);
+       /*
+        * Wait for an in-use mailbox to complete
+        *
+        * If the XPU is responding with Ack's, the mailbox shouldn't be in
+        * a busy state, since we serialize access to it on our end.
+        *
+        * If the wait for ack after sending a previous command was interrupted
+        * by a signal, we may get here and find a busy mailbox.  After waiting,
+        * mark it "not busy" from our end, if the XPU hasn't ack'ed it still.
+        */
+       req = cx18_readl(cx, &mb->request);
+       timeout = msecs_to_jiffies(10);
+       ret = wait_event_timeout(*waitq,
+                                (ack = cx18_readl(cx, &mb->ack)) == req,
+                                timeout);
+       if (req != ack) {
+               /* waited long enough, make the mbox "not busy" from our end */
+               cx18_writel(cx, req, &mb->ack);
+               CX18_ERR("mbox was found stuck busy when setting up for %s; "
+                        "clearing busy and trying to proceed\n", info->name);
+       } else if (ret != timeout)
+               CX18_DEBUG_API("waited %u msecs for busy mbox to be acked\n",
+                              jiffies_to_msecs(timeout-ret));
+
+       /* Build the outgoing mailbox */
+       req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1;
+
+       cx18_writel(cx, cmd, &mb->cmd);
+       for (i = 0; i < args; i++)
+               cx18_writel(cx, data[i], &mb->args[i]);
+       cx18_writel(cx, 0, &mb->error);
+       cx18_writel(cx, req, &mb->request);
+       cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */
+
+       /*
+        * Notify the XPU and wait for it to send an Ack back
+        */
+       timeout = msecs_to_jiffies((info->flags & API_FAST) ? 10 : 20);
+
+       CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
+                         irq, info->name);
+
+       /* So we don't miss the wakeup, prepare to wait before notifying fw */
+       prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE);
+       cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
+
+       t0 = jiffies;
+       ack = cx18_readl(cx, &mb->ack);
+       if (ack != req) {
+               schedule_timeout(timeout);
+               ret = jiffies - t0;
+               ack = cx18_readl(cx, &mb->ack);
+       } else {
+               ret = jiffies - t0;
+       }
+
+       finish_wait(waitq, &w);
+
+       if (req != ack) {
+               mutex_unlock(mb_lock);
+               if (ret >= timeout) {
+                       /* Timed out */
+                       CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
+                                       "for RPU acknowledgement\n",
+                                       info->name, jiffies_to_msecs(ret));
+               } else {
+                       CX18_DEBUG_WARN("woken up before mailbox ack was ready "
+                                       "after submitting %s to RPU.  only "
+                                       "waited %d msecs on req %u but awakened"
+                                       " with unmatched ack %u\n",
+                                       info->name,
+                                       jiffies_to_msecs(ret),
+                                       req, ack);
+               }
+               return -EINVAL;
+       }
+
+       if (ret >= timeout)
+               CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
+                               "sending %s; timed out waiting %d msecs\n",
+                               info->name, jiffies_to_msecs(ret));
+       else
+               CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
+                                 jiffies_to_msecs(ret), info->name);
+
+       /* Collect data returned by the XPU */
+       for (i = 0; i < MAX_MB_ARGUMENTS; i++)
+               data[i] = cx18_readl(cx, &mb->args[i]);
+       err = cx18_readl(cx, &mb->error);
+       mutex_unlock(mb_lock);
+
+       /*
+        * Wait for XPU to perform extra actions for the caller in some cases.
+        * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all MDLs
+        * back in a burst shortly thereafter
+        */
+       if (info->flags & API_SLOW)
+               cx18_msleep_timeout(300, 0);
+
+       if (err)
+               CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
+                               info->name);
+       return err ? -EIO : 0;
+}
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+       return cx18_api_call(cx, cmd, args, data);
+}
+
+static int cx18_set_filter_param(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       u32 mode;
+       int ret;
+
+       mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
+       ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+                       s->handle, 1, mode, cx->spatial_strength);
+       mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
+       ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+                       s->handle, 0, mode, cx->temporal_strength);
+       ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+                       s->handle, 2, cx->filter_mode >> 2, 0);
+       return ret;
+}
+
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+               u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct cx18_stream *s = priv;
+       struct cx18 *cx = s->cx;
+
+       switch (cmd) {
+       case CX2341X_ENC_SET_OUTPUT_PORT:
+               return 0;
+       case CX2341X_ENC_SET_FRAME_RATE:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
+                               s->handle, 0, 0, 0, 0, data[0]);
+       case CX2341X_ENC_SET_FRAME_SIZE:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
+                               s->handle, data[1], data[0]);
+       case CX2341X_ENC_SET_STREAM_TYPE:
+               return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_SET_ASPECT_RATIO:
+               return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
+                               s->handle, data[0]);
+
+       case CX2341X_ENC_SET_GOP_PROPERTIES:
+               return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
+                               s->handle, data[0], data[1]);
+       case CX2341X_ENC_SET_GOP_CLOSURE:
+               return 0;
+       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+               return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_MUTE_AUDIO:
+               return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_SET_BIT_RATE:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
+                               s->handle, data[0], data[1], data[2], data[3]);
+       case CX2341X_ENC_MUTE_VIDEO:
+               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_SET_FRAME_DROP_RATE:
+               return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
+                               s->handle, data[0]);
+       case CX2341X_ENC_MISC:
+               return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
+                               s->handle, data[0], data[1], data[2]);
+       case CX2341X_ENC_SET_DNR_FILTER_MODE:
+               cx->filter_mode = (data[0] & 3) | (data[1] << 2);
+               return cx18_set_filter_param(s);
+       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+               cx->spatial_strength = data[0];
+               cx->temporal_strength = data[1];
+               return cx18_set_filter_param(s);
+       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+               return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
+                               s->handle, data[0], data[1]);
+       case CX2341X_ENC_SET_CORING_LEVELS:
+               return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
+                               s->handle, data[0], data[1], data[2], data[3]);
+       }
+       CX18_WARN("Unknown cmd %x\n", cmd);
+       return 0;
+}
+
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
+               u32 cmd, int args, ...)
+{
+       va_list ap;
+       int i;
+
+       va_start(ap, args);
+       for (i = 0; i < args; i++)
+               data[i] = va_arg(ap, u32);
+       va_end(ap);
+       return cx18_api(cx, cmd, args, data);
+}
+
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
+{
+       u32 data[MAX_MB_ARGUMENTS];
+       va_list ap;
+       int i;
+
+       if (cx == NULL) {
+               CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
+               return 0;
+       }
+       if (args > MAX_MB_ARGUMENTS) {
+               CX18_ERR("args too big (cmd=%x)\n", cmd);
+               args = MAX_MB_ARGUMENTS;
+       }
+       va_start(ap, args);
+       for (i = 0; i < args; i++)
+               data[i] = va_arg(ap, u32);
+       va_end(ap);
+       return cx18_api(cx, cmd, args, data);
+}
diff --git a/drivers/media/pci/cx18/cx18-mailbox.h b/drivers/media/pci/cx18/cx18-mailbox.h
new file mode 100644 (file)
index 0000000..b63fdfa
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  cx18 mailbox functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef _CX18_MAILBOX_H_
+#define _CX18_MAILBOX_H_
+
+/* mailbox max args */
+#define MAX_MB_ARGUMENTS 6
+/* compatibility, should be same as the define in cx2341x.h */
+#define CX2341X_MBOX_MAX_DATA 16
+
+#define MB_RESERVED_HANDLE_0 0
+#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
+
+#define APU 0
+#define CPU 1
+#define EPU 2
+#define HPU 3
+
+struct cx18;
+
+/*
+ * This structure is used by CPU to provide completed MDL & buffers information.
+ * Its structure is dictated by the layout of the SCB, required by the
+ * firmware, but its definition needs to be here, instead of in cx18-scb.h,
+ * for mailbox work order scheduling
+ */
+struct cx18_mdl_ack {
+    u32 id;        /* ID of a completed MDL */
+    u32 data_used; /* Total data filled in the MDL with 'id' */
+};
+
+/* The cx18_mailbox struct is the mailbox structure which is used for passing
+   messages between processors */
+struct cx18_mailbox {
+    /* The sender sets a handle in 'request' after he fills the command. The
+       'request' should be different than 'ack'. The sender, also, generates
+       an interrupt on XPU2YPU_irq where XPU is the sender and YPU is the
+       receiver. */
+    u32       request;
+    /* The receiver detects a new command when 'req' is different than 'ack'.
+       He sets 'ack' to the same value as 'req' to clear the command. He, also,
+       generates an interrupt on YPU2XPU_irq where XPU is the sender and YPU
+       is the receiver. */
+    u32       ack;
+    u32       reserved[6];
+    /* 'cmd' identifies the command. The list of these commands are in
+       cx23418.h */
+    u32       cmd;
+    /* Each command can have up to 6 arguments */
+    u32       args[MAX_MB_ARGUMENTS];
+    /* The return code can be one of the codes in the file cx23418.h. If the
+       command is completed successfully, the error will be ERR_SYS_SUCCESS.
+       If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
+       code would indicate the task from which the error originated and will
+       be one of the errors in cx23418.h. In that case, the following
+       applies ((error & 0xff) != 0).
+       If the command is pending, the return will be passed in a MB from the
+       receiver to the sender. 'req' will be returned in args[0] */
+    u32       error;
+};
+
+struct cx18_stream;
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
+               int args, ...);
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+               u32 data[CX2341X_MBOX_MAX_DATA]);
+
+void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu);
+
+void cx18_in_work_handler(struct work_struct *work);
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-queue.c b/drivers/media/pci/cx18/cx18-queue.c
new file mode 100644 (file)
index 0000000..8884537
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ *  cx18 buffer queues
+ *
+ *  Derived from ivtv-queue.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-scb.h"
+#include "cx18-io.h"
+
+void cx18_buf_swap(struct cx18_buffer *buf)
+{
+       int i;
+
+       for (i = 0; i < buf->bytesused; i += 4)
+               swab32s((u32 *)(buf->buf + i));
+}
+
+void _cx18_mdl_swap(struct cx18_mdl *mdl)
+{
+       struct cx18_buffer *buf;
+
+       list_for_each_entry(buf, &mdl->buf_list, list) {
+               if (buf->bytesused == 0)
+                       break;
+               cx18_buf_swap(buf);
+       }
+}
+
+void cx18_queue_init(struct cx18_queue *q)
+{
+       INIT_LIST_HEAD(&q->list);
+       atomic_set(&q->depth, 0);
+       q->bytesused = 0;
+}
+
+struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
+                                struct cx18_queue *q, int to_front)
+{
+       /* clear the mdl if it is not to be enqueued to the full queue */
+       if (q != &s->q_full) {
+               mdl->bytesused = 0;
+               mdl->readpos = 0;
+               mdl->m_flags = 0;
+               mdl->skipped = 0;
+               mdl->curr_buf = NULL;
+       }
+
+       /* q_busy is restricted to a max buffer count imposed by firmware */
+       if (q == &s->q_busy &&
+           atomic_read(&q->depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
+               q = &s->q_free;
+
+       spin_lock(&q->lock);
+
+       if (to_front)
+               list_add(&mdl->list, &q->list); /* LIFO */
+       else
+               list_add_tail(&mdl->list, &q->list); /* FIFO */
+       q->bytesused += mdl->bytesused - mdl->readpos;
+       atomic_inc(&q->depth);
+
+       spin_unlock(&q->lock);
+       return q;
+}
+
+struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
+{
+       struct cx18_mdl *mdl = NULL;
+
+       spin_lock(&q->lock);
+       if (!list_empty(&q->list)) {
+               mdl = list_first_entry(&q->list, struct cx18_mdl, list);
+               list_del_init(&mdl->list);
+               q->bytesused -= mdl->bytesused - mdl->readpos;
+               mdl->skipped = 0;
+               atomic_dec(&q->depth);
+       }
+       spin_unlock(&q->lock);
+       return mdl;
+}
+
+static void _cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
+                                         struct cx18_mdl *mdl)
+{
+       struct cx18_buffer *buf;
+       u32 buf_size = s->buf_size;
+       u32 bytesused = mdl->bytesused;
+
+       list_for_each_entry(buf, &mdl->buf_list, list) {
+               buf->readpos = 0;
+               if (bytesused >= buf_size) {
+                       buf->bytesused = buf_size;
+                       bytesused -= buf_size;
+               } else {
+                       buf->bytesused = bytesused;
+                       bytesused = 0;
+               }
+               cx18_buf_sync_for_cpu(s, buf);
+       }
+}
+
+static inline void cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
+                                               struct cx18_mdl *mdl)
+{
+       struct cx18_buffer *buf;
+
+       if (list_is_singular(&mdl->buf_list)) {
+               buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
+                                      list);
+               buf->bytesused = mdl->bytesused;
+               buf->readpos = 0;
+               cx18_buf_sync_for_cpu(s, buf);
+       } else {
+               _cx18_mdl_update_bufs_for_cpu(s, mdl);
+       }
+}
+
+struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
+       u32 bytesused)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_mdl *mdl;
+       struct cx18_mdl *tmp;
+       struct cx18_mdl *ret = NULL;
+       LIST_HEAD(sweep_up);
+
+       /*
+        * We don't have to acquire multiple q locks here, because we are
+        * serialized by the single threaded work handler.
+        * MDLs from the firmware will thus remain in order as
+        * they are moved from q_busy to q_full or to the dvb ring buffer.
+        */
+       spin_lock(&s->q_busy.lock);
+       list_for_each_entry_safe(mdl, tmp, &s->q_busy.list, list) {
+               /*
+                * We should find what the firmware told us is done,
+                * right at the front of the queue.  If we don't, we likely have
+                * missed an mdl done message from the firmware.
+                * Once we skip an mdl repeatedly, relative to the size of
+                * q_busy, we have high confidence we've missed it.
+                */
+               if (mdl->id != id) {
+                       mdl->skipped++;
+                       if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) {
+                               /* mdl must have fallen out of rotation */
+                               CX18_WARN("Skipped %s, MDL %d, %d "
+                                         "times - it must have dropped out of "
+                                         "rotation\n", s->name, mdl->id,
+                                         mdl->skipped);
+                               /* Sweep it up to put it back into rotation */
+                               list_move_tail(&mdl->list, &sweep_up);
+                               atomic_dec(&s->q_busy.depth);
+                       }
+                       continue;
+               }
+               /*
+                * We pull the desired mdl off of the queue here.  Something
+                * will have to put it back on a queue later.
+                */
+               list_del_init(&mdl->list);
+               atomic_dec(&s->q_busy.depth);
+               ret = mdl;
+               break;
+       }
+       spin_unlock(&s->q_busy.lock);
+
+       /*
+        * We found the mdl for which we were looking.  Get it ready for
+        * the caller to put on q_full or in the dvb ring buffer.
+        */
+       if (ret != NULL) {
+               ret->bytesused = bytesused;
+               ret->skipped = 0;
+               /* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */
+               cx18_mdl_update_bufs_for_cpu(s, ret);
+               if (s->type != CX18_ENC_STREAM_TYPE_TS)
+                       set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags);
+       }
+
+       /* Put any mdls the firmware is ignoring back into normal rotation */
+       list_for_each_entry_safe(mdl, tmp, &sweep_up, list) {
+               list_del_init(&mdl->list);
+               cx18_enqueue(s, mdl, &s->q_free);
+       }
+       return ret;
+}
+
+/* Move all mdls of a queue, while flushing the mdl */
+static void cx18_queue_flush(struct cx18_stream *s,
+                            struct cx18_queue *q_src, struct cx18_queue *q_dst)
+{
+       struct cx18_mdl *mdl;
+
+       /* It only makes sense to flush to q_free or q_idle */
+       if (q_src == q_dst || q_dst == &s->q_full || q_dst == &s->q_busy)
+               return;
+
+       spin_lock(&q_src->lock);
+       spin_lock(&q_dst->lock);
+       while (!list_empty(&q_src->list)) {
+               mdl = list_first_entry(&q_src->list, struct cx18_mdl, list);
+               list_move_tail(&mdl->list, &q_dst->list);
+               mdl->bytesused = 0;
+               mdl->readpos = 0;
+               mdl->m_flags = 0;
+               mdl->skipped = 0;
+               mdl->curr_buf = NULL;
+               atomic_inc(&q_dst->depth);
+       }
+       cx18_queue_init(q_src);
+       spin_unlock(&q_src->lock);
+       spin_unlock(&q_dst->lock);
+}
+
+void cx18_flush_queues(struct cx18_stream *s)
+{
+       cx18_queue_flush(s, &s->q_busy, &s->q_free);
+       cx18_queue_flush(s, &s->q_full, &s->q_free);
+}
+
+/*
+ * Note, s->buf_pool is not protected by a lock,
+ * the stream better not have *anything* going on when calling this
+ */
+void cx18_unload_queues(struct cx18_stream *s)
+{
+       struct cx18_queue *q_idle = &s->q_idle;
+       struct cx18_mdl *mdl;
+       struct cx18_buffer *buf;
+
+       /* Move all MDLS to q_idle */
+       cx18_queue_flush(s, &s->q_busy, q_idle);
+       cx18_queue_flush(s, &s->q_full, q_idle);
+       cx18_queue_flush(s, &s->q_free, q_idle);
+
+       /* Reset MDL id's and move all buffers back to the stream's buf_pool */
+       spin_lock(&q_idle->lock);
+       list_for_each_entry(mdl, &q_idle->list, list) {
+               while (!list_empty(&mdl->buf_list)) {
+                       buf = list_first_entry(&mdl->buf_list,
+                                              struct cx18_buffer, list);
+                       list_move_tail(&buf->list, &s->buf_pool);
+                       buf->bytesused = 0;
+                       buf->readpos = 0;
+               }
+               mdl->id = s->mdl_base_idx; /* reset id to a "safe" value */
+               /* all other mdl fields were cleared by cx18_queue_flush() */
+       }
+       spin_unlock(&q_idle->lock);
+}
+
+/*
+ * Note, s->buf_pool is not protected by a lock,
+ * the stream better not have *anything* going on when calling this
+ */
+void cx18_load_queues(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_mdl *mdl;
+       struct cx18_buffer *buf;
+       int mdl_id;
+       int i;
+       u32 partial_buf_size;
+
+       /*
+        * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free
+        * Excess MDLs are left on q_idle
+        * Excess buffers are left in buf_pool and/or on an MDL in q_idle
+        */
+       mdl_id = s->mdl_base_idx;
+       for (mdl = cx18_dequeue(s, &s->q_idle), i = s->bufs_per_mdl;
+            mdl != NULL && i == s->bufs_per_mdl;
+            mdl = cx18_dequeue(s, &s->q_idle)) {
+
+               mdl->id = mdl_id;
+
+               for (i = 0; i < s->bufs_per_mdl; i++) {
+                       if (list_empty(&s->buf_pool))
+                               break;
+
+                       buf = list_first_entry(&s->buf_pool, struct cx18_buffer,
+                                              list);
+                       list_move_tail(&buf->list, &mdl->buf_list);
+
+                       /* update the firmware's MDL array with this buffer */
+                       cx18_writel(cx, buf->dma_handle,
+                                   &cx->scb->cpu_mdl[mdl_id + i].paddr);
+                       cx18_writel(cx, s->buf_size,
+                                   &cx->scb->cpu_mdl[mdl_id + i].length);
+               }
+
+               if (i == s->bufs_per_mdl) {
+                       /*
+                        * The encoder doesn't honor s->mdl_size.  So in the
+                        * case of a non-integral number of buffers to meet
+                        * mdl_size, we lie about the size of the last buffer
+                        * in the MDL to get the encoder to really only send
+                        * us mdl_size bytes per MDL transfer.
+                        */
+                       partial_buf_size = s->mdl_size % s->buf_size;
+                       if (partial_buf_size) {
+                               cx18_writel(cx, partial_buf_size,
+                                     &cx->scb->cpu_mdl[mdl_id + i - 1].length);
+                       }
+                       cx18_enqueue(s, mdl, &s->q_free);
+               } else {
+                       /* Not enough buffers for this MDL; we won't use it */
+                       cx18_push(s, mdl, &s->q_idle);
+               }
+               mdl_id += i;
+       }
+}
+
+void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl)
+{
+       int dma = s->dma;
+       u32 buf_size = s->buf_size;
+       struct pci_dev *pci_dev = s->cx->pci_dev;
+       struct cx18_buffer *buf;
+
+       list_for_each_entry(buf, &mdl->buf_list, list)
+               pci_dma_sync_single_for_device(pci_dev, buf->dma_handle,
+                                              buf_size, dma);
+}
+
+int cx18_stream_alloc(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       int i;
+
+       if (s->buffers == 0)
+               return 0;
+
+       CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers "
+                       "(%d.%02d kB total)\n",
+               s->name, s->buffers, s->buf_size,
+               s->buffers * s->buf_size / 1024,
+               (s->buffers * s->buf_size * 100 / 1024) % 100);
+
+       if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] -
+                               (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
+               unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
+                                       ((char __iomem *)cx->scb->cpu_mdl));
+
+               CX18_ERR("Too many buffers, cannot fit in SCB area\n");
+               CX18_ERR("Max buffers = %zd\n",
+                       bufsz / sizeof(struct cx18_mdl_ent));
+               return -ENOMEM;
+       }
+
+       s->mdl_base_idx = cx->free_mdl_idx;
+
+       /* allocate stream buffers and MDLs */
+       for (i = 0; i < s->buffers; i++) {
+               struct cx18_mdl *mdl;
+               struct cx18_buffer *buf;
+
+               /* 1 MDL per buffer to handle the worst & also default case */
+               mdl = kzalloc(sizeof(struct cx18_mdl), GFP_KERNEL|__GFP_NOWARN);
+               if (mdl == NULL)
+                       break;
+
+               buf = kzalloc(sizeof(struct cx18_buffer),
+                               GFP_KERNEL|__GFP_NOWARN);
+               if (buf == NULL) {
+                       kfree(mdl);
+                       break;
+               }
+
+               buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN);
+               if (buf->buf == NULL) {
+                       kfree(mdl);
+                       kfree(buf);
+                       break;
+               }
+
+               INIT_LIST_HEAD(&mdl->list);
+               INIT_LIST_HEAD(&mdl->buf_list);
+               mdl->id = s->mdl_base_idx; /* a somewhat safe value */
+               cx18_enqueue(s, mdl, &s->q_idle);
+
+               INIT_LIST_HEAD(&buf->list);
+               buf->dma_handle = pci_map_single(s->cx->pci_dev,
+                               buf->buf, s->buf_size, s->dma);
+               cx18_buf_sync_for_cpu(s, buf);
+               list_add_tail(&buf->list, &s->buf_pool);
+       }
+       if (i == s->buffers) {
+               cx->free_mdl_idx += s->buffers;
+               return 0;
+       }
+       CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
+       cx18_stream_free(s);
+       return -ENOMEM;
+}
+
+void cx18_stream_free(struct cx18_stream *s)
+{
+       struct cx18_mdl *mdl;
+       struct cx18_buffer *buf;
+       struct cx18 *cx = s->cx;
+
+       CX18_DEBUG_INFO("Deallocating buffers for %s stream\n", s->name);
+
+       /* move all buffers to buf_pool and all MDLs to q_idle */
+       cx18_unload_queues(s);
+
+       /* empty q_idle */
+       while ((mdl = cx18_dequeue(s, &s->q_idle)))
+               kfree(mdl);
+
+       /* empty buf_pool */
+       while (!list_empty(&s->buf_pool)) {
+               buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list);
+               list_del_init(&buf->list);
+
+               pci_unmap_single(s->cx->pci_dev, buf->dma_handle,
+                               s->buf_size, s->dma);
+               kfree(buf->buf);
+               kfree(buf);
+       }
+}
diff --git a/drivers/media/pci/cx18/cx18-queue.h b/drivers/media/pci/cx18/cx18-queue.h
new file mode 100644 (file)
index 0000000..4201ddc
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  cx18 buffer queues
+ *
+ *  Derived from ivtv-queue.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#define CX18_DMA_UNMAPPED      ((u32) -1)
+
+/* cx18_buffer utility functions */
+
+static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
+       struct cx18_buffer *buf)
+{
+       pci_dma_sync_single_for_cpu(s->cx->pci_dev, buf->dma_handle,
+                               s->buf_size, s->dma);
+}
+
+static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
+       struct cx18_buffer *buf)
+{
+       pci_dma_sync_single_for_device(s->cx->pci_dev, buf->dma_handle,
+                               s->buf_size, s->dma);
+}
+
+void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl);
+
+static inline void cx18_mdl_sync_for_device(struct cx18_stream *s,
+                                           struct cx18_mdl *mdl)
+{
+       if (list_is_singular(&mdl->buf_list))
+               cx18_buf_sync_for_device(s, list_first_entry(&mdl->buf_list,
+                                                            struct cx18_buffer,
+                                                            list));
+       else
+               _cx18_mdl_sync_for_device(s, mdl);
+}
+
+void cx18_buf_swap(struct cx18_buffer *buf);
+void _cx18_mdl_swap(struct cx18_mdl *mdl);
+
+static inline void cx18_mdl_swap(struct cx18_mdl *mdl)
+{
+       if (list_is_singular(&mdl->buf_list))
+               cx18_buf_swap(list_first_entry(&mdl->buf_list,
+                                              struct cx18_buffer, list));
+       else
+               _cx18_mdl_swap(mdl);
+}
+
+/* cx18_queue utility functions */
+struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
+                                struct cx18_queue *q, int to_front);
+
+static inline
+struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
+                               struct cx18_queue *q)
+{
+       return _cx18_enqueue(s, mdl, q, 0); /* FIFO */
+}
+
+static inline
+struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_mdl *mdl,
+                            struct cx18_queue *q)
+{
+       return _cx18_enqueue(s, mdl, q, 1); /* LIFO */
+}
+
+void cx18_queue_init(struct cx18_queue *q);
+struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
+struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
+       u32 bytesused);
+void cx18_flush_queues(struct cx18_stream *s);
+
+/* queue MDL reconfiguration helpers */
+void cx18_unload_queues(struct cx18_stream *s);
+void cx18_load_queues(struct cx18_stream *s);
+
+/* cx18_stream utility functions */
+int cx18_stream_alloc(struct cx18_stream *s);
+void cx18_stream_free(struct cx18_stream *s);
diff --git a/drivers/media/pci/cx18/cx18-scb.c b/drivers/media/pci/cx18/cx18-scb.c
new file mode 100644 (file)
index 0000000..85cc596
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  cx18 System Control Block initialization
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-scb.h"
+
+void cx18_init_scb(struct cx18 *cx)
+{
+       cx18_setup_page(cx, SCB_OFFSET);
+       cx18_memset_io(cx, cx->scb, 0, 0x10000);
+
+       cx18_writel(cx, IRQ_APU_TO_CPU,     &cx->scb->apu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_CPU,     &cx->scb->hpu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_CPU,     &cx->scb->ppu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_CPU,     &cx->scb->epu2cpu_irq);
+       cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
+
+       cx18_writel(cx, IRQ_CPU_TO_APU,     &cx->scb->cpu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_APU,     &cx->scb->hpu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_APU,     &cx->scb->ppu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_APU,     &cx->scb->epu2apu_irq);
+       cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
+
+       cx18_writel(cx, IRQ_CPU_TO_HPU,     &cx->scb->cpu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_HPU,     &cx->scb->apu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_HPU,     &cx->scb->ppu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_HPU,     &cx->scb->epu2hpu_irq);
+       cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
+
+       cx18_writel(cx, IRQ_CPU_TO_PPU,     &cx->scb->cpu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_PPU,     &cx->scb->apu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_PPU,     &cx->scb->hpu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_EPU_TO_PPU,     &cx->scb->epu2ppu_irq);
+       cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
+
+       cx18_writel(cx, IRQ_CPU_TO_EPU,     &cx->scb->cpu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
+       cx18_writel(cx, IRQ_APU_TO_EPU,     &cx->scb->apu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
+       cx18_writel(cx, IRQ_HPU_TO_EPU,     &cx->scb->hpu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
+       cx18_writel(cx, IRQ_PPU_TO_EPU,     &cx->scb->ppu2epu_irq);
+       cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
+
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
+                       &cx->scb->apu2cpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
+                       &cx->scb->hpu2cpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
+                       &cx->scb->ppu2cpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
+                       &cx->scb->epu2cpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
+                       &cx->scb->cpu2apu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
+                       &cx->scb->hpu2apu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
+                       &cx->scb->ppu2apu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
+                       &cx->scb->epu2apu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
+                       &cx->scb->cpu2hpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
+                       &cx->scb->apu2hpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
+                       &cx->scb->ppu2hpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
+                       &cx->scb->epu2hpu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
+                       &cx->scb->cpu2ppu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
+                       &cx->scb->apu2ppu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
+                       &cx->scb->hpu2ppu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
+                       &cx->scb->epu2ppu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
+                       &cx->scb->cpu2epu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
+                       &cx->scb->apu2epu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
+                       &cx->scb->hpu2epu_mb_offset);
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
+                       &cx->scb->ppu2epu_mb_offset);
+
+       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
+                       &cx->scb->ipc_offset);
+
+       cx18_writel(cx, 1, &cx->scb->epu_state);
+}
diff --git a/drivers/media/pci/cx18/cx18-scb.h b/drivers/media/pci/cx18/cx18-scb.h
new file mode 100644 (file)
index 0000000..0887765
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *  cx18 System Control Block initialization
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX18_SCB_H
+#define CX18_SCB_H
+
+#include "cx18-mailbox.h"
+
+/* NOTE: All ACK interrupts are in the SW2 register.  All non-ACK interrupts
+   are in the SW1 register. */
+
+#define IRQ_APU_TO_CPU         0x00000001
+#define IRQ_CPU_TO_APU_ACK     0x00000001
+#define IRQ_HPU_TO_CPU         0x00000002
+#define IRQ_CPU_TO_HPU_ACK     0x00000002
+#define IRQ_PPU_TO_CPU         0x00000004
+#define IRQ_CPU_TO_PPU_ACK     0x00000004
+#define IRQ_EPU_TO_CPU         0x00000008
+#define IRQ_CPU_TO_EPU_ACK     0x00000008
+
+#define IRQ_CPU_TO_APU         0x00000010
+#define IRQ_APU_TO_CPU_ACK     0x00000010
+#define IRQ_HPU_TO_APU         0x00000020
+#define IRQ_APU_TO_HPU_ACK     0x00000020
+#define IRQ_PPU_TO_APU         0x00000040
+#define IRQ_APU_TO_PPU_ACK     0x00000040
+#define IRQ_EPU_TO_APU         0x00000080
+#define IRQ_APU_TO_EPU_ACK     0x00000080
+
+#define IRQ_CPU_TO_HPU         0x00000100
+#define IRQ_HPU_TO_CPU_ACK     0x00000100
+#define IRQ_APU_TO_HPU         0x00000200
+#define IRQ_HPU_TO_APU_ACK     0x00000200
+#define IRQ_PPU_TO_HPU         0x00000400
+#define IRQ_HPU_TO_PPU_ACK     0x00000400
+#define IRQ_EPU_TO_HPU         0x00000800
+#define IRQ_HPU_TO_EPU_ACK     0x00000800
+
+#define IRQ_CPU_TO_PPU         0x00001000
+#define IRQ_PPU_TO_CPU_ACK     0x00001000
+#define IRQ_APU_TO_PPU         0x00002000
+#define IRQ_PPU_TO_APU_ACK     0x00002000
+#define IRQ_HPU_TO_PPU         0x00004000
+#define IRQ_PPU_TO_HPU_ACK     0x00004000
+#define IRQ_EPU_TO_PPU         0x00008000
+#define IRQ_PPU_TO_EPU_ACK     0x00008000
+
+#define IRQ_CPU_TO_EPU         0x00010000
+#define IRQ_EPU_TO_CPU_ACK     0x00010000
+#define IRQ_APU_TO_EPU         0x00020000
+#define IRQ_EPU_TO_APU_ACK     0x00020000
+#define IRQ_HPU_TO_EPU         0x00040000
+#define IRQ_EPU_TO_HPU_ACK     0x00040000
+#define IRQ_PPU_TO_EPU         0x00080000
+#define IRQ_EPU_TO_PPU_ACK     0x00080000
+
+#define SCB_OFFSET  0xDC0000
+
+/* If Firmware uses fixed memory map, it shall not allocate the area
+   between SCB_OFFSET and SCB_OFFSET+SCB_RESERVED_SIZE-1 inclusive */
+#define SCB_RESERVED_SIZE 0x10000
+
+
+/* This structure is used by EPU to provide memory descriptors in its memory */
+struct cx18_mdl_ent {
+    u32 paddr;  /* Physical address of a buffer segment */
+    u32 length; /* Length of the buffer segment */
+};
+
+struct cx18_scb {
+       /* These fields form the System Control Block which is used at boot time
+          for localizing the IPC data as well as the code positions for all
+          processors. The offsets are from the start of this struct. */
+
+       /* Offset where to find the Inter-Processor Communication data */
+       u32 ipc_offset;
+       u32 reserved01[7];
+       /* Offset where to find the start of the CPU code */
+       u32 cpu_code_offset;
+       u32 reserved02[3];
+       /* Offset where to find the start of the APU code */
+       u32 apu_code_offset;
+       u32 reserved03[3];
+       /* Offset where to find the start of the HPU code */
+       u32 hpu_code_offset;
+       u32 reserved04[3];
+       /* Offset where to find the start of the PPU code */
+       u32 ppu_code_offset;
+       u32 reserved05[3];
+
+       /* These fields form Inter-Processor Communication data which is used
+          by all processors to locate the information needed for communicating
+          with other processors */
+
+       /* Fields for CPU: */
+
+       /* bit 0: 1/0 processor ready/not ready. Set other bits to 0. */
+       u32 cpu_state;
+       u32 reserved1[7];
+       /* Offset to the mailbox used for sending commands from APU to CPU */
+       u32 apu2cpu_mb_offset;
+       /* Value to write to register SW1 register set (0xC7003100) after the
+          command is ready */
+       u32 apu2cpu_irq;
+       /* Value to write to register SW2 register set (0xC7003140) after the
+          command is cleared */
+       u32 cpu2apu_irq_ack;
+       u32 reserved2[13];
+
+       u32 hpu2cpu_mb_offset;
+       u32 hpu2cpu_irq;
+       u32 cpu2hpu_irq_ack;
+       u32 reserved3[13];
+
+       u32 ppu2cpu_mb_offset;
+       u32 ppu2cpu_irq;
+       u32 cpu2ppu_irq_ack;
+       u32 reserved4[13];
+
+       u32 epu2cpu_mb_offset;
+       u32 epu2cpu_irq;
+       u32 cpu2epu_irq_ack;
+       u32 reserved5[13];
+       u32 reserved6[8];
+
+       /* Fields for APU: */
+
+       u32 apu_state;
+       u32 reserved11[7];
+       u32 cpu2apu_mb_offset;
+       u32 cpu2apu_irq;
+       u32 apu2cpu_irq_ack;
+       u32 reserved12[13];
+
+       u32 hpu2apu_mb_offset;
+       u32 hpu2apu_irq;
+       u32 apu2hpu_irq_ack;
+       u32 reserved13[13];
+
+       u32 ppu2apu_mb_offset;
+       u32 ppu2apu_irq;
+       u32 apu2ppu_irq_ack;
+       u32 reserved14[13];
+
+       u32 epu2apu_mb_offset;
+       u32 epu2apu_irq;
+       u32 apu2epu_irq_ack;
+       u32 reserved15[13];
+       u32 reserved16[8];
+
+       /* Fields for HPU: */
+
+       u32 hpu_state;
+       u32 reserved21[7];
+       u32 cpu2hpu_mb_offset;
+       u32 cpu2hpu_irq;
+       u32 hpu2cpu_irq_ack;
+       u32 reserved22[13];
+
+       u32 apu2hpu_mb_offset;
+       u32 apu2hpu_irq;
+       u32 hpu2apu_irq_ack;
+       u32 reserved23[13];
+
+       u32 ppu2hpu_mb_offset;
+       u32 ppu2hpu_irq;
+       u32 hpu2ppu_irq_ack;
+       u32 reserved24[13];
+
+       u32 epu2hpu_mb_offset;
+       u32 epu2hpu_irq;
+       u32 hpu2epu_irq_ack;
+       u32 reserved25[13];
+       u32 reserved26[8];
+
+       /* Fields for PPU: */
+
+       u32 ppu_state;
+       u32 reserved31[7];
+       u32 cpu2ppu_mb_offset;
+       u32 cpu2ppu_irq;
+       u32 ppu2cpu_irq_ack;
+       u32 reserved32[13];
+
+       u32 apu2ppu_mb_offset;
+       u32 apu2ppu_irq;
+       u32 ppu2apu_irq_ack;
+       u32 reserved33[13];
+
+       u32 hpu2ppu_mb_offset;
+       u32 hpu2ppu_irq;
+       u32 ppu2hpu_irq_ack;
+       u32 reserved34[13];
+
+       u32 epu2ppu_mb_offset;
+       u32 epu2ppu_irq;
+       u32 ppu2epu_irq_ack;
+       u32 reserved35[13];
+       u32 reserved36[8];
+
+       /* Fields for EPU: */
+
+       u32 epu_state;
+       u32 reserved41[7];
+       u32 cpu2epu_mb_offset;
+       u32 cpu2epu_irq;
+       u32 epu2cpu_irq_ack;
+       u32 reserved42[13];
+
+       u32 apu2epu_mb_offset;
+       u32 apu2epu_irq;
+       u32 epu2apu_irq_ack;
+       u32 reserved43[13];
+
+       u32 hpu2epu_mb_offset;
+       u32 hpu2epu_irq;
+       u32 epu2hpu_irq_ack;
+       u32 reserved44[13];
+
+       u32 ppu2epu_mb_offset;
+       u32 ppu2epu_irq;
+       u32 epu2ppu_irq_ack;
+       u32 reserved45[13];
+       u32 reserved46[8];
+
+       u32 semaphores[8];  /* Semaphores */
+
+       u32 reserved50[32]; /* Reserved for future use */
+
+       struct cx18_mailbox  apu2cpu_mb;
+       struct cx18_mailbox  hpu2cpu_mb;
+       struct cx18_mailbox  ppu2cpu_mb;
+       struct cx18_mailbox  epu2cpu_mb;
+
+       struct cx18_mailbox  cpu2apu_mb;
+       struct cx18_mailbox  hpu2apu_mb;
+       struct cx18_mailbox  ppu2apu_mb;
+       struct cx18_mailbox  epu2apu_mb;
+
+       struct cx18_mailbox  cpu2hpu_mb;
+       struct cx18_mailbox  apu2hpu_mb;
+       struct cx18_mailbox  ppu2hpu_mb;
+       struct cx18_mailbox  epu2hpu_mb;
+
+       struct cx18_mailbox  cpu2ppu_mb;
+       struct cx18_mailbox  apu2ppu_mb;
+       struct cx18_mailbox  hpu2ppu_mb;
+       struct cx18_mailbox  epu2ppu_mb;
+
+       struct cx18_mailbox  cpu2epu_mb;
+       struct cx18_mailbox  apu2epu_mb;
+       struct cx18_mailbox  hpu2epu_mb;
+       struct cx18_mailbox  ppu2epu_mb;
+
+       struct cx18_mdl_ack  cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];
+       struct cx18_mdl_ent  cpu_mdl[1];
+};
+
+void cx18_init_scb(struct cx18 *cx);
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
new file mode 100644 (file)
index 0000000..9d598ab
--- /dev/null
@@ -0,0 +1,1060 @@
+/*
+ *  cx18 init/start/stop/exit stream functions
+ *
+ *  Derived from ivtv-streams.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-fileops.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-ioctl.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "cx18-scb.h"
+#include "cx18-dvb.h"
+
+#define CX18_DSP0_INTERRUPT_MASK       0xd0004C
+
+static struct v4l2_file_operations cx18_v4l2_enc_fops = {
+       .owner = THIS_MODULE,
+       .read = cx18_v4l2_read,
+       .open = cx18_v4l2_open,
+       .unlocked_ioctl = video_ioctl2,
+       .release = cx18_v4l2_close,
+       .poll = cx18_v4l2_enc_poll,
+       .mmap = cx18_v4l2_mmap,
+};
+
+/* offset from 0 to register ts v4l2 minors on */
+#define CX18_V4L2_ENC_TS_OFFSET   16
+/* offset from 0 to register pcm v4l2 minors on */
+#define CX18_V4L2_ENC_PCM_OFFSET  24
+/* offset from 0 to register yuv v4l2 minors on */
+#define CX18_V4L2_ENC_YUV_OFFSET  32
+
+static struct {
+       const char *name;
+       int vfl_type;
+       int num_offset;
+       int dma;
+       enum v4l2_buf_type buf_type;
+} cx18_stream_info[] = {
+       {       /* CX18_ENC_STREAM_TYPE_MPG */
+               "encoder MPEG",
+               VFL_TYPE_GRABBER, 0,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       },
+       {       /* CX18_ENC_STREAM_TYPE_TS */
+               "TS",
+               VFL_TYPE_GRABBER, -1,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       },
+       {       /* CX18_ENC_STREAM_TYPE_YUV */
+               "encoder YUV",
+               VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       },
+       {       /* CX18_ENC_STREAM_TYPE_VBI */
+               "encoder VBI",
+               VFL_TYPE_VBI, 0,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
+       },
+       {       /* CX18_ENC_STREAM_TYPE_PCM */
+               "encoder PCM audio",
+               VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
+       },
+       {       /* CX18_ENC_STREAM_TYPE_IDX */
+               "encoder IDX",
+               VFL_TYPE_GRABBER, -1,
+               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       },
+       {       /* CX18_ENC_STREAM_TYPE_RAD */
+               "encoder radio",
+               VFL_TYPE_RADIO, 0,
+               PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
+       },
+};
+
+
+void cx18_dma_free(struct videobuf_queue *q,
+       struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
+{
+       videobuf_waiton(q, &buf->vb, 0, 0);
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int cx18_prepare_buffer(struct videobuf_queue *q,
+       struct cx18_stream *s,
+       struct cx18_videobuf_buffer *buf,
+       u32 pixelformat,
+       unsigned int width, unsigned int height,
+       enum v4l2_field field)
+{
+        struct cx18 *cx = s->cx;
+       int rc = 0;
+
+       /* check settings */
+       buf->bytes_used = 0;
+
+       if ((width  < 48) || (height < 32))
+               return -EINVAL;
+
+       buf->vb.size = (width * height * 2);
+       if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
+               return -EINVAL;
+
+       /* alloc + fill struct (if changed) */
+       if (buf->vb.width != width || buf->vb.height != height ||
+           buf->vb.field != field || s->pixelformat != pixelformat ||
+           buf->tvnorm != cx->std) {
+
+               buf->vb.width  = width;
+               buf->vb.height = height;
+               buf->vb.field  = field;
+               buf->tvnorm    = cx->std;
+               s->pixelformat = pixelformat;
+
+               /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+                  UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+               if (s->pixelformat == V4L2_PIX_FMT_HM12)
+                       s->vb_bytes_per_frame = height * 720 * 3 / 2;
+               else
+                       s->vb_bytes_per_frame = height * 720 * 2;
+               cx18_dma_free(q, s, buf);
+       }
+
+       if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
+               return -EINVAL;
+
+       if (buf->vb.field == 0)
+               buf->vb.field = V4L2_FIELD_INTERLACED;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               buf->vb.width  = width;
+               buf->vb.height = height;
+               buf->vb.field  = field;
+               buf->tvnorm    = cx->std;
+               s->pixelformat = pixelformat;
+
+               /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+                  UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+               if (s->pixelformat == V4L2_PIX_FMT_HM12)
+                       s->vb_bytes_per_frame = height * 720 * 3 / 2;
+               else
+                       s->vb_bytes_per_frame = height * 720 * 2;
+               rc = videobuf_iolock(q, &buf->vb, NULL);
+               if (rc != 0)
+                       goto fail;
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       cx18_dma_free(q, s, buf);
+       return rc;
+
+}
+
+/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)
+   1440 is a single line of 4:2:2 YUV at 720 luma samples wide
+*/
+#define VB_MIN_BUFFERS 32
+#define VB_MIN_BUFSIZE 4147200
+
+static int buffer_setup(struct videobuf_queue *q,
+       unsigned int *count, unsigned int *size)
+{
+       struct cx18_stream *s = q->priv_data;
+       struct cx18 *cx = s->cx;
+
+       *size = 2 * cx->cxhdl.width * cx->cxhdl.height;
+       if (*count == 0)
+               *count = VB_MIN_BUFFERS;
+
+       while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
+               (*count)--;
+
+       q->field = V4L2_FIELD_INTERLACED;
+       q->last = V4L2_FIELD_INTERLACED;
+
+       return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q,
+       struct videobuf_buffer *vb,
+       enum v4l2_field field)
+{
+       struct cx18_videobuf_buffer *buf =
+               container_of(vb, struct cx18_videobuf_buffer, vb);
+       struct cx18_stream *s = q->priv_data;
+       struct cx18 *cx = s->cx;
+
+       return cx18_prepare_buffer(q, s, buf, s->pixelformat,
+               cx->cxhdl.width, cx->cxhdl.height, field);
+}
+
+static void buffer_release(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       struct cx18_videobuf_buffer *buf =
+               container_of(vb, struct cx18_videobuf_buffer, vb);
+       struct cx18_stream *s = q->priv_data;
+
+       cx18_dma_free(q, s, buf);
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx18_videobuf_buffer *buf =
+               container_of(vb, struct cx18_videobuf_buffer, vb);
+       struct cx18_stream *s = q->priv_data;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+
+       list_add_tail(&buf->vb.queue, &s->vb_capture);
+}
+
+static struct videobuf_queue_ops cx18_videobuf_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+
+static void cx18_stream_init(struct cx18 *cx, int type)
+{
+       struct cx18_stream *s = &cx->streams[type];
+       struct video_device *video_dev = s->video_dev;
+
+       /* we need to keep video_dev, so restore it afterwards */
+       memset(s, 0, sizeof(*s));
+       s->video_dev = video_dev;
+
+       /* initialize cx18_stream fields */
+       s->dvb = NULL;
+       s->cx = cx;
+       s->type = type;
+       s->name = cx18_stream_info[type].name;
+       s->handle = CX18_INVALID_TASK_HANDLE;
+
+       s->dma = cx18_stream_info[type].dma;
+       s->buffers = cx->stream_buffers[type];
+       s->buf_size = cx->stream_buf_size[type];
+       INIT_LIST_HEAD(&s->buf_pool);
+       s->bufs_per_mdl = 1;
+       s->mdl_size = s->buf_size * s->bufs_per_mdl;
+
+       init_waitqueue_head(&s->waitq);
+       s->id = -1;
+       spin_lock_init(&s->q_free.lock);
+       cx18_queue_init(&s->q_free);
+       spin_lock_init(&s->q_busy.lock);
+       cx18_queue_init(&s->q_busy);
+       spin_lock_init(&s->q_full.lock);
+       cx18_queue_init(&s->q_full);
+       spin_lock_init(&s->q_idle.lock);
+       cx18_queue_init(&s->q_idle);
+
+       INIT_WORK(&s->out_work_order, cx18_out_work_handler);
+
+       INIT_LIST_HEAD(&s->vb_capture);
+       s->vb_timeout.function = cx18_vb_timeout;
+       s->vb_timeout.data = (unsigned long)s;
+       init_timer(&s->vb_timeout);
+       spin_lock_init(&s->vb_lock);
+       if (type == CX18_ENC_STREAM_TYPE_YUV) {
+               spin_lock_init(&s->vbuf_q_lock);
+
+               s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,
+                       &cx->pci_dev->dev, &s->vbuf_q_lock,
+                       V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                       V4L2_FIELD_INTERLACED,
+                       sizeof(struct cx18_videobuf_buffer),
+                       s, &cx->serialize_lock);
+
+               /* Assume the previous pixel default */
+               s->pixelformat = V4L2_PIX_FMT_HM12;
+               s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
+       }
+}
+
+static int cx18_prep_dev(struct cx18 *cx, int type)
+{
+       struct cx18_stream *s = &cx->streams[type];
+       u32 cap = cx->v4l2_cap;
+       int num_offset = cx18_stream_info[type].num_offset;
+       int num = cx->instance + cx18_first_minor + num_offset;
+
+       /*
+        * These five fields are always initialized.
+        * For analog capture related streams, if video_dev == NULL then the
+        * stream is not in use.
+        * For the TS stream, if dvb == NULL then the stream is not in use.
+        * In those cases no other fields but these four can be used.
+        */
+       s->video_dev = NULL;
+       s->dvb = NULL;
+       s->cx = cx;
+       s->type = type;
+       s->name = cx18_stream_info[type].name;
+
+       /* Check whether the radio is supported */
+       if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))
+               return 0;
+
+       /* Check whether VBI is supported */
+       if (type == CX18_ENC_STREAM_TYPE_VBI &&
+           !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
+               return 0;
+
+       /* User explicitly selected 0 buffers for these streams, so don't
+          create them. */
+       if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
+           cx->stream_buffers[type] == 0) {
+               CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
+               return 0;
+       }
+
+       cx18_stream_init(cx, type);
+
+       /* Allocate the cx18_dvb struct only for the TS on cards with DTV */
+       if (type == CX18_ENC_STREAM_TYPE_TS) {
+               if (cx->card->hw_all & CX18_HW_DVB) {
+                       s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
+                       if (s->dvb == NULL) {
+                               CX18_ERR("Couldn't allocate cx18_dvb structure"
+                                        " for %s\n", s->name);
+                               return -ENOMEM;
+                       }
+               } else {
+                       /* Don't need buffers for the TS, if there is no DVB */
+                       s->buffers = 0;
+               }
+       }
+
+       if (num_offset == -1)
+               return 0;
+
+       /* allocate and initialize the v4l2 video device structure */
+       s->video_dev = video_device_alloc();
+       if (s->video_dev == NULL) {
+               CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
+                               s->name);
+               return -ENOMEM;
+       }
+
+       snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",
+                cx->v4l2_dev.name, s->name);
+
+       s->video_dev->num = num;
+       s->video_dev->v4l2_dev = &cx->v4l2_dev;
+       s->video_dev->fops = &cx18_v4l2_enc_fops;
+       s->video_dev->release = video_device_release;
+       s->video_dev->tvnorms = V4L2_STD_ALL;
+       s->video_dev->lock = &cx->serialize_lock;
+       set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
+       cx18_set_funcs(s->video_dev);
+       return 0;
+}
+
+/* Initialize v4l2 variables and register v4l2 devices */
+int cx18_streams_setup(struct cx18 *cx)
+{
+       int type, ret;
+
+       /* Setup V4L2 Devices */
+       for (type = 0; type < CX18_MAX_STREAMS; type++) {
+               /* Prepare device */
+               ret = cx18_prep_dev(cx, type);
+               if (ret < 0)
+                       break;
+
+               /* Allocate Stream */
+               ret = cx18_stream_alloc(&cx->streams[type]);
+               if (ret < 0)
+                       break;
+       }
+       if (type == CX18_MAX_STREAMS)
+               return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       cx18_streams_cleanup(cx, 0);
+       return ret;
+}
+
+static int cx18_reg_dev(struct cx18 *cx, int type)
+{
+       struct cx18_stream *s = &cx->streams[type];
+       int vfl_type = cx18_stream_info[type].vfl_type;
+       const char *name;
+       int num, ret;
+
+       if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
+               ret = cx18_dvb_register(s);
+               if (ret < 0) {
+                       CX18_ERR("DVB failed to register\n");
+                       return ret;
+               }
+       }
+
+       if (s->video_dev == NULL)
+               return 0;
+
+       num = s->video_dev->num;
+       /* card number + user defined offset + device offset */
+       if (type != CX18_ENC_STREAM_TYPE_MPG) {
+               struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+
+               if (s_mpg->video_dev)
+                       num = s_mpg->video_dev->num
+                           + cx18_stream_info[type].num_offset;
+       }
+       video_set_drvdata(s->video_dev, s);
+
+       /* Register device. First try the desired minor, then any free one. */
+       ret = video_register_device_no_warn(s->video_dev, vfl_type, num);
+       if (ret < 0) {
+               CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
+                       s->name, num);
+               video_device_release(s->video_dev);
+               s->video_dev = NULL;
+               return ret;
+       }
+
+       name = video_device_node_name(s->video_dev);
+
+       switch (vfl_type) {
+       case VFL_TYPE_GRABBER:
+               CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
+                         name, s->name, cx->stream_buffers[type],
+                         cx->stream_buf_size[type] / 1024,
+                         (cx->stream_buf_size[type] * 100 / 1024) % 100);
+               break;
+
+       case VFL_TYPE_RADIO:
+               CX18_INFO("Registered device %s for %s\n", name, s->name);
+               break;
+
+       case VFL_TYPE_VBI:
+               if (cx->stream_buffers[type])
+                       CX18_INFO("Registered device %s for %s "
+                                 "(%d x %d bytes)\n",
+                                 name, s->name, cx->stream_buffers[type],
+                                 cx->stream_buf_size[type]);
+               else
+                       CX18_INFO("Registered device %s for %s\n",
+                               name, s->name);
+               break;
+       }
+
+       return 0;
+}
+
+/* Register v4l2 devices */
+int cx18_streams_register(struct cx18 *cx)
+{
+       int type;
+       int err;
+       int ret = 0;
+
+       /* Register V4L2 devices */
+       for (type = 0; type < CX18_MAX_STREAMS; type++) {
+               err = cx18_reg_dev(cx, type);
+               if (err && ret == 0)
+                       ret = err;
+       }
+
+       if (ret == 0)
+               return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       cx18_streams_cleanup(cx, 1);
+       return ret;
+}
+
+/* Unregister v4l2 devices */
+void cx18_streams_cleanup(struct cx18 *cx, int unregister)
+{
+       struct video_device *vdev;
+       int type;
+
+       /* Teardown all streams */
+       for (type = 0; type < CX18_MAX_STREAMS; type++) {
+
+               /* The TS has a cx18_dvb structure, not a video_device */
+               if (type == CX18_ENC_STREAM_TYPE_TS) {
+                       if (cx->streams[type].dvb != NULL) {
+                               if (unregister)
+                                       cx18_dvb_unregister(&cx->streams[type]);
+                               kfree(cx->streams[type].dvb);
+                               cx->streams[type].dvb = NULL;
+                               cx18_stream_free(&cx->streams[type]);
+                       }
+                       continue;
+               }
+
+               /* No struct video_device, but can have buffers allocated */
+               if (type == CX18_ENC_STREAM_TYPE_IDX) {
+                       /* If the module params didn't inhibit IDX ... */
+                       if (cx->stream_buffers[type] != 0) {
+                               cx->stream_buffers[type] = 0;
+                               /*
+                                * Before calling cx18_stream_free(),
+                                * check if the IDX stream was actually set up.
+                                * Needed, since the cx18_probe() error path
+                                * exits through here as well as normal clean up
+                                */
+                               if (cx->streams[type].buffers != 0)
+                                       cx18_stream_free(&cx->streams[type]);
+                       }
+                       continue;
+               }
+
+               /* If struct video_device exists, can have buffers allocated */
+               vdev = cx->streams[type].video_dev;
+
+               cx->streams[type].video_dev = NULL;
+               if (vdev == NULL)
+                       continue;
+
+               if (type == CX18_ENC_STREAM_TYPE_YUV)
+                       videobuf_mmap_free(&cx->streams[type].vbuf_q);
+
+               cx18_stream_free(&cx->streams[type]);
+
+               /* Unregister or release device */
+               if (unregister)
+                       video_unregister_device(vdev);
+               else
+                       video_device_release(vdev);
+       }
+}
+
+static void cx18_vbi_setup(struct cx18_stream *s)
+{
+       struct cx18 *cx = s->cx;
+       int raw = cx18_raw_vbi(cx);
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       int lines;
+
+       if (cx->is_60hz) {
+               cx->vbi.count = 12;
+               cx->vbi.start[0] = 10;
+               cx->vbi.start[1] = 273;
+       } else {        /* PAL/SECAM */
+               cx->vbi.count = 18;
+               cx->vbi.start[0] = 6;
+               cx->vbi.start[1] = 318;
+       }
+
+       /* setup VBI registers */
+       if (raw)
+               v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi);
+       else
+               v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced);
+
+       /*
+        * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw
+        * VBI when the first analog capture channel starts, as once it starts
+        * (e.g. MPEG), we can't effect any change in the Encoder Raw VBI setup
+        * (i.e. for the VBI capture channels).  We also send it for each
+        * analog capture channel anyway just to make sure we get the proper
+        * behavior
+        */
+       if (raw) {
+               lines = cx->vbi.count * 2;
+       } else {
+               /*
+                * For 525/60 systems, according to the VIP 2 & BT.656 std:
+                * The EAV RP code's Field bit toggles on line 4, a few lines
+                * after the Vertcal Blank bit has already toggled.
+                * Tell the encoder to capture 21-4+1=18 lines per field,
+                * since we want lines 10 through 21.
+                *
+                * For 625/50 systems, according to the VIP 2 & BT.656 std:
+                * The EAV RP code's Field bit toggles on line 1, a few lines
+                * after the Vertcal Blank bit has already toggled.
+                * (We've actually set the digitizer so that the Field bit
+                * toggles on line 2.) Tell the encoder to capture 23-2+1=22
+                * lines per field, since we want lines 6 through 23.
+                */
+               lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2;
+       }
+
+       data[0] = s->handle;
+       /* Lines per field */
+       data[1] = (lines / 2) | ((lines / 2) << 16);
+       /* bytes per line */
+       data[2] = (raw ? vbi_active_samples
+                      : (cx->is_60hz ? vbi_hblank_samples_60Hz
+                                     : vbi_hblank_samples_50Hz));
+       /* Every X number of frames a VBI interrupt arrives
+          (frames as in 25 or 30 fps) */
+       data[3] = 1;
+       /*
+        * Set the SAV/EAV RP codes to look for as start/stop points
+        * when in VIP-1.1 mode
+        */
+       if (raw) {
+               /*
+                * Start codes for beginning of "active" line in vertical blank
+                * 0x20 (               VerticalBlank                )
+                * 0x60 (     EvenField VerticalBlank                )
+                */
+               data[4] = 0x20602060;
+               /*
+                * End codes for end of "active" raw lines and regular lines
+                * 0x30 (               VerticalBlank HorizontalBlank)
+                * 0x70 (     EvenField VerticalBlank HorizontalBlank)
+                * 0x90 (Task                         HorizontalBlank)
+                * 0xd0 (Task EvenField               HorizontalBlank)
+                */
+               data[5] = 0x307090d0;
+       } else {
+               /*
+                * End codes for active video, we want data in the hblank region
+                * 0xb0 (Task         0 VerticalBlank HorizontalBlank)
+                * 0xf0 (Task EvenField VerticalBlank HorizontalBlank)
+                *
+                * Since the V bit is only allowed to toggle in the EAV RP code,
+                * just before the first active region line, these two
+                * are problematic:
+                * 0x90 (Task                         HorizontalBlank)
+                * 0xd0 (Task EvenField               HorizontalBlank)
+                *
+                * We have set the digitzer such that we don't have to worry
+                * about these problem codes.
+                */
+               data[4] = 0xB0F0B0F0;
+               /*
+                * Start codes for beginning of active line in vertical blank
+                * 0xa0 (Task           VerticalBlank                )
+                * 0xe0 (Task EvenField VerticalBlank                )
+                */
+               data[5] = 0xA0E0A0E0;
+       }
+
+       CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",
+                       data[0], data[1], data[2], data[3], data[4], data[5]);
+
+       cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
+}
+
+void cx18_stream_rotate_idx_mdls(struct cx18 *cx)
+{
+       struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+       struct cx18_mdl *mdl;
+
+       if (!cx18_stream_enabled(s))
+               return;
+
+       /* Return if the firmware is not running low on MDLs */
+       if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >=
+                                           CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN)
+               return;
+
+       /* Return if there are no MDLs to rotate back to the firmware */
+       if (atomic_read(&s->q_full.depth) < 2)
+               return;
+
+       /*
+        * Take the oldest IDX MDL still holding data, and discard its index
+        * entries by scheduling the MDL to go back to the firmware
+        */
+       mdl = cx18_dequeue(s, &s->q_full);
+       if (mdl != NULL)
+               cx18_enqueue(s, mdl, &s->q_free);
+}
+
+static
+struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,
+                                          struct cx18_mdl *mdl)
+{
+       struct cx18 *cx = s->cx;
+       struct cx18_queue *q;
+
+       /* Don't give it to the firmware, if we're not running a capture */
+       if (s->handle == CX18_INVALID_TASK_HANDLE ||
+           test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
+           !test_bit(CX18_F_S_STREAMING, &s->s_flags))
+               return cx18_enqueue(s, mdl, &s->q_free);
+
+       q = cx18_enqueue(s, mdl, &s->q_busy);
+       if (q != &s->q_busy)
+               return q; /* The firmware has the max MDLs it can handle */
+
+       cx18_mdl_sync_for_device(s, mdl);
+       cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+                 (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem,
+                 s->bufs_per_mdl, mdl->id, s->mdl_size);
+       return q;
+}
+
+static
+void _cx18_stream_load_fw_queue(struct cx18_stream *s)
+{
+       struct cx18_queue *q;
+       struct cx18_mdl *mdl;
+
+       if (atomic_read(&s->q_free.depth) == 0 ||
+           atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
+               return;
+
+       /* Move from q_free to q_busy notifying the firmware, until the limit */
+       do {
+               mdl = cx18_dequeue(s, &s->q_free);
+               if (mdl == NULL)
+                       break;
+               q = _cx18_stream_put_mdl_fw(s, mdl);
+       } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM
+                && q == &s->q_busy);
+}
+
+void cx18_out_work_handler(struct work_struct *work)
+{
+       struct cx18_stream *s =
+                        container_of(work, struct cx18_stream, out_work_order);
+
+       _cx18_stream_load_fw_queue(s);
+}
+
+static void cx18_stream_configure_mdls(struct cx18_stream *s)
+{
+       cx18_unload_queues(s);
+
+       switch (s->type) {
+       case CX18_ENC_STREAM_TYPE_YUV:
+               /*
+                * Height should be a multiple of 32 lines.
+                * Set the MDL size to the exact size needed for one frame.
+                * Use enough buffers per MDL to cover the MDL size
+                */
+               if (s->pixelformat == V4L2_PIX_FMT_HM12)
+                       s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
+               else
+                       s->mdl_size = 720 * s->cx->cxhdl.height * 2;
+               s->bufs_per_mdl = s->mdl_size / s->buf_size;
+               if (s->mdl_size % s->buf_size)
+                       s->bufs_per_mdl++;
+               break;
+       case CX18_ENC_STREAM_TYPE_VBI:
+               s->bufs_per_mdl = 1;
+               if  (cx18_raw_vbi(s->cx)) {
+                       s->mdl_size = (s->cx->is_60hz ? 12 : 18)
+                                                      * 2 * vbi_active_samples;
+               } else {
+                       /*
+                        * See comment in cx18_vbi_setup() below about the
+                        * extra lines we capture in sliced VBI mode due to
+                        * the lines on which EAV RP codes toggle.
+                       */
+                       s->mdl_size = s->cx->is_60hz
+                                  ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz
+                                  : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;
+               }
+               break;
+       default:
+               s->bufs_per_mdl = 1;
+               s->mdl_size = s->buf_size * s->bufs_per_mdl;
+               break;
+       }
+
+       cx18_load_queues(s);
+}
+
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
+{
+       u32 data[MAX_MB_ARGUMENTS];
+       struct cx18 *cx = s->cx;
+       int captype = 0;
+       struct cx18_stream *s_idx;
+
+       if (!cx18_stream_enabled(s))
+               return -EINVAL;
+
+       CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
+       switch (s->type) {
+       case CX18_ENC_STREAM_TYPE_MPG:
+               captype = CAPTURE_CHANNEL_TYPE_MPEG;
+               cx->mpg_data_received = cx->vbi_data_inserted = 0;
+               cx->dualwatch_jiffies = jiffies;
+               cx->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
+               cx->search_pack_header = 0;
+               break;
+
+       case CX18_ENC_STREAM_TYPE_IDX:
+               captype = CAPTURE_CHANNEL_TYPE_INDEX;
+               break;
+       case CX18_ENC_STREAM_TYPE_TS:
+               captype = CAPTURE_CHANNEL_TYPE_TS;
+               break;
+       case CX18_ENC_STREAM_TYPE_YUV:
+               captype = CAPTURE_CHANNEL_TYPE_YUV;
+               break;
+       case CX18_ENC_STREAM_TYPE_PCM:
+               captype = CAPTURE_CHANNEL_TYPE_PCM;
+               break;
+       case CX18_ENC_STREAM_TYPE_VBI:
+#ifdef CX18_ENCODER_PARSES_SLICED
+               captype = cx18_raw_vbi(cx) ?
+                    CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI;
+#else
+               /*
+                * Currently we set things up so that Sliced VBI from the
+                * digitizer is handled as Raw VBI by the encoder
+                */
+               captype = CAPTURE_CHANNEL_TYPE_VBI;
+#endif
+               cx->vbi.frame = 0;
+               cx->vbi.inserted_frame = 0;
+               memset(cx->vbi.sliced_mpeg_size,
+                       0, sizeof(cx->vbi.sliced_mpeg_size));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Clear Streamoff flags in case left from last capture */
+       clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+       cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);
+       s->handle = data[0];
+       cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
+
+       /*
+        * For everything but CAPTURE_CHANNEL_TYPE_TS, play it safe and
+        * set up all the parameters, as it is not obvious which parameters the
+        * firmware shares across capture channel types and which it does not.
+        *
+        * Some of the cx18_vapi() calls below apply to only certain capture
+        * channel types.  We're hoping there's no harm in calling most of them
+        * anyway, as long as the values are all consistent.  Setting some
+        * shared parameters will have no effect once an analog capture channel
+        * has started streaming.
+        */
+       if (captype != CAPTURE_CHANNEL_TYPE_TS) {
+               cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);
+               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);
+
+               /*
+                * Audio related reset according to
+                * Documentation/video4linux/cx2341x/fw-encoder-api.txt
+                */
+               if (atomic_read(&cx->ana_capturing) == 0)
+                       cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
+                                 s->handle, 12);
+
+               /*
+                * Number of lines for Field 1 & Field 2 according to
+                * Documentation/video4linux/cx2341x/fw-encoder-api.txt
+                * Field 1 is 312 for 625 line systems in BT.656
+                * Field 2 is 313 for 625 line systems in BT.656
+                */
+               cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,
+                         s->handle, 312, 313);
+
+               if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
+                       cx18_vbi_setup(s);
+
+               /*
+                * Select to receive I, P, and B frame index entries, if the
+                * index stream is enabled.  Otherwise disable index entry
+                * generation.
+                */
+               s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+               cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2,
+                                s->handle, cx18_stream_enabled(s_idx) ? 7 : 0);
+
+               /* Call out to the common CX2341x API setup for user controls */
+               cx->cxhdl.priv = s;
+               cx2341x_handler_setup(&cx->cxhdl);
+
+               /*
+                * When starting a capture and we're set for radio,
+                * ensure the video is muted, despite the user control.
+                */
+               if (!cx->cxhdl.video_mute &&
+                   test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
+                       cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+                         (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);
+
+               /* Enable the Video Format Converter for UYVY 4:2:2 support,
+                * rather than the default HM12 Macroblovk 4:2:0 support.
+                */
+               if (captype == CAPTURE_CHANNEL_TYPE_YUV) {
+                       if (s->pixelformat == V4L2_PIX_FMT_UYVY)
+                               cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
+                                       s->handle, 1);
+                       else
+                               /* If in doubt, default to HM12 */
+                               cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
+                                       s->handle, 0);
+               }
+       }
+
+       if (atomic_read(&cx->tot_capturing) == 0) {
+               cx2341x_handler_set_busy(&cx->cxhdl, 1);
+               clear_bit(CX18_F_I_EOS, &cx->i_flags);
+               cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
+       }
+
+       cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
+               (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
+               (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
+
+       /* Init all the cpu_mdls for this stream */
+       cx18_stream_configure_mdls(s);
+       _cx18_stream_load_fw_queue(s);
+
+       /* begin_capture */
+       if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
+               CX18_DEBUG_WARN("Error starting capture!\n");
+               /* Ensure we're really not capturing before releasing MDLs */
+               set_bit(CX18_F_S_STOPPING, &s->s_flags);
+               if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
+               else
+                       cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+               clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+               /* FIXME - CX18_F_S_STREAMOFF as well? */
+               cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+               cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+               s->handle = CX18_INVALID_TASK_HANDLE;
+               clear_bit(CX18_F_S_STOPPING, &s->s_flags);
+               if (atomic_read(&cx->tot_capturing) == 0) {
+                       set_bit(CX18_F_I_EOS, &cx->i_flags);
+                       cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
+               }
+               return -EINVAL;
+       }
+
+       /* you're live! sit back and await interrupts :) */
+       if (captype != CAPTURE_CHANNEL_TYPE_TS)
+               atomic_inc(&cx->ana_capturing);
+       atomic_inc(&cx->tot_capturing);
+       return 0;
+}
+EXPORT_SYMBOL(cx18_start_v4l2_encode_stream);
+
+void cx18_stop_all_captures(struct cx18 *cx)
+{
+       int i;
+
+       for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
+               struct cx18_stream *s = &cx->streams[i];
+
+               if (!cx18_stream_enabled(s))
+                       continue;
+               if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
+                       cx18_stop_v4l2_encode_stream(s, 0);
+       }
+}
+
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
+{
+       struct cx18 *cx = s->cx;
+
+       if (!cx18_stream_enabled(s))
+               return -EINVAL;
+
+       /* This function assumes that you are allowed to stop the capture
+          and that we are actually capturing */
+
+       CX18_DEBUG_INFO("Stop Capture\n");
+
+       if (atomic_read(&cx->tot_capturing) == 0)
+               return 0;
+
+       set_bit(CX18_F_S_STOPPING, &s->s_flags);
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+               cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
+       else
+               cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+
+       if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {
+               CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
+       }
+
+       if (s->type != CX18_ENC_STREAM_TYPE_TS)
+               atomic_dec(&cx->ana_capturing);
+       atomic_dec(&cx->tot_capturing);
+
+       /* Clear capture and no-read bits */
+       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+
+       /* Tell the CX23418 it can't use our buffers anymore */
+       cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
+       cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+       s->handle = CX18_INVALID_TASK_HANDLE;
+       clear_bit(CX18_F_S_STOPPING, &s->s_flags);
+
+       if (atomic_read(&cx->tot_capturing) > 0)
+               return 0;
+
+       cx2341x_handler_set_busy(&cx->cxhdl, 0);
+       cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
+       wake_up(&s->waitq);
+
+       return 0;
+}
+EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream);
+
+u32 cx18_find_handle(struct cx18 *cx)
+{
+       int i;
+
+       /* find first available handle to be used for global settings */
+       for (i = 0; i < CX18_MAX_STREAMS; i++) {
+               struct cx18_stream *s = &cx->streams[i];
+
+               if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE))
+                       return s->handle;
+       }
+       return CX18_INVALID_TASK_HANDLE;
+}
+
+struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle)
+{
+       int i;
+       struct cx18_stream *s;
+
+       if (handle == CX18_INVALID_TASK_HANDLE)
+               return NULL;
+
+       for (i = 0; i < CX18_MAX_STREAMS; i++) {
+               s = &cx->streams[i];
+               if (s->handle != handle)
+                       continue;
+               if (cx18_stream_enabled(s))
+                       return s;
+       }
+       return NULL;
+}
diff --git a/drivers/media/pci/cx18/cx18-streams.h b/drivers/media/pci/cx18/cx18-streams.h
new file mode 100644 (file)
index 0000000..713b0e6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  cx18 init/start/stop/exit stream functions
+ *
+ *  Derived from ivtv-streams.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+u32 cx18_find_handle(struct cx18 *cx);
+struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle);
+int cx18_streams_setup(struct cx18 *cx);
+int cx18_streams_register(struct cx18 *cx);
+void cx18_streams_cleanup(struct cx18 *cx, int unregister);
+
+#define CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN (3)
+void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
+
+static inline bool cx18_stream_enabled(struct cx18_stream *s)
+{
+       return s->video_dev ||
+              (s->dvb && s->dvb->enabled) ||
+              (s->type == CX18_ENC_STREAM_TYPE_IDX &&
+               s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
+}
+
+/* Related to submission of mdls to firmware */
+static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
+{
+       schedule_work(&s->out_work_order);
+}
+
+static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s,
+                                         struct cx18_mdl *mdl)
+{
+       /* Put mdl on q_free; the out work handler will move mdl(s) to q_busy */
+       cx18_enqueue(s, mdl, &s->q_free);
+       cx18_stream_load_fw_queue(s);
+}
+
+void cx18_out_work_handler(struct work_struct *work);
+
+/* Capture related */
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
+
+void cx18_stop_all_captures(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c
new file mode 100644 (file)
index 0000000..6d3121f
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  cx18 Vertical Blank Interval support functions
+ *
+ *  Derived from ivtv-vbi.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-vbi.h"
+#include "cx18-ioctl.h"
+#include "cx18-queue.h"
+
+/*
+ * Raster Reference/Protection (RP) bytes, used in Start/End Active
+ * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start
+ * of VBI sample or VBI ancillary data regions in the digitial ratser line.
+ *
+ * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0
+ */
+static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 };    /* __V_, _FV_ */
+static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */
+
+static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
+{
+       int line = 0;
+       int i;
+       u32 linemask[2] = { 0, 0 };
+       unsigned short size;
+       static const u8 mpeg_hdr_data[] = {
+               /* MPEG-2 Program Pack */
+               0x00, 0x00, 0x01, 0xba,             /* Prog Pack start code */
+               0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */
+               0x01, 0xd1, 0xd3,                   /* Mux Rate, markers */
+               0xfa, 0xff, 0xff,                   /* Res, Suff cnt, Stuff */
+               /* MPEG-2 Private Stream 1 PES Packet */
+               0x00, 0x00, 0x01, 0xbd,             /* Priv Stream 1 start */
+               0x00, 0x1a,                         /* length */
+               0x84, 0x80, 0x07,                   /* flags, hdr data len */
+               0x21, 0x00, 0x5d, 0x63, 0xa7,       /* PTS, markers */
+               0xff, 0xff                          /* stuffing */
+       };
+       const int sd = sizeof(mpeg_hdr_data);   /* start of vbi data */
+       int idx = cx->vbi.frame % CX18_VBI_FRAMES;
+       u8 *dst = &cx->vbi.sliced_mpeg_data[idx][0];
+
+       for (i = 0; i < lines; i++) {
+               struct v4l2_sliced_vbi_data *sdata = cx->vbi.sliced_data + i;
+               int f, l;
+
+               if (sdata->id == 0)
+                       continue;
+
+               l = sdata->line - 6;
+               f = sdata->field;
+               if (f)
+                       l += 18;
+               if (l < 32)
+                       linemask[0] |= (1 << l);
+               else
+                       linemask[1] |= (1 << (l - 32));
+               dst[sd + 12 + line * 43] = cx18_service2vbi(sdata->id);
+               memcpy(dst + sd + 12 + line * 43 + 1, sdata->data, 42);
+               line++;
+       }
+       memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
+       if (line == 36) {
+               /* All lines are used, so there is no space for the linemask
+                  (the max size of the VBI data is 36 * 43 + 4 bytes).
+                  So in this case we use the magic number 'ITV0'. */
+               memcpy(dst + sd, "ITV0", 4);
+               memcpy(dst + sd + 4, dst + sd + 12, line * 43);
+               size = 4 + ((43 * line + 3) & ~3);
+       } else {
+               memcpy(dst + sd, "itv0", 4);
+               cpu_to_le32s(&linemask[0]);
+               cpu_to_le32s(&linemask[1]);
+               memcpy(dst + sd + 4, &linemask[0], 8);
+               size = 12 + ((43 * line + 3) & ~3);
+       }
+       dst[4+16] = (size + 10) >> 8;
+       dst[5+16] = (size + 10) & 0xff;
+       dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
+       dst[10+16] = (pts_stamp >> 22) & 0xff;
+       dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
+       dst[12+16] = (pts_stamp >> 7) & 0xff;
+       dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
+       cx->vbi.sliced_mpeg_size[idx] = sd + size;
+}
+
+/* Compress raw VBI format, removes leading SAV codes and surplus space
+   after the frame.  Returns new compressed size. */
+/* FIXME - this function ignores the input size. */
+static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size)
+{
+       u32 line_size = vbi_active_samples;
+       u32 lines = cx->vbi.count * 2;
+       u8 *q = buf;
+       u8 *p;
+       int i;
+
+       /* Skip the header */
+       buf += hdr_size;
+
+       for (i = 0; i < lines; i++) {
+               p = buf + i * line_size;
+
+               /* Look for SAV code */
+               if (p[0] != 0xff || p[1] || p[2] ||
+                   (p[3] != raw_vbi_sav_rp[0] &&
+                    p[3] != raw_vbi_sav_rp[1]))
+                       break;
+               if (i == lines - 1) {
+                       /* last line is hdr_size bytes short - extrapolate it */
+                       memcpy(q, p + 4, line_size - 4 - hdr_size);
+                       q += line_size - 4 - hdr_size;
+                       p += line_size - hdr_size - 1;
+                       memset(q, (int) *p, hdr_size);
+               } else {
+                       memcpy(q, p + 4, line_size - 4);
+                       q += line_size - 4;
+               }
+       }
+       return lines * (line_size - 4);
+}
+
+static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
+                              const u32 hdr_size)
+{
+       struct v4l2_decode_vbi_line vbi;
+       int i;
+       u32 line = 0;
+       u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz
+                                   : vbi_hblank_samples_50Hz;
+
+       /* find the first valid line */
+       for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) {
+               if (buf[0] == 0xff && !buf[1] && !buf[2] &&
+                   (buf[3] == sliced_vbi_eav_rp[0] ||
+                    buf[3] == sliced_vbi_eav_rp[1]))
+                       break;
+       }
+
+       /*
+        * The last line is short by hdr_size bytes, but for the remaining
+        * checks against size, we pretend that it is not, by counting the
+        * header bytes we knowingly skipped
+        */
+       size -= (i - hdr_size);
+       if (size < line_size)
+               return line;
+
+       for (i = 0; i < size / line_size; i++) {
+               u8 *p = buf + i * line_size;
+
+               /* Look for EAV code  */
+               if (p[0] != 0xff || p[1] || p[2] ||
+                   (p[3] != sliced_vbi_eav_rp[0] &&
+                    p[3] != sliced_vbi_eav_rp[1]))
+                       continue;
+               vbi.p = p + 4;
+               v4l2_subdev_call(cx->sd_av, vbi, decode_vbi_line, &vbi);
+               if (vbi.type) {
+                       cx->vbi.sliced_data[line].id = vbi.type;
+                       cx->vbi.sliced_data[line].field = vbi.is_second_field;
+                       cx->vbi.sliced_data[line].line = vbi.line;
+                       memcpy(cx->vbi.sliced_data[line].data, vbi.p, 42);
+                       line++;
+               }
+       }
+       return line;
+}
+
+static void _cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf)
+{
+       /*
+        * The CX23418 provides a 12 byte header in its raw VBI buffers to us:
+        * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp]
+        */
+       struct vbi_data_hdr {
+               __be32 magic;
+               __be32 unknown;
+               __be32 pts;
+       } *hdr = (struct vbi_data_hdr *) buf->buf;
+
+       u8 *p = (u8 *) buf->buf;
+       u32 size = buf->bytesused;
+       u32 pts;
+       int lines;
+
+       /*
+        * The CX23418 sends us data that is 32 bit little-endian swapped,
+        * but we want the raw VBI bytes in the order they were in the raster
+        * line.  This has a side effect of making the header big endian
+        */
+       cx18_buf_swap(buf);
+
+       /* Raw VBI data */
+       if (cx18_raw_vbi(cx)) {
+
+               size = buf->bytesused =
+                    compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr));
+
+               /*
+                * Hack needed for compatibility with old VBI software.
+                * Write the frame # at the last 4 bytes of the frame
+                */
+               p += size - 4;
+               memcpy(p, &cx->vbi.frame, 4);
+               cx->vbi.frame++;
+               return;
+       }
+
+       /* Sliced VBI data with data insertion */
+
+       pts = (be32_to_cpu(hdr->magic) == 0x3fffffff) ? be32_to_cpu(hdr->pts)
+                                                     : 0;
+
+       lines = compress_sliced_buf(cx, p, size, sizeof(struct vbi_data_hdr));
+
+       /* always return at least one empty line */
+       if (lines == 0) {
+               cx->vbi.sliced_data[0].id = 0;
+               cx->vbi.sliced_data[0].line = 0;
+               cx->vbi.sliced_data[0].field = 0;
+               lines = 1;
+       }
+       buf->bytesused = size = lines * sizeof(cx->vbi.sliced_data[0]);
+       memcpy(p, &cx->vbi.sliced_data[0], size);
+
+       if (cx->vbi.insert_mpeg)
+               copy_vbi_data(cx, lines, pts);
+       cx->vbi.frame++;
+}
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
+                          int streamtype)
+{
+       struct cx18_buffer *buf;
+       u32 orig_used;
+
+       if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
+               return;
+
+       /*
+        * Big assumption here:
+        * Every buffer hooked to the MDL's buf_list is a complete VBI frame
+        * that ends at the end of the buffer.
+        *
+        * To assume anything else would make the code in this file
+        * more complex, or require extra memcpy()'s to make the
+        * buffers satisfy the above assumption.  It's just simpler to set
+        * up the encoder buffer transfers to make the assumption true.
+        */
+       list_for_each_entry(buf, &mdl->buf_list, list) {
+               orig_used = buf->bytesused;
+               if (orig_used == 0)
+                       break;
+               _cx18_process_vbi_data(cx, buf);
+               mdl->bytesused -= (orig_used - buf->bytesused);
+       }
+}
diff --git a/drivers/media/pci/cx18/cx18-vbi.h b/drivers/media/pci/cx18/cx18-vbi.h
new file mode 100644 (file)
index 0000000..b365cf4
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *  cx18 Vertical Blank Interval support functions
+ *
+ *  Derived from ivtv-vbi.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
+                          int streamtype);
+int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/drivers/media/pci/cx18/cx18-version.h b/drivers/media/pci/cx18/cx18-version.h
new file mode 100644 (file)
index 0000000..fed48b6
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  cx18 driver version information
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX18_VERSION_H
+#define CX18_VERSION_H
+
+#define CX18_DRIVER_NAME "cx18"
+#define CX18_VERSION "1.5.1"
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-video.c b/drivers/media/pci/cx18/cx18-video.c
new file mode 100644 (file)
index 0000000..6dc84aa
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  cx18 video interface functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-video.h"
+#include "cx18-cards.h"
+
+void cx18_video_set_io(struct cx18 *cx)
+{
+       int inp = cx->active_input;
+
+       v4l2_subdev_call(cx->sd_av, video, s_routing,
+                       cx->card->video_inputs[inp].video_input, 0, 0);
+}
diff --git a/drivers/media/pci/cx18/cx18-video.h b/drivers/media/pci/cx18/cx18-video.h
new file mode 100644 (file)
index 0000000..529006a
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ *  cx18 video interface functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  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
+ */
+
+void cx18_video_set_io(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx23418.h b/drivers/media/pci/cx18/cx23418.h
new file mode 100644 (file)
index 0000000..767a8d2
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ *  cx18 header containing common defines.
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX23418_H
+#define CX23418_H
+
+#include <media/cx2341x.h>
+
+#define MGR_CMD_MASK                           0x40000000
+/* The MSB of the command code indicates that this is the completion of a
+   command */
+#define MGR_CMD_MASK_ACK                       (MGR_CMD_MASK | 0x80000000)
+
+/* Description: This command creates a new instance of a certain task
+   IN[0]  - Task ID. This is one of the XPU_CMD_MASK_YYY where XPU is
+           the processor on which the task YYY will be created
+   OUT[0] - Task handle. This handle is passed along with commands to
+           dispatch to the right instance of the task
+   ReturnCode - One of the ERR_SYS_... */
+#define CX18_CREATE_TASK                       (MGR_CMD_MASK | 0x0001)
+
+/* Description: This command destroys an instance of a task
+   IN[0] - Task handle. Hanlde of the task to destroy
+   ReturnCode - One of the ERR_SYS_... */
+#define CX18_DESTROY_TASK                      (MGR_CMD_MASK | 0x0002)
+
+/* All commands for CPU have the following mask set */
+#define CPU_CMD_MASK                           0x20000000
+#define CPU_CMD_MASK_DEBUG                     (CPU_CMD_MASK | 0x00000000)
+#define CPU_CMD_MASK_ACK                       (CPU_CMD_MASK | 0x80000000)
+#define CPU_CMD_MASK_CAPTURE                   (CPU_CMD_MASK | 0x00020000)
+#define CPU_CMD_MASK_TS                        (CPU_CMD_MASK | 0x00040000)
+
+#define EPU_CMD_MASK                           0x02000000
+#define EPU_CMD_MASK_DEBUG                     (EPU_CMD_MASK | 0x000000)
+#define EPU_CMD_MASK_DE                        (EPU_CMD_MASK | 0x040000)
+
+#define APU_CMD_MASK                           0x10000000
+#define APU_CMD_MASK_ACK                       (APU_CMD_MASK | 0x80000000)
+
+#define CX18_APU_ENCODING_METHOD_MPEG          (0 << 28)
+#define CX18_APU_ENCODING_METHOD_AC3           (1 << 28)
+
+/* Description: Command APU to start audio
+   IN[0] - audio parameters (same as CX18_CPU_SET_AUDIO_PARAMETERS?)
+   IN[1] - caller buffer address, or 0
+   ReturnCode - ??? */
+#define CX18_APU_START                         (APU_CMD_MASK | 0x01)
+
+/* Description: Command APU to stop audio
+   IN[0] - encoding method to stop
+   ReturnCode - ??? */
+#define CX18_APU_STOP                          (APU_CMD_MASK | 0x02)
+
+/* Description: Command APU to reset the AI
+   ReturnCode - ??? */
+#define CX18_APU_RESETAI                       (APU_CMD_MASK | 0x05)
+
+/* Description: This command indicates that a Memory Descriptor List has been
+   filled with the requested channel type
+   IN[0] - Task handle. Handle of the task
+   IN[1] - Offset of the MDL_ACK from the beginning of the local DDR.
+   IN[2] - Number of CNXT_MDL_ACK structures in the array pointed to by IN[1]
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_EPU_DMA_DONE                              (EPU_CMD_MASK_DE | 0x0001)
+
+/* Something interesting happened
+   IN[0] - A value to log
+   IN[1] - An offset of a string in the MiniMe memory;
+          0/zero/NULL means "I have nothing to say" */
+#define CX18_EPU_DEBUG                                 (EPU_CMD_MASK_DEBUG | 0x0003)
+
+/* Reads memory/registers (32-bit)
+   IN[0] - Address
+   OUT[1] - Value */
+#define CX18_CPU_DEBUG_PEEK32                  (CPU_CMD_MASK_DEBUG | 0x0003)
+
+/* Description: This command starts streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to start
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_START                 (CPU_CMD_MASK_CAPTURE | 0x0002)
+
+/* Description: This command stops streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to stop
+   IN[1] - 0 = stop at end of GOP, 1 = stop at end of frame (MPEG only)
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_STOP                  (CPU_CMD_MASK_CAPTURE | 0x0003)
+
+/* Description: This command pauses streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to pause
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_PAUSE                 (CPU_CMD_MASK_CAPTURE | 0x0007)
+
+/* Description: This command resumes streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to resume
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_RESUME                (CPU_CMD_MASK_CAPTURE | 0x0008)
+
+#define CAPTURE_CHANNEL_TYPE_NONE              0
+#define CAPTURE_CHANNEL_TYPE_MPEG              1
+#define CAPTURE_CHANNEL_TYPE_INDEX             2
+#define CAPTURE_CHANNEL_TYPE_YUV               3
+#define CAPTURE_CHANNEL_TYPE_PCM               4
+#define CAPTURE_CHANNEL_TYPE_VBI               5
+#define CAPTURE_CHANNEL_TYPE_SLICED_VBI                6
+#define CAPTURE_CHANNEL_TYPE_TS                        7
+#define CAPTURE_CHANNEL_TYPE_MAX               15
+
+/* Description: This command sets the channel type. This can only be done
+   when stopped.
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Channel Type. See Below.
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CHANNEL_TYPE                      (CPU_CMD_MASK_CAPTURE + 1)
+
+/* Description: Set stream output type
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - type
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_STREAM_OUTPUT_TYPE                (CPU_CMD_MASK_CAPTURE | 0x0012)
+
+/* Description: Set video input resolution and frame rate
+   IN[0] - task handle
+   IN[1] - reserved
+   IN[2] - reserved
+   IN[3] - reserved
+   IN[4] - reserved
+   IN[5] - frame rate, 0 - 29.97f/s, 1 - 25f/s
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_IN                  (CPU_CMD_MASK_CAPTURE | 0x0004)
+
+/* Description: Set video frame rate
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - video bit rate mode
+   IN[2] - video average rate
+   IN[3] - video peak rate
+   IN[4] - system mux rate
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RATE                (CPU_CMD_MASK_CAPTURE | 0x0005)
+
+/* Description: Set video output resolution
+   IN[0] - task handle
+   IN[1] - horizontal size
+   IN[2] - vertical size
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RESOLUTION          (CPU_CMD_MASK_CAPTURE | 0x0006)
+
+/* Description: This command set filter parameters
+   IN[0] - Task handle. Handle of the task
+   IN[1] - type, 0 - temporal, 1 - spatial, 2 - median
+   IN[2] - mode,  temporal/spatial: 0 - disable, 1 - static, 2 - dynamic
+                       median: 0 = disable, 1 = horizontal, 2 = vertical,
+                               3 = horizontal/vertical, 4 = diagonal
+   IN[3] - strength, temporal 0 - 31, spatial 0 - 15
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_FILTER_PARAM              (CPU_CMD_MASK_CAPTURE | 0x0009)
+
+/* Description: This command set spatial filter type
+   IN[0] - Task handle.
+   IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
+                     3 = 2D H/V separable, 4 = 2D symmetric non-separable
+   IN[2] - chroma type: 0 - disable, 1 = 1D horizontal
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SPATIAL_FILTER_TYPE       (CPU_CMD_MASK_CAPTURE | 0x000C)
+
+/* Description: This command set coring levels for median filter
+   IN[0] - Task handle.
+   IN[1] - luma_high
+   IN[2] - luma_low
+   IN[3] - chroma_high
+   IN[4] - chroma_low
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MEDIAN_CORING             (CPU_CMD_MASK_CAPTURE | 0x000E)
+
+/* Description: This command set the picture type mask for index file
+   IN[0] - Task handle (ignored by firmware)
+   IN[1] -     0 = disable index file output
+                       1 = output I picture
+                       2 = P picture
+                       4 = B picture
+                       other = illegal */
+#define CX18_CPU_SET_INDEXTABLE                (CPU_CMD_MASK_CAPTURE | 0x0010)
+
+/* Description: Set audio parameters
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - audio parameter
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PARAMETERS          (CPU_CMD_MASK_CAPTURE | 0x0011)
+
+/* Description: Set video mute
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - bit31-24: muteYvalue
+          bit23-16: muteUvalue
+          bit15-8:  muteVvalue
+          bit0:     1:mute, 0: unmute
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_MUTE                        (CPU_CMD_MASK_CAPTURE | 0x0013)
+
+/* Description: Set audio mute
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - mute/unmute
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_MUTE                        (CPU_CMD_MASK_CAPTURE | 0x0014)
+
+/* Description: Set stream output type
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - subType
+           SET_INITIAL_SCR                     1
+           SET_QUALITY_MODE            2
+           SET_VIM_PROTECT_MODE        3
+           SET_PTS_CORRECTION          4
+           SET_USB_FLUSH_MODE          5
+           SET_MERAQPAR_ENABLE         6
+           SET_NAV_PACK_INSERTION      7
+           SET_SCENE_CHANGE_ENABLE     8
+   IN[2] - parameter 1
+   IN[3] - parameter 2
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MISC_PARAMETERS           (CPU_CMD_MASK_CAPTURE | 0x0015)
+
+/* Description: Set raw VBI parameters
+   IN[0] - Task handle
+   IN[1] - No. of input lines per field:
+                               bit[15:0]: field 1,
+                               bit[31:16]: field 2
+   IN[2] - No. of input bytes per line
+   IN[3] - No. of output frames per transfer
+   IN[4] - start code
+   IN[5] - stop code
+   ReturnCode */
+#define CX18_CPU_SET_RAW_VBI_PARAM             (CPU_CMD_MASK_CAPTURE | 0x0016)
+
+/* Description: Set capture line No.
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - height1
+   IN[2] - height2
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CAPTURE_LINE_NO           (CPU_CMD_MASK_CAPTURE | 0x0017)
+
+/* Description: Set copyright
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - copyright
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_COPYRIGHT                 (CPU_CMD_MASK_CAPTURE | 0x0018)
+
+/* Description: Set audio PID
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - PID
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PID                 (CPU_CMD_MASK_CAPTURE | 0x0019)
+
+/* Description: Set video PID
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - PID
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_PID                 (CPU_CMD_MASK_CAPTURE | 0x001A)
+
+/* Description: Set Vertical Crop Line
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - Line
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VER_CROP_LINE             (CPU_CMD_MASK_CAPTURE | 0x001B)
+
+/* Description: Set COP structure
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - M
+   IN[2] - N
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_GOP_STRUCTURE             (CPU_CMD_MASK_CAPTURE | 0x001C)
+
+/* Description: Set Scene Change Detection
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - scene change
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SCENE_CHANGE_DETECTION    (CPU_CMD_MASK_CAPTURE | 0x001D)
+
+/* Description: Set Aspect Ratio
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - AspectRatio
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_ASPECT_RATIO              (CPU_CMD_MASK_CAPTURE | 0x001E)
+
+/* Description: Set Skip Input Frame
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - skip input frames
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SKIP_INPUT_FRAME          (CPU_CMD_MASK_CAPTURE | 0x001F)
+
+/* Description: Set sliced VBI parameters -
+   Note This API will only apply to MPEG and Sliced VBI Channels
+   IN[0] - Task handle
+   IN[1] - output type, 0 - CC, 1 - Moji, 2 - Teletext
+   IN[2] - start / stop line
+                       bit[15:0] start line number
+                       bit[31:16] stop line number
+   IN[3] - number of output frames per interrupt
+   IN[4] - VBI insertion mode
+                       bit 0:  output user data, 1 - enable
+                       bit 1:  output private stream, 1 - enable
+                       bit 2:  mux option, 0 - in GOP, 1 - in picture
+                       bit[7:0]        private stream ID
+   IN[5] - insertion period while mux option is in picture
+   ReturnCode - VBI data offset */
+#define CX18_CPU_SET_SLICED_VBI_PARAM          (CPU_CMD_MASK_CAPTURE | 0x0020)
+
+/* Description: Set the user data place holder
+   IN[0] - type of data (0 for user)
+   IN[1] - Stuffing period
+   IN[2] - ID data size in word (less than 10)
+   IN[3] - Pointer to ID buffer */
+#define CX18_CPU_SET_USERDATA_PLACE_HOLDER     (CPU_CMD_MASK_CAPTURE | 0x0021)
+
+
+/* Description:
+   In[0] Task Handle
+   return parameter:
+   Out[0]  Reserved
+   Out[1]  Video PTS bit[32:2] of last output video frame.
+   Out[2]  Video PTS bit[ 1:0] of last output video frame.
+   Out[3]  Hardware Video PTS counter bit[31:0],
+            these bits get incremented on every 90kHz clock tick.
+   Out[4]  Hardware Video PTS counter bit32,
+            these bits get incremented on every 90kHz clock tick.
+   ReturnCode */
+#define CX18_CPU_GET_ENC_PTS                   (CPU_CMD_MASK_CAPTURE | 0x0022)
+
+/* Description: Set VFC parameters
+   IN[0] - task handle
+   IN[1] - VFC enable flag, 1 - enable, 0 - disable
+*/
+#define CX18_CPU_SET_VFC_PARAM                  (CPU_CMD_MASK_CAPTURE | 0x0023)
+
+/* Below is the list of commands related to the data exchange */
+#define CPU_CMD_MASK_DE                        (CPU_CMD_MASK | 0x040000)
+
+/* Description: This command provides the physical base address of the local
+   DDR as viewed by EPU
+   IN[0] - Physical offset where EPU has the local DDR mapped
+   ReturnCode - One of the ERR_DE_... */
+#define CPU_CMD_DE_SetBase                     (CPU_CMD_MASK_DE | 0x0001)
+
+/* Description: This command provides the offsets in the device memory where
+   the 2 cx18_mdl_ack blocks reside
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Offset of the first cx18_mdl_ack from the beginning of the
+          local DDR.
+   IN[2] - Offset of the second cx18_mdl_ack from the beginning of the
+          local DDR.
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL_ACK                        (CPU_CMD_MASK_DE | 0x0002)
+
+/* Description: This command provides the offset to a Memory Descriptor List
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Offset of the MDL from the beginning of the local DDR.
+   IN[2] - Number of cx18_mdl_ent structures in the array pointed to by IN[1]
+   IN[3] - Buffer ID
+   IN[4] - Total buffer length
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL                    (CPU_CMD_MASK_DE | 0x0005)
+
+/* Description: This command requests return of all current Memory
+   Descriptor Lists to the driver
+   IN[0] - Task handle. Handle of the task to start
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_RELEASE_MDL                (CPU_CMD_MASK_DE | 0x0006)
+
+/* Description: This command signals the cpu that the dat buffer has been
+   consumed and ready for re-use.
+   IN[0] - Task handle. Handle of the task
+   IN[1] - Offset of the data block from the beginning of the local DDR.
+   IN[2] - Number of bytes in the data block
+   ReturnCode - One of the ERR_DE_... */
+/* #define CX18_CPU_DE_RELEASE_BUFFER           (CPU_CMD_MASK_DE | 0x0007) */
+
+/* No Error / Success */
+#define CNXT_OK                 0x000000
+
+/* Received unknown command */
+#define CXERR_UNK_CMD           0x000001
+
+/* First parameter in the command is invalid */
+#define CXERR_INVALID_PARAM1    0x000002
+
+/* Second parameter in the command is invalid */
+#define CXERR_INVALID_PARAM2    0x000003
+
+/* Device interface is not open/found */
+#define CXERR_DEV_NOT_FOUND     0x000004
+
+/* Requested function is not implemented/available */
+#define CXERR_NOTSUPPORTED      0x000005
+
+/* Invalid pointer is provided */
+#define CXERR_BADPTR            0x000006
+
+/* Unable to allocate memory */
+#define CXERR_NOMEM             0x000007
+
+/* Object/Link not found */
+#define CXERR_LINK              0x000008
+
+/* Device busy, command cannot be executed */
+#define CXERR_BUSY              0x000009
+
+/* File/device/handle is not open. */
+#define CXERR_NOT_OPEN          0x00000A
+
+/* Value is out of range */
+#define CXERR_OUTOFRANGE        0x00000B
+
+/* Buffer overflow */
+#define CXERR_OVERFLOW          0x00000C
+
+/* Version mismatch */
+#define CXERR_BADVER            0x00000D
+
+/* Operation timed out */
+#define CXERR_TIMEOUT           0x00000E
+
+/* Operation aborted */
+#define CXERR_ABORT             0x00000F
+
+/* Specified I2C device not found for read/write */
+#define CXERR_I2CDEV_NOTFOUND   0x000010
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_XFERERR    0x000011
+
+/* Chanel changing component not ready */
+#define CXERR_CHANNELNOTREADY   0x000012
+
+/* PPU (Presensation/Decoder) mail box is corrupted */
+#define CXERR_PPU_MB_CORRUPT    0x000013
+
+/* CPU (Capture/Encoder) mail box is corrupted */
+#define CXERR_CPU_MB_CORRUPT    0x000014
+
+/* APU (Audio) mail box is corrupted */
+#define CXERR_APU_MB_CORRUPT    0x000015
+
+/* Unable to open file for reading */
+#define CXERR_FILE_OPEN_READ    0x000016
+
+/* Unable to open file for writing */
+#define CXERR_FILE_OPEN_WRITE   0x000017
+
+/* Unable to find the I2C section specified */
+#define CXERR_I2C_BADSECTION    0x000018
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_DATALOW    0x000019
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_CLOCKLOW   0x00001A
+
+/* No Interrupt received from HW (for I2C access) */
+#define CXERR_NO_HW_I2C_INTR    0x00001B
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NOT_READY     0x00001C
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NO_ACK        0x00001D
+
+/* The are no buffers ready. Try again soon! */
+#define CXERR_NODATA_AGAIN      0x00001E
+
+/* The stream is stopping. Function not allowed now! */
+#define CXERR_STOPPING_STATUS   0x00001F
+
+/* Trying to access hardware when the power is turned OFF */
+#define CXERR_DEVPOWER_OFF      0x000020
+
+#endif /* CX23418_H */
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
new file mode 100644 (file)
index 0000000..b391e9b
--- /dev/null
@@ -0,0 +1,46 @@
+config VIDEO_CX23885
+       tristate "Conexant cx23885 (2388x successor) support"
+       depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
+       select SND_PCM
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       depends on RC_CORE
+       select VIDEOBUF_DVB
+       select VIDEOBUF_DMA_SG
+       select VIDEO_CX25840
+       select VIDEO_CX2341X
+       select DVB_DIB7000P if !DVB_FE_CUSTOMISE
+       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_STV6110 if !DVB_FE_CUSTOMISE
+       select DVB_CX24116 if !DVB_FE_CUSTOMISE
+       select DVB_STV0900 if !DVB_FE_CUSTOMISE
+       select DVB_DS3000 if !DVB_FE_CUSTOMISE
+       select DVB_STV0367 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+       ---help---
+         This is a video4linux driver for Conexant 23885 based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx23885
+
+config MEDIA_ALTERA_CI
+       tristate "Altera FPGA based CI module"
+       depends on VIDEO_CX23885 && DVB_CORE
+       select ALTERA_STAPL
+       ---help---
+         An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
+
+         To compile this driver as a module, choose M here: the
+         module will be called altera-ci
diff --git a/drivers/media/pci/cx23885/Makefile b/drivers/media/pci/cx23885/Makefile
new file mode 100644 (file)
index 0000000..f92cc4c
--- /dev/null
@@ -0,0 +1,15 @@
+cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
+                   cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
+                   cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
+                   cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
+                   cx23885-f300.o cx23885-alsa.o
+
+obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
+obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
+
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c
new file mode 100644 (file)
index 0000000..1fa8927
--- /dev/null
@@ -0,0 +1,837 @@
+/*
+ * altera-ci.c
+ *
+ *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
+ *
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * 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.
+ */
+
+/*
+ * currently cx23885 GPIO's used.
+ * GPIO-0 ~INT in
+ * GPIO-1 TMS out
+ * GPIO-2 ~reset chips out
+ * GPIO-3 to GPIO-10 data/addr for CA in/out
+ * GPIO-11 ~CS out
+ * GPIO-12 AD_RG out
+ * GPIO-13 ~WR out
+ * GPIO-14 ~RD out
+ * GPIO-15 ~RDY in
+ * GPIO-16 TCK out
+ * GPIO-17 TDO in
+ * GPIO-18 TDI out
+ */
+/*
+ *  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
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |  TDI  |  TDO  |  TCK  |  RDY# |  #RD  |  #WR  | AD_RG |  #CS  |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+#include "altera-ci.h"
+#include "dvb_ca_en50221.h"
+
+/* FPGA regs */
+#define NETUP_CI_INT_CTRL      0x00
+#define NETUP_CI_BUSCTRL2      0x01
+#define NETUP_CI_ADDR0         0x04
+#define NETUP_CI_ADDR1         0x05
+#define NETUP_CI_DATA          0x06
+#define NETUP_CI_BUSCTRL       0x07
+#define NETUP_CI_PID_ADDR0     0x08
+#define NETUP_CI_PID_ADDR1     0x09
+#define NETUP_CI_PID_DATA      0x0a
+#define NETUP_CI_TSA_DIV       0x0c
+#define NETUP_CI_TSB_DIV       0x0d
+#define NETUP_CI_REVISION      0x0f
+
+/* const for ci op */
+#define NETUP_CI_FLG_CTL       1
+#define NETUP_CI_FLG_RD                1
+#define NETUP_CI_FLG_AD                1
+
+static unsigned int ci_dbg;
+module_param(ci_dbg, int, 0644);
+MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
+
+static unsigned int pid_dbg;
+module_param(pid_dbg, int, 0644);
+MODULE_PARM_DESC(pid_dbg, "Enable PID filtering debugging");
+
+MODULE_DESCRIPTION("altera FPGA CI module");
+MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");
+MODULE_LICENSE("GPL");
+
+#define ci_dbg_print(args...) \
+       do { \
+               if (ci_dbg) \
+                       printk(KERN_DEBUG args); \
+       } while (0)
+
+#define pid_dbg_print(args...) \
+       do { \
+               if (pid_dbg) \
+                       printk(KERN_DEBUG args); \
+       } while (0)
+
+struct altera_ci_state;
+struct netup_hw_pid_filter;
+
+struct fpga_internal {
+       void *dev;
+       struct mutex fpga_mutex;/* two CI's on the same fpga */
+       struct netup_hw_pid_filter *pid_filt[2];
+       struct altera_ci_state *state[2];
+       struct work_struct work;
+       int (*fpga_rw) (void *dev, int flag, int data, int rw);
+       int cis_used;
+       int filts_used;
+       int strt_wrk;
+};
+
+/* stores all private variables for communication with CI */
+struct altera_ci_state {
+       struct fpga_internal *internal;
+       struct dvb_ca_en50221 ca;
+       int status;
+       int nr;
+};
+
+/* stores all private variables for hardware pid filtering */
+struct netup_hw_pid_filter {
+       struct fpga_internal *internal;
+       struct dvb_demux *demux;
+       /* save old functions */
+       int (*start_feed)(struct dvb_demux_feed *feed);
+       int (*stop_feed)(struct dvb_demux_feed *feed);
+
+       int status;
+       int nr;
+};
+
+/* internal params node */
+struct fpga_inode {
+       /* pointer for internal params, one for each pair of CI's */
+       struct fpga_internal            *internal;
+       struct fpga_inode               *next_inode;
+};
+
+/* first internal params */
+static struct fpga_inode *fpga_first_inode;
+
+/* find chip by dev */
+static struct fpga_inode *find_inode(void *dev)
+{
+       struct fpga_inode *temp_chip = fpga_first_inode;
+
+       if (temp_chip == NULL)
+               return temp_chip;
+
+       /*
+        Search for the last fpga CI chip or
+        find it by dev */
+       while ((temp_chip != NULL) &&
+                               (temp_chip->internal->dev != dev))
+               temp_chip = temp_chip->next_inode;
+
+       return temp_chip;
+}
+/* check demux */
+static struct fpga_internal *check_filter(struct fpga_internal *temp_int,
+                                               void *demux_dev, int filt_nr)
+{
+       if (temp_int == NULL)
+               return NULL;
+
+       if ((temp_int->pid_filt[filt_nr]) == NULL)
+               return NULL;
+
+       if (temp_int->pid_filt[filt_nr]->demux == demux_dev)
+               return temp_int;
+
+       return NULL;
+}
+
+/* find chip by demux */
+static struct fpga_inode *find_dinode(void *demux_dev)
+{
+       struct fpga_inode *temp_chip = fpga_first_inode;
+       struct fpga_internal *temp_int;
+
+       /*
+        * Search of the last fpga CI chip or
+        * find it by demux
+        */
+       while (temp_chip != NULL) {
+               if (temp_chip->internal != NULL) {
+                       temp_int = temp_chip->internal;
+                       if (check_filter(temp_int, demux_dev, 0))
+                               break;
+                       if (check_filter(temp_int, demux_dev, 1))
+                               break;
+               }
+
+               temp_chip = temp_chip->next_inode;
+       }
+
+       return temp_chip;
+}
+
+/* deallocating chip */
+static void remove_inode(struct fpga_internal *internal)
+{
+       struct fpga_inode *prev_node = fpga_first_inode;
+       struct fpga_inode *del_node = find_inode(internal->dev);
+
+       if (del_node != NULL) {
+               if (del_node == fpga_first_inode) {
+                       fpga_first_inode = del_node->next_inode;
+               } else {
+                       while (prev_node->next_inode != del_node)
+                               prev_node = prev_node->next_inode;
+
+                       if (del_node->next_inode == NULL)
+                               prev_node->next_inode = NULL;
+                       else
+                               prev_node->next_inode =
+                                       prev_node->next_inode->next_inode;
+               }
+
+               kfree(del_node);
+       }
+}
+
+/* allocating new chip */
+static struct fpga_inode *append_internal(struct fpga_internal *internal)
+{
+       struct fpga_inode *new_node = fpga_first_inode;
+
+       if (new_node == NULL) {
+               new_node = kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
+               fpga_first_inode = new_node;
+       } else {
+               while (new_node->next_inode != NULL)
+                       new_node = new_node->next_inode;
+
+               new_node->next_inode =
+                               kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
+               if (new_node->next_inode != NULL)
+                       new_node = new_node->next_inode;
+               else
+                       new_node = NULL;
+       }
+
+       if (new_node != NULL) {
+               new_node->internal = internal;
+               new_node->next_inode = NULL;
+       }
+
+       return new_node;
+}
+
+static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,
+                                                       u8 val, u8 read)
+{
+       inter->fpga_rw(inter->dev, NETUP_CI_FLG_AD, addr, 0);
+       return inter->fpga_rw(inter->dev, 0, val, read);
+}
+
+/* flag - mem/io, read - read/write */
+int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+                               u8 flag, u8 read, int addr, u8 val)
+{
+
+       struct altera_ci_state *state = en50221->data;
+       struct fpga_internal *inter = state->internal;
+
+       u8 store;
+       int mem = 0;
+
+       if (0 != slot)
+               return -EINVAL;
+
+       mutex_lock(&inter->fpga_mutex);
+
+       netup_fpga_op_rw(inter, NETUP_CI_ADDR0, ((addr << 1) & 0xfe), 0);
+       netup_fpga_op_rw(inter, NETUP_CI_ADDR1, ((addr >> 7) & 0x7f), 0);
+       store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+
+       store &= 0x0f;
+       store |= ((state->nr << 7) | (flag << 6));
+
+       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, store, 0);
+       mem = netup_fpga_op_rw(inter, NETUP_CI_DATA, val, read);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
+                       (read) ? "read" : "write", addr,
+                       (flag == NETUP_CI_FLG_CTL) ? "ctl" : "mem",
+                       (read) ? mem : val);
+
+       return mem;
+}
+
+int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                               int slot, int addr)
+{
+       return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);
+}
+
+int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                               int slot, int addr, u8 data)
+{
+       return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);
+}
+
+int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+       return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,
+                                               NETUP_CI_FLG_RD, addr, 0);
+}
+
+int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+                                               u8 addr, u8 data)
+{
+       return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);
+}
+
+int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+       struct altera_ci_state *state = en50221->data;
+       struct fpga_internal *inter = state->internal;
+       /* reasonable timeout for CI reset is 10 seconds */
+       unsigned long t_out = jiffies + msecs_to_jiffies(9999);
+       int ret;
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (0 != slot)
+               return -EINVAL;
+
+       mutex_lock(&inter->fpga_mutex);
+
+       ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+                               (ret & 0xcf) | (1 << (5 - state->nr)), 0);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       for (;;) {
+               mdelay(50);
+
+               mutex_lock(&inter->fpga_mutex);
+
+               ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+                                               0, NETUP_CI_FLG_RD);
+               mutex_unlock(&inter->fpga_mutex);
+
+               if ((ret & (1 << (5 - state->nr))) == 0)
+                       break;
+               if (time_after(jiffies, t_out))
+                       break;
+       }
+
+
+       ci_dbg_print("%s: %d msecs\n", __func__,
+               jiffies_to_msecs(jiffies + msecs_to_jiffies(9999) - t_out));
+
+       return 0;
+}
+
+int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+       /* not implemented */
+       return 0;
+}
+
+int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+{
+       struct altera_ci_state *state = en50221->data;
+       struct fpga_internal *inter = state->internal;
+       int ret;
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (0 != slot)
+               return -EINVAL;
+
+       mutex_lock(&inter->fpga_mutex);
+
+       ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+                               (ret & 0x0f) | (1 << (3 - state->nr)), 0);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       return 0;
+}
+
+/* work handler */
+static void netup_read_ci_status(struct work_struct *work)
+{
+       struct fpga_internal *inter =
+                       container_of(work, struct fpga_internal, work);
+       int ret;
+
+       ci_dbg_print("%s\n", __func__);
+
+       mutex_lock(&inter->fpga_mutex);
+       /* ack' irq */
+       ret = netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0, NETUP_CI_FLG_RD);
+       ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       if (inter->state[1] != NULL) {
+               inter->state[1]->status =
+                               ((ret & 1) == 0 ?
+                               DVB_CA_EN50221_POLL_CAM_PRESENT |
+                               DVB_CA_EN50221_POLL_CAM_READY : 0);
+               ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
+                               __func__, inter->state[1]->status);
+       };
+
+       if (inter->state[0] != NULL) {
+               inter->state[0]->status =
+                               ((ret & 2) == 0 ?
+                               DVB_CA_EN50221_POLL_CAM_PRESENT |
+                               DVB_CA_EN50221_POLL_CAM_READY : 0);
+               ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
+                               __func__, inter->state[0]->status);
+       };
+}
+
+/* CI irq handler */
+int altera_ci_irq(void *dev)
+{
+       struct fpga_inode *temp_int = NULL;
+       struct fpga_internal *inter = NULL;
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (dev != NULL) {
+               temp_int = find_inode(dev);
+               if (temp_int != NULL) {
+                       inter = temp_int->internal;
+                       schedule_work(&inter->work);
+               }
+       }
+
+       return 1;
+}
+EXPORT_SYMBOL(altera_ci_irq);
+
+int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
+                                                               int open)
+{
+       struct altera_ci_state *state = en50221->data;
+
+       if (0 != slot)
+               return -EINVAL;
+
+       return state->status;
+}
+
+void altera_hw_filt_release(void *main_dev, int filt_nr)
+{
+       struct fpga_inode *temp_int = find_inode(main_dev);
+       struct netup_hw_pid_filter *pid_filt = NULL;
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (temp_int != NULL) {
+               pid_filt = temp_int->internal->pid_filt[filt_nr - 1];
+               /* stored old feed controls */
+               pid_filt->demux->start_feed = pid_filt->start_feed;
+               pid_filt->demux->stop_feed = pid_filt->stop_feed;
+
+               if (((--(temp_int->internal->filts_used)) <= 0) &&
+                        ((temp_int->internal->cis_used) <= 0)) {
+
+                       ci_dbg_print("%s: Actually removing\n", __func__);
+
+                       remove_inode(temp_int->internal);
+                       kfree(pid_filt->internal);
+               }
+
+               kfree(pid_filt);
+
+       }
+
+}
+EXPORT_SYMBOL(altera_hw_filt_release);
+
+void altera_ci_release(void *dev, int ci_nr)
+{
+       struct fpga_inode *temp_int = find_inode(dev);
+       struct altera_ci_state *state = NULL;
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (temp_int != NULL) {
+               state = temp_int->internal->state[ci_nr - 1];
+               altera_hw_filt_release(dev, ci_nr);
+
+
+               if (((temp_int->internal->filts_used) <= 0) &&
+                               ((--(temp_int->internal->cis_used)) <= 0)) {
+
+                       ci_dbg_print("%s: Actually removing\n", __func__);
+
+                       remove_inode(temp_int->internal);
+                       kfree(state->internal);
+               }
+
+               if (state != NULL) {
+                       if (state->ca.data != NULL)
+                               dvb_ca_en50221_release(&state->ca);
+
+                       kfree(state);
+               }
+       }
+
+}
+EXPORT_SYMBOL(altera_ci_release);
+
+static void altera_pid_control(struct netup_hw_pid_filter *pid_filt,
+               u16 pid, int onoff)
+{
+       struct fpga_internal *inter = pid_filt->internal;
+       u8 store = 0;
+
+       /* pid 0-0x1f always enabled, don't touch them */
+       if ((pid == 0x2000) || (pid < 0x20))
+               return;
+
+       mutex_lock(&inter->fpga_mutex);
+
+       netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, (pid >> 3) & 0xff, 0);
+       netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
+                       ((pid >> 11) & 0x03) | (pid_filt->nr << 2), 0);
+
+       store = netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, 0, NETUP_CI_FLG_RD);
+
+       if (onoff)/* 0 - on, 1 - off */
+               store |= (1 << (pid & 7));
+       else
+               store &= ~(1 << (pid & 7));
+
+       netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, store, 0);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       pid_dbg_print("%s: (%d) set pid: %5d 0x%04x '%s'\n", __func__,
+               pid_filt->nr, pid, pid, onoff ? "off" : "on");
+}
+
+static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,
+                                       int filt_nr, int onoff)
+{
+       struct fpga_internal *inter = pid_filt->internal;
+       u8 store = 0;
+       int i;
+
+       pid_dbg_print("%s: pid_filt->nr[%d]  now %s\n", __func__, pid_filt->nr,
+                       onoff ? "off" : "on");
+
+       if (onoff)/* 0 - on, 1 - off */
+               store = 0xff;/* ignore pid */
+       else
+               store = 0;/* enable pid */
+
+       mutex_lock(&inter->fpga_mutex);
+
+       for (i = 0; i < 1024; i++) {
+               netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, i & 0xff, 0);
+
+               netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
+                               ((i >> 8) & 0x03) | (pid_filt->nr << 2), 0);
+               /* pid 0-0x1f always enabled */
+               netup_fpga_op_rw(inter, NETUP_CI_PID_DATA,
+                               (i > 3 ? store : 0), 0);
+       }
+
+       mutex_unlock(&inter->fpga_mutex);
+}
+
+int altera_pid_feed_control(void *demux_dev, int filt_nr,
+               struct dvb_demux_feed *feed, int onoff)
+{
+       struct fpga_inode *temp_int = find_dinode(demux_dev);
+       struct fpga_internal *inter = temp_int->internal;
+       struct netup_hw_pid_filter *pid_filt = inter->pid_filt[filt_nr - 1];
+
+       altera_pid_control(pid_filt, feed->pid, onoff ? 0 : 1);
+       /* call old feed proc's */
+       if (onoff)
+               pid_filt->start_feed(feed);
+       else
+               pid_filt->stop_feed(feed);
+
+       if (feed->pid == 0x2000)
+               altera_toggle_fullts_streaming(pid_filt, filt_nr,
+                                               onoff ? 0 : 1);
+
+       return 0;
+}
+EXPORT_SYMBOL(altera_pid_feed_control);
+
+int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
+{
+       altera_pid_feed_control(feed->demux, num, feed, 1);
+
+       return 0;
+}
+
+int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
+{
+       altera_pid_feed_control(feed->demux, num, feed, 0);
+
+       return 0;
+}
+
+int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
+{
+       return altera_ci_start_feed(feed, 1);
+}
+
+int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
+{
+       return altera_ci_stop_feed(feed, 1);
+}
+
+int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
+{
+       return altera_ci_start_feed(feed, 2);
+}
+
+int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
+{
+       return altera_ci_stop_feed(feed, 2);
+}
+
+int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
+{
+       struct netup_hw_pid_filter *pid_filt = NULL;
+       struct fpga_inode *temp_int = find_inode(config->dev);
+       struct fpga_internal *inter = NULL;
+       int ret = 0;
+
+       pid_filt = kzalloc(sizeof(struct netup_hw_pid_filter), GFP_KERNEL);
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (!pid_filt) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       if (temp_int != NULL) {
+               inter = temp_int->internal;
+               (inter->filts_used)++;
+               ci_dbg_print("%s: Find Internal Structure!\n", __func__);
+       } else {
+               inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
+               if (!inter) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               temp_int = append_internal(inter);
+               inter->filts_used = 1;
+               inter->dev = config->dev;
+               inter->fpga_rw = config->fpga_rw;
+               mutex_init(&inter->fpga_mutex);
+               inter->strt_wrk = 1;
+               ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
+       }
+
+       ci_dbg_print("%s: setting hw pid filter = %p for ci = %d\n", __func__,
+                                               pid_filt, hw_filt_nr - 1);
+       inter->pid_filt[hw_filt_nr - 1] = pid_filt;
+       pid_filt->demux = config->demux;
+       pid_filt->internal = inter;
+       pid_filt->nr = hw_filt_nr - 1;
+       /* store old feed controls */
+       pid_filt->start_feed = config->demux->start_feed;
+       pid_filt->stop_feed = config->demux->stop_feed;
+       /* replace with new feed controls */
+       if (hw_filt_nr == 1) {
+               pid_filt->demux->start_feed = altera_ci_start_feed_1;
+               pid_filt->demux->stop_feed = altera_ci_stop_feed_1;
+       } else if (hw_filt_nr == 2) {
+               pid_filt->demux->start_feed = altera_ci_start_feed_2;
+               pid_filt->demux->stop_feed = altera_ci_stop_feed_2;
+       }
+
+       altera_toggle_fullts_streaming(pid_filt, 0, 1);
+
+       return 0;
+err:
+       ci_dbg_print("%s: Can't init hardware filter: Error %d\n",
+                    __func__, ret);
+
+       kfree(pid_filt);
+
+       return ret;
+}
+EXPORT_SYMBOL(altera_hw_filt_init);
+
+int altera_ci_init(struct altera_ci_config *config, int ci_nr)
+{
+       struct altera_ci_state *state;
+       struct fpga_inode *temp_int = find_inode(config->dev);
+       struct fpga_internal *inter = NULL;
+       int ret = 0;
+       u8 store = 0;
+
+       state = kzalloc(sizeof(struct altera_ci_state), GFP_KERNEL);
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (!state) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       if (temp_int != NULL) {
+               inter = temp_int->internal;
+               (inter->cis_used)++;
+               ci_dbg_print("%s: Find Internal Structure!\n", __func__);
+       } else {
+               inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
+               if (!inter) {
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               temp_int = append_internal(inter);
+               inter->cis_used = 1;
+               inter->dev = config->dev;
+               inter->fpga_rw = config->fpga_rw;
+               mutex_init(&inter->fpga_mutex);
+               inter->strt_wrk = 1;
+               ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
+       }
+
+       ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__,
+                                               state, ci_nr - 1);
+       inter->state[ci_nr - 1] = state;
+       state->internal = inter;
+       state->nr = ci_nr - 1;
+
+       state->ca.owner = THIS_MODULE;
+       state->ca.read_attribute_mem = altera_ci_read_attribute_mem;
+       state->ca.write_attribute_mem = altera_ci_write_attribute_mem;
+       state->ca.read_cam_control = altera_ci_read_cam_ctl;
+       state->ca.write_cam_control = altera_ci_write_cam_ctl;
+       state->ca.slot_reset = altera_ci_slot_reset;
+       state->ca.slot_shutdown = altera_ci_slot_shutdown;
+       state->ca.slot_ts_enable = altera_ci_slot_ts_ctl;
+       state->ca.poll_slot_status = altera_poll_ci_slot_status;
+       state->ca.data = state;
+
+       ret = dvb_ca_en50221_init(config->adapter,
+                                  &state->ca,
+                                  /* flags */ 0,
+                                  /* n_slots */ 1);
+       if (0 != ret)
+               goto err;
+
+       altera_hw_filt_init(config, ci_nr);
+
+       if (inter->strt_wrk) {
+               INIT_WORK(&inter->work, netup_read_ci_status);
+               inter->strt_wrk = 0;
+       }
+
+       ci_dbg_print("%s: CI initialized!\n", __func__);
+
+       mutex_lock(&inter->fpga_mutex);
+
+       /* Enable div */
+       netup_fpga_op_rw(inter, NETUP_CI_TSA_DIV, 0x0, 0);
+       netup_fpga_op_rw(inter, NETUP_CI_TSB_DIV, 0x0, 0);
+
+       /* enable TS out */
+       store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
+       store |= (3 << 4);
+       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+
+       ret = netup_fpga_op_rw(inter, NETUP_CI_REVISION, 0, NETUP_CI_FLG_RD);
+       /* enable irq */
+       netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0x44, 0);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       ci_dbg_print("%s: NetUP CI Revision = 0x%x\n", __func__, ret);
+
+       schedule_work(&inter->work);
+
+       return 0;
+err:
+       ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
+
+       kfree(state);
+
+       return ret;
+}
+EXPORT_SYMBOL(altera_ci_init);
+
+int altera_ci_tuner_reset(void *dev, int ci_nr)
+{
+       struct fpga_inode *temp_int = find_inode(dev);
+       struct fpga_internal *inter = NULL;
+       u8 store;
+
+       ci_dbg_print("%s\n", __func__);
+
+       if (temp_int == NULL)
+               return -1;
+
+       if (temp_int->internal == NULL)
+               return -1;
+
+       inter = temp_int->internal;
+
+       mutex_lock(&inter->fpga_mutex);
+
+       store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
+       store &= ~(4 << (2 - ci_nr));
+       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+       msleep(100);
+       store |= (4 << (2 - ci_nr));
+       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+
+       mutex_unlock(&inter->fpga_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL(altera_ci_tuner_reset);
diff --git a/drivers/media/pci/cx23885/altera-ci.h b/drivers/media/pci/cx23885/altera-ci.h
new file mode 100644 (file)
index 0000000..70e4fd6
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * altera-ci.c
+ *
+ *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
+ *
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * 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 __ALTERA_CI_H
+#define __ALTERA_CI_H
+
+#define ALT_DATA       0x000000ff
+#define ALT_TDI                0x00008000
+#define ALT_TDO                0x00004000
+#define ALT_TCK                0x00002000
+#define ALT_RDY                0x00001000
+#define ALT_RD         0x00000800
+#define ALT_WR         0x00000400
+#define ALT_AD_RG      0x00000200
+#define ALT_CS         0x00000100
+
+struct altera_ci_config {
+       void *dev;/* main dev, for example cx23885_dev */
+       void *adapter;/* for CI to connect to */
+       struct dvb_demux *demux;/* for hardware PID filter to connect to */
+       int (*fpga_rw) (void *dev, int ad_rg, int val, int rw);
+};
+
+#if defined(CONFIG_MEDIA_ALTERA_CI) || (defined(CONFIG_MEDIA_ALTERA_CI_MODULE) \
+                                                       && defined(MODULE))
+
+extern int altera_ci_init(struct altera_ci_config *config, int ci_nr);
+extern void altera_ci_release(void *dev, int ci_nr);
+extern int altera_ci_irq(void *dev);
+extern int altera_ci_tuner_reset(void *dev, int ci_nr);
+
+#else
+
+static inline int altera_ci_init(struct altera_ci_config *config, int ci_nr)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+
+static inline void altera_ci_release(void *dev, int ci_nr)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int altera_ci_irq(void *dev)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+
+static inline int altera_ci_tuner_reset(void *dev, int ci_nr)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+
+#endif
+#if 0
+static inline int altera_hw_filt_init(struct altera_ci_config *config,
+                                                       int hw_filt_nr)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+
+static inline void altera_hw_filt_release(void *dev, int filt_nr)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int altera_pid_feed_control(void *dev, int filt_nr,
+               struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       return 0;
+}
+
+#endif /* CONFIG_MEDIA_ALTERA_CI */
+
+#endif /* __ALTERA_CI_H */
diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c
new file mode 100644 (file)
index 0000000..c9f15d6
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ * cimax2.c
+ *
+ * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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 "cx23885.h"
+#include "dvb_ca_en50221.h"
+/**** 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
++-------+-------+-------+-------+-------+-------+-------+-------+
+|  WR#  |  RD#  |       |  ACK# |  ADHI |  ADLO |  CS1# |  CS0# |
++-------+-------+-------+-------+-------+-------+-------+-------+
+ bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
++-------+-------+-------+-------+-------+-------+-------+-------+
+|  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+***/
+/* MC417 */
+#define NETUP_DATA             0x000000ff
+#define NETUP_WR               0x00008000
+#define NETUP_RD               0x00004000
+#define NETUP_ACK              0x00001000
+#define NETUP_ADHI             0x00000800
+#define NETUP_ADLO             0x00000400
+#define NETUP_CS1              0x00000200
+#define NETUP_CS0              0x00000100
+#define NETUP_EN_ALL           0x00001000
+#define NETUP_CTRL_OFF         (NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD)
+#define NETUP_CI_CTL           0x04
+#define NETUP_CI_RD            1
+
+#define NETUP_IRQ_DETAM        0x1
+#define NETUP_IRQ_IRQAM                0x4
+
+static unsigned int ci_dbg;
+module_param(ci_dbg, int, 0644);
+MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
+
+static unsigned int ci_irq_enable;
+module_param(ci_irq_enable, int, 0644);
+MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");
+
+#define ci_dbg_print(args...) \
+       do { \
+               if (ci_dbg) \
+                       printk(KERN_DEBUG args); \
+       } while (0)
+
+#define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0)
+
+/* stores all private variables for communication with CI */
+struct netup_ci_state {
+       struct dvb_ca_en50221 ca;
+       struct mutex ca_mutex;
+       struct i2c_adapter *i2c_adap;
+       u8 ci_i2c_addr;
+       int status;
+       struct work_struct work;
+       void *priv;
+       u8 current_irq_mode;
+       int current_ci_flag;
+       unsigned long next_status_checked_time;
+};
+
+
+int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+                                               u8 *buf, int len)
+{
+       int ret;
+       struct i2c_msg msg[] = {
+               {
+                       .addr   = addr,
+                       .flags  = 0,
+                       .buf    = &reg,
+                       .len    = 1
+               }, {
+                       .addr   = addr,
+                       .flags  = I2C_M_RD,
+                       .buf    = buf,
+                       .len    = len
+               }
+       };
+
+       ret = i2c_transfer(i2c_adap, msg, 2);
+
+       if (ret != 2) {
+               ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n",
+                                               __func__, reg, ret);
+
+               return -1;
+       }
+
+       ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n",
+                                               __func__, addr, reg, buf[0]);
+
+       return 0;
+}
+
+int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
+                                               u8 *buf, int len)
+{
+       int ret;
+       u8 buffer[len + 1];
+
+       struct i2c_msg msg = {
+               .addr   = addr,
+               .flags  = 0,
+               .buf    = &buffer[0],
+               .len    = len + 1
+       };
+
+       buffer[0] = reg;
+       memcpy(&buffer[1], buf, len);
+
+       ret = i2c_transfer(i2c_adap, &msg, 1);
+
+       if (ret != 1) {
+               ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n",
+                                               __func__, reg, ret);
+               return -1;
+       }
+
+       return 0;
+}
+
+int netup_ci_get_mem(struct cx23885_dev *dev)
+{
+       int mem;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+       for (;;) {
+               mem = cx_read(MC417_RWD);
+               if ((mem & NETUP_ACK) == 0)
+                       break;
+               if (time_after(jiffies, timeout))
+                       break;
+               udelay(1);
+       }
+
+       cx_set(MC417_RWD, NETUP_CTRL_OFF);
+
+       return mem & 0xff;
+}
+
+int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+                               u8 flag, u8 read, int addr, u8 data)
+{
+       struct netup_ci_state *state = en50221->data;
+       struct cx23885_tsport *port = state->priv;
+       struct cx23885_dev *dev = port->dev;
+
+       u8 store;
+       int mem;
+       int ret;
+
+       if (0 != slot)
+               return -EINVAL;
+
+       if (state->current_ci_flag != flag) {
+               ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+                               0, &store, 1);
+               if (ret != 0)
+                       return ret;
+
+               store &= ~0x0c;
+               store |= flag;
+
+               ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                               0, &store, 1);
+               if (ret != 0)
+                       return ret;
+       };
+       state->current_ci_flag = flag;
+
+       mutex_lock(&dev->gpio_lock);
+
+       /* write addr */
+       cx_write(MC417_OEN, NETUP_EN_ALL);
+       cx_write(MC417_RWD, NETUP_CTRL_OFF |
+                               NETUP_ADLO | (0xff & addr));
+       cx_clear(MC417_RWD, NETUP_ADLO);
+       cx_write(MC417_RWD, NETUP_CTRL_OFF |
+                               NETUP_ADHI | (0xff & (addr >> 8)));
+       cx_clear(MC417_RWD, NETUP_ADHI);
+
+       if (read) { /* data in */
+               cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
+       } else /* data out */
+               cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
+
+       /* choose chip */
+       cx_clear(MC417_RWD,
+                       (state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1);
+       /* read/write */
+       cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR);
+       mem = netup_ci_get_mem(dev);
+
+       mutex_unlock(&dev->gpio_lock);
+
+       if (!read)
+               if (mem < 0)
+                       return -EREMOTEIO;
+
+       ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
+                       (read) ? "read" : "write", state->ci_i2c_addr, addr,
+                       (flag == NETUP_CI_CTL) ? "ctl" : "mem",
+                       (read) ? mem : data);
+
+       if (read)
+               return mem;
+
+       return 0;
+}
+
+int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                               int slot, int addr)
+{
+       return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0);
+}
+
+int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                               int slot, int addr, u8 data)
+{
+       return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
+}
+
+int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+       return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
+                                                       NETUP_CI_RD, addr, 0);
+}
+
+int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+                                                       u8 addr, u8 data)
+{
+       return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data);
+}
+
+int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+       struct netup_ci_state *state = en50221->data;
+       u8 buf =  0x80;
+       int ret;
+
+       if (0 != slot)
+               return -EINVAL;
+
+       udelay(500);
+       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                                       0, &buf, 1);
+
+       if (ret != 0)
+               return ret;
+
+       udelay(500);
+
+       buf = 0x00;
+       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                                       0, &buf, 1);
+
+       msleep(1000);
+       dvb_ca_en50221_camready_irq(&state->ca, 0);
+
+       return 0;
+
+}
+
+int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+       /* not implemented */
+       return 0;
+}
+
+int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
+{
+       struct netup_ci_state *state = en50221->data;
+       int ret;
+
+       if (irq_mode == state->current_irq_mode)
+               return 0;
+
+       ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
+                       __func__, state->ci_i2c_addr, irq_mode);
+       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                                       0x1b, &irq_mode, 1);
+
+       if (ret != 0)
+               return ret;
+
+       state->current_irq_mode = irq_mode;
+
+       return 0;
+}
+
+int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+{
+       struct netup_ci_state *state = en50221->data;
+       u8 buf;
+
+       if (0 != slot)
+               return -EINVAL;
+
+       netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+                       0, &buf, 1);
+       buf |= 0x60;
+
+       return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                                       0, &buf, 1);
+}
+
+/* work handler */
+static void netup_read_ci_status(struct work_struct *work)
+{
+       struct netup_ci_state *state =
+                       container_of(work, struct netup_ci_state, work);
+       u8 buf[33];
+       int ret;
+
+       /* CAM module IRQ processing. fast operation */
+       dvb_ca_en50221_frda_irq(&state->ca, 0);
+
+       /* CAM module INSERT/REMOVE processing. slow operation because of i2c
+        * transfers */
+       if (time_after(jiffies, state->next_status_checked_time)
+                       || !state->status) {
+               ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+                               0, &buf[0], 33);
+
+               state->next_status_checked_time = jiffies
+                       + msecs_to_jiffies(1000);
+
+               if (ret != 0)
+                       return;
+
+               ci_dbg_print("%s: Slot Status Addr=[0x%04x], "
+                               "Reg=[0x%02x], data=%02x, "
+                               "TS config = %02x\n", __func__,
+                               state->ci_i2c_addr, 0, buf[0],
+                               buf[0]);
+
+
+               if (buf[0] & 1)
+                       state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
+                               DVB_CA_EN50221_POLL_CAM_READY;
+               else
+                       state->status = 0;
+       }
+}
+
+/* CI irq handler */
+int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
+{
+       struct cx23885_tsport *port = NULL;
+       struct netup_ci_state *state = NULL;
+
+       ci_dbg_print("%s:\n", __func__);
+
+       if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1)))
+               return 0;
+
+       if (pci_status & PCI_MSK_GPIO0) {
+               port = &dev->ts1;
+               state = port->port_priv;
+               schedule_work(&state->work);
+               ci_dbg_print("%s: Wakeup CI0\n", __func__);
+       }
+
+       if (pci_status & PCI_MSK_GPIO1) {
+               port = &dev->ts2;
+               state = port->port_priv;
+               schedule_work(&state->work);
+               ci_dbg_print("%s: Wakeup CI1\n", __func__);
+       }
+
+       return 1;
+}
+
+int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
+{
+       struct netup_ci_state *state = en50221->data;
+
+       if (0 != slot)
+               return -EINVAL;
+
+       netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags())
+                       : NETUP_IRQ_DETAM);
+
+       return state->status;
+}
+
+int netup_ci_init(struct cx23885_tsport *port)
+{
+       struct netup_ci_state *state;
+       u8 cimax_init[34] = {
+               0x00, /* module A control*/
+               0x00, /* auto select mask high A */
+               0x00, /* auto select mask low A */
+               0x00, /* auto select pattern high A */
+               0x00, /* auto select pattern low A */
+               0x44, /* memory access time A */
+               0x00, /* invert input A */
+               0x00, /* RFU */
+               0x00, /* RFU */
+               0x00, /* module B control*/
+               0x00, /* auto select mask high B */
+               0x00, /* auto select mask low B */
+               0x00, /* auto select pattern high B */
+               0x00, /* auto select pattern low B */
+               0x44, /* memory access time B */
+               0x00, /* invert input B */
+               0x00, /* RFU */
+               0x00, /* RFU */
+               0x00, /* auto select mask high Ext */
+               0x00, /* auto select mask low Ext */
+               0x00, /* auto select pattern high Ext */
+               0x00, /* auto select pattern low Ext */
+               0x00, /* RFU */
+               0x02, /* destination - module A */
+               0x01, /* power on (use it like store place) */
+               0x00, /* RFU */
+               0x00, /* int status read only */
+               ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
+               0x05, /* EXTINT=active-high, INT=push-pull */
+               0x00, /* USCG1 */
+               0x04, /* ack active low */
+               0x00, /* LOCK = 0 */
+               0x33, /* serial mode, rising in, rising out, MSB first*/
+               0x31, /* synchronization */
+       };
+       int ret;
+
+       ci_dbg_print("%s\n", __func__);
+       state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL);
+       if (!state) {
+               ci_dbg_print("%s: Unable create CI structure!\n", __func__);
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       port->port_priv = state;
+
+       switch (port->nr) {
+       case 1:
+               state->ci_i2c_addr = 0x40;
+               break;
+       case 2:
+               state->ci_i2c_addr = 0x41;
+               break;
+       }
+
+       state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap;
+       state->ca.owner = THIS_MODULE;
+       state->ca.read_attribute_mem = netup_ci_read_attribute_mem;
+       state->ca.write_attribute_mem = netup_ci_write_attribute_mem;
+       state->ca.read_cam_control = netup_ci_read_cam_ctl;
+       state->ca.write_cam_control = netup_ci_write_cam_ctl;
+       state->ca.slot_reset = netup_ci_slot_reset;
+       state->ca.slot_shutdown = netup_ci_slot_shutdown;
+       state->ca.slot_ts_enable = netup_ci_slot_ts_ctl;
+       state->ca.poll_slot_status = netup_poll_ci_slot_status;
+       state->ca.data = state;
+       state->priv = port;
+       state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM;
+
+       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                               0, &cimax_init[0], 34);
+       /* lock registers */
+       ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                               0x1f, &cimax_init[0x18], 1);
+       /* power on slots */
+       ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+                                               0x18, &cimax_init[0x18], 1);
+
+       if (0 != ret)
+               goto err;
+
+       ret = dvb_ca_en50221_init(&port->frontends.adapter,
+                                  &state->ca,
+                                  /* flags */ 0,
+                                  /* n_slots */ 1);
+       if (0 != ret)
+               goto err;
+
+       INIT_WORK(&state->work, netup_read_ci_status);
+       schedule_work(&state->work);
+
+       ci_dbg_print("%s: CI initialized!\n", __func__);
+
+       return 0;
+err:
+       ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
+       kfree(state);
+       return ret;
+}
+
+void netup_ci_exit(struct cx23885_tsport *port)
+{
+       struct netup_ci_state *state;
+
+       if (NULL == port)
+               return;
+
+       state = (struct netup_ci_state *)port->port_priv;
+       if (NULL == state)
+               return;
+
+       if (NULL == state->ca.data)
+               return;
+
+       dvb_ca_en50221_release(&state->ca);
+       kfree(state);
+}
diff --git a/drivers/media/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h
new file mode 100644 (file)
index 0000000..518744a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * cimax2.h
+ *
+ * CIMax(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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 CIMAX2_H
+#define CIMAX2_H
+#include "dvb_ca_en50221.h"
+
+extern int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                               int slot, int addr);
+extern int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+                                               int slot, int addr, u8 data);
+extern int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
+                                               int slot, u8 addr);
+extern int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
+                                               int slot, u8 addr, u8 data);
+extern int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot);
+extern int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot);
+extern int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot);
+extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status);
+extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
+                                               int slot, int open);
+extern int netup_ci_init(struct cx23885_tsport *port);
+extern void netup_ci_exit(struct cx23885_tsport *port);
+
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
new file mode 100644 (file)
index 0000000..5d5052d
--- /dev/null
@@ -0,0 +1,1790 @@
+/*
+ *
+ *  Support for a cx23417 mpeg encoder via cx23885 host port.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *    (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *      - CX23885/7/8 support
+ *
+ *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
+ *
+ *  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 <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/cx2341x.h>
+
+#include "cx23885.h"
+#include "cx23885-ioctl.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) ? dev->name : "cx23885[?]", ## 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);
+       }
+}
+
+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);
+}
+
+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;
+}
+
+void mc417_gpio_set(struct cx23885_dev *dev, u32 mask)
+{
+       u32 val;
+
+       /* Set the gpio value */
+       mc417_register_read(dev, 0x900C, &val);
+       val |= (mask & 0x000ffff);
+       mc417_register_write(dev, 0x900C, val);
+}
+
+void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask)
+{
+       u32 val;
+
+       /* Clear the gpio value */
+       mc417_register_read(dev, 0x900C, &val);
+       val &= ~(mask & 0x0000ffff);
+       mc417_register_write(dev, 0x900C, val);
+}
+
+void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
+{
+       u32 val;
+
+       /* Enable GPIO direction bits */
+       mc417_register_read(dev, 0x9020, &val);
+       if (asoutput)
+               val |= (mask & 0x0000ffff);
+       else
+               val &= ~(mask & 0x0000ffff);
+
+       mc417_register_write(dev, 0x9020, val);
+}
+/* ------------------------------------------------------------------ */
+
+/* MPEG encoder API */
+static 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_ID";
+       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_MODE";
+       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 gpio_value;
+       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, &gpio_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",
+                       CX23885_FIRM_IMAGE_NAME);
+               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);
+
+       /* F/W power up disturbs the GPIOs, restore state */
+       retval |= mc417_register_write(dev, 0x9020, gpio_output);
+       retval |= mc417_register_write(dev, 0x900C, gpio_value);
+
+       retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
+       retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+       /* Hardcoded GPIO's here */
+       retval |= mc417_register_write(dev, 0x9020, 0x4000);
+       retval |= mc417_register_write(dev, 0x900C, 0x4000);
+
+       mc417_register_read(dev, 0x9020, &gpio_output);
+       mc417_register_read(dev, 0x900C, &gpio_value);
+
+       if (retval < 0)
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+       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__);
+
+       /* Dynamically change the height based on video standard */
+       if (dev->encodernorm.id & V4L2_STD_525_60)
+               dev->ts1.height = 480;
+       else
+               dev->ts1.height = 576;
+
+       /* assign frame size */
+       cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               dev->ts1.height, dev->ts1.width);
+
+       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 startencoder)
+{
+       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;
+               }
+               retval = cx23885_find_mailbox(dev);
+               if (retval < 0) {
+                       printk(KERN_ERR "%s() mailbox < 0, error\n",
+                               __func__);
+                       return -1;
+               }
+               dev->cx23417_mailbox = retval;
+               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 */
+       if (startencoder) {
+               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(&dev->mpeg_params, qmenu->id));
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       call_all(dev, core, g_std, id);
+
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+       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];
+
+       /* Have the drier core notify the subdevices */
+       mutex_lock(&dev->lock);
+       cx23885_set_tvnorm(dev, *id);
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+       struct v4l2_input *i)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       dprintk(1, "%s()\n", __func__);
+       return cx23885_enum_input(dev, i);
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       return cx23885_get_input(file, priv, i);
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       return cx23885_set_input(file, priv, i);
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+       strcpy(t->name, "Television");
+       call_all(dev, tuner, g_tuner, t);
+
+       dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+
+       /* Update the A/V core */
+       call_all(dev, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+       f->type = V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->freq;
+
+       call_all(dev, tuner, g_frequency, f);
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       return cx23885_set_frequency(file, priv, f);
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       return cx23885_get_control(dev, ctl);
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       return cx23885_set_control(dev, ctl);
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                               struct v4l2_capability *cap)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+       struct cx23885_tsport  *tsport = &dev->ts1;
+
+       strlcpy(cap->driver, dev->name, sizeof(cap->driver));
+       strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+       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;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "MPEG", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       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;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       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_TRY_FMT: w: %d, h: %d, f: %d\n",
+               dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       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;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                               struct v4l2_requestbuffers *p)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+
+       return videobuf_reqbufs(&fh->mpegq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                               struct v4l2_buffer *p)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+
+       return videobuf_querybuf(&fh->mpegq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv,
+                               struct v4l2_buffer *p)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+
+       return videobuf_qbuf(&fh->mpegq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx23885_fh  *fh  = priv;
+
+       return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv,
+                               enum v4l2_buf_type i)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+
+       return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx23885_fh  *fh  = file->private_data;
+
+       return videobuf_streamoff(&fh->mpegq);
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+       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, VIDIOC_S_EXT_CTRLS);
+
+       if (err == 0) {
+               err = cx2341x_update(dev, cx23885_mbox_func,
+                       &dev->mpeg_params, &p);
+               dev->mpeg_params = p;
+       }
+       return err;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+       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, VIDIOC_TRY_EXT_CTRLS);
+       return err;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+       char name[32 + 2];
+
+       snprintf(name, sizeof(name), "%s/2", dev->name);
+       printk(KERN_INFO
+               "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+       call_all(dev, core, log_status);
+       cx2341x_log_status(&dev->mpeg_params, name);
+       printk(KERN_INFO
+               "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+       return 0;
+}
+
+static int vidioc_querymenu(struct file *file, void *priv,
+                               struct v4l2_querymenu *a)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+
+       return cx23885_querymenu(dev, a);
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *c)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+
+       return cx23885_queryctrl(dev, c);
+}
+
+static int mpeg_open(struct file *file)
+{
+       struct cx23885_dev *dev = video_drvdata(file);
+       struct cx23885_fh *fh;
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (!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, NULL);
+       return 0;
+}
+
+static int mpeg_release(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, 1) < 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 v4l2_file_operations mpeg_fops = {
+       .owner         = THIS_MODULE,
+       .open          = mpeg_open,
+       .release       = mpeg_release,
+       .read          = mpeg_read,
+       .poll          = mpeg_poll,
+       .mmap          = mpeg_mmap,
+       .ioctl         = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+       .vidioc_querystd         = vidioc_g_std,
+       .vidioc_g_std            = vidioc_g_std,
+       .vidioc_s_std            = vidioc_s_std,
+       .vidioc_enum_input       = vidioc_enum_input,
+       .vidioc_g_input          = vidioc_g_input,
+       .vidioc_s_input          = vidioc_s_input,
+       .vidioc_g_tuner          = vidioc_g_tuner,
+       .vidioc_s_tuner          = vidioc_s_tuner,
+       .vidioc_g_frequency      = vidioc_g_frequency,
+       .vidioc_s_frequency      = vidioc_s_frequency,
+       .vidioc_s_ctrl           = vidioc_s_ctrl,
+       .vidioc_g_ctrl           = vidioc_g_ctrl,
+       .vidioc_querycap         = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_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_g_ext_ctrls      = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
+       .vidioc_log_status       = vidioc_log_status,
+       .vidioc_querymenu        = vidioc_querymenu,
+       .vidioc_queryctrl        = vidioc_queryctrl,
+       .vidioc_g_chip_ident     = cx23885_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register       = cx23885_g_register,
+       .vidioc_s_register       = cx23885_s_register,
+#endif
+};
+
+static struct video_device cx23885_mpeg_template = {
+       .name          = "cx23885",
+       .fops          = &mpeg_fops,
+       .ioctl_ops     = &mpeg_ioctl_ops,
+       .tvnorms       = CX23885_NORMS,
+       .current_norm  = V4L2_STD_NTSC_M,
+};
+
+void cx23885_417_unregister(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       if (dev->v4l_device) {
+               if (video_is_registered(dev->v4l_device))
+                       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;
+       snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+               cx23885_boards[tsport->dev->board].name, type);
+       vfd->parent  = &pci->dev;
+       vfd->release = video_device_release;
+       return vfd;
+}
+
+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");
+       video_set_drvdata(dev->v4l_device, dev);
+       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;
+       }
+
+       printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+              dev->name, video_device_node_name(dev->v4l_device));
+
+       /* ST: Configure the encoder paramaters, but don't begin
+        * encoding, this resolves an issue where the first time the
+        * encoder is started video can be choppy.
+        */
+       cx23885_initialize_codec(dev, 0);
+
+       return 0;
+}
+
+MODULE_FIRMWARE(CX23885_FIRM_IMAGE_NAME);
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
new file mode 100644 (file)
index 0000000..7951692
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ *
+ *  Support for CX23885 analog audio capture
+ *
+ *    (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
+ *    Adapted from cx88-alsa.c
+ *    (c) 2009 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include <sound/tlv.h>
+
+
+#include "cx23885.h"
+#include "cx23885-reg.h"
+
+#define AUDIO_SRAM_CHANNEL     SRAM_CH07
+
+#define dprintk(level, fmt, arg...)    if (audio_debug >= level) \
+       printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level, fmt, arg...)       if (audio_debug >= level) \
+       printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
+
+/****************************************************************************
+                       Module global static vars
+ ****************************************************************************/
+
+static unsigned int disable_analog_audio;
+module_param(disable_analog_audio, int, 0644);
+MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
+
+static unsigned int audio_debug;
+module_param(audio_debug, int, 0644);
+MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
+
+/****************************************************************************
+                       Board specific funtions
+ ****************************************************************************/
+
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET 0x3
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
+{
+       struct cx23885_audio_buffer *buf = chip->buf;
+       struct cx23885_dev *dev  = chip->dev;
+       struct sram_channel *audio_ch =
+               &dev->sram_channels[AUDIO_SRAM_CHANNEL];
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+       cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+       /* setup fifo + format - out channel */
+       cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
+               buf->risc.dma);
+
+       /* sets bpl size */
+       cx_write(AUD_INT_A_LNGTH, buf->bpl);
+
+       /* This is required to get good audio (1 seems to be ok) */
+       cx_write(AUD_INT_A_MODE, 1);
+
+       /* reset counter */
+       cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+       atomic_set(&chip->count, 0);
+
+       dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+               "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
+               chip->num_periods, buf->bpl * chip->num_periods);
+
+       /* Enables corresponding bits at AUD_INT_STAT */
+       cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+                                   AUD_INT_DN_RISCI1);
+
+       /* Clean any pending interrupt bits already set */
+       cx_write(AUDIO_INT_INT_STAT, ~0);
+
+       /* enable audio irqs */
+       cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+       /* start dma */
+       cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+       cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
+                                         RISC enable */
+       if (audio_debug)
+               cx23885_sram_channel_dump(chip->dev, audio_ch);
+
+       return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
+{
+       struct cx23885_dev *dev = chip->dev;
+       dprintk(1, "Stopping audio DMA\n");
+
+       /* stop dma */
+       cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+       /* disable irqs */
+       cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+       cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+                                   AUD_INT_DN_RISCI1);
+
+       if (audio_debug)
+               cx23885_sram_channel_dump(chip->dev,
+                       &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+
+       return 0;
+}
+
+/*
+ * BOARD Specific: Handles audio IRQ
+ */
+int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
+{
+       struct cx23885_audio_dev *chip = dev->audio_dev;
+
+       if (0 == (status & mask))
+               return 0;
+
+       cx_write(AUDIO_INT_INT_STAT, status);
+
+       /* risc op code error */
+       if (status & AUD_INT_OPC_ERR) {
+               printk(KERN_WARNING "%s/1: Audio risc op code error\n",
+                       dev->name);
+               cx_clear(AUD_INT_DMA_CTL, 0x11);
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+       }
+       if (status & AUD_INT_DN_SYNC) {
+               dprintk(1, "Downstream sync error\n");
+               cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+               return 1;
+       }
+       /* risc1 downstream */
+       if (status & AUD_INT_DN_RISCI1) {
+               atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
+               snd_pcm_period_elapsed(chip->substream);
+       }
+       /* FIXME: Any other status should deserve a special handling? */
+
+       return 1;
+}
+
+static int dsp_buffer_free(struct cx23885_audio_dev *chip)
+{
+       BUG_ON(!chip->dma_size);
+
+       dprintk(2, "Freeing buffer\n");
+       videobuf_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);
+
+       chip->dma_risc = NULL;
+       chip->dma_size = 0;
+
+       return 0;
+}
+
+/****************************************************************************
+                               ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE      4096
+
+static struct snd_pcm_hardware snd_cx23885_digital_hw = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates =                SNDRV_PCM_RATE_48000,
+       .rate_min =             48000,
+       .rate_max =             48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* Analog audio output will be full of clicks and pops if there
+          are not exactly four lines in the SRAM FIFO buffer.  */
+       .period_bytes_min = DEFAULT_FIFO_SIZE/4,
+       .period_bytes_max = DEFAULT_FIFO_SIZE/4,
+       .periods_min = 1,
+       .periods_max = 1024,
+       .buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
+
+       if (!chip) {
+               printk(KERN_ERR "BUG: cx23885 can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       err = snd_pcm_hw_constraint_pow2(runtime, 0,
+               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               goto _error;
+
+       chip->substream = substream;
+
+       runtime->hw = snd_cx23885_digital_hw;
+
+       if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+               DEFAULT_FIFO_SIZE) {
+               unsigned int bpl = chip->dev->
+                       sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
+               bpl &= ~7; /* must be multiple of 8 */
+               runtime->hw.period_bytes_min = bpl;
+               runtime->hw.period_bytes_max = bpl;
+       }
+
+       return 0;
+_error:
+       dprintk(1, "Error opening PCM!\n");
+       return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx23885_close(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *hw_params)
+{
+       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+       struct videobuf_dmabuf *dma;
+
+       struct cx23885_audio_buffer *buf;
+       int ret;
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       chip->period_size = params_period_bytes(hw_params);
+       chip->num_periods = params_periods(hw_params);
+       chip->dma_size = chip->period_size * params_periods(hw_params);
+
+       BUG_ON(!chip->dma_size);
+       BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (NULL == buf)
+               return -ENOMEM;
+
+       buf->bpl = chip->period_size;
+
+       dma = &buf->dma;
+       videobuf_dma_init(dma);
+       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+       if (ret < 0)
+               goto error;
+
+       ret = videobuf_dma_map(&chip->pci->dev, dma);
+       if (ret < 0)
+               goto error;
+
+       ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+                                  chip->period_size, chip->num_periods, 1);
+       if (ret < 0)
+               goto error;
+
+       /* Loop back to start of program */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+       chip->buf = buf;
+       chip->dma_risc = dma;
+
+       substream->runtime->dma_area = chip->dma_risc->vaddr;
+       substream->runtime->dma_bytes = chip->dma_size;
+       substream->runtime->dma_addr = 0;
+
+       return 0;
+
+error:
+       kfree(buf);
+       return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
+{
+
+       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
+       int cmd)
+{
+       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+       int err;
+
+       /* Local interrupts are already disabled by ALSA */
+       spin_lock(&chip->lock);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               err = cx23885_start_audio_dma(chip);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               err = cx23885_stop_audio_dma(chip);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+
+       spin_unlock(&chip->lock);
+
+       return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx23885_pointer(
+       struct snd_pcm_substream *substream)
+{
+       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       u16 count;
+
+       count = atomic_read(&chip->count);
+
+       return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
+                               unsigned long offset)
+{
+       void *pageptr = substream->runtime->dma_area + offset;
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx23885_pcm_ops = {
+       .open = snd_cx23885_pcm_open,
+       .close = snd_cx23885_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_cx23885_hw_params,
+       .hw_free = snd_cx23885_hw_free,
+       .prepare = snd_cx23885_prepare,
+       .trigger = snd_cx23885_card_trigger,
+       .pointer = snd_cx23885_pointer,
+       .page = snd_cx23885_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
+       char *name)
+{
+       int err;
+       struct snd_pcm *pcm;
+
+       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+       if (err < 0)
+               return err;
+       pcm->private_data = chip;
+       strcpy(pcm->name, name);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
+
+       return 0;
+}
+
+/****************************************************************************
+                       Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
+{
+       struct snd_card *card;
+       struct cx23885_audio_dev *chip;
+       int err;
+
+       if (disable_analog_audio)
+               return NULL;
+
+       if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
+               printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
+                       "for analog TV Audio\n", __func__);
+               return NULL;
+       }
+
+       err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                       THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
+       if (err < 0)
+               goto error;
+
+       chip = (struct cx23885_audio_dev *) card->private_data;
+       chip->dev = dev;
+       chip->pci = dev->pci;
+       chip->card = card;
+       spin_lock_init(&chip->lock);
+
+       snd_card_set_dev(card, &dev->pci->dev);
+
+       err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
+       if (err < 0)
+               goto error;
+
+       strcpy(card->driver, "CX23885");
+       sprintf(card->shortname, "Conexant CX23885");
+       sprintf(card->longname, "%s at %s", card->shortname, dev->name);
+
+       err = snd_card_register(card);
+       if (err < 0)
+               goto error;
+
+       dprintk(0, "registered ALSA audio device\n");
+
+       return chip;
+
+error:
+       snd_card_free(card);
+       printk(KERN_ERR "%s(): Failed to register analog "
+                       "audio adapter\n", __func__);
+
+       return NULL;
+}
+
+/*
+ * ALSA destructor
+ */
+void cx23885_audio_unregister(struct cx23885_dev *dev)
+{
+       struct cx23885_audio_dev *chip = dev->audio_dev;
+
+       snd_card_free(chip->card);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c
new file mode 100644 (file)
index 0000000..134ebdd
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  AV device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include "cx23885.h"
+
+void cx23885_av_work_handler(struct work_struct *work)
+{
+       struct cx23885_dev *dev =
+                          container_of(work, struct cx23885_dev, cx25840_work);
+       bool handled;
+
+       v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
+                        PCI_MSK_AV_CORE, &handled);
+       cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-av.h b/drivers/media/pci/cx23885/cx23885-av.h
new file mode 100644 (file)
index 0000000..d2915c3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  AV device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX23885_AV_H_
+#define _CX23885_AV_H_
+void cx23885_av_work_handler(struct work_struct *work);
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
new file mode 100644 (file)
index 0000000..d365e9a
--- /dev/null
@@ -0,0 +1,1684 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+#include <linux/firmware.h>
+#include <misc/altera.h>
+
+#include "cx23885.h"
+#include "tuner-xc2028.h"
+#include "netup-eeprom.h"
+#include "netup-init.h"
+#include "altera-ci.h"
+#include "xc4000.h"
+#include "xc5000.h"
+#include "cx23888-ir.h"
+
+static unsigned int netup_card_rev = 1;
+module_param(netup_card_rev, int, 0644);
+MODULE_PARM_DESC(netup_card_rev,
+               "NetUP Dual DVB-T/C CI card revision");
+static unsigned int enable_885_ir;
+module_param(enable_885_ir, int, 0644);
+MODULE_PARM_DESC(enable_885_ir,
+                "Enable integrated IR controller for supported\n"
+                "\t\t    CX2388[57] boards that are wired for it:\n"
+                "\t\t\tHVR-1250 (reported safe)\n"
+                "\t\t\tTerraTec Cinergy T PCIe Dual (not well tested, appears to be safe)\n"
+                "\t\t\tTeVii S470 (reported unsafe)\n"
+                "\t\t    This can cause an interrupt storm with some cards.\n"
+                "\t\t    Default: 0 [Disabled]");
+
+/* ------------------------------------------------------------------ */
+/* board config info                                                  */
+
+struct cx23885_board cx23885_boards[] = {
+       [CX23885_BOARD_UNKNOWN] = {
+               .name           = "UNKNOWN/GENERIC",
+               /* Ensure safe default for unknown boards */
+               .clk_freq       = 0,
+               .input          = {{
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = 0,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE2,
+                       .vmux   = 1,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE3,
+                       .vmux   = 2,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE4,
+                       .vmux   = 3,
+               } },
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1800lp] = {
+               .name           = "Hauppauge WinTV-HVR1800lp",
+               .portc          = CX23885_MPEG_DVB,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xff00,
+               }, {
+                       .type   = CX23885_VMUX_DEBUG,
+                       .vmux   = 0,
+                       .gpio0  = 0xff01,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xff02,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xff02,
+               } },
+       },
+       [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 */
+               .tuner_bus      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1,
+                       .amux   = CX25840_AUDIO8,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+                       .gpio0  = 0,
+               } },
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1250] = {
+               .name           = "Hauppauge WinTV-HVR1250",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+#ifdef MT2131_NO_ANALOG_SUPPORT_YET
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .tuner_bus      = 1,
+#endif
+               .force_bff      = 1,
+               .input          = {{
+#ifdef MT2131_NO_ANALOG_SUPPORT_YET
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1,
+                       .amux   = CX25840_AUDIO8,
+                       .gpio0  = 0xff00,
+               }, {
+#endif
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
+                       .gpio0  = 0xff02,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+                       .gpio0  = 0xff02,
+               } },
+       },
+       [CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = {
+               .name           = "DViCO FusionHDTV5 Express",
+               .portb          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1500Q] = {
+               .name           = "Hauppauge WinTV-HVR1500Q",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1500] = {
+               .name           = "Hauppauge WinTV-HVR1500",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61, /* 0xc2 >> 1 */
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .gpio0  = 0,
+               } },
+       },
+       [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,
+       },
+       [CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
+               .name           = "DViCO FusionHDTV7 Dual Express",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = {
+               .name           = "DViCO FusionHDTV DVB-T Dual Express",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = {
+               .name           = "Leadtek Winfast PxDVR3200 H",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
+               .name           = "Leadtek Winfast PxDVR3200 H XC4000",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   = CX25840_VIN2_CH1 |
+                                 CX25840_VIN5_CH2 |
+                                 CX25840_NONE0_CH3,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = CX25840_COMPOSITE1,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   = CX25840_SVIDEO_LUMA3 |
+                                 CX25840_SVIDEO_CHROMA4,
+               }, {
+                       .type   = CX23885_VMUX_COMPONENT,
+                       .vmux   = CX25840_VIN7_CH1 |
+                                 CX25840_VIN6_CH2 |
+                                 CX25840_VIN8_CH3 |
+                                 CX25840_COMPONENT_ON,
+               } },
+       },
+       [CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
+               .name           = "Compro VideoMate E650F",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_TBS_6920] = {
+               .name           = "TurboSight TBS 6920",
+               .portb          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_TEVII_S470] = {
+               .name           = "TeVii S470",
+               .portb          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_DVBWORLD_2005] = {
+               .name           = "DVBWorld DVB-S2 2005",
+               .portb          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = {
+               .ci_type        = 1,
+               .name           = "NetUP Dual DVB-S2 CI",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1270] = {
+               .name           = "Hauppauge WinTV-HVR1270",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1275] = {
+               .name           = "Hauppauge WinTV-HVR1275",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1255] = {
+               .name           = "Hauppauge WinTV-HVR1255",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .force_bff      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1 |
+                                       CX25840_DIF_ON,
+                       .amux   = CX25840_AUDIO8,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+               } },
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1255_22111] = {
+               .name           = "Hauppauge WinTV-HVR1255",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .force_bff      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1 |
+                                       CX25840_DIF_ON,
+                       .amux   = CX25840_AUDIO8,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+               } },
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1210] = {
+               .name           = "Hauppauge WinTV-HVR1210",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_MYGICA_X8506] = {
+               .name           = "Mygica X8506 DMB-TH",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_bus      = 1,
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_DVB,
+               .input          = {
+                       {
+                               .type   = CX23885_VMUX_TELEVISION,
+                               .vmux   = CX25840_COMPOSITE2,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPOSITE1,
+                               .vmux   = CX25840_COMPOSITE8,
+                       },
+                       {
+                               .type   = CX23885_VMUX_SVIDEO,
+                               .vmux   = CX25840_SVIDEO_LUMA3 |
+                                               CX25840_SVIDEO_CHROMA4,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPONENT,
+                               .vmux   = CX25840_COMPONENT_ON |
+                                       CX25840_VIN1_CH1 |
+                                       CX25840_VIN6_CH2 |
+                                       CX25840_VIN7_CH3,
+                       },
+               },
+       },
+       [CX23885_BOARD_MAGICPRO_PROHDTVE2] = {
+               .name           = "Magic-Pro ProHDTV Extreme 2",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_bus      = 1,
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_DVB,
+               .input          = {
+                       {
+                               .type   = CX23885_VMUX_TELEVISION,
+                               .vmux   = CX25840_COMPOSITE2,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPOSITE1,
+                               .vmux   = CX25840_COMPOSITE8,
+                       },
+                       {
+                               .type   = CX23885_VMUX_SVIDEO,
+                               .vmux   = CX25840_SVIDEO_LUMA3 |
+                                               CX25840_SVIDEO_CHROMA4,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPONENT,
+                               .vmux   = CX25840_COMPONENT_ON |
+                                       CX25840_VIN1_CH1 |
+                                       CX25840_VIN6_CH2 |
+                                       CX25840_VIN7_CH3,
+                       },
+               },
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1850] = {
+               .name           = "Hauppauge WinTV-HVR1850",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_ENCODER,
+               .portc          = CX23885_MPEG_DVB,
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_addr     = 0x42, /* 0x84 >> 1 */
+               .force_bff      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN5_CH2 |
+                                       CX25840_VIN2_CH1 |
+                                       CX25840_DIF_ON,
+                       .amux   = CX25840_AUDIO8,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN6_CH1,
+                       .amux   = CX25840_AUDIO7,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   =       CX25840_VIN7_CH3 |
+                                       CX25840_VIN4_CH2 |
+                                       CX25840_VIN8_CH1 |
+                                       CX25840_SVIDEO_ON,
+                       .amux   = CX25840_AUDIO7,
+               } },
+       },
+       [CX23885_BOARD_COMPRO_VIDEOMATE_E800] = {
+               .name           = "Compro VideoMate E800",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_HAUPPAUGE_HVR1290] = {
+               .name           = "Hauppauge WinTV-HVR1290",
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_MYGICA_X8558PRO] = {
+               .name           = "Mygica X8558 PRO DMB-TH",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_LEADTEK_WINFAST_PXTV1200] = {
+               .name           = "LEADTEK WinFast PxTV1200",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .tuner_bus      = 1,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   = CX25840_VIN2_CH1 |
+                                 CX25840_VIN5_CH2 |
+                                 CX25840_NONE0_CH3,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = CX25840_COMPOSITE1,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   = CX25840_SVIDEO_LUMA3 |
+                                 CX25840_SVIDEO_CHROMA4,
+               }, {
+                       .type   = CX23885_VMUX_COMPONENT,
+                       .vmux   = CX25840_VIN7_CH1 |
+                                 CX25840_VIN6_CH2 |
+                                 CX25840_VIN8_CH3 |
+                                 CX25840_COMPONENT_ON,
+               } },
+       },
+       [CX23885_BOARD_GOTVIEW_X5_3D_HYBRID] = {
+               .name           = "GoTView X5 3D Hybrid",
+               .tuner_type     = TUNER_XC5000,
+               .tuner_addr     = 0x64,
+               .tuner_bus      = 1,
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_DVB,
+               .input          = {{
+                       .type   = CX23885_VMUX_TELEVISION,
+                       .vmux   = CX25840_VIN2_CH1 |
+                                 CX25840_VIN5_CH2,
+                       .gpio0  = 0x02,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = CX23885_VMUX_COMPOSITE1,
+               }, {
+                       .type   = CX23885_VMUX_SVIDEO,
+                       .vmux   = CX25840_SVIDEO_LUMA3 |
+                                 CX25840_SVIDEO_CHROMA4,
+               } },
+       },
+       [CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF] = {
+               .ci_type        = 2,
+               .name           = "NetUP Dual DVB-T/C-CI RF",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+               .num_fds_portb  = 2,
+               .num_fds_portc  = 2,
+               .tuner_type     = TUNER_XC5000,
+               .tuner_addr     = 0x64,
+               .input          = { {
+                               .type   = CX23885_VMUX_TELEVISION,
+                               .vmux   = CX25840_COMPOSITE1,
+               } },
+       },
+       [CX23885_BOARD_MPX885] = {
+               .name           = "MPX-885",
+               .porta          = CX23885_ANALOG_VIDEO,
+               .input          = {{
+                       .type   = CX23885_VMUX_COMPOSITE1,
+                       .vmux   = CX25840_COMPOSITE1,
+                       .amux   = CX25840_AUDIO6,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE2,
+                       .vmux   = CX25840_COMPOSITE2,
+                       .amux   = CX25840_AUDIO6,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE3,
+                       .vmux   = CX25840_COMPOSITE3,
+                       .amux   = CX25840_AUDIO7,
+                       .gpio0  = 0,
+               }, {
+                       .type   = CX23885_VMUX_COMPOSITE4,
+                       .vmux   = CX25840_COMPOSITE4,
+                       .amux   = CX25840_AUDIO7,
+                       .gpio0  = 0,
+               } },
+       },
+       [CX23885_BOARD_MYGICA_X8507] = {
+               .name           = "Mygica X8507",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_bus      = 1,
+               .porta          = CX23885_ANALOG_VIDEO,
+               .input          = {
+                       {
+                               .type   = CX23885_VMUX_TELEVISION,
+                               .vmux   = CX25840_COMPOSITE2,
+                               .amux   = CX25840_AUDIO8,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPOSITE1,
+                               .vmux   = CX25840_COMPOSITE8,
+                       },
+                       {
+                               .type   = CX23885_VMUX_SVIDEO,
+                               .vmux   = CX25840_SVIDEO_LUMA3 |
+                                               CX25840_SVIDEO_CHROMA4,
+                       },
+                       {
+                               .type   = CX23885_VMUX_COMPONENT,
+                               .vmux   = CX25840_COMPONENT_ON |
+                                       CX25840_VIN1_CH1 |
+                                       CX25840_VIN6_CH2 |
+                                       CX25840_VIN7_CH3,
+                       },
+               },
+       },
+       [CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL] = {
+               .name           = "TerraTec Cinergy T PCIe Dual",
+               .portb          = CX23885_MPEG_DVB,
+               .portc          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_TEVII_S471] = {
+               .name           = "TeVii S471",
+               .portb          = CX23885_MPEG_DVB,
+       }
+};
+const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
+
+/* ------------------------------------------------------------------ */
+/* PCI subsystem IDs                                                  */
+
+struct cx23885_subid cx23885_subids[] = {
+       {
+               .subvendor = 0x0070,
+               .subdevice = 0x3400,
+               .card      = CX23885_BOARD_UNKNOWN,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7600,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800lp,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7800,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7801,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7809,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7911,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1250,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd500,
+               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7790,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7797,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7710,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x7717,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x71d1,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x71d3,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8101,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1700,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8010,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xd618,
+               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb78,
+               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6681,
+               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f39,
+               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000,
+       }, {
+               .subvendor = 0x185b,
+               .subdevice = 0xe800,
+               .card      = CX23885_BOARD_COMPRO_VIDEOMATE_E650F,
+       }, {
+               .subvendor = 0x6920,
+               .subdevice = 0x8888,
+               .card      = CX23885_BOARD_TBS_6920,
+       }, {
+               .subvendor = 0xd470,
+               .subdevice = 0x9022,
+               .card      = CX23885_BOARD_TEVII_S470,
+       }, {
+               .subvendor = 0x0001,
+               .subdevice = 0x2005,
+               .card      = CX23885_BOARD_DVBWORLD_2005,
+       }, {
+               .subvendor = 0x1b55,
+               .subdevice = 0x2a2c,
+               .card      = CX23885_BOARD_NETUP_DUAL_DVBS2_CI,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2211,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1270,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2215,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x221d,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2251,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2259,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255_22111,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2291,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2295,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x2299,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x229d,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x22f0,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x22f1,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x22f2,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x22f3,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x22f4,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x22f5,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8651,
+               .card      = CX23885_BOARD_MYGICA_X8506,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8657,
+               .card      = CX23885_BOARD_MAGICPRO_PROHDTVE2,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8541,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1850,
+       }, {
+               .subvendor = 0x1858,
+               .subdevice = 0xe800,
+               .card      = CX23885_BOARD_COMPRO_VIDEOMATE_E800,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8551,
+               .card      = CX23885_BOARD_HAUPPAUGE_HVR1290,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8578,
+               .card      = CX23885_BOARD_MYGICA_X8558PRO,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f22,
+               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200,
+       }, {
+               .subvendor = 0x5654,
+               .subdevice = 0x2390,
+               .card      = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID,
+       }, {
+               .subvendor = 0x1b55,
+               .subdevice = 0xe2e4,
+               .card      = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF,
+       }, {
+               .subvendor = 0x14f1,
+               .subdevice = 0x8502,
+               .card      = CX23885_BOARD_MYGICA_X8507,
+       }, {
+               .subvendor = 0x153b,
+               .subdevice = 0x117e,
+               .card      = CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL,
+       }, {
+               .subvendor = 0xd471,
+               .subdevice = 0x9022,
+               .card      = CX23885_BOARD_TEVII_S471,
+       },
+};
+const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
+
+void cx23885_card_list(struct cx23885_dev *dev)
+{
+       int i;
+
+       if (0 == dev->pci->subsystem_vendor &&
+           0 == dev->pci->subsystem_device) {
+               printk(KERN_INFO
+                       "%s: Board has no valid PCIe Subsystem ID and can't\n"
+                      "%s: be autodetected. Pass card=<n> insmod option\n"
+                      "%s: to workaround that. Redirect complaints to the\n"
+                      "%s: vendor of the TV card.  Best regards,\n"
+                      "%s:         -- tux\n",
+                      dev->name, dev->name, dev->name, dev->name, dev->name);
+       } else {
+               printk(KERN_INFO
+                       "%s: Your board isn't known (yet) to the driver.\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",
+                      dev->name, dev->name, dev->name, dev->name);
+       }
+       printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+              dev->name);
+       for (i = 0; i < cx23885_bcount; i++)
+               printk(KERN_INFO "%s:    card=%d -> %s\n",
+                      dev->name, i, cx23885_boards[i].name);
+}
+
+static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
+               eeprom_data);
+
+       /* Make sure we support the board model */
+       switch (tv.model) {
+       case 22001:
+               /* WinTV-HVR1270 (PCIe, Retail, half height)
+                * ATSC/QAM and basic analog, IR Blast */
+       case 22009:
+               /* WinTV-HVR1210 (PCIe, Retail, half height)
+                * DVB-T and basic analog, IR Blast */
+       case 22011:
+               /* WinTV-HVR1270 (PCIe, Retail, half height)
+                * ATSC/QAM and basic analog, IR Recv */
+       case 22019:
+               /* WinTV-HVR1210 (PCIe, Retail, half height)
+                * DVB-T and basic analog, IR Recv */
+       case 22021:
+               /* WinTV-HVR1275 (PCIe, Retail, half height)
+                * ATSC/QAM and basic analog, IR Recv */
+       case 22029:
+               /* WinTV-HVR1210 (PCIe, Retail, half height)
+                * DVB-T and basic analog, IR Recv */
+       case 22101:
+               /* WinTV-HVR1270 (PCIe, Retail, full height)
+                * ATSC/QAM and basic analog, IR Blast */
+       case 22109:
+               /* WinTV-HVR1210 (PCIe, Retail, full height)
+                * DVB-T and basic analog, IR Blast */
+       case 22111:
+               /* WinTV-HVR1270 (PCIe, Retail, full height)
+                * ATSC/QAM and basic analog, IR Recv */
+       case 22119:
+               /* WinTV-HVR1210 (PCIe, Retail, full height)
+                * DVB-T and basic analog, IR Recv */
+       case 22121:
+               /* WinTV-HVR1275 (PCIe, Retail, full height)
+                * ATSC/QAM and basic analog, IR Recv */
+       case 22129:
+               /* WinTV-HVR1210 (PCIe, Retail, full height)
+                * DVB-T and basic analog, IR Recv */
+       case 71009:
+               /* WinTV-HVR1200 (PCIe, Retail, full height)
+                * DVB-T and basic analog */
+       case 71359:
+               /* WinTV-HVR1200 (PCIe, OEM, half height)
+                * DVB-T and basic analog */
+       case 71439:
+               /* WinTV-HVR1200 (PCIe, OEM, half height)
+                * DVB-T and basic analog */
+       case 71449:
+               /* WinTV-HVR1200 (PCIe, OEM, full height)
+                * DVB-T and basic analog */
+       case 71939:
+               /* WinTV-HVR1200 (PCIe, OEM, half height)
+                * DVB-T and basic analog */
+       case 71949:
+               /* WinTV-HVR1200 (PCIe, OEM, full height)
+                * DVB-T and basic analog */
+       case 71959:
+               /* WinTV-HVR1200 (PCIe, OEM, full height)
+                * DVB-T and basic analog */
+       case 71979:
+               /* WinTV-HVR1200 (PCIe, OEM, half height)
+                * DVB-T and basic analog */
+       case 71999:
+               /* WinTV-HVR1200 (PCIe, OEM, full height)
+                * DVB-T and basic analog */
+       case 76601:
+               /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual
+                       channel ATSC and MPEG2 HW Encoder */
+       case 77001:
+               /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC
+                       and Basic analog */
+       case 77011:
+               /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC
+                       and Basic analog */
+       case 77041:
+               /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM
+                       and Basic analog */
+       case 77051:
+               /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM
+                       and Basic analog */
+       case 78011:
+               /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM,
+                       Dual channel ATSC and MPEG2 HW Encoder */
+       case 78501:
+               /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+                       Dual channel ATSC and MPEG2 HW Encoder */
+       case 78521:
+               /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+                       Dual channel ATSC and MPEG2 HW Encoder */
+       case 78531:
+               /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM,
+                       Dual channel ATSC and MPEG2 HW Encoder */
+       case 78631:
+               /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM,
+                       Dual channel ATSC and MPEG2 HW Encoder */
+       case 79001:
+               /* WinTV-HVR1250 (PCIe, Retail, IR, full height,
+                       ATSC and Basic analog */
+       case 79101:
+               /* WinTV-HVR1250 (PCIe, Retail, IR, half height,
+                       ATSC and Basic analog */
+       case 79501:
+               /* WinTV-HVR1250 (PCIe, No IR, half height,
+                       ATSC [at least] and Basic analog) */
+       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 81509:
+               /* WinTV-HVR1700 (PCIe, OEM, No IR, half height)
+                * DVB-T and MPEG2 HW Encoder */
+       case 81519:
+               /* WinTV-HVR1700 (PCIe, OEM, No IR, full height)
+                * DVB-T and MPEG2 HW Encoder */
+               break;
+       case 85021:
+               /* WinTV-HVR1850 (PCIe, Retail, 3.5mm in, IR, FM,
+                       Dual channel ATSC and MPEG2 HW Encoder */
+               break;
+       case 85721:
+               /* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
+                       Dual channel ATSC and Basic analog */
+               break;
+       default:
+               printk(KERN_WARNING "%s: warning: "
+                       "unknown hauppauge model #%d\n",
+                       dev->name, tv.model);
+               break;
+       }
+
+       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+                       dev->name, tv.model);
+}
+
+int cx23885_tuner_callback(void *priv, int component, int command, int arg)
+{
+       struct cx23885_tsport *port = priv;
+       struct cx23885_dev *dev = port->dev;
+       u32 bitmask = 0;
+
+       if ((command == XC2028_RESET_CLK) || (command == XC2028_I2C_FLUSH))
+               return 0;
+
+       if (command != 0) {
+               printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
+                       __func__, command);
+               return -EINVAL;
+       }
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+       case CX23885_BOARD_HAUPPAUGE_HVR1500:
+       case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+               /* Tuner Reset Command */
+               bitmask = 0x04;
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               /* Two identical tuners on two different i2c buses,
+                * we need to reset the correct gpio. */
+               if (port->nr == 1)
+                       bitmask = 0x01;
+               else if (port->nr == 2)
+                       bitmask = 0x04;
+               break;
+       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+               /* Tuner Reset Command */
+               bitmask = 0x02;
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+               altera_ci_tuner_reset(dev, port->nr);
+               break;
+       }
+
+       if (bitmask) {
+               /* Drive the tuner into reset and back out */
+               cx_clear(GP0_IO, bitmask);
+               mdelay(200);
+               cx_set(GP0_IO, bitmask);
+       }
+
+       return 0;
+}
+
+void cx23885_gpio_setup(struct cx23885_dev *dev)
+{
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               /* GPIO-0 cx24227 demodulator reset */
+               cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1500:
+               /* GPIO-0 cx24227 demodulator */
+               /* GPIO-2 xc3028 tuner */
+
+               /* Put the parts into reset */
+               cx_set(GP0_IO, 0x00050000);
+               cx_clear(GP0_IO, 0x00000005);
+               msleep(5);
+
+               /* Bring the parts out of reset */
+               cx_set(GP0_IO, 0x00050005);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+               /* GPIO-0 cx24227 demodulator reset */
+               /* GPIO-2 xc5000 tuner reset */
+               cx_set(GP0_IO, 0x00050005); /* Bring the part out of reset */
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+               /* GPIO-0 656_CLK */
+               /* GPIO-1 656_D0 */
+               /* GPIO-2 8295A Reset */
+               /* GPIO-3-10 cx23417 data0-7 */
+               /* GPIO-11-14 cx23417 addr0-3 */
+               /* GPIO-15-18 cx23417 READY, CS, RD, WR */
+               /* GPIO-19 IR_RX */
+
+               /* CX23417 GPIO's */
+               /* EIO15 Zilog Reset */
+               /* EIO14 S5H1409/CX24227 Reset */
+               mc417_gpio_enable(dev, GPIO_15 | GPIO_14, 1);
+
+               /* Put the demod into reset and protect the eeprom */
+               mc417_gpio_clear(dev, GPIO_15 | GPIO_14);
+               mdelay(100);
+
+               /* Bring the demod and blaster out of reset */
+               mc417_gpio_set(dev, GPIO_15 | GPIO_14);
+               mdelay(100);
+
+               /* Force the TDA8295A into reset and back */
+               cx23885_gpio_enable(dev, GPIO_2, 1);
+               cx23885_gpio_set(dev, GPIO_2);
+               mdelay(20);
+               cx23885_gpio_clear(dev, GPIO_2);
+               mdelay(20);
+               cx23885_gpio_set(dev, GPIO_2);
+               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;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+               /* GPIO-0 xc5000 tuner reset i2c bus 0 */
+               /* GPIO-1 s5h1409 demod reset i2c bus 0 */
+               /* GPIO-2 xc5000 tuner reset i2c bus 1 */
+               /* GPIO-3 s5h1409 demod reset i2c bus 0 */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x000f0000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x0000000f);
+               mdelay(20);
+               cx_set(GP0_IO, 0x000f000f);
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               /* GPIO-0 portb xc3028 reset */
+               /* GPIO-1 portb zl10353 reset */
+               /* GPIO-2 portc xc3028 reset */
+               /* GPIO-3 portc zl10353 reset */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x000f0000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x0000000f);
+               mdelay(20);
+               cx_set(GP0_IO, 0x000f000f);
+               break;
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+               /* GPIO-2  xc3028 tuner reset */
+
+               /* The following GPIO's are on the internal AVCore (cx25840) */
+               /* GPIO-?  zl10353 demod reset */
+
+               /* Put the parts into reset and back */
+               cx_set(GP0_IO, 0x00040000);
+               mdelay(20);
+               cx_clear(GP0_IO, 0x00000004);
+               mdelay(20);
+               cx_set(GP0_IO, 0x00040004);
+               break;
+       case CX23885_BOARD_TBS_6920:
+               cx_write(MC417_CTL, 0x00000036);
+               cx_write(MC417_OEN, 0x00001000);
+               cx_set(MC417_RWD, 0x00000002);
+               mdelay(200);
+               cx_clear(MC417_RWD, 0x00000800);
+               mdelay(200);
+               cx_set(MC417_RWD, 0x00000800);
+               mdelay(200);
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               /* GPIO-0 INTA from CiMax1
+                  GPIO-1 INTB from CiMax2
+                  GPIO-2 reset chips
+                  GPIO-3 to GPIO-10 data/addr for CA
+                  GPIO-11 ~CS0 to CiMax1
+                  GPIO-12 ~CS1 to CiMax2
+                  GPIO-13 ADL0 load LSB addr
+                  GPIO-14 ADL1 load MSB addr
+                  GPIO-15 ~RDY from CiMax
+                  GPIO-17 ~RD to CiMax
+                  GPIO-18 ~WR to CiMax
+                */
+               cx_set(GP0_IO, 0x00040000); /* GPIO as out */
+               /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */
+               cx_clear(GP0_IO, 0x00030004);
+               mdelay(100);/* reset delay */
+               cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */
+               cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */
+               /* GPIO-15 IN as ~ACK, rest as OUT */
+               cx_write(MC417_OEN, 0x00001000);
+               /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
+               cx_write(MC417_RWD, 0x0000c300);
+               /* enable irq */
+               cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+       case CX23885_BOARD_HAUPPAUGE_HVR1210:
+               /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */
+               /* GPIO-6 I2C Gate which can isolate the demod from the bus */
+               /* GPIO-9 Demod reset */
+
+               /* Put the parts into reset and back */
+               cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1);
+               cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5);
+               cx23885_gpio_clear(dev, GPIO_9);
+               mdelay(20);
+               cx23885_gpio_set(dev, GPIO_9);
+               break;
+       case CX23885_BOARD_MYGICA_X8506:
+       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+       case CX23885_BOARD_MYGICA_X8507:
+               /* GPIO-0 (0)Analog / (1)Digital TV */
+               /* GPIO-1 reset XC5000 */
+               /* GPIO-2 reset LGS8GL5 / LGS8G75 */
+               cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1);
+               cx23885_gpio_clear(dev, GPIO_1 | GPIO_2);
+               mdelay(100);
+               cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2);
+               mdelay(100);
+               break;
+       case CX23885_BOARD_MYGICA_X8558PRO:
+               /* GPIO-0 reset first ATBM8830 */
+               /* GPIO-1 reset second ATBM8830 */
+               cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1);
+               cx23885_gpio_clear(dev, GPIO_0 | GPIO_1);
+               mdelay(100);
+               cx23885_gpio_set(dev, GPIO_0 | GPIO_1);
+               mdelay(100);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+               /* GPIO-0 656_CLK */
+               /* GPIO-1 656_D0 */
+               /* GPIO-2 Wake# */
+               /* GPIO-3-10 cx23417 data0-7 */
+               /* GPIO-11-14 cx23417 addr0-3 */
+               /* GPIO-15-18 cx23417 READY, CS, RD, WR */
+               /* GPIO-19 IR_RX */
+               /* GPIO-20 C_IR_TX */
+               /* GPIO-21 I2S DAT */
+               /* GPIO-22 I2S WCLK */
+               /* GPIO-23 I2S BCLK */
+               /* ALT GPIO: EXP GPIO LATCH */
+
+               /* CX23417 GPIO's */
+               /* GPIO-14 S5H1411/CX24228 Reset */
+               /* GPIO-13 EEPROM write protect */
+               mc417_gpio_enable(dev, GPIO_14 | GPIO_13, 1);
+
+               /* Put the demod into reset and protect the eeprom */
+               mc417_gpio_clear(dev, GPIO_14 | GPIO_13);
+               mdelay(100);
+
+               /* Bring the demod out of reset */
+               mc417_gpio_set(dev, GPIO_14);
+               mdelay(100);
+
+               /* CX24228 GPIO */
+               /* Connected to IF / Mux */
+               break;
+       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+               cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+               /* GPIO-0 ~INT in
+                  GPIO-1 TMS out
+                  GPIO-2 ~reset chips out
+                  GPIO-3 to GPIO-10 data/addr for CA in/out
+                  GPIO-11 ~CS out
+                  GPIO-12 ADDR out
+                  GPIO-13 ~WR out
+                  GPIO-14 ~RD out
+                  GPIO-15 ~RDY in
+                  GPIO-16 TCK out
+                  GPIO-17 TDO in
+                  GPIO-18 TDI out
+                */
+               cx_set(GP0_IO, 0x00060000); /* GPIO-1,2 as out */
+               /* GPIO-0 as INT, reset & TMS low */
+               cx_clear(GP0_IO, 0x00010006);
+               mdelay(100);/* reset delay */
+               cx_set(GP0_IO, 0x00000004); /* reset high */
+               cx_write(MC417_CTL, 0x00000037);/* enable GPIO-3..18 pins */
+               /* GPIO-17 is TDO in, GPIO-15 is ~RDY in, rest is out */
+               cx_write(MC417_OEN, 0x00005000);
+               /* ~RD, ~WR high; ADDR low; ~CS high */
+               cx_write(MC417_RWD, 0x00000d00);
+               /* enable irq */
+               cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
+               break;
+       }
+}
+
+int cx23885_ir_init(struct cx23885_dev *dev)
+{
+       static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = {
+               {
+                       .flags    = V4L2_SUBDEV_IO_PIN_INPUT,
+                       .pin      = CX23885_PIN_IR_RX_GPIO19,
+                       .function = CX23885_PAD_IR_RX,
+                       .value    = 0,
+                       .strength = CX25840_PIN_DRIVE_MEDIUM,
+               }, {
+                       .flags    = V4L2_SUBDEV_IO_PIN_OUTPUT,
+                       .pin      = CX23885_PIN_IR_TX_GPIO20,
+                       .function = CX23885_PAD_IR_TX,
+                       .value    = 0,
+                       .strength = CX25840_PIN_DRIVE_MEDIUM,
+               }
+       };
+       const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg);
+
+       static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = {
+               {
+                       .flags    = V4L2_SUBDEV_IO_PIN_INPUT,
+                       .pin      = CX23885_PIN_IR_RX_GPIO19,
+                       .function = CX23885_PAD_IR_RX,
+                       .value    = 0,
+                       .strength = CX25840_PIN_DRIVE_MEDIUM,
+               }
+       };
+       const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg);
+
+       struct v4l2_subdev_ir_parameters params;
+       int ret = 0;
+       switch (dev->board) {
+       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:
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+       case CX23885_BOARD_HAUPPAUGE_HVR1210:
+               /* FIXME: Implement me */
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+               ret = cx23888_ir_probe(dev);
+               if (ret)
+                       break;
+               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
+               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+                                ir_rx_pin_cfg_count, ir_rx_pin_cfg);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+               ret = cx23888_ir_probe(dev);
+               if (ret)
+                       break;
+               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
+               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+                                ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
+               /*
+                * For these boards we need to invert the Tx output via the
+                * IR controller to have the LED off while idle
+                */
+               v4l2_subdev_call(dev->sd_ir, ir, tx_g_parameters, &params);
+               params.enable = false;
+               params.shutdown = false;
+               params.invert_level = true;
+               v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
+               params.shutdown = true;
+               v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
+               break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+       case CX23885_BOARD_TEVII_S470:
+               if (!enable_885_ir)
+                       break;
+               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
+               if (dev->sd_ir == NULL) {
+                       ret = -ENODEV;
+                       break;
+               }
+               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+                                ir_rx_pin_cfg_count, ir_rx_pin_cfg);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               if (!enable_885_ir)
+                       break;
+               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
+               if (dev->sd_ir == NULL) {
+                       ret = -ENODEV;
+                       break;
+               }
+               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+                                ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               request_module("ir-kbd-i2c");
+               break;
+       }
+
+       return ret;
+}
+
+void cx23885_ir_fini(struct cx23885_dev *dev)
+{
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+               cx23885_irq_remove(dev, PCI_MSK_IR);
+               cx23888_ir_remove(dev);
+               dev->sd_ir = NULL;
+               break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+       case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
+               /* sd_ir is a duplicate pointer to the AV Core, just clear it */
+               dev->sd_ir = NULL;
+               break;
+       }
+}
+
+int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
+{
+       int data;
+       int tdo = 0;
+       struct cx23885_dev *dev = (struct cx23885_dev *)device;
+       /*TMS*/
+       data = ((cx_read(GP0_IO)) & (~0x00000002));
+       data |= (tms ? 0x00020002 : 0x00020000);
+       cx_write(GP0_IO, data);
+
+       /*TDI*/
+       data = ((cx_read(MC417_RWD)) & (~0x0000a000));
+       data |= (tdi ? 0x00008000 : 0);
+       cx_write(MC417_RWD, data);
+       if (read_tdo)
+               tdo = (data & 0x00004000) ? 1 : 0; /*TDO*/
+
+       cx_write(MC417_RWD, data | 0x00002000);
+       udelay(1);
+       /*TCK*/
+       cx_write(MC417_RWD, data);
+
+       return tdo;
+}
+
+void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
+{
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+               if (dev->sd_ir)
+                       cx23885_irq_add_enable(dev, PCI_MSK_IR);
+               break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+       case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               if (dev->sd_ir)
+                       cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
+               break;
+       }
+}
+
+void cx23885_card_setup(struct cx23885_dev *dev)
+{
+       struct cx23885_tsport *ts1 = &dev->ts1;
+       struct cx23885_tsport *ts2 = &dev->ts2;
+
+       static u8 eeprom[256];
+
+       if (dev->i2c_bus[0].i2c_rc == 0) {
+               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_bus[0].i2c_client,
+                             eeprom, sizeof(eeprom));
+       }
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               if (dev->i2c_bus[0].i2c_rc == 0) {
+                       if (eeprom[0x80] != 0x84)
+                               hauppauge_eeprom(dev, eeprom+0xc0);
+                       else
+                               hauppauge_eeprom(dev, eeprom+0x80);
+               }
+               break;
+       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:
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+       case CX23885_BOARD_HAUPPAUGE_HVR1210:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+               if (dev->i2c_bus[0].i2c_rc == 0)
+                       hauppauge_eeprom(dev, eeprom+0xc0);
+               break;
+       }
+
+       switch (dev->board) {
+       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+               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 omitted intentionally */
+       case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
+               ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+               /* Defaults for VID B - Analog encoder */
+               /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
+               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);
+               cx_write(0x130184, 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_TBS_6920:
+               ts1->gen_ctrl_val  = 0x4; /* Parallel */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
+       case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_TEVII_S471:
+       case CX23885_BOARD_DVBWORLD_2005:
+               ts1->gen_ctrl_val  = 0x5; /* Parallel */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+               ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               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_MYGICA_X8506:
+       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+               ts1->gen_ctrl_val  = 0x5; /* Parallel */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               break;
+       case CX23885_BOARD_MYGICA_X8558PRO:
+               ts1->gen_ctrl_val  = 0x5; /* Parallel */
+               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+               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_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1200:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+       case CX23885_BOARD_HAUPPAUGE_HVR1210:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+       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_TEVII_S470:
+               /* Currently only enabled for the integrated IR controller */
+               if (!enable_885_ir)
+                       break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+       case CX23885_BOARD_HAUPPAUGE_HVR1700:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_MYGICA_X8506:
+       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+       case CX23885_BOARD_HAUPPAUGE_HVR1500:
+       case CX23885_BOARD_MPX885:
+       case CX23885_BOARD_MYGICA_X8507:
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+               dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_bus[2].i2c_adap,
+                               "cx25840", 0x88 >> 1, NULL);
+               if (dev->sd_cx25840) {
+                       dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
+                       v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
+               }
+               break;
+       }
+
+       /* AUX-PLL 27MHz CLK */
+       switch (dev->board) {
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               netup_initialize(dev);
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+               int ret;
+               const struct firmware *fw;
+               const char *filename = "dvb-netup-altera-01.fw";
+               char *action = "configure";
+               static struct netup_card_info cinfo;
+               struct altera_config netup_config = {
+                       .dev = dev,
+                       .action = action,
+                       .jtag_io = netup_jtag_io,
+               };
+
+               netup_initialize(dev);
+
+               netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+               if (netup_card_rev)
+                       cinfo.rev = netup_card_rev;
+
+               switch (cinfo.rev) {
+               case 0x4:
+                       filename = "dvb-netup-altera-04.fw";
+                       break;
+               default:
+                       filename = "dvb-netup-altera-01.fw";
+                       break;
+               }
+               printk(KERN_INFO "NetUP card rev=0x%x fw_filename=%s\n",
+                               cinfo.rev, filename);
+
+               ret = request_firmware(&fw, filename, &dev->pci->dev);
+               if (ret != 0)
+                       printk(KERN_ERR "did not find the firmware file. (%s) "
+                       "Please see linux/Documentation/dvb/ for more details "
+                       "on firmware-problems.", filename);
+               else
+                       altera_init(&netup_config, fw);
+
+               release_firmware(fw);
+               break;
+       }
+       }
+}
+
+/* ------------------------------------------------------------------ */
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
new file mode 100644 (file)
index 0000000..697728f
--- /dev/null
@@ -0,0 +1,2234 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+#include <linux/firmware.h>
+
+#include "cx23885.h"
+#include "cimax2.h"
+#include "altera-ci.h"
+#include "cx23888-ir.h"
+#include "cx23885-ir.h"
+#include "cx23885-av.h"
+#include "cx23885-input.h"
+
+MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX23885_VERSION);
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[]  = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+module_param_array(card,  int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (debug >= level)\
+               printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+       } while (0)
+
+static unsigned int cx23885_devcount;
+
+#define NO_SYNC_LINE (-1U)
+
+/* FIXME, these allocations will change when
+ * analog arrives. The be reviewed.
+ * CX23887 Assumptions
+ * 1 line = 16 bytes of CDT
+ * cmds size = 80
+ * cdt size = 16 * linesize
+ * iqsize = 64
+ * maxlines = 6
+ *
+ * Address Space:
+ * 0x00000000 0x00008fff FIFO clusters
+ * 0x00010000 0x000104af Channel Management Data Structures
+ * 0x000104b0 0x000104ff Free
+ * 0x00010500 0x000108bf 15 channels * iqsize
+ * 0x000108c0 0x000108ff Free
+ * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables
+ *                       15 channels * (iqsize + (maxlines * linesize))
+ * 0x00010ea0 0x00010xxx Free
+ */
+
+static struct sram_channel cx23885_sram_channels[] = {
+       [SRAM_CH01] = {
+               .name           = "VID A",
+               .cmds_start     = 0x10000,
+               .ctrl_start     = 0x10380,
+               .cdt            = 0x104c0,
+               .fifo_start     = 0x40,
+               .fifo_size      = 0x2800,
+               .ptr1_reg       = DMA1_PTR1,
+               .ptr2_reg       = DMA1_PTR2,
+               .cnt1_reg       = DMA1_CNT1,
+               .cnt2_reg       = DMA1_CNT2,
+       },
+       [SRAM_CH02] = {
+               .name           = "ch2",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA2_PTR1,
+               .ptr2_reg       = DMA2_PTR2,
+               .cnt1_reg       = DMA2_CNT1,
+               .cnt2_reg       = DMA2_CNT2,
+       },
+       [SRAM_CH03] = {
+               .name           = "TS1 B",
+               .cmds_start     = 0x100A0,
+               .ctrl_start     = 0x10400,
+               .cdt            = 0x10580,
+               .fifo_start     = 0x5000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA3_PTR1,
+               .ptr2_reg       = DMA3_PTR2,
+               .cnt1_reg       = DMA3_CNT1,
+               .cnt2_reg       = DMA3_CNT2,
+       },
+       [SRAM_CH04] = {
+               .name           = "ch4",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA4_PTR1,
+               .ptr2_reg       = DMA4_PTR2,
+               .cnt1_reg       = DMA4_CNT1,
+               .cnt2_reg       = DMA4_CNT2,
+       },
+       [SRAM_CH05] = {
+               .name           = "ch5",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH06] = {
+               .name           = "TS2 C",
+               .cmds_start     = 0x10140,
+               .ctrl_start     = 0x10440,
+               .cdt            = 0x105e0,
+               .fifo_start     = 0x6000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH07] = {
+               .name           = "TV Audio",
+               .cmds_start     = 0x10190,
+               .ctrl_start     = 0x10480,
+               .cdt            = 0x10a00,
+               .fifo_start     = 0x7000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA6_PTR1,
+               .ptr2_reg       = DMA6_PTR2,
+               .cnt1_reg       = DMA6_CNT1,
+               .cnt2_reg       = DMA6_CNT2,
+       },
+       [SRAM_CH08] = {
+               .name           = "ch8",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA7_PTR1,
+               .ptr2_reg       = DMA7_PTR2,
+               .cnt1_reg       = DMA7_CNT1,
+               .cnt2_reg       = DMA7_CNT2,
+       },
+       [SRAM_CH09] = {
+               .name           = "ch9",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA8_PTR1,
+               .ptr2_reg       = DMA8_PTR2,
+               .cnt1_reg       = DMA8_CNT1,
+               .cnt2_reg       = DMA8_CNT2,
+       },
+};
+
+static struct sram_channel cx23887_sram_channels[] = {
+       [SRAM_CH01] = {
+               .name           = "VID A",
+               .cmds_start     = 0x10000,
+               .ctrl_start     = 0x105b0,
+               .cdt            = 0x107b0,
+               .fifo_start     = 0x40,
+               .fifo_size      = 0x2800,
+               .ptr1_reg       = DMA1_PTR1,
+               .ptr2_reg       = DMA1_PTR2,
+               .cnt1_reg       = DMA1_CNT1,
+               .cnt2_reg       = DMA1_CNT2,
+       },
+       [SRAM_CH02] = {
+               .name           = "VID A (VBI)",
+               .cmds_start     = 0x10050,
+               .ctrl_start     = 0x105F0,
+               .cdt            = 0x10810,
+               .fifo_start     = 0x3000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA2_PTR1,
+               .ptr2_reg       = DMA2_PTR2,
+               .cnt1_reg       = DMA2_CNT1,
+               .cnt2_reg       = DMA2_CNT2,
+       },
+       [SRAM_CH03] = {
+               .name           = "TS1 B",
+               .cmds_start     = 0x100A0,
+               .ctrl_start     = 0x10630,
+               .cdt            = 0x10870,
+               .fifo_start     = 0x5000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA3_PTR1,
+               .ptr2_reg       = DMA3_PTR2,
+               .cnt1_reg       = DMA3_CNT1,
+               .cnt2_reg       = DMA3_CNT2,
+       },
+       [SRAM_CH04] = {
+               .name           = "ch4",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA4_PTR1,
+               .ptr2_reg       = DMA4_PTR2,
+               .cnt1_reg       = DMA4_CNT1,
+               .cnt2_reg       = DMA4_CNT2,
+       },
+       [SRAM_CH05] = {
+               .name           = "ch5",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH06] = {
+               .name           = "TS2 C",
+               .cmds_start     = 0x10140,
+               .ctrl_start     = 0x10670,
+               .cdt            = 0x108d0,
+               .fifo_start     = 0x6000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA5_PTR1,
+               .ptr2_reg       = DMA5_PTR2,
+               .cnt1_reg       = DMA5_CNT1,
+               .cnt2_reg       = DMA5_CNT2,
+       },
+       [SRAM_CH07] = {
+               .name           = "TV Audio",
+               .cmds_start     = 0x10190,
+               .ctrl_start     = 0x106B0,
+               .cdt            = 0x10930,
+               .fifo_start     = 0x7000,
+               .fifo_size      = 0x1000,
+               .ptr1_reg       = DMA6_PTR1,
+               .ptr2_reg       = DMA6_PTR2,
+               .cnt1_reg       = DMA6_CNT1,
+               .cnt2_reg       = DMA6_CNT2,
+       },
+       [SRAM_CH08] = {
+               .name           = "ch8",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA7_PTR1,
+               .ptr2_reg       = DMA7_PTR2,
+               .cnt1_reg       = DMA7_CNT1,
+               .cnt2_reg       = DMA7_CNT2,
+       },
+       [SRAM_CH09] = {
+               .name           = "ch9",
+               .cmds_start     = 0x0,
+               .ctrl_start     = 0x0,
+               .cdt            = 0x0,
+               .fifo_start     = 0x0,
+               .fifo_size      = 0x0,
+               .ptr1_reg       = DMA8_PTR1,
+               .ptr2_reg       = DMA8_PTR2,
+               .cnt1_reg       = DMA8_CNT1,
+               .cnt2_reg       = DMA8_CNT2,
+       },
+};
+
+void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+       dev->pci_irqmask |= mask;
+
+       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+       dev->pci_irqmask |= mask;
+       cx_set(PCI_INT_MSK, mask);
+
+       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask)
+{
+       u32 v;
+       unsigned long flags;
+       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+       v = mask & dev->pci_irqmask;
+       if (v)
+               cx_set(PCI_INT_MSK, v);
+
+       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+static inline void cx23885_irq_enable_all(struct cx23885_dev *dev)
+{
+       cx23885_irq_enable(dev, 0xffffffff);
+}
+
+void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+       cx_clear(PCI_INT_MSK, mask);
+
+       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+static inline void cx23885_irq_disable_all(struct cx23885_dev *dev)
+{
+       cx23885_irq_disable(dev, 0xffffffff);
+}
+
+void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+       dev->pci_irqmask &= ~mask;
+       cx_clear(PCI_INT_MSK, mask);
+
+       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+static u32 cx23885_irq_get_mask(struct cx23885_dev *dev)
+{
+       u32 v;
+       unsigned long flags;
+       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+       v = cx_read(PCI_INT_MSK);
+
+       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+       return v;
+}
+
+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",
+       };
+       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,
+       };
+       static char *bits[] = {
+               "12",   "13",   "14",   "resync",
+               "cnt0", "cnt1", "18",   "19",
+               "20",   "21",   "22",   "23",
+               "irq1", "irq2", "eol",  "sol",
+       };
+       int i;
+
+       printk("0x%08x [ %s", risc,
+              instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+       for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)
+               if (risc & (1 << (i + 12)))
+                       printk(" %s", bits[i]);
+       printk(" count=%d ]\n", risc & 0xfff);
+       return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+void cx23885_wakeup(struct cx23885_tsport *port,
+                          struct cx23885_dmaqueue *q, u32 count)
+{
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_buffer *buf;
+       int bc;
+
+       for (bc = 0;; bc++) {
+               if (list_empty(&q->active))
+                       break;
+               buf = list_entry(q->active.next,
+                                struct cx23885_buffer, vb.queue);
+
+               /* count comes from the hw and is is 16bit wide --
+                * this trick handles wrap-arounds correctly for
+                * up to 32767 buffers in flight... */
+               if ((s16) (count - buf->count) < 0)
+                       break;
+
+               do_gettimeofday(&buf->vb.ts);
+               dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
+                       count, buf->count);
+               buf->vb.state = VIDEOBUF_DONE;
+               list_del(&buf->vb.queue);
+               wake_up(&buf->vb.done);
+       }
+       if (list_empty(&q->active))
+               del_timer(&q->timeout);
+       else
+               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+       if (bc != 1)
+               printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
+                      __func__, bc);
+}
+
+int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+                                     struct sram_channel *ch,
+                                     unsigned int bpl, u32 risc)
+{
+       unsigned int i, lines;
+       u32 cdt;
+
+       if (ch->cmds_start == 0) {
+               dprintk(1, "%s() Erasing channel [%s]\n", __func__,
+                       ch->name);
+               cx_write(ch->ptr1_reg, 0);
+               cx_write(ch->ptr2_reg, 0);
+               cx_write(ch->cnt2_reg, 0);
+               cx_write(ch->cnt1_reg, 0);
+               return 0;
+       } else {
+               dprintk(1, "%s() Configuring channel [%s]\n", __func__,
+                       ch->name);
+       }
+
+       bpl   = (bpl + 7) & ~7; /* alignment */
+       cdt   = ch->cdt;
+       lines = ch->fifo_size / bpl;
+       if (lines > 6)
+               lines = 6;
+       BUG_ON(lines < 2);
+
+       cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       cx_write(8 + 4, 8);
+       cx_write(8 + 8, 0);
+
+       /* write CDT */
+       for (i = 0; i < lines; 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);
+               cx_write(cdt + 16*i +  8, 0);
+               cx_write(cdt + 16*i + 12, 0);
+       }
+
+       /* write CMDS */
+       if (ch->jumponly)
+               cx_write(ch->cmds_start + 0, 8);
+       else
+               cx_write(ch->cmds_start + 0, risc);
+       cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */
+       cx_write(ch->cmds_start +  8, cdt);
+       cx_write(ch->cmds_start + 12, (lines*16) >> 3);
+       cx_write(ch->cmds_start + 16, ch->ctrl_start);
+       if (ch->jumponly)
+               cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+       else
+               cx_write(ch->cmds_start + 20, 64 >> 2);
+       for (i = 24; i < 80; i += 4)
+               cx_write(ch->cmds_start + i, 0);
+
+       /* fill registers */
+       cx_write(ch->ptr1_reg, ch->fifo_start);
+       cx_write(ch->ptr2_reg, cdt);
+       cx_write(ch->cnt2_reg, (lines*16) >> 3);
+       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+       dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
+               dev->bridge,
+               ch->name,
+               bpl,
+               lines);
+
+       return 0;
+}
+
+void cx23885_sram_channel_dump(struct cx23885_dev *dev,
+                                     struct sram_channel *ch)
+{
+       static char *name[] = {
+               "init risc lo",
+               "init risc hi",
+               "cdt base",
+               "cdt size",
+               "iq base",
+               "iq size",
+               "risc pc lo",
+               "risc pc hi",
+               "iq wr ptr",
+               "iq rd ptr",
+               "cdt current",
+               "pci target lo",
+               "pci target hi",
+               "line / byte",
+       };
+       u32 risc;
+       unsigned int i, j, n;
+
+       printk(KERN_WARNING "%s: %s - dma channel status dump\n",
+              dev->name, ch->name);
+       for (i = 0; i < ARRAY_SIZE(name); i++)
+               printk(KERN_WARNING "%s:   cmds: %-15s: 0x%08x\n",
+                      dev->name, name[i],
+                      cx_read(ch->cmds_start + 4*i));
+
+       for (i = 0; i < 4; i++) {
+               risc = cx_read(ch->cmds_start + 4 * (i + 14));
+               printk(KERN_WARNING "%s:   risc%d: ", dev->name, i);
+               cx23885_risc_decode(risc);
+       }
+       for (i = 0; i < (64 >> 2); i += n) {
+               risc = cx_read(ch->ctrl_start + 4 * i);
+               /* No consideration for bits 63-32 */
+
+               printk(KERN_WARNING "%s:   (0x%08x) iq %x: ", dev->name,
+                      ch->ctrl_start + 4 * i, i);
+               n = cx23885_risc_decode(risc);
+               for (j = 1; j < n; j++) {
+                       risc = cx_read(ch->ctrl_start + 4 * (i + j));
+                       printk(KERN_WARNING "%s:   iq %x: 0x%08x [ arg #%d ]\n",
+                              dev->name, i+j, risc, j);
+               }
+       }
+
+       printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
+              dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
+       printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
+              dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
+       printk(KERN_WARNING "%s:   ptr1_reg: 0x%08x\n",
+              dev->name, cx_read(ch->ptr1_reg));
+       printk(KERN_WARNING "%s:   ptr2_reg: 0x%08x\n",
+              dev->name, cx_read(ch->ptr2_reg));
+       printk(KERN_WARNING "%s:   cnt1_reg: 0x%08x\n",
+              dev->name, cx_read(ch->cnt1_reg));
+       printk(KERN_WARNING "%s:   cnt2_reg: 0x%08x\n",
+              dev->name, cx_read(ch->cnt2_reg));
+}
+
+static void cx23885_risc_disasm(struct cx23885_tsport *port,
+                               struct btcx_riscmem *risc)
+{
+       struct cx23885_dev *dev = port->dev;
+       unsigned int i, j, n;
+
+       printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
+              dev->name, risc->cpu, (unsigned long)risc->dma);
+       for (i = 0; i < (risc->size >> 2); i += n) {
+               printk(KERN_INFO "%s:   %04d: ", dev->name, i);
+               n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
+               for (j = 1; j < n; j++)
+                       printk(KERN_INFO "%s:   %04d: 0x%08x [ arg #%d ]\n",
+                              dev->name, i + j, risc->cpu[i + j], j);
+               if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
+                       break;
+       }
+}
+
+static void cx23885_shutdown(struct cx23885_dev *dev)
+{
+       /* disable RISC controller */
+       cx_write(DEV_CNTRL2, 0);
+
+       /* Disable all IR activity */
+       cx_write(IR_CNTRL_REG, 0);
+
+       /* Disable Video A/B activity */
+       cx_write(VID_A_DMA_CTL, 0);
+       cx_write(VID_B_DMA_CTL, 0);
+       cx_write(VID_C_DMA_CTL, 0);
+
+       /* Disable Audio activity */
+       cx_write(AUD_INT_DMA_CTL, 0);
+       cx_write(AUD_EXT_DMA_CTL, 0);
+
+       /* Disable Serial port */
+       cx_write(UART_CTL, 0);
+
+       /* Disable Interrupts */
+       cx23885_irq_disable_all(dev);
+       cx_write(VID_A_INT_MSK, 0);
+       cx_write(VID_B_INT_MSK, 0);
+       cx_write(VID_C_INT_MSK, 0);
+       cx_write(AUDIO_INT_INT_MSK, 0);
+       cx_write(AUDIO_EXT_INT_MSK, 0);
+
+}
+
+static void cx23885_reset(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       cx23885_shutdown(dev);
+
+       cx_write(PCI_INT_STAT, 0xffffffff);
+       cx_write(VID_A_INT_STAT, 0xffffffff);
+       cx_write(VID_B_INT_STAT, 0xffffffff);
+       cx_write(VID_C_INT_STAT, 0xffffffff);
+       cx_write(AUDIO_INT_INT_STAT, 0xffffffff);
+       cx_write(AUDIO_EXT_INT_STAT, 0xffffffff);
+       cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+       cx_write(PAD_CTRL, 0x00500300);
+
+       mdelay(100);
+
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
+               720*4, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03],
+               188*4, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06],
+               188*4, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0);
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0);
+
+       cx23885_gpio_setup(dev);
+}
+
+
+static int cx23885_pci_quirks(struct cx23885_dev *dev)
+{
+       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
+        * occur on the cx23887 bridge.
+        */
+       if (dev->bridge == CX23885_BRIDGE_885)
+               cx_clear(RDR_TLCTL0, 1 << 4);
+
+       return 0;
+}
+
+static int get_resources(struct cx23885_dev *dev)
+{
+       if (request_mem_region(pci_resource_start(dev->pci, 0),
+                              pci_resource_len(dev->pci, 0),
+                              dev->name))
+               return 0;
+
+       printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+               dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+       return -EBUSY;
+}
+
+static void cx23885_timeout(unsigned long data);
+int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+                               u32 reg, u32 mask, u32 value);
+
+static int cx23885_init_tsport(struct cx23885_dev *dev,
+       struct cx23885_tsport *port, int 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;
+       port->nr = portno;
+
+       INIT_LIST_HEAD(&port->mpegq.active);
+       INIT_LIST_HEAD(&port->mpegq.queued);
+       port->mpegq.timeout.function = cx23885_timeout;
+       port->mpegq.timeout.data = (unsigned long)port;
+       init_timer(&port->mpegq.timeout);
+
+       mutex_init(&port->frontends.lock);
+       INIT_LIST_HEAD(&port->frontends.felist);
+       port->frontends.active_fe_id = 0;
+
+       /* This should be hardcoded allow a single frontend
+        * attachment to this tsport, keeping the -dvb.c
+        * code clean and safe.
+        */
+       if (!port->num_frontends)
+               port->num_frontends = 1;
+
+       switch (portno) {
+       case 1:
+               port->reg_gpcnt          = VID_B_GPCNT;
+               port->reg_gpcnt_ctl      = VID_B_GPCNT_CTL;
+               port->reg_dma_ctl        = VID_B_DMA_CTL;
+               port->reg_lngth          = VID_B_LNGTH;
+               port->reg_hw_sop_ctrl    = VID_B_HW_SOP_CTL;
+               port->reg_gen_ctrl       = VID_B_GEN_CTL;
+               port->reg_bd_pkt_status  = VID_B_BD_PKT_STATUS;
+               port->reg_sop_status     = VID_B_SOP_STATUS;
+               port->reg_fifo_ovfl_stat = VID_B_FIFO_OVFL_STAT;
+               port->reg_vld_misc       = VID_B_VLD_MISC;
+               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->sram_chno          = SRAM_CH03; /* VID_B */
+               port->pci_irqmask        = 0x02; /* VID_B bit1 */
+               break;
+       case 2:
+               port->reg_gpcnt          = VID_C_GPCNT;
+               port->reg_gpcnt_ctl      = VID_C_GPCNT_CTL;
+               port->reg_dma_ctl        = VID_C_DMA_CTL;
+               port->reg_lngth          = VID_C_LNGTH;
+               port->reg_hw_sop_ctrl    = VID_C_HW_SOP_CTL;
+               port->reg_gen_ctrl       = VID_C_GEN_CTL;
+               port->reg_bd_pkt_status  = VID_C_BD_PKT_STATUS;
+               port->reg_sop_status     = VID_C_SOP_STATUS;
+               port->reg_fifo_ovfl_stat = VID_C_FIFO_OVFL_STAT;
+               port->reg_vld_misc       = VID_C_VLD_MISC;
+               port->reg_ts_clk_en      = VID_C_TS_CLK_EN;
+               port->reg_src_sel        = 0;
+               port->reg_ts_int_msk     = VID_C_INT_MSK;
+               port->reg_ts_int_stat    = VID_C_INT_STAT;
+               port->sram_chno          = SRAM_CH06; /* VID_C */
+               port->pci_irqmask        = 0x04; /* VID_C bit2 */
+               break;
+       default:
+               BUG();
+       }
+
+       cx23885_risc_stopper(dev->pci, &port->mpegq.stopper,
+                    port->reg_dma_ctl, port->dma_ctl_val, 0x00);
+
+       return 0;
+}
+
+static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
+{
+       switch (cx_read(RDR_CFG2) & 0xff) {
+       case 0x00:
+               /* cx23885 */
+               dev->hwrevision = 0xa0;
+               break;
+       case 0x01:
+               /* CX23885-12Z */
+               dev->hwrevision = 0xa1;
+               break;
+       case 0x02:
+               /* CX23885-13Z/14Z */
+               dev->hwrevision = 0xb0;
+               break;
+       case 0x03:
+               if (dev->pci->device == 0x8880) {
+                       /* CX23888-21Z/22Z */
+                       dev->hwrevision = 0xc0;
+               } else {
+                       /* CX23885-14Z */
+                       dev->hwrevision = 0xa4;
+               }
+               break;
+       case 0x04:
+               if (dev->pci->device == 0x8880) {
+                       /* CX23888-31Z */
+                       dev->hwrevision = 0xd0;
+               } else {
+                       /* CX23885-15Z, CX23888-31Z */
+                       dev->hwrevision = 0xa5;
+               }
+               break;
+       case 0x0e:
+               /* CX23887-15Z */
+               dev->hwrevision = 0xc0;
+               break;
+       case 0x0f:
+               /* CX23887-14Z */
+               dev->hwrevision = 0xb1;
+               break;
+       default:
+               printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
+                       __func__, dev->hwrevision);
+       }
+       if (dev->hwrevision)
+               printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
+                       __func__, dev->hwrevision);
+       else
+               printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
+                       __func__, dev->hwrevision);
+}
+
+/* Find the first v4l2_subdev member of the group id in hw */
+struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw)
+{
+       struct v4l2_subdev *result = NULL;
+       struct v4l2_subdev *sd;
+
+       spin_lock(&dev->v4l2_dev.lock);
+       v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) {
+               if (sd->grp_id == hw) {
+                       result = sd;
+                       break;
+               }
+       }
+       spin_unlock(&dev->v4l2_dev.lock);
+       return result;
+}
+
+static int cx23885_dev_setup(struct cx23885_dev *dev)
+{
+       int i;
+
+       spin_lock_init(&dev->pci_irqmask_lock);
+
+       mutex_init(&dev->lock);
+       mutex_init(&dev->gpio_lock);
+
+       atomic_inc(&dev->refcount);
+
+       dev->nr = cx23885_devcount++;
+       sprintf(dev->name, "cx23885[%d]", dev->nr);
+
+       /* Configure the internal memory */
+       if (dev->pci->device == 0x8880) {
+               /* Could be 887 or 888, assume a default */
+               dev->bridge = CX23885_BRIDGE_887;
+               /* Apply a sensible clock frequency for the PCIe bridge */
+               dev->clk_freq = 25000000;
+               dev->sram_channels = cx23887_sram_channels;
+       } else
+       if (dev->pci->device == 0x8852) {
+               dev->bridge = CX23885_BRIDGE_885;
+               /* Apply a sensible clock frequency for the PCIe bridge */
+               dev->clk_freq = 28000000;
+               dev->sram_channels = cx23885_sram_channels;
+       } else
+               BUG();
+
+       dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
+               __func__, dev->bridge);
+
+       /* board config */
+       dev->board = UNSET;
+       if (card[dev->nr] < cx23885_bcount)
+               dev->board = card[dev->nr];
+       for (i = 0; UNSET == dev->board  &&  i < cx23885_idcount; i++)
+               if (dev->pci->subsystem_vendor == cx23885_subids[i].subvendor &&
+                   dev->pci->subsystem_device == cx23885_subids[i].subdevice)
+                       dev->board = cx23885_subids[i].card;
+       if (UNSET == dev->board) {
+               dev->board = CX23885_BOARD_UNKNOWN;
+               cx23885_card_list(dev);
+       }
+
+       /* If the user specific a clk freq override, apply it */
+       if (cx23885_boards[dev->board].clk_freq > 0)
+               dev->clk_freq = cx23885_boards[dev->board].clk_freq;
+
+       dev->pci_bus  = dev->pci->bus->number;
+       dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+       cx23885_irq_add(dev, 0x001f00);
+
+       /* External Master 1 Bus */
+       dev->i2c_bus[0].nr = 0;
+       dev->i2c_bus[0].dev = dev;
+       dev->i2c_bus[0].reg_stat  = I2C1_STAT;
+       dev->i2c_bus[0].reg_ctrl  = I2C1_CTRL;
+       dev->i2c_bus[0].reg_addr  = I2C1_ADDR;
+       dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+       dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+       dev->i2c_bus[0].i2c_period = (0x9d << 24); /* 100kHz */
+
+       /* External Master 2 Bus */
+       dev->i2c_bus[1].nr = 1;
+       dev->i2c_bus[1].dev = dev;
+       dev->i2c_bus[1].reg_stat  = I2C2_STAT;
+       dev->i2c_bus[1].reg_ctrl  = I2C2_CTRL;
+       dev->i2c_bus[1].reg_addr  = I2C2_ADDR;
+       dev->i2c_bus[1].reg_rdata = I2C2_RDATA;
+       dev->i2c_bus[1].reg_wdata = I2C2_WDATA;
+       dev->i2c_bus[1].i2c_period = (0x9d << 24); /* 100kHz */
+
+       /* Internal Master 3 Bus */
+       dev->i2c_bus[2].nr = 2;
+       dev->i2c_bus[2].dev = dev;
+       dev->i2c_bus[2].reg_stat  = I2C3_STAT;
+       dev->i2c_bus[2].reg_ctrl  = I2C3_CTRL;
+       dev->i2c_bus[2].reg_addr  = I2C3_ADDR;
+       dev->i2c_bus[2].reg_rdata = I2C3_RDATA;
+       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) ||
+               (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
+               cx23885_init_tsport(dev, &dev->ts1, 1);
+
+       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) {
+               printk(KERN_ERR "CORE %s No more PCIe resources for "
+                      "subsystem: %04x:%04x\n",
+                      dev->name, dev->pci->subsystem_vendor,
+                      dev->pci->subsystem_device);
+
+               cx23885_devcount--;
+               return -ENODEV;
+       }
+
+       /* PCIe stuff */
+       dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
+                            pci_resource_len(dev->pci, 0));
+
+       dev->bmmio = (u8 __iomem *)dev->lmmio;
+
+       printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+              dev->name, dev->pci->subsystem_vendor,
+              dev->pci->subsystem_device, cx23885_boards[dev->board].name,
+              dev->board, card[dev->nr] == dev->board ?
+              "insmod option" : "autodetected");
+
+       cx23885_pci_quirks(dev);
+
+       /* Assume some sensible defaults */
+       dev->tuner_type = cx23885_boards[dev->board].tuner_type;
+       dev->tuner_addr = cx23885_boards[dev->board].tuner_addr;
+       dev->tuner_bus = cx23885_boards[dev->board].tuner_bus;
+       dev->radio_type = cx23885_boards[dev->board].radio_type;
+       dev->radio_addr = cx23885_boards[dev->board].radio_addr;
+
+       dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x tuner_bus = %d\n",
+               __func__, dev->tuner_type, dev->tuner_addr, dev->tuner_bus);
+       dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
+               __func__, dev->radio_type, dev->radio_addr);
+
+       /* The cx23417 encoder has GPIO's that need to be initialised
+        * before DVB, so that demodulators and tuners are out of
+        * reset before DVB uses them.
+        */
+       if ((cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) ||
+               (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
+                       cx23885_mc417_init(dev);
+
+       /* init hardware */
+       cx23885_reset(dev);
+
+       cx23885_i2c_register(&dev->i2c_bus[0]);
+       cx23885_i2c_register(&dev->i2c_bus[1]);
+       cx23885_i2c_register(&dev->i2c_bus[2]);
+       cx23885_card_setup(dev);
+       call_all(dev, core, s_power, 0);
+       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", __func__);
+               }
+       }
+
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+               if (cx23885_boards[dev->board].num_fds_portb)
+                       dev->ts1.num_frontends =
+                               cx23885_boards[dev->board].num_fds_portb;
+               if (cx23885_dvb_register(&dev->ts1) < 0) {
+                       printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
+                              __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_boards[dev->board].num_fds_portc)
+                       dev->ts2.num_frontends =
+                               cx23885_boards[dev->board].num_fds_portc;
+               if (cx23885_dvb_register(&dev->ts2) < 0) {
+                       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__);
+               }
+       }
+
+       cx23885_dev_checkrevision(dev);
+
+       /* disable MSI for NetUP cards, otherwise CI is not working */
+       if (cx23885_boards[dev->board].ci_type > 0)
+               cx_clear(RDR_RDRCTL1, 1 << 8);
+
+       switch (dev->board) {
+       case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_TEVII_S471:
+               cx_clear(RDR_RDRCTL1, 1 << 8);
+               break;
+       }
+
+       return 0;
+}
+
+static void cx23885_dev_unregister(struct cx23885_dev *dev)
+{
+       release_mem_region(pci_resource_start(dev->pci, 0),
+                          pci_resource_len(dev->pci, 0));
+
+       if (!atomic_dec_and_test(&dev->refcount))
+               return;
+
+       if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
+               cx23885_video_unregister(dev);
+
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+               cx23885_dvb_unregister(&dev->ts1);
+
+       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]);
+
+       iounmap(dev->lmmio);
+}
+
+static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
+                              unsigned int offset, u32 sync_line,
+                              unsigned int bpl, unsigned int padding,
+                              unsigned int lines,  unsigned int lpi)
+{
+       struct scatterlist *sg;
+       unsigned int line, todo, sol;
+
+       /* sync instruction */
+       if (sync_line != NO_SYNC_LINE)
+               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       /* scan lines */
+       sg = sglist;
+       for (line = 0; line < lines; line++) {
+               while (offset && offset >= sg_dma_len(sg)) {
+                       offset -= sg_dma_len(sg);
+                       sg++;
+               }
+
+               if (lpi && line > 0 && !(line % lpi))
+                       sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+               else
+                       sol = RISC_SOL;
+
+               if (bpl <= sg_dma_len(sg)-offset) {
+                       /* fits into current chunk */
+                       *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+                       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+                       offset += bpl;
+               } else {
+                       /* scanline needs to be split */
+                       todo = bpl;
+                       *(rp++) = cpu_to_le32(RISC_WRITE|sol|
+                                           (sg_dma_len(sg)-offset));
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+                       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+                       todo -= (sg_dma_len(sg)-offset);
+                       offset = 0;
+                       sg++;
+                       while (todo > sg_dma_len(sg)) {
+                               *(rp++) = cpu_to_le32(RISC_WRITE|
+                                                   sg_dma_len(sg));
+                               *(rp++) = cpu_to_le32(sg_dma_address(sg));
+                               *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+                               todo -= sg_dma_len(sg);
+                               sg++;
+                       }
+                       *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg));
+                       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+                       offset += todo;
+               }
+               offset += padding;
+       }
+
+       return rp;
+}
+
+int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                       struct scatterlist *sglist, unsigned int top_offset,
+                       unsigned int bottom_offset, unsigned int bpl,
+                       unsigned int padding, unsigned int lines)
+{
+       u32 instructions, fields;
+       __le32 *rp;
+       int rc;
+
+       fields = 0;
+       if (UNSET != top_offset)
+               fields++;
+       if (UNSET != bottom_offset)
+               fields++;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Padding
+          can cause next bpl to start close to a page border.  First DMA
+          region may be smaller than PAGE_SIZE */
+       /* write and jump need and extra dword */
+       instructions  = fields * (1 + ((bpl + padding) * lines)
+               / PAGE_SIZE + lines);
+       instructions += 2;
+       rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+       if (rc < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       if (UNSET != top_offset)
+               rp = cx23885_risc_field(rp, sglist, top_offset, 0,
+                                       bpl, padding, lines, 0);
+       if (UNSET != bottom_offset)
+               rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
+                                       bpl, padding, lines, 0);
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       return 0;
+}
+
+int cx23885_risc_databuffer(struct pci_dev *pci,
+                                  struct btcx_riscmem *risc,
+                                  struct scatterlist *sglist,
+                                  unsigned int bpl,
+                                  unsigned int lines, unsigned int lpi)
+{
+       u32 instructions;
+       __le32 *rp;
+       int rc;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Here
+          there is no padding and no sync.  First DMA region may be smaller
+          than PAGE_SIZE */
+       /* Jump and write need an extra dword */
+       instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
+       instructions += 1;
+
+       rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+       if (rc < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
+                               bpl, 0, lines, lpi);
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       return 0;
+}
+
+int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                       struct scatterlist *sglist, unsigned int top_offset,
+                       unsigned int bottom_offset, unsigned int bpl,
+                       unsigned int padding, unsigned int lines)
+{
+       u32 instructions, fields;
+       __le32 *rp;
+       int rc;
+
+       fields = 0;
+       if (UNSET != top_offset)
+               fields++;
+       if (UNSET != bottom_offset)
+               fields++;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Padding
+          can cause next bpl to start close to a page border.  First DMA
+          region may be smaller than PAGE_SIZE */
+       /* write and jump need and extra dword */
+       instructions  = fields * (1 + ((bpl + padding) * lines)
+               / PAGE_SIZE + lines);
+       instructions += 2;
+       rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+       if (rc < 0)
+               return rc;
+       /* write risc instructions */
+       rp = risc->cpu;
+
+       /* Sync to line 6, so US CC line 21 will appear in line '12'
+        * in the userland vbi payload */
+       if (UNSET != top_offset)
+               rp = cx23885_risc_field(rp, sglist, top_offset, 6,
+                                       bpl, padding, lines, 0);
+
+       if (UNSET != bottom_offset)
+               rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
+                                       bpl, padding, lines, 0);
+
+
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       return 0;
+}
+
+
+int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+                               u32 reg, u32 mask, u32 value)
+{
+       __le32 *rp;
+       int rc;
+
+       rc = btcx_riscmem_alloc(pci, risc, 4*16);
+       if (rc < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2);
+       *(rp++) = cpu_to_le32(reg);
+       *(rp++) = cpu_to_le32(value);
+       *(rp++) = cpu_to_le32(mask);
+       *(rp++) = cpu_to_le32(RISC_JUMP);
+       *(rp++) = cpu_to_le32(risc->dma);
+       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
+       return 0;
+}
+
+void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
+{
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+       BUG_ON(in_interrupt());
+       videobuf_waiton(q, &buf->vb, 0, 0);
+       videobuf_dma_unmap(q->dev, dma);
+       videobuf_dma_free(dma);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
+{
+       struct cx23885_dev *dev = port->dev;
+
+       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", __func__,
+               cx23885_irq_get_mask(dev));
+       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", __func__,
+               cx_read(AUD_INT_DMA_CTL));
+       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", __func__,
+               cx_read(AUD_EXT_DMA_CTL));
+       dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,
+               cx_read(PAD_CTRL));
+       dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,
+               cx_read(ALT_PIN_OUT_SEL));
+       dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,
+               cx_read(GPIO2));
+       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", __func__,
+               port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
+       dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
+               port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
+       if (port->reg_src_sel)
+               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", __func__,
+               port->reg_lngth, cx_read(port->reg_lngth));
+       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", __func__,
+               port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
+       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", __func__,
+               port->reg_sop_status, cx_read(port->reg_sop_status));
+       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", __func__,
+               port->reg_vld_misc, cx_read(port->reg_vld_misc));
+       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", __func__,
+               port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
+}
+
+static int cx23885_start_dma(struct cx23885_tsport *port,
+                            struct cx23885_dmaqueue *q,
+                            struct cx23885_buffer   *buf)
+{
+       struct cx23885_dev *dev = port->dev;
+       u32 reg;
+
+       dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
+               buf->vb.width, buf->vb.height, buf->vb.field);
+
+       /* Stop the fifo and risc engine for this port */
+       cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+
+       /* setup fifo + format */
+       cx23885_sram_channel_setup(dev,
+                                  &dev->sram_channels[port->sram_chno],
+                                  port->ts_packet_size, buf->risc.dma);
+       if (debug > 5) {
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[port->sram_chno]);
+               cx23885_risc_disasm(port, &buf->risc);
+       }
+
+       /* write TS length to chip */
+       cx_write(port->reg_lngth, buf->vb.width);
+
+       if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+               (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
+               printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
+                       __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, port->hw_sop_ctrl_val);
+       cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
+       cx_write(port->reg_vld_misc, port->vld_misc_val);
+       cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
+       udelay(100);
+
+       /* NOTE: this is 2 (reserved) for portb, does it matter? */
+       /* reset counter to zero */
+       cx_write(port->reg_gpcnt_ctl, 3);
+       q->count = 1;
+
+       /* Set VIDB pins to input */
+       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+               reg = cx_read(PAD_CTRL);
+               reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */
+               cx_write(PAD_CTRL, reg);
+       }
+
+       /* Set VIDC pins to input */
+       if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+               reg = cx_read(PAD_CTRL);
+               reg &= ~0x4; /* Clear TS2_SOP_OE */
+               cx_write(PAD_CTRL, reg);
+       }
+
+       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:
+       case CX23885_BRIDGE_888:
+               /* enable irqs */
+               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);
+               cx23885_irq_add(dev, port->pci_irqmask);
+               cx23885_irq_enable_all(dev);
+               break;
+       default:
+               BUG();
+       }
+
+       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);
+
+       return 0;
+}
+
+static int cx23885_stop_dma(struct cx23885_tsport *port)
+{
+       struct cx23885_dev *dev = port->dev;
+       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;
+}
+
+int cx23885_restart_queue(struct cx23885_tsport *port,
+                               struct cx23885_dmaqueue *q)
+{
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_buffer *buf;
+
+       dprintk(5, "%s()\n", __func__);
+       if (list_empty(&q->active)) {
+               struct cx23885_buffer *prev;
+               prev = NULL;
+
+               dprintk(5, "%s() queue is empty\n", __func__);
+
+               for (;;) {
+                       if (list_empty(&q->queued))
+                               return 0;
+                       buf = list_entry(q->queued.next, struct cx23885_buffer,
+                                        vb.queue);
+                       if (NULL == prev) {
+                               list_del(&buf->vb.queue);
+                               list_add_tail(&buf->vb.queue, &q->active);
+                               cx23885_start_dma(port, q, buf);
+                               buf->vb.state = VIDEOBUF_ACTIVE;
+                               buf->count    = q->count++;
+                               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+                               dprintk(5, "[%p/%d] restart_queue - f/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, &q->active);
+                               buf->vb.state = VIDEOBUF_ACTIVE;
+                               buf->count    = q->count++;
+                               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                               /* 64 bit bits 63-32 */
+                               prev->risc.jmp[2] = cpu_to_le32(0);
+                               dprintk(5, "[%p/%d] restart_queue - m/active\n",
+                                       buf, buf->vb.i);
+                       } else {
+                               return 0;
+                       }
+                       prev = buf;
+               }
+               return 0;
+       }
+
+       buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
+       dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+               buf, buf->vb.i);
+       cx23885_start_dma(port, q, buf);
+       list_for_each_entry(buf, &q->active, vb.queue)
+               buf->count = q->count++;
+       mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
+                       struct cx23885_buffer *buf, enum v4l2_field field)
+{
+       struct cx23885_dev *dev = port->dev;
+       int size = port->ts_packet_size * port->ts_packet_count;
+       int rc;
+
+       dprintk(1, "%s: %p\n", __func__, buf);
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               buf->vb.width  = port->ts_packet_size;
+               buf->vb.height = port->ts_packet_count;
+               buf->vb.size   = size;
+               buf->vb.field  = field /*V4L2_FIELD_TOP*/;
+
+               rc = videobuf_iolock(q, &buf->vb, NULL);
+               if (0 != rc)
+                       goto fail;
+               cx23885_risc_databuffer(dev->pci, &buf->risc,
+                                       videobuf_to_dma(&buf->vb)->sglist,
+                                       buf->vb.width, buf->vb.height, 0);
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       cx23885_free_buffer(q, buf);
+       return rc;
+}
+
+void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
+{
+       struct cx23885_buffer    *prev;
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_dmaqueue  *cx88q = &port->mpegq;
+
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+       if (list_empty(&cx88q->active)) {
+               dprintk(1, "queue is empty - first active\n");
+               list_add_tail(&buf->vb.queue, &cx88q->active);
+               cx23885_start_dma(port, cx88q, buf);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = cx88q->count++;
+               mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
+               dprintk(1, "[%p/%d] %s - first active\n",
+                       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,
+                                 vb.queue);
+               list_add_tail(&buf->vb.queue, &cx88q->active);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = cx88q->count++;
+               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, __func__);
+       }
+}
+
+/* ----------------------------------------------------------- */
+
+static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
+                             int restart)
+{
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_dmaqueue *q = &port->mpegq;
+       struct cx23885_buffer *buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->slock, flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx23885_buffer,
+                                vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
+                       buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
+       }
+       if (restart) {
+               dprintk(1, "restarting queue\n");
+               cx23885_restart_queue(port, q);
+       }
+       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", __func__);
+       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", __func__);
+
+       if (debug > 5)
+               cx23885_sram_channel_dump(dev,
+                       &dev->sram_channels[port->sram_chno]);
+
+       cx23885_stop_dma(port);
+       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)
+                       dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+                               VID_BC_MSK_OPC_ERR);
+
+               if (status & VID_BC_MSK_BAD_PKT)
+                       dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
+                               VID_BC_MSK_BAD_PKT);
+
+               if (status & VID_BC_MSK_SYNC)
+                       dprintk(7, " (VID_BC_MSK_SYNC    0x%08x)\n",
+                               VID_BC_MSK_SYNC);
+
+               if (status & VID_BC_MSK_OF)
+                       dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n",
+                               VID_BC_MSK_OF);
+
+               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]);
+
+       } else if (status & VID_BC_MSK_RISCI1) {
+
+               dprintk(7, " (RISCI1            0x%08x)\n", VID_BC_MSK_RISCI1);
+
+               spin_lock(&port->slock);
+               count = cx_read(port->reg_gpcnt);
+               cx23885_wakeup(port, &port->mpegq, count);
+               spin_unlock(&port->slock);
+
+       } else if (status & VID_BC_MSK_RISCI2) {
+
+               dprintk(7, " (RISCI2            0x%08x)\n", VID_BC_MSK_RISCI2);
+
+               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 irqreturn_t cx23885_irq(int irq, void *dev_id)
+{
+       struct cx23885_dev *dev = dev_id;
+       struct cx23885_tsport *ts1 = &dev->ts1;
+       struct cx23885_tsport *ts2 = &dev->ts2;
+       u32 pci_status, pci_mask;
+       u32 vida_status, vida_mask;
+       u32 audint_status, audint_mask;
+       u32 ts1_status, ts1_mask;
+       u32 ts2_status, ts2_mask;
+       int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+       int audint_count = 0;
+       bool subdev_handled;
+
+       pci_status = cx_read(PCI_INT_STAT);
+       pci_mask = cx23885_irq_get_mask(dev);
+       vida_status = cx_read(VID_A_INT_STAT);
+       vida_mask = cx_read(VID_A_INT_MSK);
+       audint_status = cx_read(AUDIO_INT_INT_STAT);
+       audint_mask = cx_read(AUDIO_INT_INT_MSK);
+       ts1_status = cx_read(VID_B_INT_STAT);
+       ts1_mask = cx_read(VID_B_INT_MSK);
+       ts2_status = cx_read(VID_C_INT_STAT);
+       ts2_mask = cx_read(VID_C_INT_MSK);
+
+       if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
+               goto out;
+
+       vida_count = cx_read(VID_A_GPCNT);
+       audint_count = cx_read(AUD_INT_A_GPCNT);
+       ts1_count = cx_read(ts1->reg_gpcnt);
+       ts2_count = cx_read(ts2->reg_gpcnt);
+       dprintk(7, "pci_status: 0x%08x  pci_mask: 0x%08x\n",
+               pci_status, pci_mask);
+       dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
+               vida_status, vida_mask, vida_count);
+       dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
+               audint_status, audint_mask, audint_count);
+       dprintk(7, "ts1_status: 0x%08x  ts1_mask: 0x%08x count: 0x%x\n",
+               ts1_status, ts1_mask, ts1_count);
+       dprintk(7, "ts2_status: 0x%08x  ts2_mask: 0x%08x count: 0x%x\n",
+               ts2_status, ts2_mask, ts2_count);
+
+       if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
+                         PCI_MSK_AL_RD   | PCI_MSK_AL_WR   | PCI_MSK_APB_DMA |
+                         PCI_MSK_VID_C   | PCI_MSK_VID_B   | PCI_MSK_VID_A   |
+                         PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
+                         PCI_MSK_GPIO0   | PCI_MSK_GPIO1   |
+                         PCI_MSK_AV_CORE | PCI_MSK_IR)) {
+
+               if (pci_status & PCI_MSK_RISC_RD)
+                       dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n",
+                               PCI_MSK_RISC_RD);
+
+               if (pci_status & PCI_MSK_RISC_WR)
+                       dprintk(7, " (PCI_MSK_RISC_WR   0x%08x)\n",
+                               PCI_MSK_RISC_WR);
+
+               if (pci_status & PCI_MSK_AL_RD)
+                       dprintk(7, " (PCI_MSK_AL_RD     0x%08x)\n",
+                               PCI_MSK_AL_RD);
+
+               if (pci_status & PCI_MSK_AL_WR)
+                       dprintk(7, " (PCI_MSK_AL_WR     0x%08x)\n",
+                               PCI_MSK_AL_WR);
+
+               if (pci_status & PCI_MSK_APB_DMA)
+                       dprintk(7, " (PCI_MSK_APB_DMA   0x%08x)\n",
+                               PCI_MSK_APB_DMA);
+
+               if (pci_status & PCI_MSK_VID_C)
+                       dprintk(7, " (PCI_MSK_VID_C     0x%08x)\n",
+                               PCI_MSK_VID_C);
+
+               if (pci_status & PCI_MSK_VID_B)
+                       dprintk(7, " (PCI_MSK_VID_B     0x%08x)\n",
+                               PCI_MSK_VID_B);
+
+               if (pci_status & PCI_MSK_VID_A)
+                       dprintk(7, " (PCI_MSK_VID_A     0x%08x)\n",
+                               PCI_MSK_VID_A);
+
+               if (pci_status & PCI_MSK_AUD_INT)
+                       dprintk(7, " (PCI_MSK_AUD_INT   0x%08x)\n",
+                               PCI_MSK_AUD_INT);
+
+               if (pci_status & PCI_MSK_AUD_EXT)
+                       dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n",
+                               PCI_MSK_AUD_EXT);
+
+               if (pci_status & PCI_MSK_GPIO0)
+                       dprintk(7, " (PCI_MSK_GPIO0     0x%08x)\n",
+                               PCI_MSK_GPIO0);
+
+               if (pci_status & PCI_MSK_GPIO1)
+                       dprintk(7, " (PCI_MSK_GPIO1     0x%08x)\n",
+                               PCI_MSK_GPIO1);
+
+               if (pci_status & PCI_MSK_AV_CORE)
+                       dprintk(7, " (PCI_MSK_AV_CORE   0x%08x)\n",
+                               PCI_MSK_AV_CORE);
+
+               if (pci_status & PCI_MSK_IR)
+                       dprintk(7, " (PCI_MSK_IR        0x%08x)\n",
+                               PCI_MSK_IR);
+       }
+
+       if (cx23885_boards[dev->board].ci_type == 1 &&
+                       (pci_status & (PCI_MSK_GPIO1 | PCI_MSK_GPIO0)))
+               handled += netup_ci_slot_status(dev, pci_status);
+
+       if (cx23885_boards[dev->board].ci_type == 2 &&
+                       (pci_status & PCI_MSK_GPIO0))
+               handled += altera_ci_irq(dev);
+
+       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)
+               handled += cx23885_video_irq(dev, vida_status);
+
+       if (audint_status)
+               handled += cx23885_audio_irq(dev, audint_status, audint_mask);
+
+       if (pci_status & PCI_MSK_IR) {
+               subdev_handled = false;
+               v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
+                                pci_status, &subdev_handled);
+               if (subdev_handled)
+                       handled++;
+       }
+
+       if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) {
+               cx23885_irq_disable(dev, PCI_MSK_AV_CORE);
+               if (!schedule_work(&dev->cx25840_work))
+                       printk(KERN_ERR "%s: failed to set up deferred work for"
+                              " AV Core/IR interrupt. Interrupt is disabled"
+                              " and won't be re-enabled\n", dev->name);
+               handled++;
+       }
+
+       if (handled)
+               cx_write(PCI_INT_STAT, pci_status);
+out:
+       return IRQ_RETVAL(handled);
+}
+
+static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
+                                   unsigned int notification, void *arg)
+{
+       struct cx23885_dev *dev;
+
+       if (sd == NULL)
+               return;
+
+       dev = to_cx23885(sd->v4l2_dev);
+
+       switch (notification) {
+       case V4L2_SUBDEV_IR_RX_NOTIFY: /* Possibly called in an IRQ context */
+               if (sd == dev->sd_ir)
+                       cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
+               break;
+       case V4L2_SUBDEV_IR_TX_NOTIFY: /* Possibly called in an IRQ context */
+               if (sd == dev->sd_ir)
+                       cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
+               break;
+       }
+}
+
+static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
+{
+       INIT_WORK(&dev->cx25840_work, cx23885_av_work_handler);
+       INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
+       INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
+       dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
+}
+
+static inline int encoder_on_portb(struct cx23885_dev *dev)
+{
+       return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
+}
+
+static inline int encoder_on_portc(struct cx23885_dev *dev)
+{
+       return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER;
+}
+
+/* Mask represents 32 different GPIOs, GPIO's are split into multiple
+ * registers depending on the board configuration (and whether the
+ * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will
+ * be pushed into the correct hardware register, regardless of the
+ * physical location. Certain registers are shared so we sanity check
+ * and report errors if we think we're tampering with a GPIo that might
+ * be assigned to the encoder (and used for the host bus).
+ *
+ * GPIO  2 thru  0 - On the cx23885 bridge
+ * GPIO 18 thru  3 - On the cx23417 host bus interface
+ * GPIO 23 thru 19 - On the cx25840 a/v core
+ */
+void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask)
+{
+       if (mask & 0x7)
+               cx_set(GP0_IO, mask & 0x7);
+
+       if (mask & 0x0007fff8) {
+               if (encoder_on_portb(dev) || encoder_on_portc(dev))
+                       printk(KERN_ERR
+                               "%s: Setting GPIO on encoder ports\n",
+                               dev->name);
+               cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3);
+       }
+
+       /* TODO: 23-19 */
+       if (mask & 0x00f80000)
+               printk(KERN_INFO "%s: Unsupported\n", dev->name);
+}
+
+void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
+{
+       if (mask & 0x00000007)
+               cx_clear(GP0_IO, mask & 0x7);
+
+       if (mask & 0x0007fff8) {
+               if (encoder_on_portb(dev) || encoder_on_portc(dev))
+                       printk(KERN_ERR
+                               "%s: Clearing GPIO moving on encoder ports\n",
+                               dev->name);
+               cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3);
+       }
+
+       /* TODO: 23-19 */
+       if (mask & 0x00f80000)
+               printk(KERN_INFO "%s: Unsupported\n", dev->name);
+}
+
+u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
+{
+       if (mask & 0x00000007)
+               return (cx_read(GP0_IO) >> 8) & mask & 0x7;
+
+       if (mask & 0x0007fff8) {
+               if (encoder_on_portb(dev) || encoder_on_portc(dev))
+                       printk(KERN_ERR
+                               "%s: Reading GPIO moving on encoder ports\n",
+                               dev->name);
+               return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
+       }
+
+       /* TODO: 23-19 */
+       if (mask & 0x00f80000)
+               printk(KERN_INFO "%s: Unsupported\n", dev->name);
+
+       return 0;
+}
+
+void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
+{
+       if ((mask & 0x00000007) && asoutput)
+               cx_set(GP0_IO, (mask & 0x7) << 16);
+       else if ((mask & 0x00000007) && !asoutput)
+               cx_clear(GP0_IO, (mask & 0x7) << 16);
+
+       if (mask & 0x0007fff8) {
+               if (encoder_on_portb(dev) || encoder_on_portc(dev))
+                       printk(KERN_ERR
+                               "%s: Enabling GPIO on encoder ports\n",
+                               dev->name);
+       }
+
+       /* MC417_OEN is active low for output, write 1 for an input */
+       if ((mask & 0x0007fff8) && asoutput)
+               cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3);
+
+       else if ((mask & 0x0007fff8) && !asoutput)
+               cx_set(MC417_OEN, (mask & 0x7fff8) >> 3);
+
+       /* TODO: 23-19 */
+}
+
+static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
+                                    const struct pci_device_id *pci_id)
+{
+       struct cx23885_dev *dev;
+       int err;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (NULL == dev)
+               return -ENOMEM;
+
+       err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+       if (err < 0)
+               goto fail_free;
+
+       /* Prepare to handle notifications from subdevices */
+       cx23885_v4l2_dev_notify_init(dev);
+
+       /* pci init */
+       dev->pci = pci_dev;
+       if (pci_enable_device(pci_dev)) {
+               err = -EIO;
+               goto fail_unreg;
+       }
+
+       if (cx23885_dev_setup(dev) < 0) {
+               err = -EINVAL;
+               goto fail_unreg;
+       }
+
+       /* print pci info */
+       dev->pci_rev = pci_dev->revision;
+       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+       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));
+
+       pci_set_master(pci_dev);
+       if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+               printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+               err = -EIO;
+               goto fail_irq;
+       }
+
+       err = request_irq(pci_dev->irq, cx23885_irq,
+                         IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+       if (err < 0) {
+               printk(KERN_ERR "%s: can't get IRQ %d\n",
+                      dev->name, pci_dev->irq);
+               goto fail_irq;
+       }
+
+       switch (dev->board) {
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0);
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+               cx23885_irq_add_enable(dev, PCI_MSK_GPIO0);
+               break;
+       }
+
+       /*
+        * The CX2388[58] IR controller can start firing interrupts when
+        * enabled, so these have to take place after the cx23885_irq() handler
+        * is hooked up by the call to request_irq() above.
+        */
+       cx23885_ir_pci_int_enable(dev);
+       cx23885_input_init(dev);
+
+       return 0;
+
+fail_irq:
+       cx23885_dev_unregister(dev);
+fail_unreg:
+       v4l2_device_unregister(&dev->v4l2_dev);
+fail_free:
+       kfree(dev);
+       return err;
+}
+
+static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct cx23885_dev *dev = to_cx23885(v4l2_dev);
+
+       cx23885_input_fini(dev);
+       cx23885_ir_fini(dev);
+
+       cx23885_shutdown(dev);
+
+       pci_disable_device(pci_dev);
+
+       /* unregister stuff */
+       free_irq(pci_dev->irq, dev);
+
+       cx23885_dev_unregister(dev);
+       v4l2_device_unregister(v4l2_dev);
+       kfree(dev);
+}
+
+static struct pci_device_id cx23885_pci_tbl[] = {
+       {
+               /* CX23885 */
+               .vendor       = 0x14f1,
+               .device       = 0x8852,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       }, {
+               /* CX23887 Rev 2 */
+               .vendor       = 0x14f1,
+               .device       = 0x8880,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       }, {
+               /* --- end of list --- */
+       }
+};
+MODULE_DEVICE_TABLE(pci, cx23885_pci_tbl);
+
+static struct pci_driver cx23885_pci_driver = {
+       .name     = "cx23885",
+       .id_table = cx23885_pci_tbl,
+       .probe    = cx23885_initdev,
+       .remove   = __devexit_p(cx23885_finidev),
+       /* TODO */
+       .suspend  = NULL,
+       .resume   = NULL,
+};
+
+static int __init cx23885_init(void)
+{
+       printk(KERN_INFO "cx23885 driver version %s loaded\n",
+               CX23885_VERSION);
+       return pci_register_driver(&cx23885_pci_driver);
+}
+
+static void __exit cx23885_fini(void)
+{
+       pci_unregister_driver(&cx23885_pci_driver);
+}
+
+module_init(cx23885_init);
+module_exit(cx23885_fini);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
new file mode 100644 (file)
index 0000000..f3202a5
--- /dev/null
@@ -0,0 +1,1356 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/suspend.h>
+
+#include "cx23885.h"
+#include <media/v4l2-common.h>
+
+#include "dvb_ca_en50221.h"
+#include "s5h1409.h"
+#include "s5h1411.h"
+#include "mt2131.h"
+#include "tda8290.h"
+#include "tda18271.h"
+#include "lgdt330x.h"
+#include "xc4000.h"
+#include "xc5000.h"
+#include "max2165.h"
+#include "tda10048.h"
+#include "tuner-xc2028.h"
+#include "tuner-simple.h"
+#include "dib7000p.h"
+#include "dibx000_common.h"
+#include "zl10353.h"
+#include "stv0900.h"
+#include "stv0900_reg.h"
+#include "stv6110.h"
+#include "lnbh24.h"
+#include "cx24116.h"
+#include "cimax2.h"
+#include "lgs8gxx.h"
+#include "netup-eeprom.h"
+#include "netup-init.h"
+#include "lgdt3305.h"
+#include "atbm8830.h"
+#include "ds3000.h"
+#include "cx23885-f300.h"
+#include "altera-ci.h"
+#include "stv0367.h"
+#include "drxk.h"
+#include "mt2063.h"
+
+static unsigned int debug;
+
+#define dprintk(level, fmt, arg...)\
+       do { if (debug >= level)\
+               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+       } while (0)
+
+/* ------------------------------------------------------------------ */
+
+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,
+                        unsigned int *count, unsigned int *size)
+{
+       struct cx23885_tsport *port = q->priv_data;
+
+       port->ts_packet_size  = 188 * 4;
+       port->ts_packet_count = 32;
+
+       *size  = port->ts_packet_size * port->ts_packet_count;
+       *count = 32;
+       return 0;
+}
+
+static int dvb_buf_prepare(struct videobuf_queue *q,
+                          struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct cx23885_tsport *port = q->priv_data;
+       return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
+}
+
+static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx23885_tsport *port = q->priv_data;
+       cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
+}
+
+static void dvb_buf_release(struct videobuf_queue *q,
+                           struct videobuf_buffer *vb)
+{
+       cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
+}
+
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe);
+
+static void cx23885_dvb_gate_ctrl(struct cx23885_tsport  *port, int open)
+{
+       struct videobuf_dvb_frontends *f;
+       struct videobuf_dvb_frontend *fe;
+
+       f = &port->frontends;
+
+       if (f->gate <= 1) /* undefined or fe0 */
+               fe = videobuf_dvb_get_frontend(f, 1);
+       else
+               fe = videobuf_dvb_get_frontend(f, f->gate);
+
+       if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+               fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+
+       /*
+        * FIXME: Improve this path to avoid calling the
+        * cx23885_dvb_set_frontend() every time it passes here.
+        */
+       cx23885_dvb_set_frontend(fe->dvb.frontend);
+}
+
+static struct videobuf_queue_ops dvb_qops = {
+       .buf_setup    = dvb_buf_setup,
+       .buf_prepare  = dvb_buf_prepare,
+       .buf_queue    = dvb_buf_queue,
+       .buf_release  = dvb_buf_release,
+};
+
+static struct s5h1409_config hauppauge_generic_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .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,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3800,
+       .dtv8_if_freq_khz = TDA10048_IF_4300,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+};
+
+static struct tda10048_config hauppauge_hvr1210_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+};
+
+static struct s5h1409_config hauppauge_ezqam_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .qam_if        = 4000,
+       .inversion     = S5H1409_INVERSION_ON,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config hauppauge_hvr1800lp_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config hauppauge_hvr1500_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 mt2131_config hauppauge_generic_tunerconfig = {
+       0x61
+};
+
+static struct lgdt330x_config fusionhdtv_5_express = {
+       .demod_address = 0x0e,
+       .demod_chip = LGDT3303,
+       .serial_mpeg = 0x40,
+};
+
+static struct s5h1409_config hauppauge_hvr1500q_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config dvico_s5h1409_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_SERIAL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1411_config dvico_s5h1411_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_ON,
+       .qam_if        = S5H1411_IF_44000,
+       .vsb_if        = S5H1411_IF_44000,
+       .inversion     = S5H1411_INVERSION_OFF,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1411_config hcw_s5h1411_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_44000,
+       .qam_if        = S5H1411_IF_4000,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
+       .i2c_address      = 0x61,
+       .if_khz           = 5380,
+};
+
+static struct xc5000_config dvico_xc5000_tunerconfig = {
+       .i2c_address      = 0x64,
+       .if_khz           = 5380,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+       .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+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_std_map hauppauge_hvr1200_tda18271_std_map = {
+       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+       .std_map = &hauppauge_hvr1200_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_config hauppauge_hvr1210_tuner_config = {
+       .gate    = TDA18271_GATE_DIGITAL,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_std_map hauppauge_hvr127x_std_map = {
+       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x58 },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x58 },
+};
+
+static struct tda18271_config hauppauge_hvr127x_config = {
+       .std_map = &hauppauge_hvr127x_std_map,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+       .i2c_addr           = 0x0e,
+       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 1,
+       .qam_if_khz         = 4000,
+       .vsb_if_khz         = 3250,
+};
+
+static 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 */
+static 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 struct zl10353_config dvico_fusionhdtv_xc3028 = {
+       .demod_address = 0x0f,
+       .if2           = 45600,
+       .no_tuner      = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static struct stv0900_reg stv0900_ts_regs[] = {
+       { R0900_TSGENERAL, 0x00 },
+       { R0900_P1_TSSPEED, 0x40 },
+       { R0900_P2_TSSPEED, 0x40 },
+       { R0900_P1_TSCFGM, 0xc0 },
+       { R0900_P2_TSCFGM, 0xc0 },
+       { R0900_P1_TSCFGH, 0xe0 },
+       { R0900_P2_TSCFGH, 0xe0 },
+       { R0900_P1_TSCFGL, 0x20 },
+       { R0900_P2_TSCFGL, 0x20 },
+       { 0xffff, 0xff }, /* terminate */
+};
+
+static struct stv0900_config netup_stv0900_config = {
+       .demod_address = 0x68,
+       .demod_mode = 1, /* dual */
+       .xtal = 8000000,
+       .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+       .diseqc_mode = 2,/* 2/3 PWM */
+       .ts_config_regs = stv0900_ts_regs,
+       .tun1_maddress = 0,/* 0x60 */
+       .tun2_maddress = 3,/* 0x63 */
+       .tun1_adc = 1,/* 1 Vpp */
+       .tun2_adc = 1,/* 1 Vpp */
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_a = {
+       .i2c_address = 0x60,
+       .mclk = 16000000,
+       .clk_div = 1,
+       .gain = 8, /* +16 dB  - maximum gain */
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_b = {
+       .i2c_address = 0x63,
+       .mclk = 16000000,
+       .clk_div = 1,
+       .gain = 8, /* +16 dB  - maximum gain */
+};
+
+static struct cx24116_config tbs_cx24116_config = {
+       .demod_address = 0x55,
+};
+
+static struct ds3000_config tevii_ds3000_config = {
+       .demod_address = 0x68,
+};
+
+static struct cx24116_config dvbworld_cx24116_config = {
+       .demod_address = 0x05,
+};
+
+static struct lgs8gxx_config mygica_x8506_lgs8gl5_config = {
+       .prod = LGS8GXX_PROD_LGS8GL5,
+       .demod_address = 0x19,
+       .serial_ts = 0,
+       .ts_clk_pol = 1,
+       .ts_clk_gated = 1,
+       .if_clk_freq = 30400, /* 30.4 MHz */
+       .if_freq = 5380, /* 5.38 MHz */
+       .if_neg_center = 1,
+       .ext_adc = 0,
+       .adc_signed = 0,
+       .if_neg_edge = 0,
+};
+
+static struct xc5000_config mygica_x8506_xc5000_config = {
+       .i2c_address = 0x61,
+       .if_khz = 5380,
+};
+
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+       struct cx23885_tsport *port = fe->dvb->priv;
+       struct cx23885_dev *dev = port->dev;
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+               switch (p->modulation) {
+               case VSB_8:
+                       cx23885_gpio_clear(dev, GPIO_5);
+                       break;
+               case QAM_64:
+               case QAM_256:
+               default:
+                       cx23885_gpio_set(dev, GPIO_5);
+                       break;
+               }
+               break;
+       case CX23885_BOARD_MYGICA_X8506:
+       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+               /* Select Digital TV */
+               cx23885_gpio_set(dev, GPIO_0);
+               break;
+       }
+       return 0;
+}
+
+static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
+       .prod = LGS8GXX_PROD_LGS8G75,
+       .demod_address = 0x19,
+       .serial_ts = 0,
+       .ts_clk_pol = 1,
+       .ts_clk_gated = 1,
+       .if_clk_freq = 30400, /* 30.4 MHz */
+       .if_freq = 6500, /* 6.50 MHz */
+       .if_neg_center = 1,
+       .ext_adc = 0,
+       .adc_signed = 1,
+       .adc_vpp = 2, /* 1.6 Vpp */
+       .if_neg_edge = 1,
+};
+
+static struct xc5000_config magicpro_prohdtve2_xc5000_config = {
+       .i2c_address = 0x61,
+       .if_khz = 6500,
+};
+
+static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = {
+       .prod = ATBM8830_PROD_8830,
+       .demod_address = 0x44,
+       .serial_ts = 0,
+       .ts_sampling_edge = 1,
+       .ts_clk_gated = 0,
+       .osc_clk_freq = 30400, /* in kHz */
+       .if_freq = 0, /* zero IF */
+       .zif_swap_iq = 1,
+       .agc_min = 0x2E,
+       .agc_max = 0xFF,
+       .agc_hold_loop = 0,
+};
+
+static struct max2165_config mygic_x8558pro_max2165_cfg1 = {
+       .i2c_address = 0x60,
+       .osc_clk = 20
+};
+
+static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = {
+       .prod = ATBM8830_PROD_8830,
+       .demod_address = 0x44,
+       .serial_ts = 1,
+       .ts_sampling_edge = 1,
+       .ts_clk_gated = 0,
+       .osc_clk_freq = 30400, /* in kHz */
+       .if_freq = 0, /* zero IF */
+       .zif_swap_iq = 1,
+       .agc_min = 0x2E,
+       .agc_max = 0xFF,
+       .agc_hold_loop = 0,
+};
+
+static struct max2165_config mygic_x8558pro_max2165_cfg2 = {
+       .i2c_address = 0x60,
+       .osc_clk = 20
+};
+static struct stv0367_config netup_stv0367_config[] = {
+       {
+               .demod_address = 0x1c,
+               .xtal = 27000000,
+               .if_khz = 4500,
+               .if_iq_mode = 0,
+               .ts_mode = 1,
+               .clk_pol = 0,
+       }, {
+               .demod_address = 0x1d,
+               .xtal = 27000000,
+               .if_khz = 4500,
+               .if_iq_mode = 0,
+               .ts_mode = 1,
+               .clk_pol = 0,
+       },
+};
+
+static struct xc5000_config netup_xc5000_config[] = {
+       {
+               .i2c_address = 0x61,
+               .if_khz = 4500,
+       }, {
+               .i2c_address = 0x64,
+               .if_khz = 4500,
+       },
+};
+
+static struct drxk_config terratec_drxk_config[] = {
+       {
+               .adr = 0x29,
+               .no_i2c_bridge = 1,
+       }, {
+               .adr = 0x2a,
+               .no_i2c_bridge = 1,
+       },
+};
+
+static struct mt2063_config terratec_mt2063_config[] = {
+       {
+               .tuner_address = 0x60,
+       }, {
+               .tuner_address = 0x67,
+       },
+};
+
+int netup_altera_fpga_rw(void *device, int flag, int data, int read)
+{
+       struct cx23885_dev *dev = (struct cx23885_dev *)device;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
+       uint32_t mem = 0;
+
+       mem = cx_read(MC417_RWD);
+       if (read)
+               cx_set(MC417_OEN, ALT_DATA);
+       else {
+               cx_clear(MC417_OEN, ALT_DATA);/* D0-D7 out */
+               mem &= ~ALT_DATA;
+               mem |= (data & ALT_DATA);
+       }
+
+       if (flag)
+               mem |= ALT_AD_RG;
+       else
+               mem &= ~ALT_AD_RG;
+
+       mem &= ~ALT_CS;
+       if (read)
+               mem = (mem & ~ALT_RD) | ALT_WR;
+       else
+               mem = (mem & ~ALT_WR) | ALT_RD;
+
+       cx_write(MC417_RWD, mem);  /* start RW cycle */
+
+       for (;;) {
+               mem = cx_read(MC417_RWD);
+               if ((mem & ALT_RDY) == 0)
+                       break;
+               if (time_after(jiffies, timeout))
+                       break;
+               udelay(1);
+       }
+
+       cx_set(MC417_RWD, ALT_RD | ALT_WR | ALT_CS);
+       if (read)
+               return mem & ALT_DATA;
+
+       return 0;
+};
+
+static int dvb_register(struct cx23885_tsport *port)
+{
+       struct cx23885_dev *dev = port->dev;
+       struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
+       struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+       int mfe_shared = 0; /* bus not shared by default */
+       int ret;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+       if (!fe0)
+               return -EINVAL;
+
+       /* init struct videobuf_dvb */
+       fe0->dvb.name = dev->name;
+
+       /* multi-frontend gate control is undefined or defaults to fe0 */
+       port->frontends.gate = 0;
+
+       /* Sets the gate control callback to be used by i2c command calls */
+       port->gate_ctrl = cx23885_dvb_gate_ctrl;
+
+       /* init frontend */
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &hauppauge_generic_config,
+                                               &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(mt2131_attach, fe0->dvb.frontend,
+                                  &i2c_bus->i2c_adap,
+                                  &hauppauge_generic_tunerconfig, 0);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
+                                              &hauppauge_lgdt3305_config,
+                                              &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_bus[1].i2c_adap,
+                                  &hauppauge_hvr127x_config);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                                              &hcw_s5h1411_config,
+                                              &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_bus[1].i2c_adap,
+                                  &hauppauge_tda18271_config);
+               }
+
+               tda18271_attach(&dev->ts1.analog_fe,
+                       0x60, &dev->i2c_bus[1].i2c_adap,
+                       &hauppauge_tda18271_config);
+
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1800:
+               i2c_bus = &dev->i2c_bus[0];
+               switch (alt_tuner) {
+               case 1:
+                       fe0->dvb.frontend =
+                               dvb_attach(s5h1409_attach,
+                                          &hauppauge_ezqam_config,
+                                          &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                          &dev->i2c_bus[1].i2c_adap, 0x42,
+                                          &tda829x_no_probe);
+                               dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                          0x60, &dev->i2c_bus[1].i2c_adap,
+                                          &hauppauge_tda18271_config);
+                       }
+                       break;
+               case 0:
+               default:
+                       fe0->dvb.frontend =
+                               dvb_attach(s5h1409_attach,
+                                          &hauppauge_generic_config,
+                                          &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL)
+                               dvb_attach(mt2131_attach, fe0->dvb.frontend,
+                                          &i2c_bus->i2c_adap,
+                                          &hauppauge_generic_tunerconfig, 0);
+                       break;
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &hauppauge_hvr1800lp_config,
+                                               &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(mt2131_attach, fe0->dvb.frontend,
+                                  &i2c_bus->i2c_adap,
+                                  &hauppauge_generic_tunerconfig, 0);
+               }
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                               &fusionhdtv_5_express,
+                                               &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &i2c_bus->i2c_adap, 0x61,
+                                  TUNER_LG_TDVS_H06XF);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+               i2c_bus = &dev->i2c_bus[1];
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &hauppauge_hvr1500q_config,
+                                               &dev->i2c_bus[0].i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                  &i2c_bus->i2c_adap,
+                                  &hauppauge_hvr1500q_tunerconfig);
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1500:
+               i2c_bus = &dev->i2c_bus[1];
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &hauppauge_hvr1500_config,
+                                               &dev->i2c_bus[0].i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &i2c_bus->i2c_adap,
+                               .i2c_addr  = 0x61,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
+                               .max_len     = 64,
+                               .demod       = XC3028_FE_OREN538,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       fe0->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];
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                       &hauppauge_hvr1200_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                               &dev->i2c_bus[1].i2c_adap, 0x42,
+                               &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                               0x60, &dev->i2c_bus[1].i2c_adap,
+                               &hauppauge_hvr1200_tuner_config);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1210:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                       &hauppauge_hvr1210_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                               0x60, &dev->i2c_bus[1].i2c_adap,
+                               &hauppauge_hvr1210_tuner_config);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1400:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(dib7000p_attach,
+                       &i2c_bus->i2c_adap,
+                       0x12, &hauppauge_hvr1400_dib7000_config);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+                               .i2c_addr  = 0x64,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname   = XC3028L_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                               .demod   = XC3028_FE_DIBCOM52,
+                               /* This is true for all demods with
+                                       v36 firmware? */
+                               .type    = XC2028_D2633,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       fe0->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_DVICO_FUSIONHDTV_7_DUAL_EXP:
+               i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &dvico_s5h1409_config,
+                                               &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend == NULL)
+                       fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                                                       &dvico_s5h1411_config,
+                                                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                  &i2c_bus->i2c_adap,
+                                  &dvico_xc5000_tunerconfig);
+               break;
+       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
+               i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend      *fe;
+                       struct xc2028_config      cfg = {
+                               .i2c_adap  = &i2c_bus->i2c_adap,
+                               .i2c_addr  = 0x61,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
+                               .max_len     = 64,
+                               .demod       = XC3028_FE_ZARLINK456,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, fe0->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_LEADTEK_WINFAST_PXDVR3200_H:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+               i2c_bus = &dev->i2c_bus[0];
+
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                       &dvico_fusionhdtv_xc3028,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend      *fe;
+                       struct xc2028_config      cfg = {
+                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+                               .i2c_addr  = 0x61,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
+                               .max_len     = 64,
+                               .demod       = XC3028_FE_ZARLINK456,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, fe0->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_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+               i2c_bus = &dev->i2c_bus[0];
+
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend     *fe;
+                       struct xc4000_config    cfg = {
+                               .i2c_address      = 0x61,
+                               .default_pm       = 0,
+                               .dvb_amplitude    = 134,
+                               .set_smoothedcvbs = 1,
+                               .if_khz           = 4560
+                       };
+
+                       fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
+                                       &dev->i2c_bus[1].i2c_adap, &cfg);
+                       if (!fe) {
+                               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+                                      dev->name);
+                               goto frontend_detach;
+                       }
+               }
+               break;
+       case CX23885_BOARD_TBS_6920:
+               i2c_bus = &dev->i2c_bus[1];
+
+               fe0->dvb.frontend = dvb_attach(cx24116_attach,
+                                       &tbs_cx24116_config,
+                                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
+
+               break;
+       case CX23885_BOARD_TEVII_S470:
+               i2c_bus = &dev->i2c_bus[1];
+
+               fe0->dvb.frontend = dvb_attach(ds3000_attach,
+                                       &tevii_ds3000_config,
+                                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
+
+               break;
+       case CX23885_BOARD_DVBWORLD_2005:
+               i2c_bus = &dev->i2c_bus[1];
+
+               fe0->dvb.frontend = dvb_attach(cx24116_attach,
+                       &dvbworld_cx24116_config,
+                       &i2c_bus->i2c_adap);
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               i2c_bus = &dev->i2c_bus[0];
+               switch (port->nr) {
+               /* port B */
+               case 1:
+                       fe0->dvb.frontend = dvb_attach(stv0900_attach,
+                                                       &netup_stv0900_config,
+                                                       &i2c_bus->i2c_adap, 0);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (dvb_attach(stv6110_attach,
+                                               fe0->dvb.frontend,
+                                               &netup_stv6110_tunerconfig_a,
+                                               &i2c_bus->i2c_adap)) {
+                                       if (!dvb_attach(lnbh24_attach,
+                                                       fe0->dvb.frontend,
+                                                       &i2c_bus->i2c_adap,
+                                                       LNBH24_PCL | LNBH24_TTX,
+                                                       LNBH24_TEN, 0x09))
+                                               printk(KERN_ERR
+                                                       "No LNBH24 found!\n");
+
+                               }
+                       }
+                       break;
+               /* port C */
+               case 2:
+                       fe0->dvb.frontend = dvb_attach(stv0900_attach,
+                                                       &netup_stv0900_config,
+                                                       &i2c_bus->i2c_adap, 1);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (dvb_attach(stv6110_attach,
+                                               fe0->dvb.frontend,
+                                               &netup_stv6110_tunerconfig_b,
+                                               &i2c_bus->i2c_adap)) {
+                                       if (!dvb_attach(lnbh24_attach,
+                                                       fe0->dvb.frontend,
+                                                       &i2c_bus->i2c_adap,
+                                                       LNBH24_PCL | LNBH24_TTX,
+                                                       LNBH24_TEN, 0x0a))
+                                               printk(KERN_ERR
+                                                       "No LNBH24 found!\n");
+
+                               }
+                       }
+                       break;
+               }
+               break;
+       case CX23885_BOARD_MYGICA_X8506:
+               i2c_bus = &dev->i2c_bus[0];
+               i2c_bus2 = &dev->i2c_bus[1];
+               fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+                       &mygica_x8506_lgs8gl5_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(xc5000_attach,
+                               fe0->dvb.frontend,
+                               &i2c_bus2->i2c_adap,
+                               &mygica_x8506_xc5000_config);
+               }
+               break;
+       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+               i2c_bus = &dev->i2c_bus[0];
+               i2c_bus2 = &dev->i2c_bus[1];
+               fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+                       &magicpro_prohdtve2_lgs8g75_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(xc5000_attach,
+                               fe0->dvb.frontend,
+                               &i2c_bus2->i2c_adap,
+                               &magicpro_prohdtve2_xc5000_config);
+               }
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                       &hcw_s5h1411_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                               0x60, &dev->i2c_bus[0].i2c_adap,
+                               &hauppauge_tda18271_config);
+
+               tda18271_attach(&dev->ts1.analog_fe,
+                       0x60, &dev->i2c_bus[1].i2c_adap,
+                       &hauppauge_tda18271_config);
+
+               break;
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+               i2c_bus = &dev->i2c_bus[0];
+               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                       &hcw_s5h1411_config,
+                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                               0x60, &dev->i2c_bus[0].i2c_adap,
+                               &hauppauge_tda18271_config);
+               break;
+       case CX23885_BOARD_MYGICA_X8558PRO:
+               switch (port->nr) {
+               /* port B */
+               case 1:
+                       i2c_bus = &dev->i2c_bus[0];
+                       fe0->dvb.frontend = dvb_attach(atbm8830_attach,
+                               &mygica_x8558pro_atbm8830_cfg1,
+                               &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               dvb_attach(max2165_attach,
+                                       fe0->dvb.frontend,
+                                       &i2c_bus->i2c_adap,
+                                       &mygic_x8558pro_max2165_cfg1);
+                       }
+                       break;
+               /* port C */
+               case 2:
+                       i2c_bus = &dev->i2c_bus[1];
+                       fe0->dvb.frontend = dvb_attach(atbm8830_attach,
+                               &mygica_x8558pro_atbm8830_cfg2,
+                               &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               dvb_attach(max2165_attach,
+                                       fe0->dvb.frontend,
+                                       &i2c_bus->i2c_adap,
+                                       &mygic_x8558pro_max2165_cfg2);
+                       }
+                       break;
+               }
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+               i2c_bus = &dev->i2c_bus[0];
+               mfe_shared = 1;/* MFE */
+               port->frontends.gate = 0;/* not clear for me yet */
+               /* ports B, C */
+               /* MFE frontend 1 DVB-T */
+               fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
+                                       &netup_stv0367_config[port->nr - 1],
+                                       &i2c_bus->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (NULL == dvb_attach(xc5000_attach,
+                                       fe0->dvb.frontend,
+                                       &i2c_bus->i2c_adap,
+                                       &netup_xc5000_config[port->nr - 1]))
+                               goto frontend_detach;
+                       /* load xc5000 firmware */
+                       fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
+               }
+               /* MFE frontend 2 */
+               fe1 = videobuf_dvb_get_frontend(&port->frontends, 2);
+               if (fe1 == NULL)
+                       goto frontend_detach;
+               /* DVB-C init */
+               fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
+                                       &netup_stv0367_config[port->nr - 1],
+                                       &i2c_bus->i2c_adap);
+               if (fe1->dvb.frontend != NULL) {
+                       fe1->dvb.frontend->id = 1;
+                       if (NULL == dvb_attach(xc5000_attach,
+                                       fe1->dvb.frontend,
+                                       &i2c_bus->i2c_adap,
+                                       &netup_xc5000_config[port->nr - 1]))
+                               goto frontend_detach;
+               }
+               break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+               i2c_bus = &dev->i2c_bus[0];
+               i2c_bus2 = &dev->i2c_bus[1];
+
+               switch (port->nr) {
+               /* port b */
+               case 1:
+                       fe0->dvb.frontend = dvb_attach(drxk_attach,
+                                       &terratec_drxk_config[0],
+                                       &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (!dvb_attach(mt2063_attach,
+                                               fe0->dvb.frontend,
+                                               &terratec_mt2063_config[0],
+                                               &i2c_bus2->i2c_adap))
+                                       goto frontend_detach;
+                       }
+                       break;
+               /* port c */
+               case 2:
+                       fe0->dvb.frontend = dvb_attach(drxk_attach,
+                                       &terratec_drxk_config[1],
+                                       &i2c_bus->i2c_adap);
+                       if (fe0->dvb.frontend != NULL) {
+                               if (!dvb_attach(mt2063_attach,
+                                               fe0->dvb.frontend,
+                                               &terratec_mt2063_config[1],
+                                               &i2c_bus2->i2c_adap))
+                                       goto frontend_detach;
+                       }
+                       break;
+               }
+               break;
+       case CX23885_BOARD_TEVII_S471:
+               i2c_bus = &dev->i2c_bus[1];
+
+               fe0->dvb.frontend = dvb_attach(ds3000_attach,
+                                       &tevii_ds3000_config,
+                                       &i2c_bus->i2c_adap);
+               break;
+       default:
+               printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
+                       " isn't supported yet\n",
+                      dev->name);
+               break;
+       }
+
+       if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
+               printk(KERN_ERR "%s: frontend initialization failed\n",
+                      dev->name);
+               goto frontend_detach;
+       }
+
+       /* define general-purpose callback pointer */
+       fe0->dvb.frontend->callback = cx23885_tuner_callback;
+       if (fe1)
+               fe1->dvb.frontend->callback = cx23885_tuner_callback;
+#if 0
+       /* Ensure all frontends negotiate bus access */
+       fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
+       if (fe1)
+               fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
+#endif
+
+       /* Put the analog decoder in standby to keep it quiet */
+       call_all(dev, core, s_power, 0);
+
+       if (fe0->dvb.frontend->ops.analog_ops.standby)
+               fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
+
+       /* register everything */
+       ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
+                                       &dev->pci->dev, adapter_nr, mfe_shared);
+       if (ret)
+               goto frontend_detach;
+
+       /* init CI & MAC */
+       switch (dev->board) {
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
+               static struct netup_card_info cinfo;
+
+               netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+               memcpy(port->frontends.adapter.proposed_mac,
+                               cinfo.port[port->nr - 1].mac, 6);
+               printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
+                       port->nr, port->frontends.adapter.proposed_mac);
+
+               netup_ci_init(port);
+               break;
+               }
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+               struct altera_ci_config netup_ci_cfg = {
+                       .dev = dev,/* magic number to identify*/
+                       .adapter = &port->frontends.adapter,/* for CI */
+                       .demux = &fe0->dvb.demux,/* for hw pid filter */
+                       .fpga_rw = netup_altera_fpga_rw,
+               };
+
+               altera_ci_init(&netup_ci_cfg, port->nr);
+               break;
+               }
+       case CX23885_BOARD_TEVII_S470: {
+               u8 eeprom[256]; /* 24C02 i2c eeprom */
+
+               if (port->nr != 1)
+                       break;
+
+               /* Read entire EEPROM */
+               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
+               printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
+               memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
+               break;
+               }
+       }
+
+       return ret;
+
+frontend_detach:
+       port->gate_ctrl = NULL;
+       videobuf_dvb_dealloc_frontends(&port->frontends);
+       return -EINVAL;
+}
+
+int cx23885_dvb_register(struct cx23885_tsport *port)
+{
+
+       struct videobuf_dvb_frontend *fe0;
+       struct cx23885_dev *dev = port->dev;
+       int err, i;
+
+       /* Here we need to allocate the correct number of frontends,
+        * as reflected in the cards struct. The reality is that currently
+        * no cx23885 boards support this - yet. But, if we don't modify this
+        * code then the second frontend would never be allocated (later)
+        * and fail with error before the attach in dvb_register().
+        * Without these changes we risk an OOPS later. The changes here
+        * are for safety, and should provide a good foundation for the
+        * future addition of any multi-frontend cx23885 based boards.
+        */
+       printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+               port->num_frontends);
+
+       for (i = 1; i <= port->num_frontends; i++) {
+               if (videobuf_dvb_alloc_frontend(
+                       &port->frontends, i) == NULL) {
+                       printk(KERN_ERR "%s() failed to alloc\n", __func__);
+                       return -ENOMEM;
+               }
+
+               fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
+               if (!fe0)
+                       err = -EINVAL;
+
+               dprintk(1, "%s\n", __func__);
+               dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
+                       dev->board,
+                       dev->name,
+                       dev->pci_bus,
+                       dev->pci_slot);
+
+               err = -ENODEV;
+
+               /* dvb stuff */
+               /* We have to init the queue for each frontend on a port. */
+               printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
+               videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
+                           &dev->pci->dev, &port->slock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
+                           sizeof(struct cx23885_buffer), port, NULL);
+       }
+       err = dvb_register(port);
+       if (err != 0)
+               printk(KERN_ERR "%s() dvb_register failed err = %d\n",
+                       __func__, err);
+
+       return err;
+}
+
+int cx23885_dvb_unregister(struct cx23885_tsport *port)
+{
+       struct videobuf_dvb_frontend *fe0;
+
+       /* FIXME: in an error condition where the we have
+        * an expected number of frontends (attach problem)
+        * then this might not clean up correctly, if 1
+        * is invalid.
+        * This comment only applies to future boards IF they
+        * implement MFE support.
+        */
+       fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+       if (fe0 && fe0->dvb.frontend)
+               videobuf_dvb_unregister_bus(&port->frontends);
+
+       switch (port->dev->board) {
+       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+               netup_ci_exit(port);
+               break;
+       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+               altera_ci_release(port->dev, port->nr);
+               break;
+       }
+
+       port->gate_ctrl = NULL;
+
+       return 0;
+}
+
diff --git a/drivers/media/pci/cx23885/cx23885-f300.c b/drivers/media/pci/cx23885/cx23885-f300.c
new file mode 100644 (file)
index 0000000..93998f2
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Driver for Silicon Labs C8051F300 microcontroller.
+ *
+ * It is used for LNB power control in TeVii S470,
+ * TBS 6920 PCIe DVB-S2 cards.
+ *
+ * Microcontroller connected to cx23885 GPIO pins:
+ * GPIO0 - data                - P0.3 F300
+ * GPIO1 - reset       - P0.2 F300
+ * GPIO2 - clk         - P0.1 F300
+ * GPIO3 - busy                - P0.0 F300
+ *
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
+ *
+ * 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 "cx23885.h"
+
+#define F300_DATA      GPIO_0
+#define F300_RESET     GPIO_1
+#define F300_CLK       GPIO_2
+#define F300_BUSY      GPIO_3
+
+static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
+{
+       cx23885_gpio_enable(dev, line, 1);
+       if (lvl == 1)
+               cx23885_gpio_set(dev, line);
+       else
+               cx23885_gpio_clear(dev, line);
+}
+
+static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
+{
+       cx23885_gpio_enable(dev, line, 0);
+
+       return cx23885_gpio_get(dev, line);
+}
+
+static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
+{
+       u8 i;
+
+       for (i = 0; i < 8; i++) {
+               f300_set_line(dev, F300_CLK, 0);
+               udelay(30);
+               f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
+               udelay(30);
+               dta <<= 1;
+               f300_set_line(dev, F300_CLK, 1);
+               udelay(30);
+       }
+}
+
+static u8 f300_get_byte(struct cx23885_dev *dev)
+{
+       u8 i, dta = 0;
+
+       for (i = 0; i < 8; i++) {
+               f300_set_line(dev, F300_CLK, 0);
+               udelay(30);
+               dta <<= 1;
+               f300_set_line(dev, F300_CLK, 1);
+               udelay(30);
+               dta |= f300_get_line(dev, F300_DATA);/* msb first */
+
+       }
+
+       return dta;
+}
+
+static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
+{
+       struct cx23885_tsport *port = fe->dvb->priv;
+       struct cx23885_dev *dev = port->dev;
+       u8 i, temp, ret = 0;
+
+       temp = buf[0];
+       for (i = 0; i < buf[0]; i++)
+               temp += buf[i + 1];
+       temp = (~temp + 1);/* get check sum */
+       buf[1 + buf[0]] = temp;
+
+       f300_set_line(dev, F300_RESET, 1);
+       f300_set_line(dev, F300_CLK, 1);
+       udelay(30);
+       f300_set_line(dev, F300_DATA, 1);
+       msleep(1);
+
+       /* question: */
+       f300_set_line(dev, F300_RESET, 0);/* begin to send data */
+       msleep(1);
+
+       f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
+       msleep(1);
+
+       temp = buf[0];
+       temp += 2;
+       for (i = 0; i < temp; i++)
+               f300_send_byte(dev, buf[i]);
+
+       f300_set_line(dev, F300_RESET, 1);/* sent data over */
+       f300_set_line(dev, F300_DATA, 1);
+
+       /* answer: */
+       temp = 0;
+       for (i = 0; ((i < 8) & (temp == 0)); i++) {
+               msleep(1);
+               if (f300_get_line(dev, F300_BUSY) == 0)
+                       temp = 1;
+       }
+
+       if (i > 7) {
+               printk(KERN_ERR "%s: timeout, the slave no response\n",
+                                                               __func__);
+               ret = 1; /* timeout, the slave no response */
+       } else { /* the slave not busy, prepare for getting data */
+               f300_set_line(dev, F300_RESET, 0);/*ready...*/
+               msleep(1);
+               f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
+               msleep(1);
+               temp = f300_get_byte(dev);/*get the data length */
+               if (temp > 14)
+                       temp = 14;
+
+               for (i = 0; i < (temp + 1); i++)
+                       f300_get_byte(dev);/* get data to empty buffer */
+
+               f300_set_line(dev, F300_RESET, 1);/* received data over */
+               f300_set_line(dev, F300_DATA, 1);
+       }
+
+       return ret;
+}
+
+int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       u8 buf[16];
+
+       buf[0] = 0x05;
+       buf[1] = 0x38;/* write port */
+       buf[2] = 0x01;/* A port, lnb power */
+
+       switch (voltage) {
+       case SEC_VOLTAGE_13:
+               buf[3] = 0x01;/* power on */
+               buf[4] = 0x02;/* B port, H/V */
+               buf[5] = 0x00;/*13V v*/
+               break;
+       case SEC_VOLTAGE_18:
+               buf[3] = 0x01;
+               buf[4] = 0x02;
+               buf[5] = 0x01;/* 18V h*/
+               break;
+       case SEC_VOLTAGE_OFF:
+               buf[3] = 0x00;/* power off */
+               buf[4] = 0x00;
+               buf[5] = 0x00;
+               break;
+       }
+
+       return f300_xfer(fe, buf);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-f300.h b/drivers/media/pci/cx23885/cx23885-f300.h
new file mode 100644 (file)
index 0000000..e73344c
--- /dev/null
@@ -0,0 +1,2 @@
+extern int f300_set_voltage(struct dvb_frontend *fe,
+                               fe_sec_voltage_t voltage);
diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c
new file mode 100644 (file)
index 0000000..4887314
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include "cx23885.h"
+
+#include <media/v4l2-common.h>
+
+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;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (i2c_debug >= level)\
+               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+       } while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+       struct cx23885_i2c *bus = i2c_adap->algo_data;
+       struct cx23885_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+       struct cx23885_i2c *bus = i2c_adap->algo_data;
+       struct cx23885_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x02 ? 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;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg, int joined_rlen)
+{
+       struct cx23885_i2c *bus = i2c_adap->algo_data;
+       struct cx23885_dev *dev = bus->dev;
+       u32 wdata, addr, ctrl;
+       int retval, cnt;
+
+       if (joined_rlen)
+               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+                       msg->len, joined_rlen);
+       else
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+       /* Deal with i2c probe functions with zero payload */
+       if (msg->len == 0) {
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+               if (!i2c_slave_did_ack(i2c_adap))
+                       return -ENXIO;
+
+               dprintk(1, "%s() returns 0\n", __func__);
+               return 0;
+       }
+
+
+       /* dev, reg + first byte */
+       addr = (msg->addr << 25) | msg->buf[0];
+       wdata = msg->buf[0];
+       ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+       if (msg->len > 1)
+               ctrl |= I2C_NOSTOP | I2C_EXTEND;
+       else if (joined_rlen)
+               ctrl |= I2C_NOSTOP;
+
+       cx_write(bus->reg_addr, addr);
+       cx_write(bus->reg_wdata, wdata);
+       cx_write(bus->reg_ctrl, ctrl);
+
+       if (!i2c_wait_done(i2c_adap))
+               goto eio;
+       if (i2c_debug) {
+               printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
+               if (!(ctrl & I2C_NOSTOP))
+                       printk(" >\n");
+       }
+
+       for (cnt = 1; cnt < msg->len; cnt++) {
+               /* following bytes */
+               wdata = msg->buf[cnt];
+               ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+               if (cnt < msg->len - 1)
+                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
+               else if (joined_rlen)
+                       ctrl |= I2C_NOSTOP;
+
+               cx_write(bus->reg_addr, addr);
+               cx_write(bus->reg_wdata, wdata);
+               cx_write(bus->reg_ctrl, ctrl);
+
+               if (!i2c_wait_done(i2c_adap))
+                       goto eio;
+               if (i2c_debug) {
+                       dprintk(1, " %02x", msg->buf[cnt]);
+                       if (!(ctrl & I2C_NOSTOP))
+                               dprintk(1, " >\n");
+               }
+       }
+       return msg->len;
+
+ eio:
+       retval = -EIO;
+       if (i2c_debug)
+               printk(KERN_ERR " ERR: %d\n", retval);
+       return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg, int joined)
+{
+       struct cx23885_i2c *bus = i2c_adap->algo_data;
+       struct cx23885_dev *dev = bus->dev;
+       u32 ctrl, cnt;
+       int retval;
+
+
+       if (i2c_debug && !joined)
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+       /* Deal with i2c probe functions with zero payload */
+       if (msg->len == 0) {
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+               if (!i2c_slave_did_ack(i2c_adap))
+                       return -ENXIO;
+
+
+               dprintk(1, "%s() returns 0\n", __func__);
+               return 0;
+       }
+
+       if (i2c_debug) {
+               if (joined)
+                       dprintk(1, " R");
+               else
+                       dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+       }
+
+       for (cnt = 0; cnt < msg->len; cnt++) {
+
+               ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+               if (cnt < msg->len - 1)
+                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, ctrl);
+
+               if (!i2c_wait_done(i2c_adap))
+                       goto eio;
+               msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+               if (i2c_debug) {
+                       dprintk(1, " %02x", msg->buf[cnt]);
+                       if (!(ctrl & I2C_NOSTOP))
+                               dprintk(1, " >\n");
+               }
+       }
+       return msg->len;
+
+ eio:
+       retval = -EIO;
+       if (i2c_debug)
+               printk(KERN_ERR " ERR: %d\n", retval);
+       return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap,
+                   struct i2c_msg *msgs, int num)
+{
+       struct cx23885_i2c *bus = i2c_adap->algo_data;
+       struct cx23885_dev *dev = bus->dev;
+       int i, retval = 0;
+
+       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",
+                       __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 u32 cx23885_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cx23885_i2c_algo_template = {
+       .master_xfer    = i2c_xfer,
+       .functionality  = cx23885_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter cx23885_i2c_adap_template = {
+       .name              = "cx23885",
+       .owner             = THIS_MODULE,
+       .algo              = &cx23885_i2c_algo_template,
+};
+
+static struct i2c_client cx23885_i2c_client_template = {
+       .name   = "cx23885 internal",
+};
+
+static char *i2c_devs[128] = {
+       [0x10 >> 1] = "tda10048",
+       [0x12 >> 1] = "dib7000pc",
+       [0x1c >> 1] = "lgdt3303",
+       [0x86 >> 1] = "tda9887",
+       [0x32 >> 1] = "cx24227",
+       [0x88 >> 1] = "cx25837",
+       [0x84 >> 1] = "tda8295",
+       [0x98 >> 1] = "flatiron",
+       [0xa0 >> 1] = "eeprom",
+       [0xc0 >> 1] = "tuner/mt2131/tda8275",
+       [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
+       [0xc8 >> 1] = "tuner/xc3028L",
+};
+
+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 adapter */
+int cx23885_i2c_register(struct cx23885_i2c *bus)
+{
+       struct cx23885_dev *dev = bus->dev;
+
+       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+       bus->i2c_adap = cx23885_i2c_adap_template;
+       bus->i2c_client = cx23885_i2c_client_template;
+       bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+       strlcpy(bus->i2c_adap.name, bus->dev->name,
+               sizeof(bus->i2c_adap.name));
+
+       bus->i2c_adap.algo_data = bus;
+       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+       i2c_add_adapter(&bus->i2c_adap);
+
+       bus->i2c_client.adapter = &bus->i2c_adap;
+
+       if (0 == bus->i2c_rc) {
+               dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
+               if (i2c_scan) {
+                       printk(KERN_INFO "%s: scan bus %d:\n",
+                                       dev->name, bus->nr);
+                       do_i2c_scan(dev->name, &bus->i2c_client);
+               }
+       } else
+               printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
+                       dev->name, bus->nr);
+
+       /* Instantiate the IR receiver device, if present */
+       if (0 == bus->i2c_rc) {
+               struct i2c_board_info info;
+               const unsigned short addr_list[] = {
+                       0x6b, I2C_CLIENT_END
+               };
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+               /* Use quick read command for probe, some IR chips don't
+                * support writes */
+               i2c_new_probed_device(&bus->i2c_adap, &info, addr_list,
+                                     i2c_probe_func_quick_read);
+       }
+
+       return bus->i2c_rc;
+}
+
+int cx23885_i2c_unregister(struct cx23885_i2c *bus)
+{
+       i2c_del_adapter(&bus->i2c_adap);
+       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);
+}
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
new file mode 100644 (file)
index 0000000..5606672
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared remote control input device
+ *
+ *  Most of this file is
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  However, the cx23885_input_{init,fini} functions contained herein are
+ *  derived from Linux kernel files linux/media/video/.../...-input.c marked as:
+ *
+ *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+ *  Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+ *                    Markus Rechberger <mrechberger@gmail.com>
+ *                    Mauro Carvalho Chehab <mchehab@infradead.org>
+ *                    Sascha Sommer <saschasommer@freenet.de>
+ *  Copyright (C) 2004, 2005 Chris Pascoe
+ *  Copyright (C) 2003, 2004 Gerd Knorr
+ *  Copyright (C) 2003 Pavel Machek
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include <linux/slab.h>
+#include <media/rc-core.h>
+#include <media/v4l2-subdev.h>
+
+#include "cx23885.h"
+
+#define MODULE_NAME "cx23885"
+
+static void cx23885_input_process_measurements(struct cx23885_dev *dev,
+                                              bool overrun)
+{
+       struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
+
+       ssize_t num;
+       int count, i;
+       bool handle = false;
+       struct ir_raw_event ir_core_event[64];
+
+       do {
+               num = 0;
+               v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
+                                sizeof(ir_core_event), &num);
+
+               count = num / sizeof(struct ir_raw_event);
+
+               for (i = 0; i < count; i++) {
+                       ir_raw_event_store(kernel_ir->rc,
+                                          &ir_core_event[i]);
+                       handle = true;
+               }
+       } while (num != 0);
+
+       if (overrun)
+               ir_raw_event_reset(kernel_ir->rc);
+       else if (handle)
+               ir_raw_event_handle(kernel_ir->rc);
+}
+
+void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
+{
+       struct v4l2_subdev_ir_parameters params;
+       int overrun, data_available;
+
+       if (dev->sd_ir == NULL || events == 0)
+               return;
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+       case CX23885_BOARD_TEVII_S470:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               /*
+                * The only boards we handle right now.  However other boards
+                * using the CX2388x integrated IR controller should be similar
+                */
+               break;
+       default:
+               return;
+       }
+
+       overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN |
+                           V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN);
+
+       data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED |
+                                  V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ);
+
+       if (overrun) {
+               /* If there was a FIFO overrun, stop the device */
+               v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+               params.enable = false;
+               /* Mitigate race with cx23885_input_ir_stop() */
+               params.shutdown = atomic_read(&dev->ir_input_stopping);
+               v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+       }
+
+       if (data_available)
+               cx23885_input_process_measurements(dev, overrun);
+
+       if (overrun) {
+               /* If there was a FIFO overrun, clear & restart the device */
+               params.enable = true;
+               /* Mitigate race with cx23885_input_ir_stop() */
+               params.shutdown = atomic_read(&dev->ir_input_stopping);
+               v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+       }
+}
+
+static int cx23885_input_ir_start(struct cx23885_dev *dev)
+{
+       struct v4l2_subdev_ir_parameters params;
+
+       if (dev->sd_ir == NULL)
+               return -ENODEV;
+
+       atomic_set(&dev->ir_input_stopping, 0);
+
+       v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               /*
+                * The IR controller on this board only returns pulse widths.
+                * Any other mode setting will fail to set up the device.
+               */
+               params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+               params.enable = true;
+               params.interrupt_enable = true;
+               params.shutdown = false;
+
+               /* Setup for baseband compatible with both RC-5 and RC-6A */
+               params.modulation = false;
+               /* RC-5:  2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/
+               /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/
+               params.max_pulse_width = 3333333; /* ns */
+               /* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
+               /* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
+               params.noise_filter_min_width = 333333; /* ns */
+               /*
+                * This board has inverted receive sense:
+                * mark is received as low logic level;
+                * falling edges are detected as rising edges; etc.
+                */
+               params.invert_level = true;
+               break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+       case CX23885_BOARD_TEVII_S470:
+               /*
+                * The IR controller on this board only returns pulse widths.
+                * Any other mode setting will fail to set up the device.
+                */
+               params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+               params.enable = true;
+               params.interrupt_enable = true;
+               params.shutdown = false;
+
+               /* Setup for a standard NEC protocol */
+               params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
+               params.carrier_range_lower = 33000; /* Hz */
+               params.carrier_range_upper = 43000; /* Hz */
+               params.duty_cycle = 33; /* percent, 33 percent for NEC */
+
+               /*
+                * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
+                * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
+                */
+               params.max_pulse_width = 12378022; /* ns */
+
+               /*
+                * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
+                * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
+                */
+               params.noise_filter_min_width = 351648; /* ns */
+
+               params.modulation = false;
+               params.invert_level = true;
+               break;
+       }
+       v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+       return 0;
+}
+
+static int cx23885_input_ir_open(struct rc_dev *rc)
+{
+       struct cx23885_kernel_ir *kernel_ir = rc->priv;
+
+       if (kernel_ir->cx == NULL)
+               return -ENODEV;
+
+       return cx23885_input_ir_start(kernel_ir->cx);
+}
+
+static void cx23885_input_ir_stop(struct cx23885_dev *dev)
+{
+       struct v4l2_subdev_ir_parameters params;
+
+       if (dev->sd_ir == NULL)
+               return;
+
+       /*
+        * Stop the sd_ir subdevice from generating notifications and
+        * scheduling work.
+        * It is shutdown this way in order to mitigate a race with
+        * cx23885_input_rx_work_handler() in the overrun case, which could
+        * re-enable the subdevice.
+        */
+       atomic_set(&dev->ir_input_stopping, 1);
+       v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+       while (params.shutdown == false) {
+               params.enable = false;
+               params.interrupt_enable = false;
+               params.shutdown = true;
+               v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+               v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+       }
+       flush_work_sync(&dev->cx25840_work);
+       flush_work_sync(&dev->ir_rx_work);
+       flush_work_sync(&dev->ir_tx_work);
+}
+
+static void cx23885_input_ir_close(struct rc_dev *rc)
+{
+       struct cx23885_kernel_ir *kernel_ir = rc->priv;
+
+       if (kernel_ir->cx != NULL)
+               cx23885_input_ir_stop(kernel_ir->cx);
+}
+
+int cx23885_input_init(struct cx23885_dev *dev)
+{
+       struct cx23885_kernel_ir *kernel_ir;
+       struct rc_dev *rc;
+       char *rc_map;
+       enum rc_driver_type driver_type;
+       unsigned long allowed_protos;
+
+       int ret;
+
+       /*
+        * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't
+        * encapsulated in a v4l2_subdev, then I'm not going to deal with it.
+        */
+       if (dev->sd_ir == NULL)
+               return -ENODEV;
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1270:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+       case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_HAUPPAUGE_HVR1250:
+               /* Integrated CX2388[58] IR controller */
+               driver_type = RC_DRIVER_IR_RAW;
+               allowed_protos = RC_TYPE_ALL;
+               /* The grey Hauppauge RC-5 remote */
+               rc_map = RC_MAP_HAUPPAUGE;
+               break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+               /* Integrated CX23885 IR controller */
+               driver_type = RC_DRIVER_IR_RAW;
+               allowed_protos = RC_TYPE_NEC;
+               /* The grey Terratec remote with orange buttons */
+               rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
+               break;
+       case CX23885_BOARD_TEVII_S470:
+               /* Integrated CX23885 IR controller */
+               driver_type = RC_DRIVER_IR_RAW;
+               allowed_protos = RC_TYPE_ALL;
+               /* A guess at the remote */
+               rc_map = RC_MAP_TEVII_NEC;
+               break;
+       default:
+               return -ENODEV;
+       }
+
+       /* cx23885 board instance kernel IR state */
+       kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
+       if (kernel_ir == NULL)
+               return -ENOMEM;
+
+       kernel_ir->cx = dev;
+       kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
+                                   cx23885_boards[dev->board].name);
+       kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
+                                   pci_name(dev->pci));
+
+       /* input device */
+       rc = rc_allocate_device();
+       if (!rc) {
+               ret = -ENOMEM;
+               goto err_out_free;
+       }
+
+       kernel_ir->rc = rc;
+       rc->input_name = kernel_ir->name;
+       rc->input_phys = kernel_ir->phys;
+       rc->input_id.bustype = BUS_PCI;
+       rc->input_id.version = 1;
+       if (dev->pci->subsystem_vendor) {
+               rc->input_id.vendor  = dev->pci->subsystem_vendor;
+               rc->input_id.product = dev->pci->subsystem_device;
+       } else {
+               rc->input_id.vendor  = dev->pci->vendor;
+               rc->input_id.product = dev->pci->device;
+       }
+       rc->dev.parent = &dev->pci->dev;
+       rc->driver_type = driver_type;
+       rc->allowed_protos = allowed_protos;
+       rc->priv = kernel_ir;
+       rc->open = cx23885_input_ir_open;
+       rc->close = cx23885_input_ir_close;
+       rc->map_name = rc_map;
+       rc->driver_name = MODULE_NAME;
+
+       /* Go */
+       dev->kernel_ir = kernel_ir;
+       ret = rc_register_device(rc);
+       if (ret)
+               goto err_out_stop;
+
+       return 0;
+
+err_out_stop:
+       cx23885_input_ir_stop(dev);
+       dev->kernel_ir = NULL;
+       rc_free_device(rc);
+err_out_free:
+       kfree(kernel_ir->phys);
+       kfree(kernel_ir->name);
+       kfree(kernel_ir);
+       return ret;
+}
+
+void cx23885_input_fini(struct cx23885_dev *dev)
+{
+       /* Always stop the IR hardware from generating interrupts */
+       cx23885_input_ir_stop(dev);
+
+       if (dev->kernel_ir == NULL)
+               return;
+       rc_unregister_device(dev->kernel_ir->rc);
+       kfree(dev->kernel_ir->phys);
+       kfree(dev->kernel_ir->name);
+       kfree(dev->kernel_ir);
+       dev->kernel_ir = NULL;
+}
diff --git a/drivers/media/pci/cx23885/cx23885-input.h b/drivers/media/pci/cx23885/cx23885-input.h
new file mode 100644 (file)
index 0000000..75ef15d
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared remote control input device
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX23885_INPUT_H_
+#define _CX23885_INPUT_H_
+int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
+
+int cx23885_input_init(struct cx23885_dev *dev);
+void cx23885_input_fini(struct cx23885_dev *dev);
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c
new file mode 100644 (file)
index 0000000..44812ca
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Various common ioctl() support functions
+ *
+ *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.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 "cx23885.h"
+#include <media/v4l2-chip-ident.h>
+
+int cx23885_g_chip_ident(struct file *file, void *fh,
+                        struct v4l2_dbg_chip_ident *chip)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+       int err = 0;
+       u8 rev;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               switch (chip->match.addr) {
+               case 0:
+                       rev = cx_read(RDR_CFG2) & 0xff;
+                       switch (dev->pci->device) {
+                       case 0x8852:
+                               /* rev 0x04 could be '885 or '888. Pick '888. */
+                               if (rev == 0x04)
+                                       chip->ident = V4L2_IDENT_CX23888;
+                               else
+                                       chip->ident = V4L2_IDENT_CX23885;
+                               break;
+                       case 0x8880:
+                               if (rev == 0x0e || rev == 0x0f)
+                                       chip->ident = V4L2_IDENT_CX23887;
+                               else
+                                       chip->ident = V4L2_IDENT_CX23888;
+                               break;
+                       default:
+                               chip->ident = V4L2_IDENT_UNKNOWN;
+                               break;
+                       }
+                       chip->revision = (dev->pci->device << 16) | (rev << 8) |
+                                        (dev->hwrevision & 0xff);
+                       break;
+               case 1:
+                       if (dev->v4l_device != NULL) {
+                               chip->ident = V4L2_IDENT_CX23417;
+                               chip->revision = 0;
+                       }
+                       break;
+               case 2:
+                       /*
+                        * The integrated IR controller on the CX23888 is
+                        * host chip 2.  It may not be used/initialized or sd_ir
+                        * may be pointing at the cx25840 subdevice for the
+                        * IR controller on the CX23885.  Thus we find it
+                        * without using the dev->sd_ir pointer.
+                        */
+                       call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident,
+                               chip);
+                       break;
+               default:
+                       err = -EINVAL; /* per V4L2 spec */
+                       break;
+               }
+               break;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
+               call_all(dev, core, g_chip_ident, chip);
+               break;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /*
+                * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
+                * to look if a chip is at the address with no driver.  That's a
+                * dangerous thing to do with EEPROMs anyway.
+                */
+               call_all(dev, core, g_chip_ident, chip);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       return err;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx23885_g_host_register(struct cx23885_dev *dev,
+                                  struct v4l2_dbg_register *reg)
+{
+       if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
+               return -EINVAL;
+
+       reg->size = 4;
+       reg->val = cx_read(reg->reg);
+       return 0;
+}
+
+static int cx23417_g_register(struct cx23885_dev *dev,
+                             struct v4l2_dbg_register *reg)
+{
+       u32 value;
+
+       if (dev->v4l_device == NULL)
+               return -EINVAL;
+
+       if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
+               return -EINVAL;
+
+       if (mc417_register_read(dev, (u16) reg->reg, &value))
+               return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
+
+       reg->size = 4;
+       reg->val = value;
+       return 0;
+}
+
+int cx23885_g_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
+               switch (reg->match.addr) {
+               case 0:
+                       return cx23885_g_host_register(dev, reg);
+               case 1:
+                       return cx23417_g_register(dev, reg);
+               default:
+                       break;
+               }
+       }
+
+       /* FIXME - any error returns should not be ignored */
+       call_all(dev, core, g_register, reg);
+       return 0;
+}
+
+static int cx23885_s_host_register(struct cx23885_dev *dev,
+                                  struct v4l2_dbg_register *reg)
+{
+       if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
+               return -EINVAL;
+
+       reg->size = 4;
+       cx_write(reg->reg, reg->val);
+       return 0;
+}
+
+static int cx23417_s_register(struct cx23885_dev *dev,
+                             struct v4l2_dbg_register *reg)
+{
+       if (dev->v4l_device == NULL)
+               return -EINVAL;
+
+       if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
+               return -EINVAL;
+
+       if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
+               return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
+
+       reg->size = 4;
+       return 0;
+}
+
+int cx23885_s_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
+               switch (reg->match.addr) {
+               case 0:
+                       return cx23885_s_host_register(dev, reg);
+               case 1:
+                       return cx23417_s_register(dev, reg);
+               default:
+                       break;
+               }
+       }
+
+       /* FIXME - any error returns should not be ignored */
+       call_all(dev, core, s_register, reg);
+       return 0;
+}
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.h b/drivers/media/pci/cx23885/cx23885-ioctl.h
new file mode 100644 (file)
index 0000000..315be0c
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Various common ioctl() support functions
+ *
+ *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.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.
+ */
+
+#ifndef _CX23885_IOCTL_H_
+#define _CX23885_IOCTL_H_
+
+int cx23885_g_chip_ident(struct file *file, void *fh,
+                        struct v4l2_dbg_chip_ident *chip);
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx23885_g_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg);
+
+
+int cx23885_s_register(struct file *file, void *fh,
+                      struct v4l2_dbg_register *reg);
+
+#endif
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-ir.c b/drivers/media/pci/cx23885/cx23885-ir.c
new file mode 100644 (file)
index 0000000..7125247
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include <media/v4l2-device.h>
+
+#include "cx23885.h"
+#include "cx23885-input.h"
+
+#define CX23885_IR_RX_FIFO_SERVICE_REQ         0
+#define CX23885_IR_RX_END_OF_RX_DETECTED       1
+#define CX23885_IR_RX_HW_FIFO_OVERRUN          2
+#define CX23885_IR_RX_SW_FIFO_OVERRUN          3
+
+#define CX23885_IR_TX_FIFO_SERVICE_REQ         0
+
+
+void cx23885_ir_rx_work_handler(struct work_struct *work)
+{
+       struct cx23885_dev *dev =
+                            container_of(work, struct cx23885_dev, ir_rx_work);
+       u32 events = 0;
+       unsigned long *notifications = &dev->ir_rx_notifications;
+
+       if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
+               events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
+       if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
+               events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
+       if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
+               events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
+       if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
+               events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
+
+       if (events == 0)
+               return;
+
+       if (dev->kernel_ir)
+               cx23885_input_rx_work_handler(dev, events);
+}
+
+void cx23885_ir_tx_work_handler(struct work_struct *work)
+{
+       struct cx23885_dev *dev =
+                            container_of(work, struct cx23885_dev, ir_tx_work);
+       u32 events = 0;
+       unsigned long *notifications = &dev->ir_tx_notifications;
+
+       if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
+               events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
+
+       if (events == 0)
+               return;
+
+}
+
+/* Possibly called in an IRQ context */
+void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
+{
+       struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
+       unsigned long *notifications = &dev->ir_rx_notifications;
+
+       if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
+               set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
+       if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
+               set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
+       if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
+               set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
+       if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
+               set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
+
+       /*
+        * For the integrated AV core, we are already in a workqueue context.
+        * For the CX23888 integrated IR, we are in an interrupt context.
+        */
+       if (sd == dev->sd_cx25840)
+               cx23885_ir_rx_work_handler(&dev->ir_rx_work);
+       else
+               schedule_work(&dev->ir_rx_work);
+}
+
+/* Possibly called in an IRQ context */
+void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
+{
+       struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
+       unsigned long *notifications = &dev->ir_tx_notifications;
+
+       if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
+               set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
+
+       /*
+        * For the integrated AV core, we are already in a workqueue context.
+        * For the CX23888 integrated IR, we are in an interrupt context.
+        */
+       if (sd == dev->sd_cx25840)
+               cx23885_ir_tx_work_handler(&dev->ir_tx_work);
+       else
+               schedule_work(&dev->ir_tx_work);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-ir.h b/drivers/media/pci/cx23885/cx23885-ir.h
new file mode 100644 (file)
index 0000000..0c9d8bd
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX23885_IR_H_
+#define _CX23885_IR_H_
+void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
+void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
+
+void cx23885_ir_rx_work_handler(struct work_struct *work);
+void cx23885_ir_tx_work_handler(struct work_struct *work);
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-reg.h b/drivers/media/pci/cx23885/cx23885-reg.h
new file mode 100644 (file)
index 0000000..a99936e
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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 _CX23885_REG_H_
+#define _CX23885_REG_H_
+
+/*
+Address Map
+0x00000000 -> 0x00009000   TX SRAM  (Fifos)
+0x00010000 -> 0x00013c00   RX SRAM  CMDS + CDT
+
+EACH CMDS struct is 0x80 bytes long
+
+DMAx_PTR1 = 0x03040 address of first cluster
+DMAx_PTR2 = 0x10600 address of the CDT
+DMAx_CNT1 = cluster size in (bytes >> 4) -1
+DMAx_CNT2 = total cdt size for all entries >> 3
+
+Cluster Descriptor entry = 4 DWORDS
+ DWORD 0 -> ptr to cluster
+ DWORD 1 Reserved
+ DWORD 2 Reserved
+ DWORD 3 Reserved
+
+Channel manager Data Structure entry = 20 DWORD
+  0  IntialProgramCounterLow
+  1  IntialProgramCounterHigh
+  2  ClusterDescriptorTableBase
+  3  ClusterDescriptorTableSize
+  4  InstructionQueueBase
+  5  InstructionQueueSize
+...  Reserved
+ 19  Reserved
+*/
+
+/* Risc Instructions */
+#define RISC_CNT_INC            0x00010000
+#define RISC_CNT_RESET          0x00030000
+#define RISC_IRQ1               0x01000000
+#define RISC_IRQ2               0x02000000
+#define RISC_EOL                0x04000000
+#define RISC_SOL                0x08000000
+#define RISC_WRITE              0x10000000
+#define RISC_SKIP               0x20000000
+#define RISC_JUMP               0x70000000
+#define RISC_SYNC               0x80000000
+#define RISC_RESYNC             0x80008000
+#define RISC_READ               0x90000000
+#define RISC_WRITERM            0xB0000000
+#define RISC_WRITECM            0xC0000000
+#define RISC_WRITECR            0xD0000000
+#define RISC_WRITEC             0x50000000
+#define RISC_READC              0xA0000000
+
+
+/* Audio and Video Core */
+#define HOST_REG1              0x00000000
+#define HOST_REG2              0x00000001
+#define HOST_REG3              0x00000002
+
+/* Chip Configuration Registers */
+#define CHIP_CTRL              0x00000100
+#define AFE_CTRL               0x00000104
+#define VID_PLL_INT_POST       0x00000108
+#define VID_PLL_FRAC           0x0000010C
+#define AUX_PLL_INT_POST       0x00000110
+#define AUX_PLL_FRAC           0x00000114
+#define SYS_PLL_INT_POST       0x00000118
+#define SYS_PLL_FRAC           0x0000011C
+#define PIN_CTRL               0x00000120
+#define AUD_IO_CTRL            0x00000124
+#define AUD_LOCK1              0x00000128
+#define AUD_LOCK2              0x0000012C
+#define POWER_CTRL             0x00000130
+#define AFE_DIAG_CTRL1         0x00000134
+#define AFE_DIAG_CTRL3         0x0000013C
+#define PLL_DIAG_CTRL          0x00000140
+#define AFE_CLK_OUT_CTRL       0x00000144
+#define DLL1_DIAG_CTRL         0x0000015C
+
+/* GPIO[23:19] Output Enable */
+#define GPIO2_OUT_EN_REG       0x00000160
+/* GPIO[23:19] Data Registers */
+#define GPIO2                  0x00000164
+
+#define IFADC_CTRL             0x00000180
+
+/* Infrared Remote Registers */
+#define IR_CNTRL_REG   0x00000200
+#define IR_TXCLK_REG   0x00000204
+#define IR_RXCLK_REG   0x00000208
+#define IR_CDUTY_REG   0x0000020C
+#define IR_STAT_REG    0x00000210
+#define IR_IRQEN_REG   0x00000214
+#define IR_FILTR_REG   0x00000218
+#define IR_FIFO_REG    0x0000023C
+
+/* Video Decoder Registers */
+#define MODE_CTRL              0x00000400
+#define OUT_CTRL1              0x00000404
+#define OUT_CTRL2              0x00000408
+#define GEN_STAT               0x0000040C
+#define INT_STAT_MASK          0x00000410
+#define LUMA_CTRL              0x00000414
+#define HSCALE_CTRL            0x00000418
+#define VSCALE_CTRL            0x0000041C
+#define CHROMA_CTRL            0x00000420
+#define VBI_LINE_CTRL1         0x00000424
+#define VBI_LINE_CTRL2         0x00000428
+#define VBI_LINE_CTRL3         0x0000042C
+#define VBI_LINE_CTRL4         0x00000430
+#define VBI_LINE_CTRL5         0x00000434
+#define VBI_FC_CFG             0x00000438
+#define VBI_MISC_CFG1          0x0000043C
+#define VBI_MISC_CFG2          0x00000440
+#define VBI_PAY1               0x00000444
+#define VBI_PAY2               0x00000448
+#define VBI_CUST1_CFG1         0x0000044C
+#define VBI_CUST1_CFG2         0x00000450
+#define VBI_CUST1_CFG3         0x00000454
+#define VBI_CUST2_CFG1         0x00000458
+#define VBI_CUST2_CFG2         0x0000045C
+#define VBI_CUST2_CFG3         0x00000460
+#define VBI_CUST3_CFG1         0x00000464
+#define VBI_CUST3_CFG2         0x00000468
+#define VBI_CUST3_CFG3         0x0000046C
+#define HORIZ_TIM_CTRL         0x00000470
+#define VERT_TIM_CTRL          0x00000474
+#define SRC_COMB_CFG           0x00000478
+#define CHROMA_VBIOFF_CFG      0x0000047C
+#define FIELD_COUNT            0x00000480
+#define MISC_TIM_CTRL          0x00000484
+#define DFE_CTRL1              0x00000488
+#define DFE_CTRL2              0x0000048C
+#define DFE_CTRL3              0x00000490
+#define PLL_CTRL               0x00000494
+#define HTL_CTRL               0x00000498
+#define COMB_CTRL              0x0000049C
+#define CRUSH_CTRL             0x000004A0
+#define SOFT_RST_CTRL          0x000004A4
+#define CX885_VERSION          0x000004B4
+#define VBI_PASS_CTRL          0x000004BC
+
+/* Audio Decoder Registers */
+/* 8051 Configuration */
+#define DL_CTL         0x00000800
+#define STD_DET_STATUS 0x00000804
+#define STD_DET_CTL    0x00000808
+#define DW8051_INT     0x0000080C
+#define GENERAL_CTL    0x00000810
+#define AAGC_CTL       0x00000814
+#define DEMATRIX_CTL   0x000008CC
+#define PATH1_CTL1     0x000008D0
+#define PATH1_VOL_CTL  0x000008D4
+#define PATH1_EQ_CTL   0x000008D8
+#define PATH1_SC_CTL   0x000008DC
+#define PATH2_CTL1     0x000008E0
+#define PATH2_VOL_CTL  0x000008E4
+#define PATH2_EQ_CTL   0x000008E8
+#define PATH2_SC_CTL   0x000008EC
+
+/* Sample Rate Converter */
+#define SRC_CTL                0x000008F0
+#define SRC_LF_COEF    0x000008F4
+#define SRC1_CTL       0x000008F8
+#define SRC2_CTL       0x000008FC
+#define SRC3_CTL       0x00000900
+#define SRC4_CTL       0x00000904
+#define SRC5_CTL       0x00000908
+#define SRC6_CTL       0x0000090C
+#define BAND_OUT_SEL   0x00000910
+#define I2S_N_CTL      0x00000914
+#define I2S_OUT_CTL    0x00000918
+#define AUTOCONFIG_REG 0x000009C4
+
+/* Audio ADC Registers */
+#define DSM_CTRL1      0x00000000
+#define DSM_CTRL2      0x00000001
+#define CHP_EN_CTRL    0x00000002
+#define CHP_CLK_CTRL1  0x00000004
+#define CHP_CLK_CTRL2  0x00000005
+#define BG_REF_CTRL    0x00000006
+#define SD2_SW_CTRL1   0x00000008
+#define SD2_SW_CTRL2   0x00000009
+#define SD2_BIAS_CTRL  0x0000000A
+#define AMP_BIAS_CTRL  0x0000000C
+#define CH_PWR_CTRL1   0x0000000E
+#define FLD_CH_SEL      (1 << 3)
+#define CH_PWR_CTRL2   0x0000000F
+#define DSM_STATUS1    0x00000010
+#define DSM_STATUS2    0x00000011
+#define DIG_CTL1       0x00000012
+#define DIG_CTL2       0x00000013
+#define I2S_TX_CFG     0x0000001A
+
+#define DEV_CNTRL2     0x00040000
+
+#define PCI_MSK_IR        (1 << 28)
+#define PCI_MSK_AV_CORE   (1 << 27)
+#define PCI_MSK_GPIO1     (1 << 24)
+#define PCI_MSK_GPIO0     (1 << 23)
+#define PCI_MSK_APB_DMA   (1 << 12)
+#define PCI_MSK_AL_WR     (1 << 11)
+#define PCI_MSK_AL_RD     (1 << 10)
+#define PCI_MSK_RISC_WR   (1 <<  9)
+#define PCI_MSK_RISC_RD   (1 <<  8)
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+#define PCI_MSK_VID_C     (1 <<  2)
+#define PCI_MSK_VID_B     (1 <<  1)
+#define PCI_MSK_VID_A      1
+#define PCI_INT_MSK    0x00040010
+
+#define PCI_INT_STAT   0x00040014
+#define PCI_INT_MSTAT  0x00040018
+
+#define VID_A_INT_MSK  0x00040020
+#define VID_A_INT_STAT 0x00040024
+#define VID_A_INT_MSTAT        0x00040028
+#define VID_A_INT_SSTAT        0x0004002C
+
+#define VID_B_INT_MSK  0x00040030
+#define VID_B_MSK_BAD_PKT     (1 << 20)
+#define VID_B_MSK_VBI_OPC_ERR (1 << 17)
+#define VID_B_MSK_OPC_ERR     (1 << 16)
+#define VID_B_MSK_VBI_SYNC    (1 << 13)
+#define VID_B_MSK_SYNC        (1 << 12)
+#define VID_B_MSK_VBI_OF      (1 <<  9)
+#define VID_B_MSK_OF          (1 <<  8)
+#define VID_B_MSK_VBI_RISCI2  (1 <<  5)
+#define VID_B_MSK_RISCI2      (1 <<  4)
+#define VID_B_MSK_VBI_RISCI1  (1 <<  1)
+#define VID_B_MSK_RISCI1       1
+#define VID_B_INT_STAT 0x00040034
+#define VID_B_INT_MSTAT        0x00040038
+#define VID_B_INT_SSTAT        0x0004003C
+
+#define VID_B_MSK_BAD_PKT (1 << 20)
+#define VID_B_MSK_OPC_ERR (1 << 16)
+#define VID_B_MSK_SYNC    (1 << 12)
+#define VID_B_MSK_OF      (1 <<  8)
+#define VID_B_MSK_RISCI2  (1 <<  4)
+#define VID_B_MSK_RISCI1   1
+
+#define VID_C_MSK_BAD_PKT (1 << 20)
+#define VID_C_MSK_OPC_ERR (1 << 16)
+#define VID_C_MSK_SYNC    (1 << 12)
+#define VID_C_MSK_OF      (1 <<  8)
+#define VID_C_MSK_RISCI2  (1 <<  4)
+#define VID_C_MSK_RISCI1   1
+
+/* A superset for testing purposes */
+#define VID_BC_MSK_BAD_PKT (1 << 20)
+#define VID_BC_MSK_OPC_ERR (1 << 16)
+#define VID_BC_MSK_SYNC    (1 << 12)
+#define VID_BC_MSK_OF      (1 <<  8)
+#define VID_BC_MSK_VBI_RISCI2 (1 <<  5)
+#define VID_BC_MSK_RISCI2  (1 <<  4)
+#define VID_BC_MSK_VBI_RISCI1 (1 <<  1)
+#define VID_BC_MSK_RISCI1   1
+
+#define VID_C_INT_MSK  0x00040040
+#define VID_C_INT_STAT 0x00040044
+#define VID_C_INT_MSTAT        0x00040048
+#define VID_C_INT_SSTAT        0x0004004C
+
+#define AUDIO_INT_INT_MSK      0x00040050
+#define AUDIO_INT_INT_STAT     0x00040054
+#define AUDIO_INT_INT_MSTAT    0x00040058
+#define AUDIO_INT_INT_SSTAT    0x0004005C
+
+#define AUDIO_EXT_INT_MSK      0x00040060
+#define AUDIO_EXT_INT_STAT     0x00040064
+#define AUDIO_EXT_INT_MSTAT    0x00040068
+#define AUDIO_EXT_INT_SSTAT    0x0004006C
+
+#define RDR_CFG0       0x00050000
+#define RDR_CFG1       0x00050004
+#define RDR_CFG2       0x00050008
+#define RDR_RDRCTL1    0x0005030c
+#define RDR_TLCTL0     0x00050318
+
+/* APB DMAC Current Buffer Pointer */
+#define DMA1_PTR1      0x00100000
+#define DMA2_PTR1      0x00100004
+#define DMA3_PTR1      0x00100008
+#define DMA4_PTR1      0x0010000C
+#define DMA5_PTR1      0x00100010
+#define DMA6_PTR1      0x00100014
+#define DMA7_PTR1      0x00100018
+#define DMA8_PTR1      0x0010001C
+
+/* APB DMAC Current Table Pointer */
+#define DMA1_PTR2      0x00100040
+#define DMA2_PTR2      0x00100044
+#define DMA3_PTR2      0x00100048
+#define DMA4_PTR2      0x0010004C
+#define DMA5_PTR2      0x00100050
+#define DMA6_PTR2      0x00100054
+#define DMA7_PTR2      0x00100058
+#define DMA8_PTR2      0x0010005C
+
+/* APB DMAC Buffer Limit */
+#define DMA1_CNT1      0x00100080
+#define DMA2_CNT1      0x00100084
+#define DMA3_CNT1      0x00100088
+#define DMA4_CNT1      0x0010008C
+#define DMA5_CNT1      0x00100090
+#define DMA6_CNT1      0x00100094
+#define DMA7_CNT1      0x00100098
+#define DMA8_CNT1      0x0010009C
+
+/* APB DMAC Table Size */
+#define DMA1_CNT2      0x001000C0
+#define DMA2_CNT2      0x001000C4
+#define DMA3_CNT2      0x001000C8
+#define DMA4_CNT2      0x001000CC
+#define DMA5_CNT2      0x001000D0
+#define DMA6_CNT2      0x001000D4
+#define DMA7_CNT2      0x001000D8
+#define DMA8_CNT2      0x001000DC
+
+/* Timer Counters */
+#define TM_CNT_LDW     0x00110000
+#define TM_CNT_UW      0x00110004
+#define TM_LMT_LDW     0x00110008
+#define TM_LMT_UW      0x0011000C
+
+/* GPIO */
+#define GP0_IO         0x00110010
+#define GPIO_ISM       0x00110014
+#define SOFT_RESET     0x0011001C
+
+/* GPIO (417 Microsoftcontroller) RW Data */
+#define MC417_RWD      0x00110020
+
+/* GPIO (417 Microsoftcontroller) Output Enable, Low Active */
+#define MC417_OEN      0x00110024
+#define MC417_CTL      0x00110028
+#define ALT_PIN_OUT_SEL 0x0011002C
+#define CLK_DELAY      0x00110048
+#define PAD_CTRL       0x0011004C
+
+/* Video A Interface */
+#define VID_A_GPCNT            0x00130020
+#define VBI_A_GPCNT            0x00130024
+#define VID_A_GPCNT_CTL                0x00130030
+#define VBI_A_GPCNT_CTL                0x00130034
+#define VID_A_DMA_CTL          0x00130040
+#define VID_A_VIP_CTRL         0x00130080
+#define VID_A_PIXEL_FRMT       0x00130084
+#define VID_A_VBI_CTRL         0x00130088
+
+/* Video B Interface */
+#define VID_B_DMA              0x00130100
+#define VBI_B_DMA              0x00130108
+#define VID_B_GPCNT            0x00130120
+#define VBI_B_GPCNT            0x00130124
+#define VID_B_GPCNT_CTL                0x00130134
+#define VBI_B_GPCNT_CTL                0x00130138
+#define VID_B_DMA_CTL          0x00130140
+#define VID_B_SRC_SEL          0x00130144
+#define VID_B_LNGTH            0x00130150
+#define VID_B_HW_SOP_CTL       0x00130154
+#define VID_B_GEN_CTL          0x00130158
+#define VID_B_BD_PKT_STATUS    0x0013015C
+#define VID_B_SOP_STATUS       0x00130160
+#define VID_B_FIFO_OVFL_STAT   0x00130164
+#define VID_B_VLD_MISC         0x00130168
+#define VID_B_TS_CLK_EN                0x0013016C
+#define VID_B_VIP_CTRL         0x00130180
+#define VID_B_PIXEL_FRMT       0x00130184
+
+/* Video C Interface */
+#define VID_C_GPCNT            0x00130220
+#define VID_C_GPCNT_CTL                0x00130230
+#define VBI_C_GPCNT_CTL                0x00130234
+#define VID_C_DMA_CTL          0x00130240
+#define VID_C_LNGTH            0x00130250
+#define VID_C_HW_SOP_CTL       0x00130254
+#define VID_C_GEN_CTL          0x00130258
+#define VID_C_BD_PKT_STATUS    0x0013025C
+#define VID_C_SOP_STATUS       0x00130260
+#define VID_C_FIFO_OVFL_STAT   0x00130264
+#define VID_C_VLD_MISC         0x00130268
+#define VID_C_TS_CLK_EN                0x0013026C
+
+/* Internal Audio Interface */
+#define AUD_INT_A_GPCNT                0x00140020
+#define AUD_INT_B_GPCNT                0x00140024
+#define AUD_INT_A_GPCNT_CTL    0x00140030
+#define AUD_INT_B_GPCNT_CTL    0x00140034
+#define AUD_INT_DMA_CTL                0x00140040
+#define AUD_INT_A_LNGTH                0x00140050
+#define AUD_INT_B_LNGTH                0x00140054
+#define AUD_INT_A_MODE         0x00140058
+#define AUD_INT_B_MODE         0x0014005C
+
+/* External Audio Interface */
+#define AUD_EXT_DMA            0x00140100
+#define AUD_EXT_GPCNT          0x00140120
+#define AUD_EXT_GPCNT_CTL      0x00140130
+#define AUD_EXT_DMA_CTL                0x00140140
+#define AUD_EXT_LNGTH          0x00140150
+#define AUD_EXT_A_MODE         0x00140158
+
+/* I2C Bus 1 */
+#define I2C1_ADDR      0x00180000
+#define I2C1_WDATA     0x00180004
+#define I2C1_CTRL      0x00180008
+#define I2C1_RDATA     0x0018000C
+#define I2C1_STAT      0x00180010
+
+/* I2C Bus 2 */
+#define I2C2_ADDR      0x00190000
+#define I2C2_WDATA     0x00190004
+#define I2C2_CTRL      0x00190008
+#define I2C2_RDATA     0x0019000C
+#define I2C2_STAT      0x00190010
+
+/* I2C Bus 3 */
+#define I2C3_ADDR      0x001A0000
+#define I2C3_WDATA     0x001A0004
+#define I2C3_CTRL      0x001A0008
+#define I2C3_RDATA     0x001A000C
+#define I2C3_STAT      0x001A0010
+
+/* UART */
+#define UART_CTL       0x001B0000
+#define UART_BRD       0x001B0004
+#define UART_ISR       0x001B000C
+#define UART_CNT       0x001B0010
+
+#endif /* _CX23885_REG_H_ */
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
new file mode 100644 (file)
index 0000000..a1154f0
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2007 Steven Toth <stoth@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>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include "cx23885.h"
+
+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;
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (vbi_debug >= level)\
+               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+       } while (0)
+
+/* ------------------------------------------------------------------ */
+
+#define VBI_LINE_LENGTH 1440
+#define NTSC_VBI_START_LINE 10        /* line 10 - 21 */
+#define NTSC_VBI_END_LINE   21
+#define NTSC_VBI_LINES      (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
+
+
+int cx23885_vbi_fmt(struct file *file, void *priv,
+       struct v4l2_format *f)
+{
+       struct cx23885_fh *fh = priv;
+       struct cx23885_dev *dev = fh->dev;
+
+       if (dev->tvnorm & V4L2_STD_525_60) {
+               /* ntsc */
+               f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+               f->fmt.vbi.sampling_rate = 27000000;
+               f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+               f->fmt.vbi.offset = 0;
+               f->fmt.vbi.flags = 0;
+               f->fmt.vbi.start[0] = 10;
+               f->fmt.vbi.count[0] = 17;
+               f->fmt.vbi.start[1] = 263 + 10 + 1;
+               f->fmt.vbi.count[1] = 17;
+       } else if (dev->tvnorm & V4L2_STD_625_50) {
+               /* pal */
+               f->fmt.vbi.sampling_rate = 35468950;
+               f->fmt.vbi.start[0] = 7 - 1;
+               f->fmt.vbi.start[1] = 319 - 1;
+       }
+
+       return 0;
+}
+
+/* We're given the Video Interrupt status register.
+ * The cx23885_video_irq() func has already validated
+ * the potential error bits, we just need to
+ * deal with vbi payload and return indication if
+ * we actually processed any payload.
+ */
+int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
+{
+       u32 count;
+       int handled = 0;
+
+       if (status & VID_BC_MSK_VBI_RISCI1) {
+               dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
+               spin_lock(&dev->slock);
+               count = cx_read(VID_A_GPCNT);
+               cx23885_video_wakeup(dev, &dev->vbiq, count);
+               spin_unlock(&dev->slock);
+               handled++;
+       }
+
+       if (status & VID_BC_MSK_VBI_RISCI2) {
+               dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
+               dprintk(2, "stopper vbi\n");
+               spin_lock(&dev->slock);
+               cx23885_restart_vbi_queue(dev, &dev->vbiq);
+               spin_unlock(&dev->slock);
+               handled++;
+       }
+
+       return handled;
+}
+
+static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
+                        struct cx23885_dmaqueue *q,
+                        struct cx23885_buffer   *buf)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       /* setup fifo + format */
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
+                               buf->vb.width, buf->risc.dma);
+
+       /* reset counter */
+       cx_write(VID_A_GPCNT_CTL, 3);
+       cx_write(VID_A_VBI_CTRL, 3);
+       cx_write(VBI_A_GPCNT_CTL, 3);
+       q->count = 1;
+
+       /* enable irq */
+       cx23885_irq_add_enable(dev, 0x01);
+       cx_set(VID_A_INT_MSK, 0x000022);
+
+       /* start dma */
+       cx_set(DEV_CNTRL2, (1<<5));
+       cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
+
+       return 0;
+}
+
+
+int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
+                            struct cx23885_dmaqueue *q)
+{
+       struct cx23885_buffer *buf;
+       struct list_head *item;
+
+       if (list_empty(&q->active))
+               return 0;
+
+       buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
+       dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+               buf, buf->vb.i);
+       cx23885_start_vbi_dma(dev, q, buf);
+       list_for_each(item, &q->active) {
+               buf = list_entry(item, struct cx23885_buffer, vb.queue);
+               buf->count = q->count++;
+       }
+       mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
+       return 0;
+}
+
+void cx23885_vbi_timeout(unsigned long data)
+{
+       struct cx23885_dev *dev = (struct cx23885_dev *)data;
+       struct cx23885_dmaqueue *q = &dev->vbiq;
+       struct cx23885_buffer *buf;
+       unsigned long flags;
+
+       /* Stop the VBI engine */
+       cx_clear(VID_A_DMA_CTL, 0x22);
+
+       spin_lock_irqsave(&dev->slock, flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx23885_buffer,
+                       vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->name,
+                      buf, buf->vb.i, (unsigned long)buf->risc.dma);
+       }
+       cx23885_restart_vbi_queue(dev, q);
+       spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+/* ------------------------------------------------------------------ */
+#define VBI_LINE_LENGTH 1440
+#define VBI_LINE_COUNT 17
+
+static int
+vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+       if (0 == *count)
+               *count = vbibufs;
+       if (*count < 2)
+               *count = 2;
+       if (*count > 32)
+               *count = 32;
+       return 0;
+}
+
+static int
+vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+           enum v4l2_field field)
+{
+       struct cx23885_fh *fh  = q->priv_data;
+       struct cx23885_dev *dev = fh->dev;
+       struct cx23885_buffer *buf = container_of(vb,
+               struct cx23885_buffer, vb);
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+       unsigned int size;
+       int rc;
+
+       size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               buf->vb.width  = VBI_LINE_LENGTH;
+               buf->vb.height = VBI_LINE_COUNT;
+               buf->vb.size   = size;
+               buf->vb.field  = V4L2_FIELD_SEQ_TB;
+
+               rc = videobuf_iolock(q, &buf->vb, NULL);
+               if (0 != rc)
+                       goto fail;
+               cx23885_risc_vbibuffer(dev->pci, &buf->risc,
+                                dma->sglist,
+                                0, buf->vb.width * buf->vb.height,
+                                buf->vb.width, 0,
+                                buf->vb.height);
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       cx23885_free_buffer(q, buf);
+       return rc;
+}
+
+static void
+vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx23885_buffer   *buf =
+               container_of(vb, struct cx23885_buffer, vb);
+       struct cx23885_buffer   *prev;
+       struct cx23885_fh       *fh   = vq->priv_data;
+       struct cx23885_dev      *dev  = fh->dev;
+       struct cx23885_dmaqueue *q    = &dev->vbiq;
+
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+       if (list_empty(&q->active)) {
+               list_add_tail(&buf->vb.queue, &q->active);
+               cx23885_start_vbi_dma(dev, q, buf);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = q->count++;
+               mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
+               dprintk(2, "[%p/%d] vbi_queue - first active\n",
+                       buf, buf->vb.i);
+
+       } else {
+               prev = list_entry(q->active.prev, struct cx23885_buffer,
+                       vb.queue);
+               list_add_tail(&buf->vb.queue, &q->active);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = q->count++;
+               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+               prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63-32 */
+               dprintk(2, "[%p/%d] buffer_queue - append to active\n",
+                       buf, buf->vb.i);
+       }
+}
+
+static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx23885_buffer *buf =
+               container_of(vb, struct cx23885_buffer, vb);
+
+       cx23885_free_buffer(q, buf);
+}
+
+struct videobuf_queue_ops cx23885_vbi_qops = {
+       .buf_setup    = vbi_setup,
+       .buf_prepare  = vbi_prepare,
+       .buf_queue    = vbi_queue,
+       .buf_release  = vbi_release,
+};
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
new file mode 100644 (file)
index 0000000..22f8e7f
--- /dev/null
@@ -0,0 +1,1926 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2007 Steven Toth <stoth@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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx23885.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "cx23885-ioctl.h"
+#include "tuner-xc2028.h"
+
+#include <media/cx25840.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int video_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr,   int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+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;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+#define dprintk(level, fmt, arg...)\
+       do { if (video_debug >= level)\
+               printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+       } while (0)
+
+/* ------------------------------------------------------------------- */
+/* static data                                                         */
+
+#define FORMAT_FLAGS_PACKED       0x01
+#if 0
+static struct cx23885_fmt formats[] = {
+       {
+               .name     = "8 bpp, gray",
+               .fourcc   = V4L2_PIX_FMT_GREY,
+               .depth    = 8,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "15 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB555,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "15 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB555X,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "16 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB565,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "16 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB565X,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "24 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR24,
+               .depth    = 24,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "32 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR32,
+               .depth    = 32,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "32 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB32,
+               .depth    = 32,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "4:2:2, packed, YUYV",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+               .name     = "4:2:2, packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },
+};
+#else
+static struct cx23885_fmt formats[] = {
+       {
+#if 0
+               .name     = "4:2:2, packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }, {
+#endif
+               .name     = "4:2:2, packed, YUYV",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       }
+};
+#endif
+
+static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(formats); i++)
+               if (formats[i].fourcc == fourcc)
+                       return formats+i;
+
+       printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
+               (fourcc & 0xff),
+               ((fourcc >> 8) & 0xff),
+               ((fourcc >> 16) & 0xff),
+               ((fourcc >> 24) & 0xff)
+               );
+       return NULL;
+}
+
+/* ------------------------------------------------------------------- */
+
+static const struct v4l2_queryctrl no_ctl = {
+       .name  = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct cx23885_ctrl cx23885_ctls[] = {
+       /* --- video --- */
+       {
+               .v = {
+                       .id            = V4L2_CID_BRIGHTNESS,
+                       .name          = "Brightness",
+                       .minimum       = 0x00,
+                       .maximum       = 0xff,
+                       .step          = 1,
+                       .default_value = 0x7f,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off                   = 128,
+               .reg                   = LUMA_CTRL,
+               .mask                  = 0x00ff,
+               .shift                 = 0,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_CONTRAST,
+                       .name          = "Contrast",
+                       .minimum       = 0,
+                       .maximum       = 0x7f,
+                       .step          = 1,
+                       .default_value = 0x3f,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off                   = 0,
+               .reg                   = LUMA_CTRL,
+               .mask                  = 0xff00,
+               .shift                 = 8,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_HUE,
+                       .name          = "Hue",
+                       .minimum       = -127,
+                       .maximum       = 128,
+                       .step          = 1,
+                       .default_value = 0x0,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off                   = 128,
+               .reg                   = CHROMA_CTRL,
+               .mask                  = 0xff0000,
+               .shift                 = 16,
+       }, {
+               /* strictly, this only describes only U saturation.
+                * V saturation is handled specially through code.
+                */
+               .v = {
+                       .id            = V4L2_CID_SATURATION,
+                       .name          = "Saturation",
+                       .minimum       = 0,
+                       .maximum       = 0x7f,
+                       .step          = 1,
+                       .default_value = 0x3f,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off                   = 0,
+               .reg                   = CHROMA_CTRL,
+               .mask                  = 0x00ff,
+               .shift                 = 0,
+       }, {
+       /* --- audio --- */
+               .v = {
+                       .id            = V4L2_CID_AUDIO_MUTE,
+                       .name          = "Mute",
+                       .minimum       = 0,
+                       .maximum       = 1,
+                       .default_value = 1,
+                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg                   = PATH1_CTL1,
+               .mask                  = (0x1f << 24),
+               .shift                 = 24,
+       }, {
+               .v = {
+                       .id            = V4L2_CID_AUDIO_VOLUME,
+                       .name          = "Volume",
+                       .minimum       = 0,
+                       .maximum       = 65535,
+                       .step          = 65535 / 100,
+                       .default_value = 65535,
+                       .type          = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .reg                   = PATH1_VOL_CTL,
+               .mask                  = 0xff,
+               .shift                 = 0,
+       }
+};
+static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);
+
+/* Must be sorted from low to high control ID! */
+static const u32 cx23885_user_ctrls[] = {
+       V4L2_CID_USER_CLASS,
+       V4L2_CID_BRIGHTNESS,
+       V4L2_CID_CONTRAST,
+       V4L2_CID_SATURATION,
+       V4L2_CID_HUE,
+       V4L2_CID_AUDIO_VOLUME,
+       V4L2_CID_AUDIO_MUTE,
+       0
+};
+
+static const u32 *ctrl_classes[] = {
+       cx23885_user_ctrls,
+       NULL
+};
+
+void cx23885_video_wakeup(struct cx23885_dev *dev,
+       struct cx23885_dmaqueue *q, u32 count)
+{
+       struct cx23885_buffer *buf;
+       int bc;
+
+       for (bc = 0;; bc++) {
+               if (list_empty(&q->active))
+                       break;
+               buf = list_entry(q->active.next,
+                                struct cx23885_buffer, vb.queue);
+
+               /* count comes from the hw and is is 16bit wide --
+                * this trick handles wrap-arounds correctly for
+                * up to 32767 buffers in flight... */
+               if ((s16) (count - buf->count) < 0)
+                       break;
+
+               do_gettimeofday(&buf->vb.ts);
+               dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
+                       count, buf->count);
+               buf->vb.state = VIDEOBUF_DONE;
+               list_del(&buf->vb.queue);
+               wake_up(&buf->vb.done);
+       }
+       if (list_empty(&q->active))
+               del_timer(&q->timeout);
+       else
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+       if (bc != 1)
+               printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
+                       __func__, bc);
+}
+
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+{
+       dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+               __func__,
+               (unsigned int)norm,
+               v4l2_norm_to_name(norm));
+
+       dev->tvnorm = norm;
+
+       call_all(dev, core, s_std, norm);
+
+       return 0;
+}
+
+static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
+                                   struct pci_dev *pci,
+                                   struct video_device *template,
+                                   char *type)
+{
+       struct video_device *vfd;
+       dprintk(1, "%s()\n", __func__);
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+       vfd->release = video_device_release;
+       snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+                cx23885_boards[dev->board].name, type);
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+       int i;
+
+       if (qctrl->id < V4L2_CID_BASE ||
+           qctrl->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       for (i = 0; i < CX23885_CTLS; i++)
+               if (cx23885_ctls[i].v.id == qctrl->id)
+                       break;
+       if (i == CX23885_CTLS) {
+               *qctrl = no_ctl;
+               return 0;
+       }
+       *qctrl = cx23885_ctls[i].v;
+       return 0;
+}
+
+/* ------------------------------------------------------------------- */
+/* resource management                                                 */
+
+static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
+       unsigned int bit)
+{
+       dprintk(1, "%s()\n", __func__);
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       /* is it free? */
+       mutex_lock(&dev->lock);
+       if (dev->resources & bit) {
+               /* no, someone else uses it */
+               mutex_unlock(&dev->lock);
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       dev->resources |= bit;
+       dprintk(1, "res: get %d\n", bit);
+       mutex_unlock(&dev->lock);
+       return 1;
+}
+
+static int res_check(struct cx23885_fh *fh, unsigned int bit)
+{
+       return fh->resources & bit;
+}
+
+static int res_locked(struct cx23885_dev *dev, unsigned int bit)
+{
+       return dev->resources & bit;
+}
+
+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", __func__);
+
+       mutex_lock(&dev->lock);
+       fh->resources  &= ~bits;
+       dev->resources &= ~bits;
+       dprintk(1, "res: put %d\n", bits);
+       mutex_unlock(&dev->lock);
+}
+
+static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+{
+       /* 8 bit registers, 8 bit values */
+       u8 buf[] = { reg, data };
+
+       struct i2c_msg msg = { .addr = 0x98 >> 1,
+               .flags = 0, .buf = buf, .len = 2 };
+
+       return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+{
+       /* 8 bit registers, 8 bit values */
+       int ret;
+       u8 b0[] = { reg };
+       u8 b1[] = { 0 };
+
+       struct i2c_msg msg[] = {
+               { .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
+               { .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+       };
+
+       ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
+       if (ret != 2)
+               printk(KERN_ERR "%s() error\n", __func__);
+
+       return b1[0];
+}
+
+static void cx23885_flatiron_dump(struct cx23885_dev *dev)
+{
+       int i;
+       dprintk(1, "Flatiron dump\n");
+       for (i = 0; i < 0x24; i++) {
+               dprintk(1, "FI[%02x] = %02x\n", i,
+                       cx23885_flatiron_read(dev, i));
+       }
+}
+
+static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
+{
+       u8 val;
+       dprintk(1, "%s(input = %d)\n", __func__, input);
+
+       if (input == 1)
+               val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
+       else if (input == 2)
+               val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
+       else
+               return -EINVAL;
+
+       val |= 0x20; /* Enable clock to delta-sigma and dec filter */
+
+       cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
+
+       /* Wake up */
+       cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
+
+       if (video_debug)
+               cx23885_flatiron_dump(dev);
+
+       return 0;
+}
+
+static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
+{
+       dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+               __func__,
+               input, INPUT(input)->vmux,
+               INPUT(input)->gpio0, INPUT(input)->gpio1,
+               INPUT(input)->gpio2, INPUT(input)->gpio3);
+       dev->input = input;
+
+       if (dev->board == CX23885_BOARD_MYGICA_X8506 ||
+               dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 ||
+               dev->board == CX23885_BOARD_MYGICA_X8507) {
+               /* Select Analog TV */
+               if (INPUT(input)->type == CX23885_VMUX_TELEVISION)
+                       cx23885_gpio_clear(dev, GPIO_0);
+       }
+
+       /* Tell the internal A/V decoder */
+       v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
+                       INPUT(input)->vmux, 0, 0);
+
+       if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
+               (dev->board == CX23885_BOARD_MPX885) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
+               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
+               /* Configure audio routing */
+               v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
+                       INPUT(input)->amux, 0, 0);
+
+               if (INPUT(input)->amux == CX25840_AUDIO7)
+                       cx23885_flatiron_mux(dev, 1);
+               else if (INPUT(input)->amux == CX25840_AUDIO6)
+                       cx23885_flatiron_mux(dev, 2);
+       }
+
+       return 0;
+}
+
+static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
+{
+       dprintk(1, "%s(input=%d)\n", __func__, input);
+
+       /* The baseband video core of the cx23885 has two audio inputs.
+        * LR1 and LR2. In almost every single case so far only HVR1xxx
+        * cards we've only ever supported LR1. Time to support LR2,
+        * which is available via the optional white breakout header on
+        * the board.
+        * We'll use a could of existing enums in the card struct to allow
+        * devs to specify which baseband input they need, or just default
+        * to what we've always used.
+        */
+       if (INPUT(input)->amux == CX25840_AUDIO7)
+               cx23885_flatiron_mux(dev, 1);
+       else if (INPUT(input)->amux == CX25840_AUDIO6)
+               cx23885_flatiron_mux(dev, 2);
+       else {
+               /* Not specifically defined, assume the default. */
+               cx23885_flatiron_mux(dev, 1);
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+static int cx23885_start_video_dma(struct cx23885_dev *dev,
+                          struct cx23885_dmaqueue *q,
+                          struct cx23885_buffer *buf)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       /* Stop the dma/fifo before we tamper with it's risc programs */
+       cx_clear(VID_A_DMA_CTL, 0x11);
+
+       /* setup fifo + format */
+       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
+                               buf->bpl, buf->risc.dma);
+
+       /* reset counter */
+       cx_write(VID_A_GPCNT_CTL, 3);
+       q->count = 1;
+
+       /* enable irq */
+       cx23885_irq_add_enable(dev, 0x01);
+       cx_set(VID_A_INT_MSK, 0x000011);
+
+       /* start dma */
+       cx_set(DEV_CNTRL2, (1<<5));
+       cx_set(VID_A_DMA_CTL, 0x11); /* FIFO and RISC enable */
+
+       return 0;
+}
+
+
+static int cx23885_restart_video_queue(struct cx23885_dev *dev,
+                              struct cx23885_dmaqueue *q)
+{
+       struct cx23885_buffer *buf, *prev;
+       struct list_head *item;
+       dprintk(1, "%s()\n", __func__);
+
+       if (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx23885_buffer,
+                       vb.queue);
+               dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+                       buf, buf->vb.i);
+               cx23885_start_video_dma(dev, q, buf);
+               list_for_each(item, &q->active) {
+                       buf = list_entry(item, struct cx23885_buffer,
+                               vb.queue);
+                       buf->count    = q->count++;
+               }
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+               return 0;
+       }
+
+       prev = NULL;
+       for (;;) {
+               if (list_empty(&q->queued))
+                       return 0;
+               buf = list_entry(q->queued.next, struct cx23885_buffer,
+                       vb.queue);
+               if (NULL == prev) {
+                       list_move_tail(&buf->vb.queue, &q->active);
+                       cx23885_start_video_dma(dev, q, buf);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count    = q->count++;
+                       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+                       dprintk(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_move_tail(&buf->vb.queue, &q->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count    = q->count++;
+                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                       prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+                       dprintk(2, "[%p/%d] restart_queue - move to active\n",
+                               buf, buf->vb.i);
+               } else {
+                       return 0;
+               }
+               prev = buf;
+       }
+}
+
+static int buffer_setup(struct videobuf_queue *q, unsigned int *count,
+       unsigned int *size)
+{
+       struct cx23885_fh *fh = q->priv_data;
+
+       *size = fh->fmt->depth*fh->width*fh->height >> 3;
+       if (0 == *count)
+               *count = 32;
+       if (*size * *count > vid_limit * 1024 * 1024)
+               *count = (vid_limit * 1024 * 1024) / *size;
+       return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+              enum v4l2_field field)
+{
+       struct cx23885_fh *fh  = q->priv_data;
+       struct cx23885_dev *dev = fh->dev;
+       struct cx23885_buffer *buf =
+               container_of(vb, struct cx23885_buffer, vb);
+       int rc, init_buffer = 0;
+       u32 line0_offset, line1_offset;
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+       int field_tff;
+
+       BUG_ON(NULL == fh->fmt);
+       if (fh->width  < 48 || fh->width  > norm_maxw(dev->tvnorm) ||
+           fh->height < 32 || fh->height > norm_maxh(dev->tvnorm))
+               return -EINVAL;
+       buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+       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;
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               init_buffer = 1;
+               rc = videobuf_iolock(q, &buf->vb, NULL);
+               if (0 != rc)
+                       goto fail;
+       }
+
+       if (init_buffer) {
+               buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
+               switch (buf->vb.field) {
+               case V4L2_FIELD_TOP:
+                       cx23885_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist, 0, UNSET,
+                                        buf->bpl, 0, buf->vb.height);
+                       break;
+               case V4L2_FIELD_BOTTOM:
+                       cx23885_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist, UNSET, 0,
+                                        buf->bpl, 0, buf->vb.height);
+                       break;
+               case V4L2_FIELD_INTERLACED:
+                       if (dev->tvnorm & V4L2_STD_NTSC)
+                               /* NTSC or  */
+                               field_tff = 1;
+                       else
+                               field_tff = 0;
+
+                       if (cx23885_boards[dev->board].force_bff)
+                               /* PAL / SECAM OR 888 in NTSC MODE */
+                               field_tff = 0;
+
+                       if (field_tff) {
+                               /* cx25840 transmits NTSC bottom field first */
+                               dprintk(1, "%s() Creating TFF/NTSC risc\n",
+                                       __func__);
+                               line0_offset = buf->bpl;
+                               line1_offset = 0;
+                       } else {
+                               /* All other formats are top field first */
+                               dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n",
+                                       __func__);
+                               line0_offset = 0;
+                               line1_offset = buf->bpl;
+                       }
+                       cx23885_risc_buffer(dev->pci, &buf->risc,
+                                       dma->sglist, line0_offset,
+                                       line1_offset,
+                                       buf->bpl, buf->bpl,
+                                       buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_TB:
+                       cx23885_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist,
+                                        0, buf->bpl * (buf->vb.height >> 1),
+                                        buf->bpl, 0,
+                                        buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_BT:
+                       cx23885_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist,
+                                        buf->bpl * (buf->vb.height >> 1), 0,
+                                        buf->bpl, 0,
+                                        buf->vb.height >> 1);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+       dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+               buf, buf->vb.i,
+               fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
+               (unsigned long)buf->risc.dma);
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       cx23885_free_buffer(q, buf);
+       return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx23885_buffer   *buf = container_of(vb,
+               struct cx23885_buffer, vb);
+       struct cx23885_buffer   *prev;
+       struct cx23885_fh       *fh   = vq->priv_data;
+       struct cx23885_dev      *dev  = fh->dev;
+       struct cx23885_dmaqueue *q    = &dev->vidq;
+
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+       if (!list_empty(&q->queued)) {
+               list_add_tail(&buf->vb.queue, &q->queued);
+               buf->vb.state = VIDEOBUF_QUEUED;
+               dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
+                       buf, buf->vb.i);
+
+       } else if (list_empty(&q->active)) {
+               list_add_tail(&buf->vb.queue, &q->active);
+               cx23885_start_video_dma(dev, q, buf);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = q->count++;
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+               dprintk(2, "[%p/%d] buffer_queue - first active\n",
+                       buf, buf->vb.i);
+
+       } else {
+               prev = list_entry(q->active.prev, struct cx23885_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, &q->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count    = q->count++;
+                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                       /* 64 bit bits 63-32 */
+                       prev->risc.jmp[2] = cpu_to_le32(0);
+                       dprintk(2, "[%p/%d] buffer_queue - append to active\n",
+                               buf, buf->vb.i);
+
+               } else {
+                       list_add_tail(&buf->vb.queue, &q->queued);
+                       buf->vb.state = VIDEOBUF_QUEUED;
+                       dprintk(2, "[%p/%d] buffer_queue - first queued\n",
+                               buf, buf->vb.i);
+               }
+       }
+}
+
+static void buffer_release(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       struct cx23885_buffer *buf = container_of(vb,
+               struct cx23885_buffer, vb);
+
+       cx23885_free_buffer(q, buf);
+}
+
+static struct videobuf_queue_ops cx23885_video_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+
+static struct videobuf_queue *get_queue(struct cx23885_fh *fh)
+{
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &fh->vidq;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               return &fh->vbiq;
+       default:
+               BUG();
+               return NULL;
+       }
+}
+
+static int get_resource(struct cx23885_fh *fh)
+{
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return RESOURCE_VIDEO;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               return RESOURCE_VBI;
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static int video_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx23885_dev *dev = video_drvdata(file);
+       struct cx23885_fh *fh;
+       enum v4l2_buf_type type = 0;
+       int radio = 0;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       dprintk(1, "open dev=%s radio=%d type=%s\n",
+               video_device_node_name(vdev), radio, v4l2_type_names[type]);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       file->private_data = fh;
+       fh->dev      = dev;
+       fh->radio    = radio;
+       fh->type     = type;
+       fh->width    = 320;
+       fh->height   = 240;
+       fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+       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),
+                           fh, NULL);
+
+       videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
+               &dev->pci->dev, &dev->slock,
+               V4L2_BUF_TYPE_VBI_CAPTURE,
+               V4L2_FIELD_SEQ_TB,
+               sizeof(struct cx23885_buffer),
+               fh, NULL);
+
+
+       dprintk(1, "post videobuf_queue_init()\n");
+
+       return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data,
+       size_t count, loff_t *ppos)
+{
+       struct cx23885_fh *fh = file->private_data;
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (res_locked(fh->dev, RESOURCE_VIDEO))
+                       return -EBUSY;
+               return videobuf_read_one(&fh->vidq, data, count, ppos,
+                                        file->f_flags & O_NONBLOCK);
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (!res_get(fh->dev, fh, RESOURCE_VBI))
+                       return -EBUSY;
+               return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
+                                           file->f_flags & O_NONBLOCK);
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static unsigned int video_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_buffer *buf;
+       unsigned int rc = POLLERR;
+
+       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
+               if (!res_get(fh->dev, fh, RESOURCE_VBI))
+                       return POLLERR;
+               return videobuf_poll_stream(file, &fh->vbiq, wait);
+       }
+
+       mutex_lock(&fh->vidq.vb_lock);
+       if (res_check(fh, RESOURCE_VIDEO)) {
+               /* streaming capture */
+               if (list_empty(&fh->vidq.stream))
+                       goto done;
+               buf = list_entry(fh->vidq.stream.next,
+                       struct cx23885_buffer, vb.stream);
+       } else {
+               /* read() capture */
+               buf = (struct cx23885_buffer *)fh->vidq.read_buf;
+               if (NULL == buf)
+                       goto done;
+       }
+       poll_wait(file, &buf->vb.done, wait);
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               rc =  POLLIN|POLLRDNORM;
+       else
+               rc = 0;
+done:
+       mutex_unlock(&fh->vidq.vb_lock);
+       return rc;
+}
+
+static int video_release(struct file *file)
+{
+       struct cx23885_fh *fh = file->private_data;
+       struct cx23885_dev *dev = fh->dev;
+
+       /* turn off overlay */
+       if (res_check(fh, RESOURCE_OVERLAY)) {
+               /* FIXME */
+               res_free(dev, fh, RESOURCE_OVERLAY);
+       }
+
+       /* stop video capture */
+       if (res_check(fh, RESOURCE_VIDEO)) {
+               videobuf_queue_cancel(&fh->vidq);
+               res_free(dev, fh, RESOURCE_VIDEO);
+       }
+       if (fh->vidq.read_buf) {
+               buffer_release(&fh->vidq, fh->vidq.read_buf);
+               kfree(fh->vidq.read_buf);
+       }
+
+       /* stop vbi capture */
+       if (res_check(fh, RESOURCE_VBI)) {
+               if (fh->vbiq.streaming)
+                       videobuf_streamoff(&fh->vbiq);
+               if (fh->vbiq.reading)
+                       videobuf_read_stop(&fh->vbiq);
+               res_free(dev, fh, RESOURCE_VBI);
+       }
+
+       videobuf_mmap_free(&fh->vidq);
+       videobuf_mmap_free(&fh->vbiq);
+
+       file->private_data = NULL;
+       kfree(fh);
+
+       /* We are not putting the tuner to sleep here on exit, because
+        * we want to use the mpeg encoder in another session to capture
+        * tuner video. Closing this will result in no video to the encoder.
+        */
+
+       return 0;
+}
+
+static int video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cx23885_fh *fh = file->private_data;
+
+       return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+int cx23885_get_control(struct cx23885_dev *dev,
+       struct v4l2_control *ctl)
+{
+       dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
+       call_all(dev, core, g_ctrl, ctl);
+       return 0;
+}
+
+int cx23885_set_control(struct cx23885_dev *dev,
+       struct v4l2_control *ctl)
+{
+       dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
+       call_all(dev, core, s_ctrl, ctl);
+
+       return 0;
+}
+
+static void init_controls(struct cx23885_dev *dev)
+{
+       struct v4l2_control ctrl;
+       int i;
+
+       for (i = 0; i < CX23885_CTLS; i++) {
+               ctrl.id = cx23885_ctls[i].v.id;
+               ctrl.value = cx23885_ctls[i].v.default_value;
+
+               cx23885_set_control(dev, &ctrl);
+       }
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO IOCTLS                                                       */
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+       struct v4l2_format *f)
+{
+       struct cx23885_fh *fh   = priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->vidq.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+       struct v4l2_format *f)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       struct cx23885_fmt *fmt;
+       enum v4l2_field   field;
+       unsigned int      maxw, maxh;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       maxw  = norm_maxw(dev->tvnorm);
+       maxh  = norm_maxh(dev->tvnorm);
+
+       if (V4L2_FIELD_ANY == field) {
+               field = (f->fmt.pix.height > maxh/2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+       }
+
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       f->fmt.pix.field = field;
+       v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+                             &f->fmt.pix.height, 32, maxh, 0, 0);
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+       struct v4l2_format *f)
+{
+       struct cx23885_fh *fh = priv;
+       struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int err;
+
+       dprintk(2, "%s()\n", __func__);
+       err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+       if (0 != err)
+               return err;
+       fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+       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", __func__,
+               fh->width, fh->height, fh->vidq.field);
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+       return 0;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+       struct v4l2_capability *cap)
+{
+       struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+
+       strcpy(cap->driver, "cx23885");
+       strlcpy(cap->card, cx23885_boards[dev->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE     |
+               V4L2_CAP_STREAMING     |
+               V4L2_CAP_VBI_CAPTURE;
+       if (UNSET != dev->tuner_type)
+               cap->capabilities |= V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(formats)))
+               return -EINVAL;
+
+       strlcpy(f->description, formats[f->index].name,
+               sizeof(f->description));
+       f->pixelformat = formats[f->index].fourcc;
+
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+       struct v4l2_requestbuffers *p)
+{
+       struct cx23885_fh *fh = priv;
+       return videobuf_reqbufs(get_queue(fh), p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+       struct v4l2_buffer *p)
+{
+       struct cx23885_fh *fh = priv;
+       return videobuf_querybuf(get_queue(fh), p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv,
+       struct v4l2_buffer *p)
+{
+       struct cx23885_fh *fh = priv;
+       return videobuf_qbuf(get_queue(fh), p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv,
+       struct v4l2_buffer *p)
+{
+       struct cx23885_fh *fh = priv;
+       return videobuf_dqbuf(get_queue(fh), p,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+       enum v4l2_buf_type i)
+{
+       struct cx23885_fh *fh = priv;
+       struct cx23885_dev *dev = fh->dev;
+       dprintk(1, "%s()\n", __func__);
+
+       if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+       if (unlikely(i != fh->type))
+               return -EINVAL;
+
+       if (unlikely(!res_get(dev, fh, get_resource(fh))))
+               return -EBUSY;
+
+       /* Don't start VBI streaming unless vida streaming
+        * has already started.
+        */
+       if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
+               ((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
+               return -EINVAL;
+
+       return videobuf_streamon(get_queue(fh));
+}
+
+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", __func__);
+
+       if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+               (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
+
+       res = get_resource(fh);
+       err = videobuf_streamoff(get_queue(fh));
+       if (err < 0)
+               return err;
+       res_free(dev, fh, res);
+       return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       dprintk(1, "%s()\n", __func__);
+
+       call_all(dev, core, g_std, id);
+
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       dprintk(1, "%s()\n", __func__);
+
+       mutex_lock(&dev->lock);
+       cx23885_set_tvnorm(dev, *tvnorms);
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+{
+       static const char *iname[] = {
+               [CX23885_VMUX_COMPOSITE1] = "Composite1",
+               [CX23885_VMUX_COMPOSITE2] = "Composite2",
+               [CX23885_VMUX_COMPOSITE3] = "Composite3",
+               [CX23885_VMUX_COMPOSITE4] = "Composite4",
+               [CX23885_VMUX_SVIDEO]     = "S-Video",
+               [CX23885_VMUX_COMPONENT]  = "Component",
+               [CX23885_VMUX_TELEVISION] = "Television",
+               [CX23885_VMUX_CABLE]      = "Cable TV",
+               [CX23885_VMUX_DVB]        = "DVB",
+               [CX23885_VMUX_DEBUG]      = "for debug only",
+       };
+       unsigned int n;
+       dprintk(1, "%s()\n", __func__);
+
+       n = i->index;
+       if (n >= MAX_CX23885_INPUT)
+               return -EINVAL;
+
+       if (0 == INPUT(n)->type)
+               return -EINVAL;
+
+       i->index = n;
+       i->type  = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(i->name, iname[INPUT(n)->type]);
+       if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) ||
+               (CX23885_VMUX_CABLE == INPUT(n)->type)) {
+               i->type = V4L2_INPUT_TYPE_TUNER;
+               i->std = CX23885_NORMS;
+       }
+
+       /* Two selectable audio inputs for non-tv inputs */
+       if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
+               i->audioset = 0x3;
+
+       if (dev->input == n) {
+               /* enum'd input matches our configured input.
+                * Ask the video decoder to process the call
+                * and give it an oppertunity to update the
+                * status field.
+                */
+               call_all(dev, video, g_input_status, &i->status);
+       }
+
+       return 0;
+}
+
+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", __func__);
+       return cx23885_enum_input(dev, i);
+}
+
+int cx23885_get_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", __func__, *i);
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       return cx23885_get_input(file, priv, i);
+}
+
+int cx23885_set_input(struct file *file, void *priv, unsigned int i)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       dprintk(1, "%s(%d)\n", __func__, i);
+
+       if (i >= MAX_CX23885_INPUT) {
+               dprintk(1, "%s() -EINVAL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (INPUT(i)->type == 0)
+               return -EINVAL;
+
+       mutex_lock(&dev->lock);
+       cx23885_video_mux(dev, i);
+
+       /* By default establish the default audio input for the card also */
+       /* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
+       cx23885_audio_mux(dev, i);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       return cx23885_set_input(file, priv, i);
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+       struct cx23885_fh  *fh  = priv;
+       struct cx23885_dev *dev = fh->dev;
+
+       printk(KERN_INFO
+               "%s/0: ============  START LOG STATUS  ============\n",
+               dev->name);
+       call_all(dev, core, log_status);
+       printk(KERN_INFO
+               "%s/0: =============  END LOG STATUS  =============\n",
+               dev->name);
+       return 0;
+}
+
+static int cx23885_query_audinput(struct file *file, void *priv,
+       struct v4l2_audio *i)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       static const char *iname[] = {
+               [0] = "Baseband L/R 1",
+               [1] = "Baseband L/R 2",
+       };
+       unsigned int n;
+       dprintk(1, "%s()\n", __func__);
+
+       n = i->index;
+       if (n >= 2)
+               return -EINVAL;
+
+       memset(i, 0, sizeof(*i));
+       i->index = n;
+       strcpy(i->name, iname[n]);
+       i->capability  = V4L2_AUDCAP_STEREO;
+       i->mode  = V4L2_AUDMODE_AVL;
+       return 0;
+
+}
+
+static int vidioc_enum_audinput(struct file *file, void *priv,
+                               struct v4l2_audio *i)
+{
+       return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_g_audinput(struct file *file, void *priv,
+       struct v4l2_audio *i)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       i->index = dev->audinput;
+       dprintk(1, "%s(input=%d)\n", __func__, i->index);
+
+       return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_s_audinput(struct file *file, void *priv,
+       struct v4l2_audio *i)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+       if (i->index >= 2)
+               return -EINVAL;
+
+       dprintk(1, "%s(%d)\n", __func__, i->index);
+
+       dev->audinput = i->index;
+
+       /* Skip the audio defaults from the cards struct, caller wants
+        * directly touch the audio mux hardware. */
+       cx23885_flatiron_mux(dev, dev->audinput + 1);
+       return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qctrl)
+{
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (unlikely(qctrl->id == 0))
+               return -EINVAL;
+       return cx23885_ctrl_query(qctrl);
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       return cx23885_get_control(dev, ctl);
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       return cx23885_set_control(dev, ctl);
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+
+       call_all(dev, tuner, g_tuner, t);
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+       /* Update the A/V core */
+       call_all(dev, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx23885_fh *fh = priv;
+       struct cx23885_dev *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+
+       /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->freq;
+
+       call_all(dev, tuner, g_frequency, f);
+
+       return 0;
+}
+
+static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
+{
+       struct v4l2_control ctrl;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+
+       mutex_lock(&dev->lock);
+       dev->freq = f->frequency;
+
+       /* I need to mute audio here */
+       ctrl.id = V4L2_CID_AUDIO_MUTE;
+       ctrl.value = 1;
+       cx23885_set_control(dev, &ctrl);
+
+       call_all(dev, tuner, s_frequency, f);
+
+       /* When changing channels it is required to reset TVAUDIO */
+       msleep(100);
+
+       /* I need to unmute audio here */
+       ctrl.value = 0;
+       cx23885_set_control(dev, &ctrl);
+
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
+       struct v4l2_frequency *f)
+{
+       struct v4l2_control ctrl;
+       struct videobuf_dvb_frontend *vfe;
+       struct dvb_frontend *fe;
+
+       struct analog_parameters params = {
+               .mode      = V4L2_TUNER_ANALOG_TV,
+               .audmode   = V4L2_TUNER_MODE_STEREO,
+               .std       = dev->tvnorm,
+               .frequency = f->frequency
+       };
+
+       mutex_lock(&dev->lock);
+       dev->freq = f->frequency;
+
+       /* I need to mute audio here */
+       ctrl.id = V4L2_CID_AUDIO_MUTE;
+       ctrl.value = 1;
+       cx23885_set_control(dev, &ctrl);
+
+       /* If HVR1850 */
+       dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__,
+               params.frequency, f->tuner, params.std);
+
+       vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
+       if (!vfe) {
+               mutex_unlock(&dev->lock);
+               return -EINVAL;
+       }
+
+       fe = vfe->dvb.frontend;
+
+       if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
+           (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
+           (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111))
+               fe = &dev->ts1.analog_fe;
+
+       if (fe && fe->ops.tuner_ops.set_analog_params) {
+               call_all(dev, core, s_std, dev->tvnorm);
+               fe->ops.tuner_ops.set_analog_params(fe, &params);
+       }
+       else
+               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+
+       /* When changing channels it is required to reset TVAUDIO */
+       msleep(100);
+
+       /* I need to unmute audio here */
+       ctrl.value = 0;
+       cx23885_set_control(dev, &ctrl);
+
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+int cx23885_set_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       struct cx23885_fh *fh = priv;
+       struct cx23885_dev *dev = fh->dev;
+       int ret;
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1255:
+       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+       case CX23885_BOARD_HAUPPAUGE_HVR1850:
+               ret = cx23885_set_freq_via_ops(dev, f);
+               break;
+       default:
+               ret = cx23885_set_freq(dev, f);
+       }
+
+       return ret;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       return cx23885_set_frequency(file, priv, f);
+}
+
+/* ----------------------------------------------------------- */
+
+static void cx23885_vid_timeout(unsigned long data)
+{
+       struct cx23885_dev *dev = (struct cx23885_dev *)data;
+       struct cx23885_dmaqueue *q = &dev->vidq;
+       struct cx23885_buffer *buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->slock, flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next,
+                       struct cx23885_buffer, vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
+                       dev->name, buf, buf->vb.i,
+                       (unsigned long)buf->risc.dma);
+       }
+       cx23885_restart_video_queue(dev, q);
+       spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
+{
+       u32 mask, count;
+       int handled = 0;
+
+       mask   = cx_read(VID_A_INT_MSK);
+       if (0 == (status & mask))
+               return handled;
+
+       cx_write(VID_A_INT_STAT, status);
+
+       /* risc op code error, fifo overflow or line sync detection error */
+       if ((status & VID_BC_MSK_OPC_ERR) ||
+               (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);
+                       printk(KERN_WARNING "%s: video risc op code error\n",
+                               dev->name);
+                       cx23885_sram_channel_dump(dev,
+                               &dev->sram_channels[SRAM_CH01]);
+               }
+
+               if (status & VID_BC_MSK_SYNC)
+                       dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
+                               "video lines miss-match\n",
+                               VID_BC_MSK_SYNC);
+
+               if (status & VID_BC_MSK_OF)
+                       dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
+                               VID_BC_MSK_OF);
+
+       }
+
+       /* Video */
+       if (status & VID_BC_MSK_RISCI1) {
+               spin_lock(&dev->slock);
+               count = cx_read(VID_A_GPCNT);
+               cx23885_video_wakeup(dev, &dev->vidq, count);
+               spin_unlock(&dev->slock);
+               handled++;
+       }
+       if (status & VID_BC_MSK_RISCI2) {
+               dprintk(2, "stopper video\n");
+               spin_lock(&dev->slock);
+               cx23885_restart_video_queue(dev, &dev->vidq);
+               spin_unlock(&dev->slock);
+               handled++;
+       }
+
+       /* Allow the VBI framework to process it's payload */
+       handled += cx23885_vbi_irq(dev, status);
+
+       return handled;
+}
+
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+static const struct v4l2_file_operations video_fops = {
+       .owner         = THIS_MODULE,
+       .open          = video_open,
+       .release       = video_release,
+       .read          = video_read,
+       .poll          = video_poll,
+       .mmap          = video_mmap,
+       .ioctl         = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap     = cx23885_vbi_fmt,
+       .vidioc_try_fmt_vbi_cap   = cx23885_vbi_fmt,
+       .vidioc_s_fmt_vbi_cap     = cx23885_vbi_fmt,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_querystd      = vidioc_g_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_log_status    = vidioc_log_status,
+       .vidioc_queryctrl     = vidioc_queryctrl,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_g_chip_ident  = cx23885_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = cx23885_g_register,
+       .vidioc_s_register    = cx23885_s_register,
+#endif
+       .vidioc_enumaudio     = vidioc_enum_audinput,
+       .vidioc_g_audio       = vidioc_g_audinput,
+       .vidioc_s_audio       = vidioc_s_audinput,
+};
+
+static struct video_device cx23885_vbi_template;
+static struct video_device cx23885_video_template = {
+       .name                 = "cx23885-video",
+       .fops                 = &video_fops,
+       .ioctl_ops            = &video_ioctl_ops,
+       .tvnorms              = CX23885_NORMS,
+       .current_norm         = V4L2_STD_NTSC_M,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+       .owner         = THIS_MODULE,
+       .open          = video_open,
+       .release       = video_release,
+       .ioctl         = video_ioctl2,
+};
+
+
+void cx23885_video_unregister(struct cx23885_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+       cx23885_irq_remove(dev, 0x01);
+
+       if (dev->vbi_dev) {
+               if (video_is_registered(dev->vbi_dev))
+                       video_unregister_device(dev->vbi_dev);
+               else
+                       video_device_release(dev->vbi_dev);
+               dev->vbi_dev = NULL;
+               btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
+       }
+       if (dev->video_dev) {
+               if (video_is_registered(dev->video_dev))
+                       video_unregister_device(dev->video_dev);
+               else
+                       video_device_release(dev->video_dev);
+               dev->video_dev = NULL;
+
+               btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
+       }
+
+       if (dev->audio_dev)
+               cx23885_audio_unregister(dev);
+}
+
+int cx23885_video_register(struct cx23885_dev *dev)
+{
+       int err;
+
+       dprintk(1, "%s()\n", __func__);
+       spin_lock_init(&dev->slock);
+
+       /* Initialize VBI template */
+       memcpy(&cx23885_vbi_template, &cx23885_video_template,
+               sizeof(cx23885_vbi_template));
+       strcpy(cx23885_vbi_template.name, "cx23885-vbi");
+
+       dev->tvnorm = cx23885_video_template.current_norm;
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vidq.queued);
+       dev->vidq.timeout.function = cx23885_vid_timeout;
+       dev->vidq.timeout.data = (unsigned long)dev;
+       init_timer(&dev->vidq.timeout);
+       cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
+               VID_A_DMA_CTL, 0x11, 0x00);
+
+       /* init vbi dma queues */
+       INIT_LIST_HEAD(&dev->vbiq.active);
+       INIT_LIST_HEAD(&dev->vbiq.queued);
+       dev->vbiq.timeout.function = cx23885_vbi_timeout;
+       dev->vbiq.timeout.data = (unsigned long)dev;
+       init_timer(&dev->vbiq.timeout);
+       cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
+               VID_A_DMA_CTL, 0x22, 0x00);
+
+       cx23885_irq_add_enable(dev, 0x01);
+
+       if ((TUNER_ABSENT != dev->tuner_type) &&
+                       ((dev->tuner_bus == 0) || (dev->tuner_bus == 1))) {
+               struct v4l2_subdev *sd = NULL;
+
+               if (dev->tuner_addr)
+                       sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_bus[dev->tuner_bus].i2c_adap,
+                               "tuner", dev->tuner_addr, NULL);
+               else
+                       sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_bus[dev->tuner_bus].i2c_adap,
+                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV));
+               if (sd) {
+                       struct tuner_setup tun_setup;
+
+                       memset(&tun_setup, 0, sizeof(tun_setup));
+                       tun_setup.mode_mask = T_ANALOG_TV;
+                       tun_setup.type = dev->tuner_type;
+                       tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+                       tun_setup.tuner_callback = cx23885_tuner_callback;
+
+                       v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
+
+                       if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) {
+                               struct xc2028_ctrl ctrl = {
+                                       .fname = XC2028_DEFAULT_FIRMWARE,
+                                       .max_len = 64
+                               };
+                               struct v4l2_priv_tun_config cfg = {
+                                       .tuner = dev->tuner_type,
+                                       .priv = &ctrl
+                               };
+                               v4l2_subdev_call(sd, tuner, s_config, &cfg);
+                       }
+               }
+       }
+
+       /* register Video device */
+       dev->video_dev = cx23885_vdev_init(dev, dev->pci,
+               &cx23885_video_template, "video");
+       err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
+                                   video_nr[dev->nr]);
+       if (err < 0) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                       dev->name);
+               goto fail_unreg;
+       }
+       printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+              dev->name, video_device_node_name(dev->video_dev));
+
+       /* register VBI device */
+       dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
+               &cx23885_vbi_template, "vbi");
+       err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+                                   vbi_nr[dev->nr]);
+       if (err < 0) {
+               printk(KERN_INFO "%s: can't register vbi device\n",
+                       dev->name);
+               goto fail_unreg;
+       }
+       printk(KERN_INFO "%s: registered device %s\n",
+              dev->name, video_device_node_name(dev->vbi_dev));
+
+       /* Register ALSA audio device */
+       dev->audio_dev = cx23885_audio_register(dev);
+
+       /* initial device configuration */
+       mutex_lock(&dev->lock);
+       cx23885_set_tvnorm(dev, dev->tvnorm);
+       init_controls(dev);
+       cx23885_video_mux(dev, 0);
+       cx23885_audio_mux(dev, 0);
+       mutex_unlock(&dev->lock);
+
+       return 0;
+
+fail_unreg:
+       cx23885_video_unregister(dev);
+       return err;
+}
+
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
new file mode 100644 (file)
index 0000000..5d560c7
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/pci.h>
+#include <linux/i2c.h>
+#include <linux/kdev_t.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+#include <media/rc-core.h>
+
+#include "btcx-risc.h"
+#include "cx23885-reg.h"
+#include "media/cx2341x.h"
+
+#include <linux/mutex.h>
+
+#define CX23885_VERSION "0.0.3"
+
+#define UNSET (-1U)
+
+#define CX23885_MAXBOARDS 8
+
+/* Max number of inputs by card */
+#define MAX_CX23885_INPUT 8
+#define INPUT(nr) (&cx23885_boards[dev->board].input[nr])
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO         2
+#define RESOURCE_VBI           4
+
+#define BUFFER_TIMEOUT     (HZ)  /* 0.5 seconds */
+
+#define CX23885_BOARD_NOAUTO               UNSET
+#define CX23885_BOARD_UNKNOWN                  0
+#define CX23885_BOARD_HAUPPAUGE_HVR1800lp      1
+#define CX23885_BOARD_HAUPPAUGE_HVR1800        2
+#define CX23885_BOARD_HAUPPAUGE_HVR1250        3
+#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
+#define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10
+#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12
+#define CX23885_BOARD_COMPRO_VIDEOMATE_E650F   13
+#define CX23885_BOARD_TBS_6920                 14
+#define CX23885_BOARD_TEVII_S470               15
+#define CX23885_BOARD_DVBWORLD_2005            16
+#define CX23885_BOARD_NETUP_DUAL_DVBS2_CI      17
+#define CX23885_BOARD_HAUPPAUGE_HVR1270        18
+#define CX23885_BOARD_HAUPPAUGE_HVR1275        19
+#define CX23885_BOARD_HAUPPAUGE_HVR1255        20
+#define CX23885_BOARD_HAUPPAUGE_HVR1210        21
+#define CX23885_BOARD_MYGICA_X8506             22
+#define CX23885_BOARD_MAGICPRO_PROHDTVE2       23
+#define CX23885_BOARD_HAUPPAUGE_HVR1850        24
+#define CX23885_BOARD_COMPRO_VIDEOMATE_E800    25
+#define CX23885_BOARD_HAUPPAUGE_HVR1290        26
+#define CX23885_BOARD_MYGICA_X8558PRO          27
+#define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
+#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
+#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
+#define CX23885_BOARD_MPX885                   32
+#define CX23885_BOARD_MYGICA_X8507             33
+#define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
+#define CX23885_BOARD_TEVII_S471               35
+#define CX23885_BOARD_HAUPPAUGE_HVR1255_22111  36
+
+#define GPIO_0 0x00000001
+#define GPIO_1 0x00000002
+#define GPIO_2 0x00000004
+#define GPIO_3 0x00000008
+#define GPIO_4 0x00000010
+#define GPIO_5 0x00000020
+#define GPIO_6 0x00000040
+#define GPIO_7 0x00000080
+#define GPIO_8 0x00000100
+#define GPIO_9 0x00000200
+#define GPIO_10 0x00000400
+#define GPIO_11 0x00000800
+#define GPIO_12 0x00001000
+#define GPIO_13 0x00002000
+#define GPIO_14 0x00004000
+#define GPIO_15 0x00008000
+
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
+#define CX23885_NORMS (\
+       V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443 | \
+       V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+       V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_Nc   | \
+       V4L2_STD_PAL_60 |  V4L2_STD_SECAM_L   |  V4L2_STD_SECAM_DK)
+
+struct cx23885_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+       int   flags;
+       u32   cxformat;
+};
+
+struct cx23885_ctrl {
+       struct v4l2_queryctrl v;
+       u32                   off;
+       u32                   reg;
+       u32                   mask;
+       u32                   shift;
+};
+
+struct cx23885_tvnorm {
+       char            *name;
+       v4l2_std_id     id;
+       u32             cxiformat;
+       u32             cxoformat;
+};
+
+struct cx23885_fh {
+       struct cx23885_dev         *dev;
+       enum v4l2_buf_type         type;
+       int                        radio;
+       u32                        resources;
+
+       /* video overlay */
+       struct v4l2_window         win;
+       struct v4l2_clip           *clips;
+       unsigned int               nclips;
+
+       /* video capture */
+       struct cx23885_fmt         *fmt;
+       unsigned int               width, height;
+
+       /* vbi capture */
+       struct videobuf_queue      vidq;
+       struct videobuf_queue      vbiq;
+
+       /* MPEG Encoder specifics ONLY */
+       struct videobuf_queue      mpegq;
+       atomic_t                   v4l_reading;
+};
+
+enum cx23885_itype {
+       CX23885_VMUX_COMPOSITE1 = 1,
+       CX23885_VMUX_COMPOSITE2,
+       CX23885_VMUX_COMPOSITE3,
+       CX23885_VMUX_COMPOSITE4,
+       CX23885_VMUX_SVIDEO,
+       CX23885_VMUX_COMPONENT,
+       CX23885_VMUX_TELEVISION,
+       CX23885_VMUX_CABLE,
+       CX23885_VMUX_DVB,
+       CX23885_VMUX_DEBUG,
+       CX23885_RADIO,
+};
+
+enum cx23885_src_sel_type {
+       CX23885_SRC_SEL_EXT_656_VIDEO = 0,
+       CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx23885_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       /* cx23885 specific */
+       unsigned int           bpl;
+       struct btcx_riscmem    risc;
+       struct cx23885_fmt     *fmt;
+       u32                    count;
+};
+
+struct cx23885_input {
+       enum cx23885_itype type;
+       unsigned int    vmux;
+       unsigned int    amux;
+       u32             gpio0, gpio1, gpio2, gpio3;
+};
+
+typedef enum {
+       CX23885_MPEG_UNDEFINED = 0,
+       CX23885_MPEG_DVB,
+       CX23885_ANALOG_VIDEO,
+       CX23885_MPEG_ENCODER,
+} port_t;
+
+struct cx23885_board {
+       char                    *name;
+       port_t                  porta, portb, portc;
+       int             num_fds_portb, num_fds_portc;
+       unsigned int            tuner_type;
+       unsigned int            radio_type;
+       unsigned char           tuner_addr;
+       unsigned char           radio_addr;
+       unsigned int            tuner_bus;
+
+       /* Vendors can and do run the PCIe bridge at different
+        * clock rates, driven physically by crystals on the PCBs.
+        * The core has to accommodate this. This allows the user
+        * to add new boards with new frequencys. The value is
+        * expressed in Hz.
+        *
+        * The core framework will default this value based on
+        * current designs, but it can vary.
+        */
+       u32                     clk_freq;
+       struct cx23885_input    input[MAX_CX23885_INPUT];
+       int                     ci_type; /* for NetUP */
+       /* Force bottom field first during DMA (888 workaround) */
+       u32                     force_bff;
+};
+
+struct cx23885_subid {
+       u16     subvendor;
+       u16     subdevice;
+       u32     card;
+};
+
+struct cx23885_i2c {
+       struct cx23885_dev *dev;
+
+       int                        nr;
+
+       /* i2c i/o */
+       struct i2c_adapter         i2c_adap;
+       struct i2c_client          i2c_client;
+       u32                        i2c_rc;
+
+       /* 885 registers used for raw addess */
+       u32                        i2c_period;
+       u32                        reg_ctrl;
+       u32                        reg_stat;
+       u32                        reg_addr;
+       u32                        reg_rdata;
+       u32                        reg_wdata;
+};
+
+struct cx23885_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+       struct timer_list      timeout;
+       struct btcx_riscmem    stopper;
+       u32                    count;
+};
+
+struct cx23885_tsport {
+       struct cx23885_dev *dev;
+
+       int                        nr;
+       int                        sram_chno;
+
+       struct videobuf_dvb_frontends frontends;
+
+       /* dma queues */
+       struct cx23885_dmaqueue    mpegq;
+       u32                        ts_packet_size;
+       u32                        ts_packet_count;
+
+       int                        width;
+       int                        height;
+
+       spinlock_t                 slock;
+
+       /* registers */
+       u32                        reg_gpcnt;
+       u32                        reg_gpcnt_ctl;
+       u32                        reg_dma_ctl;
+       u32                        reg_lngth;
+       u32                        reg_hw_sop_ctrl;
+       u32                        reg_gen_ctrl;
+       u32                        reg_bd_pkt_status;
+       u32                        reg_sop_status;
+       u32                        reg_fifo_ovfl_stat;
+       u32                        reg_vld_misc;
+       u32                        reg_ts_clk_en;
+       u32                        reg_ts_int_msk;
+       u32                        reg_ts_int_stat;
+       u32                        reg_src_sel;
+
+       /* Default register vals */
+       int                        pci_irqmask;
+       u32                        dma_ctl_val;
+       u32                        ts_int_msk_val;
+       u32                        gen_ctrl_val;
+       u32                        ts_clk_en_val;
+       u32                        src_sel_val;
+       u32                        vld_misc_val;
+       u32                        hw_sop_ctrl_val;
+
+       /* Allow a single tsport to have multiple frontends */
+       u32                        num_frontends;
+       void                (*gate_ctrl)(struct cx23885_tsport *port, int open);
+       void                       *port_priv;
+
+       /* Workaround for a temp dvb_frontend that the tuner can attached to */
+       struct dvb_frontend analog_fe;
+};
+
+struct cx23885_kernel_ir {
+       struct cx23885_dev      *cx;
+       char                    *name;
+       char                    *phys;
+
+       struct rc_dev           *rc;
+};
+
+struct cx23885_audio_buffer {
+       unsigned int            bpl;
+       struct btcx_riscmem     risc;
+       struct videobuf_dmabuf  dma;
+};
+
+struct cx23885_audio_dev {
+       struct cx23885_dev      *dev;
+
+       struct pci_dev          *pci;
+
+       struct snd_card         *card;
+
+       spinlock_t              lock;
+
+       atomic_t                count;
+
+       unsigned int            dma_size;
+       unsigned int            period_size;
+       unsigned int            num_periods;
+
+       struct videobuf_dmabuf  *dma_risc;
+
+       struct cx23885_audio_buffer   *buf;
+
+       struct snd_pcm_substream *substream;
+};
+
+struct cx23885_dev {
+       atomic_t                   refcount;
+       struct v4l2_device         v4l2_dev;
+
+       /* pci stuff */
+       struct pci_dev             *pci;
+       unsigned char              pci_rev, pci_lat;
+       int                        pci_bus, pci_slot;
+       u32                        __iomem *lmmio;
+       u8                         __iomem *bmmio;
+       int                        pci_irqmask;
+       spinlock_t                 pci_irqmask_lock; /* protects mask reg too */
+       int                        hwrevision;
+
+       /* This valud is board specific and is used to configure the
+        * AV core so we see nice clean and stable video and audio. */
+       u32                        clk_freq;
+
+       /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+       struct cx23885_i2c         i2c_bus[3];
+
+       int                        nr;
+       struct mutex               lock;
+       struct mutex               gpio_lock;
+
+       /* board details */
+       unsigned int               board;
+       char                       name[32];
+
+       struct cx23885_tsport      ts1, ts2;
+
+       /* sram configuration */
+       struct sram_channel        *sram_channels;
+
+       enum {
+               CX23885_BRIDGE_UNDEFINED = 0,
+               CX23885_BRIDGE_885 = 885,
+               CX23885_BRIDGE_887 = 887,
+               CX23885_BRIDGE_888 = 888,
+       } bridge;
+
+       /* Analog video */
+       u32                        resources;
+       unsigned int               input;
+       unsigned int               audinput; /* Selectable audio input */
+       u32                        tvaudio;
+       v4l2_std_id                tvnorm;
+       unsigned int               tuner_type;
+       unsigned char              tuner_addr;
+       unsigned int               tuner_bus;
+       unsigned int               radio_type;
+       unsigned char              radio_addr;
+       unsigned int               has_radio;
+       struct v4l2_subdev         *sd_cx25840;
+       struct work_struct         cx25840_work;
+
+       /* Infrared */
+       struct v4l2_subdev         *sd_ir;
+       struct work_struct         ir_rx_work;
+       unsigned long              ir_rx_notifications;
+       struct work_struct         ir_tx_work;
+       unsigned long              ir_tx_notifications;
+
+       struct cx23885_kernel_ir   *kernel_ir;
+       atomic_t                   ir_input_stopping;
+
+       /* V4l */
+       u32                        freq;
+       struct video_device        *video_dev;
+       struct video_device        *vbi_dev;
+       struct video_device        *radio_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;
+
+       /* Analog raw audio */
+       struct cx23885_audio_dev   *audio_dev;
+
+};
+
+static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev);
+}
+
+#define call_all(dev, o, f, args...) \
+       v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
+#define CX23885_HW_888_IR  (1 << 0)
+#define CX23885_HW_AV_CORE (1 << 1)
+
+#define call_hw(dev, grpid, o, f, args...) \
+       v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args)
+
+extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw);
+
+#define SRAM_CH01  0 /* Video A */
+#define SRAM_CH02  1 /* VBI A */
+#define SRAM_CH03  2 /* Video B */
+#define SRAM_CH04  3 /* Transport via B */
+#define SRAM_CH05  4 /* VBI B */
+#define SRAM_CH06  5 /* Video C */
+#define SRAM_CH07  6 /* Transport via C */
+#define SRAM_CH08  7 /* Audio Internal A */
+#define SRAM_CH09  8 /* Audio Internal B */
+#define SRAM_CH10  9 /* Audio External */
+#define SRAM_CH11 10 /* COMB_3D_N */
+#define SRAM_CH12 11 /* Comb 3D N1 */
+#define SRAM_CH13 12 /* Comb 3D N2 */
+#define SRAM_CH14 13 /* MOE Vid */
+#define SRAM_CH15 14 /* MOE RSLT */
+
+struct sram_channel {
+       char *name;
+       u32  cmds_start;
+       u32  ctrl_start;
+       u32  cdt;
+       u32  fifo_start;
+       u32  fifo_size;
+       u32  ptr1_reg;
+       u32  ptr2_reg;
+       u32  cnt1_reg;
+       u32  cnt2_reg;
+       u32  jumponly;
+};
+
+/* ----------------------------------------------------------- */
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+  writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+  ((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+/* ----------------------------------------------------------- */
+/* cx23885-core.c                                              */
+
+extern int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+       struct sram_channel *ch,
+       unsigned int bpl, u32 risc);
+
+extern void cx23885_sram_channel_dump(struct cx23885_dev *dev,
+       struct sram_channel *ch);
+
+extern int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+       u32 reg, u32 mask, u32 value);
+
+extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+       struct scatterlist *sglist,
+       unsigned int top_offset, unsigned int bottom_offset,
+       unsigned int bpl, unsigned int padding, unsigned int lines);
+
+extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
+       struct btcx_riscmem *risc, struct scatterlist *sglist,
+       unsigned int top_offset, unsigned int bottom_offset,
+       unsigned int bpl, unsigned int padding, unsigned int lines);
+
+void cx23885_cancel_buffers(struct cx23885_tsport *port);
+
+extern int cx23885_restart_queue(struct cx23885_tsport *port,
+                               struct cx23885_dmaqueue *q);
+
+extern void cx23885_wakeup(struct cx23885_tsport *port,
+                          struct cx23885_dmaqueue *q, u32 count);
+
+extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask);
+extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
+       int asoutput);
+
+extern void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask);
+
+/* ----------------------------------------------------------- */
+/* cx23885-cards.c                                             */
+extern struct cx23885_board cx23885_boards[];
+extern const unsigned int cx23885_bcount;
+
+extern struct cx23885_subid cx23885_subids[];
+extern const unsigned int cx23885_idcount;
+
+extern int cx23885_tuner_callback(void *priv, int component,
+       int command, int arg);
+extern void cx23885_card_list(struct cx23885_dev *dev);
+extern int  cx23885_ir_init(struct cx23885_dev *dev);
+extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev);
+extern void cx23885_ir_fini(struct cx23885_dev *dev);
+extern void cx23885_gpio_setup(struct cx23885_dev *dev);
+extern void cx23885_card_setup(struct cx23885_dev *dev);
+extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);
+
+extern int cx23885_dvb_register(struct cx23885_tsport *port);
+extern int cx23885_dvb_unregister(struct cx23885_tsport *port);
+
+extern int cx23885_buf_prepare(struct videobuf_queue *q,
+                              struct cx23885_tsport *port,
+                              struct cx23885_buffer *buf,
+                              enum v4l2_field field);
+extern void cx23885_buf_queue(struct cx23885_tsport *port,
+                             struct cx23885_buffer *buf);
+extern void cx23885_free_buffer(struct videobuf_queue *q,
+                               struct cx23885_buffer *buf);
+
+/* ----------------------------------------------------------- */
+/* cx23885-video.c                                             */
+/* Video */
+extern int cx23885_video_register(struct cx23885_dev *dev);
+extern void cx23885_video_unregister(struct cx23885_dev *dev);
+extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
+extern void cx23885_video_wakeup(struct cx23885_dev *dev,
+       struct cx23885_dmaqueue *q, u32 count);
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i);
+int cx23885_set_input(struct file *file, void *priv, unsigned int i);
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i);
+int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm);
+
+/* ----------------------------------------------------------- */
+/* cx23885-vbi.c                                               */
+extern int cx23885_vbi_fmt(struct file *file, void *priv,
+       struct v4l2_format *f);
+extern void cx23885_vbi_timeout(unsigned long data);
+extern struct videobuf_queue_ops cx23885_vbi_qops;
+extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+       struct cx23885_dmaqueue *q);
+extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
+
+/* cx23885-i2c.c                                                */
+extern int cx23885_i2c_register(struct cx23885_i2c *bus);
+extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
+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);
+extern int mc417_register_read(struct cx23885_dev *dev,
+                               u16 address, u32 *value);
+extern int mc417_register_write(struct cx23885_dev *dev,
+                               u16 address, u32 value);
+extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
+extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
+extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
+
+/* ----------------------------------------------------------- */
+/* cx23885-alsa.c                                             */
+extern struct cx23885_audio_dev *cx23885_audio_register(
+                                       struct cx23885_dev *dev);
+extern void cx23885_audio_unregister(struct cx23885_dev *dev);
+extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
+extern int cx23885_risc_databuffer(struct pci_dev *pci,
+                                  struct btcx_riscmem *risc,
+                                  struct scatterlist *sglist,
+                                  unsigned int bpl,
+                                  unsigned int lines,
+                                  unsigned int lpi);
+
+/* ----------------------------------------------------------- */
+/* tv norms                                                    */
+
+static inline unsigned int norm_maxw(v4l2_std_id norm)
+{
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+}
+
+static inline unsigned int norm_maxh(v4l2_std_id norm)
+{
+       return (norm & V4L2_STD_625_50) ? 576 : 480;
+}
+
+static inline unsigned int norm_swidth(v4l2_std_id norm)
+{
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
+}
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
new file mode 100644 (file)
index 0000000..c2bc39c
--- /dev/null
@@ -0,0 +1,1271 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  CX23888 Integrated Consumer Infrared Controller
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include <linux/kfifo.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/rc-core.h>
+
+#include "cx23885.h"
+
+static unsigned int ir_888_debug;
+module_param(ir_888_debug, int, 0644);
+MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
+
+#define CX23888_IR_REG_BASE    0x170000
+/*
+ * These CX23888 register offsets have a straightforward one to one mapping
+ * to the CX23885 register offsets of 0x200 through 0x218
+ */
+#define CX23888_IR_CNTRL_REG   0x170000
+#define CNTRL_WIN_3_3  0x00000000
+#define CNTRL_WIN_4_3  0x00000001
+#define CNTRL_WIN_3_4  0x00000002
+#define CNTRL_WIN_4_4  0x00000003
+#define CNTRL_WIN      0x00000003
+#define CNTRL_EDG_NONE 0x00000000
+#define CNTRL_EDG_FALL 0x00000004
+#define CNTRL_EDG_RISE 0x00000008
+#define CNTRL_EDG_BOTH 0x0000000C
+#define CNTRL_EDG      0x0000000C
+#define CNTRL_DMD      0x00000010
+#define CNTRL_MOD      0x00000020
+#define CNTRL_RFE      0x00000040
+#define CNTRL_TFE      0x00000080
+#define CNTRL_RXE      0x00000100
+#define CNTRL_TXE      0x00000200
+#define CNTRL_RIC      0x00000400
+#define CNTRL_TIC      0x00000800
+#define CNTRL_CPL      0x00001000
+#define CNTRL_LBM      0x00002000
+#define CNTRL_R                0x00004000
+/* CX23888 specific control flag */
+#define CNTRL_IVO      0x00008000
+
+#define CX23888_IR_TXCLK_REG   0x170004
+#define TXCLK_TCD      0x0000FFFF
+
+#define CX23888_IR_RXCLK_REG   0x170008
+#define RXCLK_RCD      0x0000FFFF
+
+#define CX23888_IR_CDUTY_REG   0x17000C
+#define CDUTY_CDC      0x0000000F
+
+#define CX23888_IR_STATS_REG   0x170010
+#define STATS_RTO      0x00000001
+#define STATS_ROR      0x00000002
+#define STATS_RBY      0x00000004
+#define STATS_TBY      0x00000008
+#define STATS_RSR      0x00000010
+#define STATS_TSR      0x00000020
+
+#define CX23888_IR_IRQEN_REG   0x170014
+#define IRQEN_RTE      0x00000001
+#define IRQEN_ROE      0x00000002
+#define IRQEN_RSE      0x00000010
+#define IRQEN_TSE      0x00000020
+
+#define CX23888_IR_FILTR_REG   0x170018
+#define FILTR_LPF      0x0000FFFF
+
+/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
+#define CX23888_IR_FIFO_REG    0x170040
+#define FIFO_RXTX      0x0000FFFF
+#define FIFO_RXTX_LVL  0x00010000
+#define FIFO_RXTX_RTO  0x0001FFFF
+#define FIFO_RX_NDV    0x00020000
+#define FIFO_RX_DEPTH  8
+#define FIFO_TX_DEPTH  8
+
+/* CX23888 unique registers */
+#define CX23888_IR_SEEDP_REG   0x17001C
+#define CX23888_IR_TIMOL_REG   0x170020
+#define CX23888_IR_WAKE0_REG   0x170024
+#define CX23888_IR_WAKE1_REG   0x170028
+#define CX23888_IR_WAKE2_REG   0x17002C
+#define CX23888_IR_MASK0_REG   0x170030
+#define CX23888_IR_MASK1_REG   0x170034
+#define CX23888_IR_MAKS2_REG   0x170038
+#define CX23888_IR_DPIPG_REG   0x17003C
+#define CX23888_IR_LEARN_REG   0x170044
+
+#define CX23888_VIDCLK_FREQ    108000000 /* 108 MHz, BT.656 */
+#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2)
+
+/*
+ * We use this union internally for convenience, but callers to tx_write
+ * and rx_read will be expecting records of type struct ir_raw_event.
+ * Always ensure the size of this union is dictated by struct ir_raw_event.
+ */
+union cx23888_ir_fifo_rec {
+       u32 hw_fifo_data;
+       struct ir_raw_event ir_core_data;
+};
+
+#define CX23888_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
+#define CX23888_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
+
+struct cx23888_ir_state {
+       struct v4l2_subdev sd;
+       struct cx23885_dev *dev;
+       u32 id;
+       u32 rev;
+
+       struct v4l2_subdev_ir_parameters rx_params;
+       struct mutex rx_params_lock;
+       atomic_t rxclk_divider;
+       atomic_t rx_invert;
+
+       struct kfifo rx_kfifo;
+       spinlock_t rx_kfifo_lock;
+
+       struct v4l2_subdev_ir_parameters tx_params;
+       struct mutex tx_params_lock;
+       atomic_t txclk_divider;
+};
+
+static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
+{
+       return v4l2_get_subdevdata(sd);
+}
+
+/*
+ * IR register block read and write functions
+ */
+static
+inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
+{
+       cx_write(addr, value);
+       return 0;
+}
+
+static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
+{
+       return cx_read(addr);
+}
+
+static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
+                                    u32 and_mask, u32 or_value)
+{
+       cx_andor(addr, ~and_mask, or_value);
+       return 0;
+}
+
+/*
+ * Rx and Tx Clock Divider register computations
+ *
+ * Note the largest clock divider value of 0xffff corresponds to:
+ *     (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
+ * which fits in 21 bits, so we'll use unsigned int for time arguments.
+ */
+static inline u16 count_to_clock_divider(unsigned int d)
+{
+       if (d > RXCLK_RCD + 1)
+               d = RXCLK_RCD;
+       else if (d < 2)
+               d = 1;
+       else
+               d--;
+       return (u16) d;
+}
+
+static inline u16 ns_to_clock_divider(unsigned int ns)
+{
+       return count_to_clock_divider(
+               DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
+}
+
+static inline unsigned int clock_divider_to_ns(unsigned int divider)
+{
+       /* Period of the Rx or Tx clock in ns */
+       return DIV_ROUND_CLOSEST((divider + 1) * 1000,
+                                CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
+{
+       return count_to_clock_divider(
+                         DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16));
+}
+
+static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
+{
+       return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16);
+}
+
+static inline u16 freq_to_clock_divider(unsigned int freq,
+                                       unsigned int rollovers)
+{
+       return count_to_clock_divider(
+                  DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers));
+}
+
+static inline unsigned int clock_divider_to_freq(unsigned int divider,
+                                                unsigned int rollovers)
+{
+       return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ,
+                                (divider + 1) * rollovers);
+}
+
+/*
+ * Low Pass Filter register calculations
+ *
+ * Note the largest count value of 0xffff corresponds to:
+ *     0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
+ * which fits in 21 bits, so we'll use unsigned int for time arguments.
+ */
+static inline u16 count_to_lpf_count(unsigned int d)
+{
+       if (d > FILTR_LPF)
+               d = FILTR_LPF;
+       else if (d < 4)
+               d = 0;
+       return (u16) d;
+}
+
+static inline u16 ns_to_lpf_count(unsigned int ns)
+{
+       return count_to_lpf_count(
+               DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
+}
+
+static inline unsigned int lpf_count_to_ns(unsigned int count)
+{
+       /* Duration of the Low Pass Filter rejection window in ns */
+       return DIV_ROUND_CLOSEST(count * 1000,
+                                CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+static inline unsigned int lpf_count_to_us(unsigned int count)
+{
+       /* Duration of the Low Pass Filter rejection window in us */
+       return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+/*
+ * FIFO register pulse width count compuations
+ */
+static u32 clock_divider_to_resolution(u16 divider)
+{
+       /*
+        * Resolution is the duration of 1 tick of the readable portion of
+        * of the pulse width counter as read from the FIFO.  The two lsb's are
+        * not readable, hence the << 2.  This function returns ns.
+        */
+       return DIV_ROUND_CLOSEST((1 << 2)  * ((u32) divider + 1) * 1000,
+                                CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+static u64 pulse_width_count_to_ns(u16 count, u16 divider)
+{
+       u64 n;
+       u32 rem;
+
+       /*
+        * The 2 lsb's of the pulse width timer count are not readable, hence
+        * the (count << 2) | 0x3
+        */
+       n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
+       rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000);     /* / MHz => ns */
+       if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
+               n++;
+       return n;
+}
+
+static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
+{
+       u64 n;
+       u32 rem;
+
+       /*
+        * The 2 lsb's of the pulse width timer count are not readable, hence
+        * the (count << 2) | 0x3
+        */
+       n = (((u64) count << 2) | 0x3) * (divider + 1);    /* cycles      */
+       rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
+       if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
+               n++;
+       return (unsigned int) n;
+}
+
+/*
+ * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
+ *
+ * The total pulse clock count is an 18 bit pulse width timer count as the most
+ * significant part and (up to) 16 bit clock divider count as a modulus.
+ * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
+ * width timer count's least significant bit.
+ */
+static u64 ns_to_pulse_clocks(u32 ns)
+{
+       u64 clocks;
+       u32 rem;
+       clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles  */
+       rem = do_div(clocks, 1000);                         /* /1000 = cycles */
+       if (rem >= 1000 / 2)
+               clocks++;
+       return clocks;
+}
+
+static u16 pulse_clocks_to_clock_divider(u64 count)
+{
+       do_div(count, (FIFO_RXTX << 2) | 0x3);
+
+       /* net result needs to be rounded down and decremented by 1 */
+       if (count > RXCLK_RCD + 1)
+               count = RXCLK_RCD;
+       else if (count < 2)
+               count = 1;
+       else
+               count--;
+       return (u16) count;
+}
+
+/*
+ * IR Control Register helpers
+ */
+enum tx_fifo_watermark {
+       TX_FIFO_HALF_EMPTY = 0,
+       TX_FIFO_EMPTY      = CNTRL_TIC,
+};
+
+enum rx_fifo_watermark {
+       RX_FIFO_HALF_FULL = 0,
+       RX_FIFO_NOT_EMPTY = CNTRL_RIC,
+};
+
+static inline void control_tx_irq_watermark(struct cx23885_dev *dev,
+                                           enum tx_fifo_watermark level)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level);
+}
+
+static inline void control_rx_irq_watermark(struct cx23885_dev *dev,
+                                           enum rx_fifo_watermark level)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level);
+}
+
+static inline void control_tx_enable(struct cx23885_dev *dev, bool enable)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
+                          enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
+}
+
+static inline void control_rx_enable(struct cx23885_dev *dev, bool enable)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
+                          enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
+}
+
+static inline void control_tx_modulation_enable(struct cx23885_dev *dev,
+                                               bool enable)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD,
+                          enable ? CNTRL_MOD : 0);
+}
+
+static inline void control_rx_demodulation_enable(struct cx23885_dev *dev,
+                                                 bool enable)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD,
+                          enable ? CNTRL_DMD : 0);
+}
+
+static inline void control_rx_s_edge_detection(struct cx23885_dev *dev,
+                                              u32 edge_types)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
+                          edge_types & CNTRL_EDG_BOTH);
+}
+
+static void control_rx_s_carrier_window(struct cx23885_dev *dev,
+                                       unsigned int carrier,
+                                       unsigned int *carrier_range_low,
+                                       unsigned int *carrier_range_high)
+{
+       u32 v;
+       unsigned int c16 = carrier * 16;
+
+       if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
+               v = CNTRL_WIN_3_4;
+               *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
+       } else {
+               v = CNTRL_WIN_3_3;
+               *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
+       }
+
+       if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
+               v |= CNTRL_WIN_4_3;
+               *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
+       } else {
+               v |= CNTRL_WIN_3_3;
+               *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
+       }
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v);
+}
+
+static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
+                                             bool invert)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL,
+                          invert ? CNTRL_CPL : 0);
+}
+
+static inline void control_tx_level_invert(struct cx23885_dev *dev,
+                                         bool invert)
+{
+       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO,
+                          invert ? CNTRL_IVO : 0);
+}
+
+/*
+ * IR Rx & Tx Clock Register helpers
+ */
+static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev,
+                                      unsigned int freq,
+                                      u16 *divider)
+{
+       *divider = carrier_freq_to_clock_divider(freq);
+       cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
+       return clock_divider_to_carrier_freq(*divider);
+}
+
+static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev,
+                                      unsigned int freq,
+                                      u16 *divider)
+{
+       *divider = carrier_freq_to_clock_divider(freq);
+       cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
+       return clock_divider_to_carrier_freq(*divider);
+}
+
+static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
+                                     u16 *divider)
+{
+       u64 pulse_clocks;
+
+       if (ns > IR_MAX_DURATION)
+               ns = IR_MAX_DURATION;
+       pulse_clocks = ns_to_pulse_clocks(ns);
+       *divider = pulse_clocks_to_clock_divider(pulse_clocks);
+       cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
+       return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
+}
+
+static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
+                                     u16 *divider)
+{
+       u64 pulse_clocks;
+
+       if (ns > IR_MAX_DURATION)
+               ns = IR_MAX_DURATION;
+       pulse_clocks = ns_to_pulse_clocks(ns);
+       *divider = pulse_clocks_to_clock_divider(pulse_clocks);
+       cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
+       return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
+}
+
+/*
+ * IR Tx Carrier Duty Cycle register helpers
+ */
+static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev,
+                                         unsigned int duty_cycle)
+{
+       u32 n;
+       n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
+       if (n != 0)
+               n--;
+       if (n > 15)
+               n = 15;
+       cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n);
+       return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
+}
+
+/*
+ * IR Filter Register helpers
+ */
+static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns)
+{
+       u32 count = ns_to_lpf_count(min_width_ns);
+       cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count);
+       return lpf_count_to_ns(count);
+}
+
+/*
+ * IR IRQ Enable Register helpers
+ */
+static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask)
+{
+       mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
+       cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG,
+                          ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
+}
+
+static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask)
+{
+       mask &= IRQEN_TSE;
+       cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask);
+}
+
+/*
+ * V4L2 Subdevice IR Ops
+ */
+static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
+                                 bool *handled)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+       unsigned long flags;
+
+       u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
+       u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
+       u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
+
+       union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
+       unsigned int i, j, k;
+       u32 events, v;
+       int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
+
+       tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
+       rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
+       rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
+       ror = stats & STATS_ROR; /* Rx FIFO Over Run */
+
+       tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
+       rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
+       rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
+       roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
+
+       *handled = false;
+       v4l2_dbg(2, ir_888_debug, sd, "IRQ Status:  %s %s %s %s %s %s\n",
+                tsr ? "tsr" : "   ", rsr ? "rsr" : "   ",
+                rto ? "rto" : "   ", ror ? "ror" : "   ",
+                stats & STATS_TBY ? "tby" : "   ",
+                stats & STATS_RBY ? "rby" : "   ");
+
+       v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
+                tse ? "tse" : "   ", rse ? "rse" : "   ",
+                rte ? "rte" : "   ", roe ? "roe" : "   ");
+
+       /*
+        * Transmitter interrupt service
+        */
+       if (tse && tsr) {
+               /*
+                * TODO:
+                * Check the watermark threshold setting
+                * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
+                * Push the data to the hardware FIFO.
+                * If there was nothing more to send in the tx_kfifo, disable
+                *      the TSR IRQ and notify the v4l2_device.
+                * If there was something in the tx_kfifo, check the tx_kfifo
+                *      level and notify the v4l2_device, if it is low.
+                */
+               /* For now, inhibit TSR interrupt until Tx is implemented */
+               irqenable_tx(dev, 0);
+               events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
+               v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
+               *handled = true;
+       }
+
+       /*
+        * Receiver interrupt service
+        */
+       kror = 0;
+       if ((rse && rsr) || (rte && rto)) {
+               /*
+                * Receive data on RSR to clear the STATS_RSR.
+                * Receive data on RTO, since we may not have yet hit the RSR
+                * watermark when we receive the RTO.
+                */
+               for (i = 0, v = FIFO_RX_NDV;
+                    (v & FIFO_RX_NDV) && !kror; i = 0) {
+                       for (j = 0;
+                            (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
+                               v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
+                               rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
+                               i++;
+                       }
+                       if (i == 0)
+                               break;
+                       j = i * sizeof(union cx23888_ir_fifo_rec);
+                       k = kfifo_in_locked(&state->rx_kfifo,
+                                     (unsigned char *) rx_data, j,
+                                     &state->rx_kfifo_lock);
+                       if (k != j)
+                               kror++; /* rx_kfifo over run */
+               }
+               *handled = true;
+       }
+
+       events = 0;
+       v = 0;
+       if (kror) {
+               events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
+               v4l2_err(sd, "IR receiver software FIFO overrun\n");
+       }
+       if (roe && ror) {
+               /*
+                * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
+                * the Rx FIFO Over Run status (STATS_ROR)
+                */
+               v |= CNTRL_RFE;
+               events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
+               v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
+       }
+       if (rte && rto) {
+               /*
+                * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
+                * the Rx Pulse Width Timer Time Out (STATS_RTO)
+                */
+               v |= CNTRL_RXE;
+               events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
+       }
+       if (v) {
+               /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
+               cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
+               cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
+               *handled = true;
+       }
+
+       spin_lock_irqsave(&state->rx_kfifo_lock, flags);
+       if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
+               events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
+       spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
+
+       if (events)
+               v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
+       return 0;
+}
+
+/* Receiver */
+static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
+                             ssize_t *num)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       bool invert = (bool) atomic_read(&state->rx_invert);
+       u16 divider = (u16) atomic_read(&state->rxclk_divider);
+
+       unsigned int i, n;
+       union cx23888_ir_fifo_rec *p;
+       unsigned u, v, w;
+
+       n = count / sizeof(union cx23888_ir_fifo_rec)
+               * sizeof(union cx23888_ir_fifo_rec);
+       if (n == 0) {
+               *num = 0;
+               return 0;
+       }
+
+       n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
+
+       n /= sizeof(union cx23888_ir_fifo_rec);
+       *num = n * sizeof(union cx23888_ir_fifo_rec);
+
+       for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
+
+               if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
+                       /* Assume RTO was because of no IR light input */
+                       u = 0;
+                       w = 1;
+               } else {
+                       u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
+                       if (invert)
+                               u = u ? 0 : 1;
+                       w = 0;
+               }
+
+               v = (unsigned) pulse_width_count_to_ns(
+                                 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
+               if (v > IR_MAX_DURATION)
+                       v = IR_MAX_DURATION;
+
+               init_ir_raw_event(&p->ir_core_data);
+               p->ir_core_data.pulse = u;
+               p->ir_core_data.duration = v;
+               p->ir_core_data.timeout = w;
+
+               v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s  %s\n",
+                        v, u ? "mark" : "space", w ? "(timed out)" : "");
+               if (w)
+                       v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
+       }
+       return 0;
+}
+
+static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_ir_parameters *p)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       mutex_lock(&state->rx_params_lock);
+       memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters));
+       mutex_unlock(&state->rx_params_lock);
+       return 0;
+}
+
+static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+
+       mutex_lock(&state->rx_params_lock);
+
+       /* Disable or slow down all IR Rx circuits and counters */
+       irqenable_rx(dev, 0);
+       control_rx_enable(dev, false);
+       control_rx_demodulation_enable(dev, false);
+       control_rx_s_edge_detection(dev, CNTRL_EDG_NONE);
+       filter_rx_s_min_width(dev, 0);
+       cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD);
+
+       state->rx_params.shutdown = true;
+
+       mutex_unlock(&state->rx_params_lock);
+       return 0;
+}
+
+static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_ir_parameters *p)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+       struct v4l2_subdev_ir_parameters *o = &state->rx_params;
+       u16 rxclk_divider;
+
+       if (p->shutdown)
+               return cx23888_ir_rx_shutdown(sd);
+
+       if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
+               return -ENOSYS;
+
+       mutex_lock(&state->rx_params_lock);
+
+       o->shutdown = p->shutdown;
+
+       o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+
+       o->bytes_per_data_element = p->bytes_per_data_element
+                                 = sizeof(union cx23888_ir_fifo_rec);
+
+       /* Before we tweak the hardware, we have to disable the receiver */
+       irqenable_rx(dev, 0);
+       control_rx_enable(dev, false);
+
+       control_rx_demodulation_enable(dev, p->modulation);
+       o->modulation = p->modulation;
+
+       if (p->modulation) {
+               p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq,
+                                                    &rxclk_divider);
+
+               o->carrier_freq = p->carrier_freq;
+
+               o->duty_cycle = p->duty_cycle = 50;
+
+               control_rx_s_carrier_window(dev, p->carrier_freq,
+                                           &p->carrier_range_lower,
+                                           &p->carrier_range_upper);
+               o->carrier_range_lower = p->carrier_range_lower;
+               o->carrier_range_upper = p->carrier_range_upper;
+
+               p->max_pulse_width =
+                       (u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
+       } else {
+               p->max_pulse_width =
+                           rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
+                                                      &rxclk_divider);
+       }
+       o->max_pulse_width = p->max_pulse_width;
+       atomic_set(&state->rxclk_divider, rxclk_divider);
+
+       p->noise_filter_min_width =
+                         filter_rx_s_min_width(dev, p->noise_filter_min_width);
+       o->noise_filter_min_width = p->noise_filter_min_width;
+
+       p->resolution = clock_divider_to_resolution(rxclk_divider);
+       o->resolution = p->resolution;
+
+       /* FIXME - make this dependent on resolution for better performance */
+       control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL);
+
+       control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
+
+       o->invert_level = p->invert_level;
+       atomic_set(&state->rx_invert, p->invert_level);
+
+       o->interrupt_enable = p->interrupt_enable;
+       o->enable = p->enable;
+       if (p->enable) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&state->rx_kfifo_lock, flags);
+               kfifo_reset(&state->rx_kfifo);
+               /* reset tx_fifo too if there is one... */
+               spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
+               if (p->interrupt_enable)
+                       irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
+               control_rx_enable(dev, p->enable);
+       }
+
+       mutex_unlock(&state->rx_params_lock);
+       return 0;
+}
+
+/* Transmitter */
+static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
+                              ssize_t *num)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+       /* For now enable the Tx FIFO Service interrupt & pretend we did work */
+       irqenable_tx(dev, IRQEN_TSE);
+       *num = count;
+       return 0;
+}
+
+static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_ir_parameters *p)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       mutex_lock(&state->tx_params_lock);
+       memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters));
+       mutex_unlock(&state->tx_params_lock);
+       return 0;
+}
+
+static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+
+       mutex_lock(&state->tx_params_lock);
+
+       /* Disable or slow down all IR Tx circuits and counters */
+       irqenable_tx(dev, 0);
+       control_tx_enable(dev, false);
+       control_tx_modulation_enable(dev, false);
+       cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD);
+
+       state->tx_params.shutdown = true;
+
+       mutex_unlock(&state->tx_params_lock);
+       return 0;
+}
+
+static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
+                                     struct v4l2_subdev_ir_parameters *p)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+       struct v4l2_subdev_ir_parameters *o = &state->tx_params;
+       u16 txclk_divider;
+
+       if (p->shutdown)
+               return cx23888_ir_tx_shutdown(sd);
+
+       if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
+               return -ENOSYS;
+
+       mutex_lock(&state->tx_params_lock);
+
+       o->shutdown = p->shutdown;
+
+       o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+
+       o->bytes_per_data_element = p->bytes_per_data_element
+                                 = sizeof(union cx23888_ir_fifo_rec);
+
+       /* Before we tweak the hardware, we have to disable the transmitter */
+       irqenable_tx(dev, 0);
+       control_tx_enable(dev, false);
+
+       control_tx_modulation_enable(dev, p->modulation);
+       o->modulation = p->modulation;
+
+       if (p->modulation) {
+               p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq,
+                                                    &txclk_divider);
+               o->carrier_freq = p->carrier_freq;
+
+               p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
+               o->duty_cycle = p->duty_cycle;
+
+               p->max_pulse_width =
+                       (u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
+       } else {
+               p->max_pulse_width =
+                           txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
+                                                      &txclk_divider);
+       }
+       o->max_pulse_width = p->max_pulse_width;
+       atomic_set(&state->txclk_divider, txclk_divider);
+
+       p->resolution = clock_divider_to_resolution(txclk_divider);
+       o->resolution = p->resolution;
+
+       /* FIXME - make this dependent on resolution for better performance */
+       control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
+
+       control_tx_polarity_invert(dev, p->invert_carrier_sense);
+       o->invert_carrier_sense = p->invert_carrier_sense;
+
+       control_tx_level_invert(dev, p->invert_level);
+       o->invert_level = p->invert_level;
+
+       o->interrupt_enable = p->interrupt_enable;
+       o->enable = p->enable;
+       if (p->enable) {
+               if (p->interrupt_enable)
+                       irqenable_tx(dev, IRQEN_TSE);
+               control_tx_enable(dev, p->enable);
+       }
+
+       mutex_unlock(&state->tx_params_lock);
+       return 0;
+}
+
+
+/*
+ * V4L2 Subdevice Core Ops
+ */
+static int cx23888_ir_log_status(struct v4l2_subdev *sd)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       struct cx23885_dev *dev = state->dev;
+       char *s;
+       int i, j;
+
+       u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
+       u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD;
+       u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD;
+       u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC;
+       u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
+       u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
+       u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF;
+
+       v4l2_info(sd, "IR Receiver:\n");
+       v4l2_info(sd, "\tEnabled:                           %s\n",
+                 cntrl & CNTRL_RXE ? "yes" : "no");
+       v4l2_info(sd, "\tDemodulation from a carrier:       %s\n",
+                 cntrl & CNTRL_DMD ? "enabled" : "disabled");
+       v4l2_info(sd, "\tFIFO:                              %s\n",
+                 cntrl & CNTRL_RFE ? "enabled" : "disabled");
+       switch (cntrl & CNTRL_EDG) {
+       case CNTRL_EDG_NONE:
+               s = "disabled";
+               break;
+       case CNTRL_EDG_FALL:
+               s = "falling edge";
+               break;
+       case CNTRL_EDG_RISE:
+               s = "rising edge";
+               break;
+       case CNTRL_EDG_BOTH:
+               s = "rising & falling edges";
+               break;
+       default:
+               s = "??? edge";
+               break;
+       }
+       v4l2_info(sd, "\tPulse timers' start/stop trigger:  %s\n", s);
+       v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
+                 cntrl & CNTRL_R ? "not loaded" : "overflow marker");
+       v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
+                 cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
+       v4l2_info(sd, "\tLoopback mode:                     %s\n",
+                 cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
+       if (cntrl & CNTRL_DMD) {
+               v4l2_info(sd, "\tExpected carrier (16 clocks):      %u Hz\n",
+                         clock_divider_to_carrier_freq(rxclk));
+               switch (cntrl & CNTRL_WIN) {
+               case CNTRL_WIN_3_3:
+                       i = 3;
+                       j = 3;
+                       break;
+               case CNTRL_WIN_4_3:
+                       i = 4;
+                       j = 3;
+                       break;
+               case CNTRL_WIN_3_4:
+                       i = 3;
+                       j = 4;
+                       break;
+               case CNTRL_WIN_4_4:
+                       i = 4;
+                       j = 4;
+                       break;
+               default:
+                       i = 0;
+                       j = 0;
+                       break;
+               }
+               v4l2_info(sd, "\tNext carrier edge window:          16 clocks "
+                         "-%1d/+%1d, %u to %u Hz\n", i, j,
+                         clock_divider_to_freq(rxclk, 16 + j),
+                         clock_divider_to_freq(rxclk, 16 - i));
+       }
+       v4l2_info(sd, "\tMax measurable pulse width:        %u us, %llu ns\n",
+                 pulse_width_count_to_us(FIFO_RXTX, rxclk),
+                 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
+       v4l2_info(sd, "\tLow pass filter:                   %s\n",
+                 filtr ? "enabled" : "disabled");
+       if (filtr)
+               v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, "
+                         "%u ns\n",
+                         lpf_count_to_us(filtr),
+                         lpf_count_to_ns(filtr));
+       v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
+                 stats & STATS_RTO ? "yes" : "no");
+       v4l2_info(sd, "\tPulse width timer time-out intr:   %s\n",
+                 irqen & IRQEN_RTE ? "enabled" : "disabled");
+       v4l2_info(sd, "\tFIFO overrun:                      %s\n",
+                 stats & STATS_ROR ? "yes" : "no");
+       v4l2_info(sd, "\tFIFO overrun interrupt:            %s\n",
+                 irqen & IRQEN_ROE ? "enabled" : "disabled");
+       v4l2_info(sd, "\tBusy:                              %s\n",
+                 stats & STATS_RBY ? "yes" : "no");
+       v4l2_info(sd, "\tFIFO service requested:            %s\n",
+                 stats & STATS_RSR ? "yes" : "no");
+       v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
+                 irqen & IRQEN_RSE ? "enabled" : "disabled");
+
+       v4l2_info(sd, "IR Transmitter:\n");
+       v4l2_info(sd, "\tEnabled:                           %s\n",
+                 cntrl & CNTRL_TXE ? "yes" : "no");
+       v4l2_info(sd, "\tModulation onto a carrier:         %s\n",
+                 cntrl & CNTRL_MOD ? "enabled" : "disabled");
+       v4l2_info(sd, "\tFIFO:                              %s\n",
+                 cntrl & CNTRL_TFE ? "enabled" : "disabled");
+       v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
+                 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
+       v4l2_info(sd, "\tOutput pin level inversion         %s\n",
+                 cntrl & CNTRL_IVO ? "yes" : "no");
+       v4l2_info(sd, "\tCarrier polarity:                  %s\n",
+                 cntrl & CNTRL_CPL ? "space:burst mark:noburst"
+                                   : "space:noburst mark:burst");
+       if (cntrl & CNTRL_MOD) {
+               v4l2_info(sd, "\tCarrier (16 clocks):               %u Hz\n",
+                         clock_divider_to_carrier_freq(txclk));
+               v4l2_info(sd, "\tCarrier duty cycle:                %2u/16\n",
+                         cduty + 1);
+       }
+       v4l2_info(sd, "\tMax pulse width:                   %u us, %llu ns\n",
+                 pulse_width_count_to_us(FIFO_RXTX, txclk),
+                 pulse_width_count_to_ns(FIFO_RXTX, txclk));
+       v4l2_info(sd, "\tBusy:                              %s\n",
+                 stats & STATS_TBY ? "yes" : "no");
+       v4l2_info(sd, "\tFIFO service requested:            %s\n",
+                 stats & STATS_TSR ? "yes" : "no");
+       v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
+                 irqen & IRQEN_TSE ? "enabled" : "disabled");
+
+       return 0;
+}
+
+static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match)
+{
+       return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2;
+}
+
+static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd,
+                                  struct v4l2_dbg_chip_ident *chip)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+
+       if (cx23888_ir_dbg_match(&chip->match)) {
+               chip->ident = state->id;
+               chip->revision = state->rev;
+       }
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx23888_ir_g_register(struct v4l2_subdev *sd,
+                                struct v4l2_dbg_register *reg)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
+
+       if (!cx23888_ir_dbg_match(&reg->match))
+               return -EINVAL;
+       if ((addr & 0x3) != 0)
+               return -EINVAL;
+       if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       reg->size = 4;
+       reg->val = cx23888_ir_read4(state->dev, addr);
+       return 0;
+}
+
+static int cx23888_ir_s_register(struct v4l2_subdev *sd,
+                                struct v4l2_dbg_register *reg)
+{
+       struct cx23888_ir_state *state = to_state(sd);
+       u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
+
+       if (!cx23888_ir_dbg_match(&reg->match))
+               return -EINVAL;
+       if ((addr & 0x3) != 0)
+               return -EINVAL;
+       if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       cx23888_ir_write4(state->dev, addr, reg->val);
+       return 0;
+}
+#endif
+
+static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
+       .g_chip_ident = cx23888_ir_g_chip_ident,
+       .log_status = cx23888_ir_log_status,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = cx23888_ir_g_register,
+       .s_register = cx23888_ir_s_register,
+#endif
+       .interrupt_service_routine = cx23888_ir_irq_handler,
+};
+
+static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
+       .rx_read = cx23888_ir_rx_read,
+       .rx_g_parameters = cx23888_ir_rx_g_parameters,
+       .rx_s_parameters = cx23888_ir_rx_s_parameters,
+
+       .tx_write = cx23888_ir_tx_write,
+       .tx_g_parameters = cx23888_ir_tx_g_parameters,
+       .tx_s_parameters = cx23888_ir_tx_s_parameters,
+};
+
+static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
+       .core = &cx23888_ir_core_ops,
+       .ir = &cx23888_ir_ir_ops,
+};
+
+static const struct v4l2_subdev_ir_parameters default_rx_params = {
+       .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
+       .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
+
+       .enable = false,
+       .interrupt_enable = false,
+       .shutdown = true,
+
+       .modulation = true,
+       .carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */
+
+       /* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
+       /* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
+       .noise_filter_min_width = 333333, /* ns */
+       .carrier_range_lower = 35000,
+       .carrier_range_upper = 37000,
+       .invert_level = false,
+};
+
+static const struct v4l2_subdev_ir_parameters default_tx_params = {
+       .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
+       .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
+
+       .enable = false,
+       .interrupt_enable = false,
+       .shutdown = true,
+
+       .modulation = true,
+       .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
+       .duty_cycle = 25,      /* 25 %   - RC-5 carrier */
+       .invert_level = false,
+       .invert_carrier_sense = false,
+};
+
+int cx23888_ir_probe(struct cx23885_dev *dev)
+{
+       struct cx23888_ir_state *state;
+       struct v4l2_subdev *sd;
+       struct v4l2_subdev_ir_parameters default_params;
+       int ret;
+
+       state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
+       if (state == NULL)
+               return -ENOMEM;
+
+       spin_lock_init(&state->rx_kfifo_lock);
+       if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
+               return -ENOMEM;
+
+       state->dev = dev;
+       state->id = V4L2_IDENT_CX23888_IR;
+       state->rev = 0;
+       sd = &state->sd;
+
+       v4l2_subdev_init(sd, &cx23888_ir_controller_ops);
+       v4l2_set_subdevdata(sd, state);
+       /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
+       snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
+       sd->grp_id = CX23885_HW_888_IR;
+
+       ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd);
+       if (ret == 0) {
+               /*
+                * Ensure no interrupts arrive from '888 specific conditions,
+                * since we ignore them in this driver to have commonality with
+                * similar IR controller cores.
+                */
+               cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0);
+
+               mutex_init(&state->rx_params_lock);
+               memcpy(&default_params, &default_rx_params,
+                      sizeof(struct v4l2_subdev_ir_parameters));
+               v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
+
+               mutex_init(&state->tx_params_lock);
+               memcpy(&default_params, &default_tx_params,
+                      sizeof(struct v4l2_subdev_ir_parameters));
+               v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
+       } else {
+               kfifo_free(&state->rx_kfifo);
+       }
+       return ret;
+}
+
+int cx23888_ir_remove(struct cx23885_dev *dev)
+{
+       struct v4l2_subdev *sd;
+       struct cx23888_ir_state *state;
+
+       sd = cx23885_find_hw(dev, CX23885_HW_888_IR);
+       if (sd == NULL)
+               return -ENODEV;
+
+       cx23888_ir_rx_shutdown(sd);
+       cx23888_ir_tx_shutdown(sd);
+
+       state = to_state(sd);
+       v4l2_device_unregister_subdev(sd);
+       kfifo_free(&state->rx_kfifo);
+       kfree(state);
+       /* Nothing more to free() as state held the actual v4l2_subdev object */
+       return 0;
+}
diff --git a/drivers/media/pci/cx23885/cx23888-ir.h b/drivers/media/pci/cx23885/cx23888-ir.h
new file mode 100644 (file)
index 0000000..d2de41c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  CX23888 Integrated Consumer Infrared Controller
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#ifndef _CX23888_IR_H_
+#define _CX23888_IR_H_
+int cx23888_ir_probe(struct cx23885_dev *dev);
+int cx23888_ir_remove(struct cx23885_dev *dev);
+#endif
diff --git a/drivers/media/pci/cx23885/netup-eeprom.c b/drivers/media/pci/cx23885/netup-eeprom.c
new file mode 100644 (file)
index 0000000..98a48f5
--- /dev/null
@@ -0,0 +1,107 @@
+
+/*
+ * netup-eeprom.c
+ *
+ * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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 "cx23885.h"
+#include "netup-eeprom.h"
+
+#define EEPROM_I2C_ADDR 0x50
+
+int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr)
+{
+       int ret;
+       unsigned char buf[2];
+
+       /* Read from EEPROM */
+       struct i2c_msg msg[] = {
+               {
+                       .addr   = EEPROM_I2C_ADDR,
+                       .flags  = 0,
+                       .buf    = &buf[0],
+                       .len    = 1
+               }, {
+                       .addr   = EEPROM_I2C_ADDR,
+                       .flags  = I2C_M_RD,
+                       .buf    = &buf[1],
+                       .len    = 1
+               }
+
+       };
+
+       buf[0] = addr;
+       buf[1] = 0x0;
+
+       ret = i2c_transfer(i2c_adap, msg, 2);
+
+       if (ret != 2) {
+               printk(KERN_ERR "eeprom i2c read error, status=%d\n", ret);
+               return -1;
+       }
+
+       return buf[1];
+};
+
+int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data)
+{
+       int ret;
+       unsigned char bufw[2];
+
+       /* Write into EEPROM */
+       struct i2c_msg msg[] = {
+               {
+                       .addr   = EEPROM_I2C_ADDR,
+                       .flags  = 0,
+                       .buf    = &bufw[0],
+                       .len    = 2
+               }
+       };
+
+       bufw[0] = addr;
+       bufw[1] = data;
+
+       ret = i2c_transfer(i2c_adap, msg, 1);
+
+       if (ret != 1) {
+               printk(KERN_ERR "eeprom i2c write error, status=%d\n", ret);
+               return -1;
+       }
+
+       mdelay(10); /* prophylactic delay, datasheet write cycle time = 5 ms */
+       return 0;
+};
+
+void netup_get_card_info(struct i2c_adapter *i2c_adap,
+                               struct netup_card_info *cinfo)
+{
+       int i, j;
+
+       cinfo->rev =  netup_eeprom_read(i2c_adap, 63);
+
+       for (i = 64, j = 0; i < 70; i++, j++)
+               cinfo->port[0].mac[j] =  netup_eeprom_read(i2c_adap, i);
+
+       for (i = 70, j = 0; i < 76; i++, j++)
+               cinfo->port[1].mac[j] =  netup_eeprom_read(i2c_adap, i);
+};
diff --git a/drivers/media/pci/cx23885/netup-eeprom.h b/drivers/media/pci/cx23885/netup-eeprom.h
new file mode 100644 (file)
index 0000000..13926e1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * netup-eeprom.h
+ *
+ * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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 NETUP_EEPROM_H
+#define NETUP_EEPROM_H
+
+struct netup_port_info {
+       u8 mac[6];/* card MAC address */
+};
+
+struct netup_card_info {
+       struct netup_port_info port[2];/* ports - 1,2 */
+       u8 rev;/* card revision */
+};
+
+extern int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr);
+extern int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data);
+extern void netup_get_card_info(struct i2c_adapter *i2c_adap,
+                               struct netup_card_info *cinfo);
+
+#endif
diff --git a/drivers/media/pci/cx23885/netup-init.c b/drivers/media/pci/cx23885/netup-init.c
new file mode 100644 (file)
index 0000000..f4893e6
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * netup-init.c
+ *
+ * NetUP Dual DVB-S2 CI driver
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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 "cx23885.h"
+
+static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val)
+{
+       int ret;
+       u8 buf[3];
+       struct i2c_msg msg = {
+               .addr   = 0x88 >> 1,
+               .flags  = 0,
+               .buf    = buf,
+               .len    = 3
+       };
+
+       buf[0] = reg >> 8;
+       buf[1] = reg & 0xff;
+       buf[2] = val;
+
+       ret = i2c_transfer(i2c, &msg, 1);
+
+       if (ret != 1)
+               printk(KERN_ERR "%s: i2c write error!\n", __func__);
+}
+
+static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val)
+{
+       int ret;
+       u8 buf[6];
+       struct i2c_msg msg = {
+               .addr   = 0x88 >> 1,
+               .flags  = 0,
+               .buf    = buf,
+               .len    = 6
+       };
+
+       buf[0] = reg >> 8;
+       buf[1] = reg & 0xff;
+       buf[2] = val & 0xff;
+       buf[3] = (val >> 8) & 0xff;
+       buf[4] = (val >> 16) & 0xff;
+       buf[5] = val >> 24;
+
+       ret = i2c_transfer(i2c, &msg, 1);
+
+       if (ret != 1)
+               printk(KERN_ERR "%s: i2c write error!\n", __func__);
+}
+
+static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg)
+{
+       int ret;
+       u8 buf[2];
+       struct i2c_msg msg = {
+               .addr   = 0x88 >> 1,
+               .flags  = 0,
+               .buf    = buf,
+               .len    = 2
+       };
+
+       buf[0] = reg >> 8;
+       buf[1] = reg & 0xff;
+
+       ret = i2c_transfer(i2c, &msg, 1);
+
+       if (ret != 1)
+               printk(KERN_ERR "%s: i2c write error!\n", __func__);
+
+       msg.flags = I2C_M_RD;
+       msg.len = 1;
+
+       ret = i2c_transfer(i2c, &msg, 1);
+
+       if (ret != 1)
+               printk(KERN_ERR "%s: i2c read error!\n", __func__);
+
+       return buf[0];
+}
+
+static void i2c_av_and_or(struct i2c_adapter *i2c, u16 reg, unsigned and_mask,
+                                                               u8 or_value)
+{
+       i2c_av_write(i2c, reg, (i2c_av_read(i2c, reg) & and_mask) | or_value);
+}
+/* set 27MHz on AUX_CLK */
+void netup_initialize(struct cx23885_dev *dev)
+{
+       struct cx23885_i2c *i2c_bus = &dev->i2c_bus[2];
+       struct i2c_adapter *i2c = &i2c_bus->i2c_adap;
+
+       /* Stop microcontroller */
+       i2c_av_and_or(i2c, 0x803, ~0x10, 0x00);
+
+       /* Aux PLL frac for 27 MHz */
+       i2c_av_write4(i2c, 0x114, 0xea0eb3);
+
+       /* Aux PLL int for 27 MHz */
+       i2c_av_write4(i2c, 0x110, 0x090319);
+
+       /* start microcontroller */
+       i2c_av_and_or(i2c, 0x803, ~0x10, 0x10);
+}
diff --git a/drivers/media/pci/cx23885/netup-init.h b/drivers/media/pci/cx23885/netup-init.h
new file mode 100644 (file)
index 0000000..d26ae4b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * netup-init.h
+ *
+ * NetUP Dual DVB-S2 CI driver
+ *
+ * Copyright (C) 2009 NetUP Inc.
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
+ * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
+ *
+ * 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.
+ */
+extern void netup_initialize(struct cx23885_dev *dev);
diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig
new file mode 100644 (file)
index 0000000..5f6b542
--- /dev/null
@@ -0,0 +1,34 @@
+config VIDEO_CX25821
+       tristate "Conexant cx25821 support"
+       depends on DVB_CORE && VIDEO_DEV && PCI && I2C
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEO_TVEEPROM
+       depends on RC_CORE
+       select VIDEOBUF_DVB
+       select VIDEOBUF_DMA_SG
+       select VIDEO_CX25840
+       select VIDEO_CX2341X
+       ---help---
+         This is a video4linux driver for Conexant 25821 based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx25821
+
+config VIDEO_CX25821_ALSA
+       tristate "Conexant 25821 DMA audio support"
+       depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio on
+         Conexant 25821 based capture cards using ALSA.
+
+         It only works with boards with function 01 enabled.
+         To check if your board supports, use lspci -n.
+         If supported, you should see 14f1:8801 or 14f1:8811
+         PCI device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx25821-alsa.
+
diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile
new file mode 100644 (file)
index 0000000..1434e80
--- /dev/null
@@ -0,0 +1,13 @@
+cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
+                      cx25821-gpio.o cx25821-medusa-video.o \
+                      cx25821-video.o cx25821-video-upstream.o \
+                      cx25821-video-upstream-ch2.o \
+                      cx25821-audio-upstream.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
+
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
new file mode 100644 (file)
index 0000000..1858a45
--- /dev/null
@@ -0,0 +1,784 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *     Based on SAA713x ALSA driver and CX88 driver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, version 2
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL     SRAM_CH08
+
+#define dprintk(level, fmt, arg...)                            \
+do {                                                           \
+       if (debug >= level)                                     \
+               pr_info("%s/1: " fmt, chip->dev->name, ##arg);  \
+} while (0)
+#define dprintk_core(level, fmt, arg...)                               \
+do {                                                                   \
+       if (debug >= level)                                             \
+               printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
+
+/****************************************************************************
+       Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
+static int devno;
+
+struct cx25821_audio_buffer {
+       unsigned int bpl;
+       struct btcx_riscmem risc;
+       struct videobuf_dmabuf dma;
+};
+
+struct cx25821_audio_dev {
+       struct cx25821_dev *dev;
+       struct cx25821_dmaqueue q;
+
+       /* pci i/o */
+       struct pci_dev *pci;
+
+       /* audio controls */
+       int irq;
+
+       struct snd_card *card;
+
+       unsigned long iobase;
+       spinlock_t reg_lock;
+       atomic_t count;
+
+       unsigned int dma_size;
+       unsigned int period_size;
+       unsigned int num_periods;
+
+       struct videobuf_dmabuf *dma_risc;
+
+       struct cx25821_audio_buffer *buf;
+
+       struct snd_pcm_substream *substream;
+};
+
+
+/****************************************************************************
+                       Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
+static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
+
+/****************************************************************************
+                               Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
+MODULE_AUTHOR("Hiep Huynh");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");  /* "{{Conexant,23881}," */
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+                       Module specific funtions
+ ****************************************************************************/
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4)      /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET 0x3
+
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
+{
+       struct cx25821_audio_buffer *buf = chip->buf;
+       struct cx25821_dev *dev = chip->dev;
+       struct sram_channel *audio_ch =
+           &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
+       u32 tmp = 0;
+
+       /* enable output on the GPIO 0 for the MCLK ADC (Audio) */
+       cx25821_set_gpiopin_direction(chip->dev, 0, 0);
+
+       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+       cx_clear(AUD_INT_DMA_CTL,
+                FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+       /* setup fifo + format - out channel */
+       cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl,
+                                        buf->risc.dma);
+
+       /* sets bpl size */
+       cx_write(AUD_A_LNGTH, buf->bpl);
+
+       /* reset counter */
+       /* GP_COUNT_CONTROL_RESET = 0x3 */
+       cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+       atomic_set(&chip->count, 0);
+
+       /* Set the input mode to 16-bit */
+       tmp = cx_read(AUD_A_CFG);
+       cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+                FLD_AUD_CLK_ENABLE);
+
+       /*
+       pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n",
+               buf->bpl, audio_ch->cmds_start,
+               cx_read(audio_ch->cmds_start + 12)>>1,
+               chip->num_periods, buf->bpl * chip->num_periods);
+       */
+
+       /* Enables corresponding bits at AUD_INT_STAT */
+       cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF |
+                FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR);
+
+       /* Clean any pending interrupt bits already set */
+       cx_write(AUD_A_INT_STAT, ~0);
+
+       /* enable audio irqs */
+       cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+       /* Turn on audio downstream fifo and risc enable 0x101 */
+       tmp = cx_read(AUD_INT_DMA_CTL);
+       cx_set(AUD_INT_DMA_CTL, tmp |
+              (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+
+       mdelay(100);
+       return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
+{
+       struct cx25821_dev *dev = chip->dev;
+
+       /* stop dma */
+       cx_clear(AUD_INT_DMA_CTL,
+                FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+       /* disable irqs */
+       cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+       cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+                AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+       return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx25821_aud_irqs[32] = {
+       "dn_risci1", "up_risci1", "rds_dn_risc1",       /* 0-2 */
+       NULL,                                           /* reserved */
+       "dn_risci2", "up_risci2", "rds_dn_risc2",       /* 4-6 */
+       NULL,                                           /* reserved */
+       "dnf_of", "upf_uf", "rds_dnf_uf",               /* 8-10 */
+       NULL,                                           /* reserved */
+       "dn_sync", "up_sync", "rds_dn_sync",            /* 12-14 */
+       NULL,                                           /* reserved */
+       "opc_err", "par_err", "rip_err",                /* 16-18 */
+       "pci_abort", "ber_irq", "mchg_irq"              /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
+                           u32 mask)
+{
+       struct cx25821_dev *dev = chip->dev;
+
+       if (0 == (status & mask))
+               return;
+
+       cx_write(AUD_A_INT_STAT, status);
+       if (debug > 1 || (status & mask & ~0xff))
+               cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs,
+                               ARRAY_SIZE(cx25821_aud_irqs), status, mask);
+
+       /* risc op code error */
+       if (status & AUD_INT_OPC_ERR) {
+               pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name);
+
+               cx_clear(AUD_INT_DMA_CTL,
+                        FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+               cx25821_sram_channel_dump_audio(dev,
+                               &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]);
+       }
+       if (status & AUD_INT_DN_SYNC) {
+               pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
+               cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+               return;
+       }
+
+       /* risc1 downstream */
+       if (status & AUD_INT_DN_RISCI1) {
+               atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
+               snd_pcm_period_elapsed(chip->substream);
+       }
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+       struct cx25821_audio_dev *chip = dev_id;
+       struct cx25821_dev *dev = chip->dev;
+       u32 status, pci_status;
+       u32 audint_status, audint_mask;
+       int loop, handled = 0;
+
+       audint_status = cx_read(AUD_A_INT_STAT);
+       audint_mask = cx_read(AUD_A_INT_MSK);
+       status = cx_read(PCI_INT_STAT);
+
+       for (loop = 0; loop < 1; loop++) {
+               status = cx_read(PCI_INT_STAT);
+               if (0 == status) {
+                       status = cx_read(PCI_INT_STAT);
+                       audint_status = cx_read(AUD_A_INT_STAT);
+                       audint_mask = cx_read(AUD_A_INT_MSK);
+
+                       if (status) {
+                               handled = 1;
+                               cx_write(PCI_INT_STAT, status);
+
+                               cx25821_aud_irq(chip, audint_status,
+                                               audint_mask);
+                               break;
+                       } else {
+                               goto out;
+                       }
+               }
+
+               handled = 1;
+               cx_write(PCI_INT_STAT, status);
+
+               cx25821_aud_irq(chip, audint_status, audint_mask);
+       }
+
+       pci_status = cx_read(PCI_INT_STAT);
+
+       if (handled)
+               cx_write(PCI_INT_STAT, pci_status);
+
+out:
+       return IRQ_RETVAL(handled);
+}
+
+static int dsp_buffer_free(struct cx25821_audio_dev *chip)
+{
+       BUG_ON(!chip->dma_size);
+
+       dprintk(2, "Freeing buffer\n");
+       videobuf_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);
+
+       chip->dma_risc = NULL;
+       chip->dma_size = 0;
+
+       return 0;
+}
+
+/****************************************************************************
+                               ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE      384
+static struct snd_pcm_hardware snd_cx25821_digital_hw = {
+       .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_48000,
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* Analog audio output will be full of clicks and pops if there
+          are not exactly four lines in the SRAM FIFO buffer.  */
+       .period_bytes_min = DEFAULT_FIFO_SIZE / 3,
+       .period_bytes_max = DEFAULT_FIFO_SIZE / 3,
+       .periods_min = 1,
+       .periods_max = AUDIO_LINE_SIZE,
+       /* 128 * 128 = 16384 = 1024 * 16 */
+       .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
+       unsigned int bpl = 0;
+
+       if (!chip) {
+               pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       err = snd_pcm_hw_constraint_pow2(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               goto _error;
+
+       chip->substream = substream;
+
+       runtime->hw = snd_cx25821_digital_hw;
+
+       if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+           DEFAULT_FIFO_SIZE) {
+               /* since there are 3 audio Clusters */
+               bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;
+               bpl &= ~7;      /* must be multiple of 8 */
+
+               if (bpl > AUDIO_LINE_SIZE)
+                       bpl = AUDIO_LINE_SIZE;
+
+               runtime->hw.period_bytes_min = bpl;
+               runtime->hw.period_bytes_max = bpl;
+       }
+
+       return 0;
+_error:
+       dprintk(1, "Error opening PCM!\n");
+       return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx25821_close(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
+                                struct snd_pcm_hw_params *hw_params)
+{
+       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+       struct videobuf_dmabuf *dma;
+
+       struct cx25821_audio_buffer *buf;
+       int ret;
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       chip->period_size = params_period_bytes(hw_params);
+       chip->num_periods = params_periods(hw_params);
+       chip->dma_size = chip->period_size * params_periods(hw_params);
+
+       BUG_ON(!chip->dma_size);
+       BUG_ON(chip->num_periods & (chip->num_periods - 1));
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (NULL == buf)
+               return -ENOMEM;
+
+       if (chip->period_size > AUDIO_LINE_SIZE)
+               chip->period_size = AUDIO_LINE_SIZE;
+
+       buf->bpl = chip->period_size;
+
+       dma = &buf->dma;
+       videobuf_dma_init(dma);
+       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+       if (ret < 0)
+               goto error;
+
+       ret = videobuf_dma_map(&chip->pci->dev, dma);
+       if (ret < 0)
+               goto error;
+
+       ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+                       chip->period_size, chip->num_periods, 1);
+       if (ret < 0) {
+               pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
+               goto error;
+       }
+
+       /* Loop back to start of program */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
+
+       chip->buf = buf;
+       chip->dma_risc = dma;
+
+       substream->runtime->dma_area = chip->dma_risc->vaddr;
+       substream->runtime->dma_bytes = chip->dma_size;
+       substream->runtime->dma_addr = 0;
+
+       return 0;
+
+error:
+       kfree(buf);
+       return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
+{
+       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream,
+                                   int cmd)
+{
+       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+       int err = 0;
+
+       /* Local interrupts are already disabled by ALSA */
+       spin_lock(&chip->reg_lock);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               err = _cx25821_start_audio_dma(chip);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               err = _cx25821_stop_audio_dma(chip);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+
+       spin_unlock(&chip->reg_lock);
+
+       return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream
+                                            *substream)
+{
+       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       u16 count;
+
+       count = atomic_read(&chip->count);
+
+       return runtime->period_size * (count & (runtime->periods - 1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
+                                    unsigned long offset)
+{
+       void *pageptr = substream->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx25821_pcm_ops = {
+       .open = snd_cx25821_pcm_open,
+       .close = snd_cx25821_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_cx25821_hw_params,
+       .hw_free = snd_cx25821_hw_free,
+       .prepare = snd_cx25821_prepare,
+       .trigger = snd_cx25821_card_trigger,
+       .pointer = snd_cx25821_pointer,
+       .page = snd_cx25821_page,
+};
+
+/*
+ * ALSA create a PCM device:  Called when initializing the board.
+ * Sets up the name and hooks up the callbacks
+ */
+static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
+                          char *name)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+       if (err < 0) {
+               pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
+               return err;
+       }
+       pcm->private_data = chip;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, name);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
+
+       return 0;
+}
+
+/****************************************************************************
+                       Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = {
+       {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*
+ * Not used in the function snd_cx25821_dev_free so removing
+ * from the file.
+ */
+/*
+static int snd_cx25821_free(struct cx25821_audio_dev *chip)
+{
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
+
+       cx25821_dev_unregister(chip->dev);
+       pci_disable_device(chip->pci);
+
+       return 0;
+}
+*/
+
+/*
+ * Component Destructor
+ */
+static void snd_cx25821_dev_free(struct snd_card *card)
+{
+       struct cx25821_audio_dev *chip = card->private_data;
+
+       /* snd_cx25821_free(chip); */
+       snd_card_free(chip->card);
+}
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+       struct snd_card *card;
+       struct cx25821_audio_dev *chip;
+       int err;
+
+       if (devno >= SNDRV_CARDS) {
+               pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
+               return -ENODEV;
+       }
+
+       if (!enable[devno]) {
+               ++devno;
+               pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
+               return -ENOENT;
+       }
+
+       err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+                       sizeof(struct cx25821_audio_dev), &card);
+       if (err < 0) {
+               pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
+                       __func__);
+               return err;
+       }
+
+       strcpy(card->driver, "cx25821");
+
+       /* Card "creation" */
+       card->private_free = snd_cx25821_dev_free;
+       chip = card->private_data;
+       spin_lock_init(&chip->reg_lock);
+
+       chip->dev = dev;
+       chip->card = card;
+       chip->pci = dev->pci;
+       chip->iobase = pci_resource_start(dev->pci, 0);
+
+       chip->irq = dev->pci->irq;
+
+       err = request_irq(dev->pci->irq, cx25821_irq,
+                         IRQF_SHARED, chip->dev->name, chip);
+
+       if (err < 0) {
+               pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
+                       dev->pci->irq);
+               goto error;
+       }
+
+       err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
+       if (err < 0) {
+               pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+                       __func__);
+               goto error;
+       }
+
+       snd_card_set_dev(card, &chip->pci->dev);
+
+       strcpy(card->shortname, "cx25821");
+       sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
+               chip->iobase, chip->irq);
+       strcpy(card->mixername, "CX25821");
+
+       pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
+               devno);
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               pr_info("DEBUG ERROR: cannot register sound card %s\n",
+                       __func__);
+               goto error;
+       }
+
+       snd_cx25821_cards[devno] = card;
+
+       devno++;
+       return 0;
+
+error:
+       snd_card_free(card);
+       return err;
+}
+
+/****************************************************************************
+                               LINUX MODULE INIT
+ ****************************************************************************/
+static void cx25821_audio_fini(void)
+{
+       snd_card_free(snd_cx25821_cards[0]);
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+       struct cx25821_dev *dev = NULL;
+       struct list_head *list;
+
+       mutex_lock(&cx25821_devlist_mutex);
+       list_for_each(list, &cx25821_devlist) {
+               dev = list_entry(list, struct cx25821_dev, devlist);
+               cx25821_audio_initdev(dev);
+       }
+       mutex_unlock(&cx25821_devlist_mutex);
+
+       if (dev == NULL)
+               pr_info("ERROR ALSA: no cx25821 cards found\n");
+
+       return 0;
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
new file mode 100644 (file)
index 0000000..8b2a999
--- /dev/null
@@ -0,0 +1,778 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-audio-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
+                       FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+                                             struct sram_channel *ch,
+                                             unsigned int bpl, u32 risc)
+{
+       unsigned int i, lines;
+       u32 cdt;
+
+       if (ch->cmds_start == 0) {
+               cx_write(ch->ptr1_reg, 0);
+               cx_write(ch->ptr2_reg, 0);
+               cx_write(ch->cnt2_reg, 0);
+               cx_write(ch->cnt1_reg, 0);
+               return 0;
+       }
+
+       bpl = (bpl + 7) & ~7;   /* alignment */
+       cdt = ch->cdt;
+       lines = ch->fifo_size / bpl;
+
+       if (lines > 3)
+               lines = 3;
+
+       BUG_ON(lines < 2);
+
+       /* write CDT */
+       for (i = 0; i < lines; i++) {
+               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+               cx_write(cdt + 16 * i + 4, 0);
+               cx_write(cdt + 16 * i + 8, 0);
+               cx_write(cdt + 16 * i + 12, 0);
+       }
+
+       /* write CMDS */
+       cx_write(ch->cmds_start + 0, risc);
+
+       cx_write(ch->cmds_start + 4, 0);
+       cx_write(ch->cmds_start + 8, cdt);
+       cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);
+       cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+       /* IQ size */
+       cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);
+
+       for (i = 24; i < 80; i += 4)
+               cx_write(ch->cmds_start + i, 0);
+
+       /* fill registers */
+       cx_write(ch->ptr1_reg, ch->fifo_start);
+       cx_write(ch->ptr2_reg, cdt);
+       cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);
+       cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);
+
+       return 0;
+}
+
+static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
+                                                __le32 *rp,
+                                                dma_addr_t databuf_phys_addr,
+                                                unsigned int bpl,
+                                                int fifo_enable)
+{
+       unsigned int line;
+       struct sram_channel *sram_ch =
+               dev->channels[dev->_audio_upstream_channel].sram_channels;
+       int offset = 0;
+
+       /* scan lines */
+       for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) {
+               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+               *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+
+               /* Check if we need to enable the FIFO
+                * after the first 3 lines.
+                * For the upstream audio channel,
+                * the risc engine will enable the FIFO */
+               if (fifo_enable && line == 2) {
+                       *(rp++) = RISC_WRITECR;
+                       *(rp++) = sram_ch->dma_ctl;
+                       *(rp++) = sram_ch->fld_aud_fifo_en;
+                       *(rp++) = 0x00000020;
+               }
+
+               offset += AUDIO_LINE_SIZE;
+       }
+
+       return rp;
+}
+
+int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+                                      struct pci_dev *pci,
+                                      unsigned int bpl, unsigned int lines)
+{
+       __le32 *rp;
+       int fifo_enable = 0;
+       int frame = 0, i = 0;
+       int frame_size = AUDIO_DATA_BUF_SZ;
+       int databuf_offset = 0;
+       int risc_flag = RISC_CNT_INC;
+       dma_addr_t risc_phys_jump_addr;
+
+       /* Virtual address of Risc buffer program */
+       rp = dev->_risc_virt_addr;
+
+       /* sync instruction */
+       *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);
+
+       for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) {
+               databuf_offset = frame_size * frame;
+
+               if (frame == 0) {
+                       fifo_enable = 1;
+                       risc_flag = RISC_CNT_RESET;
+               } else {
+                       fifo_enable = 0;
+                       risc_flag = RISC_CNT_INC;
+               }
+
+               /* Calculate physical jump address */
+               if ((frame + 1) == NUM_AUDIO_FRAMES) {
+                       risc_phys_jump_addr =
+                           dev->_risc_phys_start_addr +
+                           RISC_SYNC_INSTRUCTION_SIZE;
+               } else {
+                       risc_phys_jump_addr =
+                           dev->_risc_phys_start_addr +
+                           RISC_SYNC_INSTRUCTION_SIZE +
+                           AUDIO_RISC_DMA_BUF_SIZE * (frame + 1);
+               }
+
+               rp = cx25821_risc_field_upstream_audio(dev, rp,
+                               dev->_audiodata_buf_phys_addr + databuf_offset,
+                               bpl, fifo_enable);
+
+               if (USE_RISC_NOOP_AUDIO) {
+                       for (i = 0; i < NUM_NO_OPS; i++)
+                               *(rp++) = cpu_to_le32(RISC_NOOP);
+               }
+
+               /* Loop to (Nth)FrameRISC or to Start of Risc program &
+                * generate IRQ */
+               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+               *(rp++) = cpu_to_le32(0);
+
+               /* Recalculate virtual address based on frame index */
+               rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
+                       (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+       }
+
+       return 0;
+}
+
+void cx25821_free_memory_audio(struct cx25821_dev *dev)
+{
+       if (dev->_risc_virt_addr) {
+               pci_free_consistent(dev->pci, dev->_audiorisc_size,
+                                   dev->_risc_virt_addr, dev->_risc_phys_addr);
+               dev->_risc_virt_addr = NULL;
+       }
+
+       if (dev->_audiodata_buf_virt_addr) {
+               pci_free_consistent(dev->pci, dev->_audiodata_buf_size,
+                                   dev->_audiodata_buf_virt_addr,
+                                   dev->_audiodata_buf_phys_addr);
+               dev->_audiodata_buf_virt_addr = NULL;
+       }
+}
+
+void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
+{
+       struct sram_channel *sram_ch =
+               dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
+       u32 tmp = 0;
+
+       if (!dev->_audio_is_running) {
+               printk(KERN_DEBUG
+                      pr_fmt("No audio file is currently running so return!\n"));
+               return;
+       }
+       /* Disable RISC interrupts */
+       cx_write(sram_ch->int_msk, 0);
+
+       /* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */
+       tmp = cx_read(sram_ch->dma_ctl);
+       cx_write(sram_ch->dma_ctl,
+                tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en));
+
+       /* Clear data buffer memory */
+       if (dev->_audiodata_buf_virt_addr)
+               memset(dev->_audiodata_buf_virt_addr, 0,
+                      dev->_audiodata_buf_size);
+
+       dev->_audio_is_running = 0;
+       dev->_is_first_audio_frame = 0;
+       dev->_audioframe_count = 0;
+       dev->_audiofile_status = END_OF_FILE;
+
+       kfree(dev->_irq_audio_queues);
+       dev->_irq_audio_queues = NULL;
+
+       kfree(dev->_audiofilename);
+}
+
+void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
+{
+       if (dev->_audio_is_running)
+               cx25821_stop_upstream_audio(dev);
+
+       cx25821_free_memory_audio(dev);
+}
+
+int cx25821_get_audio_data(struct cx25821_dev *dev,
+                          struct sram_channel *sram_ch)
+{
+       struct file *myfile;
+       int frame_index_temp = dev->_audioframe_index;
+       int i = 0;
+       int line_size = AUDIO_LINE_SIZE;
+       int frame_size = AUDIO_DATA_BUF_SZ;
+       int frame_offset = frame_size * frame_index_temp;
+       ssize_t vfs_read_retval = 0;
+       char mybuf[line_size];
+       loff_t file_offset = dev->_audioframe_count * frame_size;
+       loff_t pos;
+       mm_segment_t old_fs;
+
+       if (dev->_audiofile_status == END_OF_FILE)
+               return 0;
+
+       myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+       if (IS_ERR(myfile)) {
+               const int open_errno = -PTR_ERR(myfile);
+               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+                      __func__, dev->_audiofilename, open_errno);
+               return PTR_ERR(myfile);
+       } else {
+               if (!(myfile->f_op)) {
+                       pr_err("%s(): File has no file operations registered!\n",
+                               __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               if (!myfile->f_op->read) {
+                       pr_err("%s(): File has no READ operations registered!\n",
+                               __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               pos = myfile->f_pos;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               for (i = 0; i < dev->_audio_lines_count; i++) {
+                       pos = file_offset;
+
+                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+                                                                       &pos);
+
+                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
+                           && dev->_audiodata_buf_virt_addr != NULL) {
+                               memcpy((void *)(dev->_audiodata_buf_virt_addr +
+                                               frame_offset / 4), mybuf,
+                                       vfs_read_retval);
+                       }
+
+                       file_offset += vfs_read_retval;
+                       frame_offset += vfs_read_retval;
+
+                       if (vfs_read_retval < line_size) {
+                               pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+                                       __func__);
+                               break;
+                       }
+               }
+
+               if (i > 0)
+                       dev->_audioframe_count++;
+
+               dev->_audiofile_status = (vfs_read_retval == line_size) ?
+                                               IN_PROGRESS : END_OF_FILE;
+
+               set_fs(old_fs);
+               filp_close(myfile, NULL);
+       }
+
+       return 0;
+}
+
+static void cx25821_audioups_handler(struct work_struct *work)
+{
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+                       _audio_work_entry);
+
+       if (!dev) {
+               pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+                       __func__);
+               return;
+       }
+
+       cx25821_get_audio_data(dev, dev->channels[dev->_audio_upstream_channel].
+                       sram_channels);
+}
+
+int cx25821_openfile_audio(struct cx25821_dev *dev,
+                          struct sram_channel *sram_ch)
+{
+       struct file *myfile;
+       int i = 0, j = 0;
+       int line_size = AUDIO_LINE_SIZE;
+       ssize_t vfs_read_retval = 0;
+       char mybuf[line_size];
+       loff_t pos;
+       loff_t offset = (unsigned long)0;
+       mm_segment_t old_fs;
+
+       myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+       if (IS_ERR(myfile)) {
+               const int open_errno = -PTR_ERR(myfile);
+               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+                       __func__, dev->_audiofilename, open_errno);
+               return PTR_ERR(myfile);
+       } else {
+               if (!(myfile->f_op)) {
+                       pr_err("%s(): File has no file operations registered!\n",
+                               __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               if (!myfile->f_op->read) {
+                       pr_err("%s(): File has no READ operations registered!\n",
+                               __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               pos = myfile->f_pos;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
+                       for (i = 0; i < dev->_audio_lines_count; i++) {
+                               pos = offset;
+
+                               vfs_read_retval = vfs_read(myfile, mybuf,
+                                               line_size, &pos);
+
+                               if (vfs_read_retval > 0 &&
+                                   vfs_read_retval == line_size &&
+                                   dev->_audiodata_buf_virt_addr != NULL) {
+                                       memcpy((void *)(dev->
+                                                       _audiodata_buf_virt_addr
+                                                       + offset / 4), mybuf,
+                                              vfs_read_retval);
+                               }
+
+                               offset += vfs_read_retval;
+
+                               if (vfs_read_retval < line_size) {
+                                       pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+                                               __func__);
+                                       break;
+                               }
+                       }
+
+                       if (i > 0)
+                               dev->_audioframe_count++;
+
+                       if (vfs_read_retval < line_size)
+                               break;
+               }
+
+               dev->_audiofile_status = (vfs_read_retval == line_size) ?
+                                               IN_PROGRESS : END_OF_FILE;
+
+               set_fs(old_fs);
+               myfile->f_pos = 0;
+               filp_close(myfile, NULL);
+       }
+
+       return 0;
+}
+
+static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
+                                                struct sram_channel *sram_ch,
+                                                int bpl)
+{
+       int ret = 0;
+       dma_addr_t dma_addr;
+       dma_addr_t data_dma_addr;
+
+       cx25821_free_memory_audio(dev);
+
+       dev->_risc_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->audio_upstream_riscbuf_size, &dma_addr);
+       dev->_risc_virt_start_addr = dev->_risc_virt_addr;
+       dev->_risc_phys_start_addr = dma_addr;
+       dev->_risc_phys_addr = dma_addr;
+       dev->_audiorisc_size = dev->audio_upstream_riscbuf_size;
+
+       if (!dev->_risc_virt_addr) {
+               printk(KERN_DEBUG
+                       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
+               return -ENOMEM;
+       }
+       /* Clear out memory at address */
+       memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
+
+       /* For Audio Data buffer allocation */
+       dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->audio_upstream_databuf_size, &data_dma_addr);
+       dev->_audiodata_buf_phys_addr = data_dma_addr;
+       dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
+
+       if (!dev->_audiodata_buf_virt_addr) {
+               printk(KERN_DEBUG
+                       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
+               return -ENOMEM;
+       }
+       /* Clear out memory at address */
+       memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size);
+
+       ret = cx25821_openfile_audio(dev, sram_ch);
+       if (ret < 0)
+               return ret;
+
+       /* Creating RISC programs */
+       ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+                                               dev->_audio_lines_count);
+       if (ret < 0) {
+               printk(KERN_DEBUG
+                       pr_fmt("ERROR creating audio upstream RISC programs!\n"));
+               goto error;
+       }
+
+       return 0;
+
+error:
+       return ret;
+}
+
+int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+                              u32 status)
+{
+       int i = 0;
+       u32 int_msk_tmp;
+       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+       dma_addr_t risc_phys_jump_addr;
+       __le32 *rp;
+
+       if (status & FLD_AUD_SRC_RISCI1) {
+               /* Get interrupt_index of the program that interrupted */
+               u32 prog_cnt = cx_read(channel->gpcnt);
+
+               /* Since we've identified our IRQ, clear our bits from the
+                * interrupt mask and interrupt status registers */
+               cx_write(channel->int_msk, 0);
+               cx_write(channel->int_stat, cx_read(channel->int_stat));
+
+               spin_lock(&dev->slock);
+
+               while (prog_cnt != dev->_last_index_irq) {
+                       /* Update _last_index_irq */
+                       if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1))
+                               dev->_last_index_irq++;
+                       else
+                               dev->_last_index_irq = 0;
+
+                       dev->_audioframe_index = dev->_last_index_irq;
+
+                       queue_work(dev->_irq_audio_queues,
+                                  &dev->_audio_work_entry);
+               }
+
+               if (dev->_is_first_audio_frame) {
+                       dev->_is_first_audio_frame = 0;
+
+                       if (dev->_risc_virt_start_addr != NULL) {
+                               risc_phys_jump_addr =
+                                       dev->_risc_phys_start_addr +
+                                       RISC_SYNC_INSTRUCTION_SIZE +
+                                       AUDIO_RISC_DMA_BUF_SIZE;
+
+                               rp = cx25821_risc_field_upstream_audio(dev,
+                                               dev->_risc_virt_start_addr + 1,
+                                               dev->_audiodata_buf_phys_addr,
+                                               AUDIO_LINE_SIZE, FIFO_DISABLE);
+
+                               if (USE_RISC_NOOP_AUDIO) {
+                                       for (i = 0; i < NUM_NO_OPS; i++) {
+                                               *(rp++) =
+                                                   cpu_to_le32(RISC_NOOP);
+                                       }
+                               }
+                               /* Jump to 2nd Audio Frame */
+                               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 |
+                                               RISC_CNT_RESET);
+                               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+                               *(rp++) = cpu_to_le32(0);
+                       }
+               }
+
+               spin_unlock(&dev->slock);
+       } else {
+               if (status & FLD_AUD_SRC_OF)
+                       pr_warn("%s(): Audio Received Overflow Error Interrupt!\n",
+                               __func__);
+
+               if (status & FLD_AUD_SRC_SYNC)
+                       pr_warn("%s(): Audio Received Sync Error Interrupt!\n",
+                               __func__);
+
+               if (status & FLD_AUD_SRC_OPC_ERR)
+                       pr_warn("%s(): Audio Received OpCode Error Interrupt!\n",
+                               __func__);
+
+               /* Read and write back the interrupt status register to clear
+                * our bits */
+               cx_write(channel->int_stat, cx_read(channel->int_stat));
+       }
+
+       if (dev->_audiofile_status == END_OF_FILE) {
+               pr_warn("EOF Channel Audio Framecount = %d\n",
+                       dev->_audioframe_count);
+               return -1;
+       }
+       /* ElSE, set the interrupt mask register, re-enable irq. */
+       int_msk_tmp = cx_read(channel->int_msk);
+       cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+       return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)
+{
+       struct cx25821_dev *dev = dev_id;
+       u32 audio_status;
+       int handled = 0;
+       struct sram_channel *sram_ch;
+
+       if (!dev)
+               return -1;
+
+       sram_ch = dev->channels[dev->_audio_upstream_channel].sram_channels;
+
+       audio_status = cx_read(sram_ch->int_stat);
+
+       /* Only deal with our interrupt */
+       if (audio_status) {
+               handled = cx25821_audio_upstream_irq(dev,
+                               dev->_audio_upstream_channel, audio_status);
+       }
+
+       if (handled < 0)
+               cx25821_stop_upstream_audio(dev);
+       else
+               handled += handled;
+
+       return IRQ_RETVAL(handled);
+}
+
+static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
+                                    struct sram_channel *sram_ch)
+{
+       int count = 0;
+       u32 tmp;
+
+       do {
+               /* Wait 10 microsecond before checking to see if the FIFO is
+                * turned ON. */
+               udelay(10);
+
+               tmp = cx_read(sram_ch->dma_ctl);
+
+               /* 10 millisecond timeout */
+               if (count++ > 1000) {
+                       pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
+                               __func__);
+                       return;
+               }
+
+       } while (!(tmp & sram_ch->fld_aud_fifo_en));
+
+}
+
+int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+                                    struct sram_channel *sram_ch)
+{
+       u32 tmp = 0;
+       int err = 0;
+
+       /* Set the physical start address of the RISC program in the initial
+        * program counter(IPC) member of the CMDS. */
+       cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);
+       /* Risc IPC High 64 bits 63-32 */
+       cx_write(sram_ch->cmds_start + 4, 0);
+
+       /* reset counter */
+       cx_write(sram_ch->gpcnt_ctl, 3);
+
+       /* Set the line length       (It looks like we do not need to set the
+        * line length) */
+       cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH);
+
+       /* Set the input mode to 16-bit */
+       tmp = cx_read(sram_ch->aud_cfg);
+       tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+               FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D |
+               FLD_AUD_SONY_MODE;
+       cx_write(sram_ch->aud_cfg, tmp);
+
+       /* Read and write back the interrupt status register to clear it */
+       tmp = cx_read(sram_ch->int_stat);
+       cx_write(sram_ch->int_stat, tmp);
+
+       /* Clear our bits from the interrupt status register. */
+       cx_write(sram_ch->int_stat, _intr_msk);
+
+       /* Set the interrupt mask register, enable irq. */
+       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+       tmp = cx_read(sram_ch->int_msk);
+       cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+       err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+                       IRQF_SHARED, dev->name, dev);
+       if (err < 0) {
+               pr_err("%s: can't get upstream IRQ %d\n", dev->name,
+                               dev->pci->irq);
+               goto fail_irq;
+       }
+
+       /* Start the DMA  engine */
+       tmp = cx_read(sram_ch->dma_ctl);
+       cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en);
+
+       dev->_audio_is_running = 1;
+       dev->_is_first_audio_frame = 1;
+
+       /* The fifo_en bit turns on by the first Risc program */
+       cx25821_wait_fifo_enable(dev, sram_ch);
+
+       return 0;
+
+fail_irq:
+       cx25821_dev_unregister(dev);
+       return err;
+}
+
+int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
+{
+       struct sram_channel *sram_ch;
+       int retval = 0;
+       int err = 0;
+       int str_length = 0;
+
+       if (dev->_audio_is_running) {
+               pr_warn("Audio Channel is still running so return!\n");
+               return 0;
+       }
+
+       dev->_audio_upstream_channel = channel_select;
+       sram_ch = dev->channels[channel_select].sram_channels;
+
+       /* Work queue */
+       INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);
+       dev->_irq_audio_queues =
+           create_singlethread_workqueue("cx25821_audioworkqueue");
+
+       if (!dev->_irq_audio_queues) {
+               printk(KERN_DEBUG
+                       pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
+               return -ENOMEM;
+       }
+
+       dev->_last_index_irq = 0;
+       dev->_audio_is_running = 0;
+       dev->_audioframe_count = 0;
+       dev->_audiofile_status = RESET_STATUS;
+       dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
+       _line_size = AUDIO_LINE_SIZE;
+
+       if (dev->input_audiofilename) {
+               str_length = strlen(dev->input_audiofilename);
+               dev->_audiofilename = kmemdup(dev->input_audiofilename,
+                                             str_length + 1, GFP_KERNEL);
+
+               if (!dev->_audiofilename)
+                       goto error;
+
+               /* Default if filename is empty string */
+               if (strcmp(dev->input_audiofilename, "") == 0)
+                       dev->_audiofilename = "/root/audioGOOD.wav";
+       } else {
+               str_length = strlen(_defaultAudioName);
+               dev->_audiofilename = kmemdup(_defaultAudioName,
+                                             str_length + 1, GFP_KERNEL);
+
+               if (!dev->_audiofilename)
+                       goto error;
+       }
+
+       retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
+                                                       _line_size, 0);
+
+       dev->audio_upstream_riscbuf_size =
+               AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+               RISC_SYNC_INSTRUCTION_SIZE;
+       dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
+
+       /* Allocating buffers and prepare RISC program */
+       retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
+                                                       _line_size);
+       if (retval < 0) {
+               pr_err("%s: Failed to set up Audio upstream buffers!\n",
+                       dev->name);
+               goto error;
+       }
+       /* Start RISC engine */
+       cx25821_start_audio_dma_upstream(dev, sram_ch);
+
+       return 0;
+
+error:
+       cx25821_dev_unregister(dev);
+
+       return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.h b/drivers/media/pci/cx25821/cx25821-audio-upstream.h
new file mode 100644 (file)
index 0000000..af2ae7c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
+#include <linux/workqueue.h>
+
+#define NUM_AUDIO_PROGS       8
+#define NUM_AUDIO_FRAMES      8
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define NUM_NO_OPS            4
+
+#define RISC_READ_INSTRUCTION_SIZE      12
+#define RISC_JUMP_INSTRUCTION_SIZE      12
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define DWORD_SIZE                      4
+#define AUDIO_SYNC_LINE                 4
+
+#define LINES_PER_AUDIO_BUFFER      15
+#define AUDIO_LINE_SIZE             128
+#define AUDIO_DATA_BUF_SZ           (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)
+
+#define USE_RISC_NOOP_AUDIO   1
+
+#ifdef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE                                                \
+       (LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +          \
+        RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS * DWORD_SIZE +      \
+        RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE                                                \
+       (LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +          \
+        RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+static int _line_size;
+char *_defaultAudioName = "/root/audioGOOD.wav";
diff --git a/drivers/media/pci/cx25821/cx25821-audio.h b/drivers/media/pci/cx25821/cx25821-audio.h
new file mode 100644 (file)
index 0000000..1fc2d24
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __CX25821_AUDIO_H__
+#define __CX25821_AUDIO_H__
+
+#define USE_RISC_NOOP          1
+#define LINES_PER_BUFFER       15
+#define AUDIO_LINE_SIZE                128
+
+/* Number of buffer programs to use at once. */
+#define NUMBER_OF_PROGRAMS     8
+
+/*
+ * Max size of the RISC program for a buffer. - worst case is 2 writes per line
+ * Space is also added for the 4 no-op instructions added on the end.
+ */
+#ifndef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE                                                \
+       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +           \
+        RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#endif
+
+/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
+#ifdef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE                                                \
+       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +           \
+        RISC_NOOP_INSTRUCTION_SIZE * 4)
+#endif
+
+/* Sizes of various instructions in bytes.  Used when adding instructions. */
+#define RISC_WRITE_INSTRUCTION_SIZE    12
+#define RISC_JUMP_INSTRUCTION_SIZE     12
+#define RISC_SKIP_INSTRUCTION_SIZE     4
+#define RISC_SYNC_INSTRUCTION_SIZE     4
+#define RISC_WRITECR_INSTRUCTION_SIZE  16
+#define RISC_NOOP_INSTRUCTION_SIZE     4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE                                      \
+       (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS +                 \
+        RISC_SYNC_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-biffuncs.h b/drivers/media/pci/cx25821/cx25821-biffuncs.h
new file mode 100644 (file)
index 0000000..9326a7c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _BITFUNCS_H
+#define _BITFUNCS_H
+
+#define SetBit(Bit)  (1 << Bit)
+
+inline u8 getBit(u32 sample, u8 index)
+{
+       return (u8) ((sample >> index) & 1);
+}
+
+inline u32 clearBitAtPos(u32 value, u8 bit)
+{
+       return value & ~(1 << bit);
+}
+
+inline u32 setBitAtPos(u32 sample, u8 bit)
+{
+       sample |= (1 << bit);
+       return sample;
+
+}
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-cards.c b/drivers/media/pci/cx25821/cx25821-cards.c
new file mode 100644 (file)
index 0000000..99988c9
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *     Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+
+#include "cx25821.h"
+#include "tuner-xc2028.h"
+
+/* board config info */
+
+struct cx25821_board cx25821_boards[] = {
+       [UNKNOWN_BOARD] = {
+               .name = "UNKNOWN/GENERIC",
+               /* Ensure safe default for unknown boards */
+               .clk_freq = 0,
+       },
+
+       [CX25821_BOARD] = {
+               .name = "CX25821",
+               .portb = CX25821_RAW,
+               .portc = CX25821_264,
+               .input[0].type = CX25821_VMUX_COMPOSITE,
+       },
+
+};
+
+const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
+
+struct cx25821_subid cx25821_subids[] = {
+       {
+               .subvendor = 0x14f1,
+               .subdevice = 0x0920,
+               .card = CX25821_BOARD,
+       },
+};
+
+void cx25821_card_setup(struct cx25821_dev *dev)
+{
+       static u8 eeprom[256];
+
+       if (dev->i2c_bus[0].i2c_rc == 0) {
+               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+                               sizeof(eeprom));
+       }
+}
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
new file mode 100644 (file)
index 0000000..f11f6f0
--- /dev/null
@@ -0,0 +1,1502 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "cx25821.h"
+#include "cx25821-sram.h"
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("Driver for Athena cards");
+MODULE_AUTHOR("Shu Lin - Hiep Huynh");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+static unsigned int cx25821_devcount;
+
+DEFINE_MUTEX(cx25821_devlist_mutex);
+EXPORT_SYMBOL(cx25821_devlist_mutex);
+LIST_HEAD(cx25821_devlist);
+EXPORT_SYMBOL(cx25821_devlist);
+
+struct sram_channel cx25821_sram_channels[] = {
+       [SRAM_CH00] = {
+               .i = SRAM_CH00,
+               .name = "VID A",
+               .cmds_start = VID_A_DOWN_CMDS,
+               .ctrl_start = VID_A_IQ,
+               .cdt = VID_A_CDT,
+               .fifo_start = VID_A_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA1_PTR1,
+               .ptr2_reg = DMA1_PTR2,
+               .cnt1_reg = DMA1_CNT1,
+               .cnt2_reg = DMA1_CNT2,
+               .int_msk = VID_A_INT_MSK,
+               .int_stat = VID_A_INT_STAT,
+               .int_mstat = VID_A_INT_MSTAT,
+               .dma_ctl = VID_DST_A_DMA_CTL,
+               .gpcnt_ctl = VID_DST_A_GPCNT_CTL,
+               .gpcnt = VID_DST_A_GPCNT,
+               .vip_ctl = VID_DST_A_VIP_CTL,
+               .pix_frmt = VID_DST_A_PIX_FRMT,
+       },
+
+       [SRAM_CH01] = {
+               .i = SRAM_CH01,
+               .name = "VID B",
+               .cmds_start = VID_B_DOWN_CMDS,
+               .ctrl_start = VID_B_IQ,
+               .cdt = VID_B_CDT,
+               .fifo_start = VID_B_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA2_PTR1,
+               .ptr2_reg = DMA2_PTR2,
+               .cnt1_reg = DMA2_CNT1,
+               .cnt2_reg = DMA2_CNT2,
+               .int_msk = VID_B_INT_MSK,
+               .int_stat = VID_B_INT_STAT,
+               .int_mstat = VID_B_INT_MSTAT,
+               .dma_ctl = VID_DST_B_DMA_CTL,
+               .gpcnt_ctl = VID_DST_B_GPCNT_CTL,
+               .gpcnt = VID_DST_B_GPCNT,
+               .vip_ctl = VID_DST_B_VIP_CTL,
+               .pix_frmt = VID_DST_B_PIX_FRMT,
+       },
+
+       [SRAM_CH02] = {
+               .i = SRAM_CH02,
+               .name = "VID C",
+               .cmds_start = VID_C_DOWN_CMDS,
+               .ctrl_start = VID_C_IQ,
+               .cdt = VID_C_CDT,
+               .fifo_start = VID_C_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA3_PTR1,
+               .ptr2_reg = DMA3_PTR2,
+               .cnt1_reg = DMA3_CNT1,
+               .cnt2_reg = DMA3_CNT2,
+               .int_msk = VID_C_INT_MSK,
+               .int_stat = VID_C_INT_STAT,
+               .int_mstat = VID_C_INT_MSTAT,
+               .dma_ctl = VID_DST_C_DMA_CTL,
+               .gpcnt_ctl = VID_DST_C_GPCNT_CTL,
+               .gpcnt = VID_DST_C_GPCNT,
+               .vip_ctl = VID_DST_C_VIP_CTL,
+               .pix_frmt = VID_DST_C_PIX_FRMT,
+       },
+
+       [SRAM_CH03] = {
+               .i = SRAM_CH03,
+               .name = "VID D",
+               .cmds_start = VID_D_DOWN_CMDS,
+               .ctrl_start = VID_D_IQ,
+               .cdt = VID_D_CDT,
+               .fifo_start = VID_D_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA4_PTR1,
+               .ptr2_reg = DMA4_PTR2,
+               .cnt1_reg = DMA4_CNT1,
+               .cnt2_reg = DMA4_CNT2,
+               .int_msk = VID_D_INT_MSK,
+               .int_stat = VID_D_INT_STAT,
+               .int_mstat = VID_D_INT_MSTAT,
+               .dma_ctl = VID_DST_D_DMA_CTL,
+               .gpcnt_ctl = VID_DST_D_GPCNT_CTL,
+               .gpcnt = VID_DST_D_GPCNT,
+               .vip_ctl = VID_DST_D_VIP_CTL,
+               .pix_frmt = VID_DST_D_PIX_FRMT,
+       },
+
+       [SRAM_CH04] = {
+               .i = SRAM_CH04,
+               .name = "VID E",
+               .cmds_start = VID_E_DOWN_CMDS,
+               .ctrl_start = VID_E_IQ,
+               .cdt = VID_E_CDT,
+               .fifo_start = VID_E_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA5_PTR1,
+               .ptr2_reg = DMA5_PTR2,
+               .cnt1_reg = DMA5_CNT1,
+               .cnt2_reg = DMA5_CNT2,
+               .int_msk = VID_E_INT_MSK,
+               .int_stat = VID_E_INT_STAT,
+               .int_mstat = VID_E_INT_MSTAT,
+               .dma_ctl = VID_DST_E_DMA_CTL,
+               .gpcnt_ctl = VID_DST_E_GPCNT_CTL,
+               .gpcnt = VID_DST_E_GPCNT,
+               .vip_ctl = VID_DST_E_VIP_CTL,
+               .pix_frmt = VID_DST_E_PIX_FRMT,
+       },
+
+       [SRAM_CH05] = {
+               .i = SRAM_CH05,
+               .name = "VID F",
+               .cmds_start = VID_F_DOWN_CMDS,
+               .ctrl_start = VID_F_IQ,
+               .cdt = VID_F_CDT,
+               .fifo_start = VID_F_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA6_PTR1,
+               .ptr2_reg = DMA6_PTR2,
+               .cnt1_reg = DMA6_CNT1,
+               .cnt2_reg = DMA6_CNT2,
+               .int_msk = VID_F_INT_MSK,
+               .int_stat = VID_F_INT_STAT,
+               .int_mstat = VID_F_INT_MSTAT,
+               .dma_ctl = VID_DST_F_DMA_CTL,
+               .gpcnt_ctl = VID_DST_F_GPCNT_CTL,
+               .gpcnt = VID_DST_F_GPCNT,
+               .vip_ctl = VID_DST_F_VIP_CTL,
+               .pix_frmt = VID_DST_F_PIX_FRMT,
+       },
+
+       [SRAM_CH06] = {
+               .i = SRAM_CH06,
+               .name = "VID G",
+               .cmds_start = VID_G_DOWN_CMDS,
+               .ctrl_start = VID_G_IQ,
+               .cdt = VID_G_CDT,
+               .fifo_start = VID_G_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA7_PTR1,
+               .ptr2_reg = DMA7_PTR2,
+               .cnt1_reg = DMA7_CNT1,
+               .cnt2_reg = DMA7_CNT2,
+               .int_msk = VID_G_INT_MSK,
+               .int_stat = VID_G_INT_STAT,
+               .int_mstat = VID_G_INT_MSTAT,
+               .dma_ctl = VID_DST_G_DMA_CTL,
+               .gpcnt_ctl = VID_DST_G_GPCNT_CTL,
+               .gpcnt = VID_DST_G_GPCNT,
+               .vip_ctl = VID_DST_G_VIP_CTL,
+               .pix_frmt = VID_DST_G_PIX_FRMT,
+       },
+
+       [SRAM_CH07] = {
+               .i = SRAM_CH07,
+               .name = "VID H",
+               .cmds_start = VID_H_DOWN_CMDS,
+               .ctrl_start = VID_H_IQ,
+               .cdt = VID_H_CDT,
+               .fifo_start = VID_H_DOWN_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA8_PTR1,
+               .ptr2_reg = DMA8_PTR2,
+               .cnt1_reg = DMA8_CNT1,
+               .cnt2_reg = DMA8_CNT2,
+               .int_msk = VID_H_INT_MSK,
+               .int_stat = VID_H_INT_STAT,
+               .int_mstat = VID_H_INT_MSTAT,
+               .dma_ctl = VID_DST_H_DMA_CTL,
+               .gpcnt_ctl = VID_DST_H_GPCNT_CTL,
+               .gpcnt = VID_DST_H_GPCNT,
+               .vip_ctl = VID_DST_H_VIP_CTL,
+               .pix_frmt = VID_DST_H_PIX_FRMT,
+       },
+
+       [SRAM_CH08] = {
+               .name = "audio from",
+               .cmds_start = AUD_A_DOWN_CMDS,
+               .ctrl_start = AUD_A_IQ,
+               .cdt = AUD_A_CDT,
+               .fifo_start = AUD_A_DOWN_CLUSTER_1,
+               .fifo_size = AUDIO_CLUSTER_SIZE * 3,
+               .ptr1_reg = DMA17_PTR1,
+               .ptr2_reg = DMA17_PTR2,
+               .cnt1_reg = DMA17_CNT1,
+               .cnt2_reg = DMA17_CNT2,
+       },
+
+       [SRAM_CH09] = {
+               .i = SRAM_CH09,
+               .name = "VID Upstream I",
+               .cmds_start = VID_I_UP_CMDS,
+               .ctrl_start = VID_I_IQ,
+               .cdt = VID_I_CDT,
+               .fifo_start = VID_I_UP_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA15_PTR1,
+               .ptr2_reg = DMA15_PTR2,
+               .cnt1_reg = DMA15_CNT1,
+               .cnt2_reg = DMA15_CNT2,
+               .int_msk = VID_I_INT_MSK,
+               .int_stat = VID_I_INT_STAT,
+               .int_mstat = VID_I_INT_MSTAT,
+               .dma_ctl = VID_SRC_I_DMA_CTL,
+               .gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
+               .gpcnt = VID_SRC_I_GPCNT,
+
+               .vid_fmt_ctl = VID_SRC_I_FMT_CTL,
+               .vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
+               .vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
+               .vid_cdt_size = VID_SRC_I_CDT_SZ,
+               .irq_bit = 8,
+       },
+
+       [SRAM_CH10] = {
+               .i = SRAM_CH10,
+               .name = "VID Upstream J",
+               .cmds_start = VID_J_UP_CMDS,
+               .ctrl_start = VID_J_IQ,
+               .cdt = VID_J_CDT,
+               .fifo_start = VID_J_UP_CLUSTER_1,
+               .fifo_size = (VID_CLUSTER_SIZE << 2),
+               .ptr1_reg = DMA16_PTR1,
+               .ptr2_reg = DMA16_PTR2,
+               .cnt1_reg = DMA16_CNT1,
+               .cnt2_reg = DMA16_CNT2,
+               .int_msk = VID_J_INT_MSK,
+               .int_stat = VID_J_INT_STAT,
+               .int_mstat = VID_J_INT_MSTAT,
+               .dma_ctl = VID_SRC_J_DMA_CTL,
+               .gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
+               .gpcnt = VID_SRC_J_GPCNT,
+
+               .vid_fmt_ctl = VID_SRC_J_FMT_CTL,
+               .vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
+               .vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
+               .vid_cdt_size = VID_SRC_J_CDT_SZ,
+               .irq_bit = 9,
+       },
+
+       [SRAM_CH11] = {
+               .i = SRAM_CH11,
+               .name = "Audio Upstream Channel B",
+               .cmds_start = AUD_B_UP_CMDS,
+               .ctrl_start = AUD_B_IQ,
+               .cdt = AUD_B_CDT,
+               .fifo_start = AUD_B_UP_CLUSTER_1,
+               .fifo_size = (AUDIO_CLUSTER_SIZE * 3),
+               .ptr1_reg = DMA22_PTR1,
+               .ptr2_reg = DMA22_PTR2,
+               .cnt1_reg = DMA22_CNT1,
+               .cnt2_reg = DMA22_CNT2,
+               .int_msk = AUD_B_INT_MSK,
+               .int_stat = AUD_B_INT_STAT,
+               .int_mstat = AUD_B_INT_MSTAT,
+               .dma_ctl = AUD_INT_DMA_CTL,
+               .gpcnt_ctl = AUD_B_GPCNT_CTL,
+               .gpcnt = AUD_B_GPCNT,
+               .aud_length = AUD_B_LNGTH,
+               .aud_cfg = AUD_B_CFG,
+               .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
+               .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
+               .irq_bit = 11,
+       },
+};
+EXPORT_SYMBOL(cx25821_sram_channels);
+
+struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
+struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
+struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
+struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
+struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
+struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
+struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
+struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
+struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
+struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
+struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
+
+struct cx25821_dmaqueue mpegq;
+
+static int cx25821_risc_decode(u32 risc)
+{
+       static const char * const 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",
+       };
+       static const 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,
+       };
+       static const char * const bits[] = {
+               "12", "13", "14", "resync",
+               "cnt0", "cnt1", "18", "19",
+               "20", "21", "22", "23",
+               "irq1", "irq2", "eol", "sol",
+       };
+       int i;
+
+       pr_cont("0x%08x [ %s",
+               risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+       for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
+               if (risc & (1 << (i + 12)))
+                       pr_cont(" %s", bits[i]);
+       }
+       pr_cont(" count=%d ]\n", risc & 0xfff);
+       return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x01;
+}
+
+static void cx25821_registers_init(struct cx25821_dev *dev)
+{
+       u32 tmp;
+
+       /* enable RUN_RISC in Pecos */
+       cx_write(DEV_CNTRL2, 0x20);
+
+       /* Set the master PCI interrupt masks to enable video, audio, MBIF,
+        * and GPIO interrupts
+        * I2C interrupt masking is handled by the I2C objects themselves. */
+       cx_write(PCI_INT_MSK, 0x2001FFFF);
+
+       tmp = cx_read(RDR_TLCTL0);
+       tmp &= ~FLD_CFG_RCB_CK_EN;      /* Clear the RCB_CK_EN bit */
+       cx_write(RDR_TLCTL0, tmp);
+
+       /* PLL-A setting for the Audio Master Clock */
+       cx_write(PLL_A_INT_FRAC, 0x9807A58B);
+
+       /* PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 */
+       cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
+
+       /* clear reset bit [31] */
+       tmp = cx_read(PLL_A_INT_FRAC);
+       cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
+
+       /* PLL-B setting for Mobilygen Host Bus Interface */
+       cx_write(PLL_B_INT_FRAC, 0x9883A86F);
+
+       /* PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 */
+       cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
+
+       /* clear reset bit [31] */
+       tmp = cx_read(PLL_B_INT_FRAC);
+       cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
+
+       /* PLL-C setting for video upstream channel */
+       cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
+
+       /* PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 */
+       cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
+
+       /* clear reset bit [31] */
+       tmp = cx_read(PLL_C_INT_FRAC);
+       cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
+
+       /* PLL-D setting for audio upstream channel */
+       cx_write(PLL_D_INT_FRAC, 0x98757F5B);
+
+       /* PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 */
+       cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
+
+       /* clear reset bit [31] */
+       tmp = cx_read(PLL_D_INT_FRAC);
+       cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
+
+       /* This selects the PLL C clock source for the video upstream channel
+        * I and J */
+       tmp = cx_read(VID_CH_CLK_SEL);
+       cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
+
+       /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+        * channel A-C
+        * select 656/VIP DST for downstream Channel A - C */
+       tmp = cx_read(VID_CH_MODE_SEL);
+       /* cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); */
+       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+       /* enables 656 port I and J as output */
+       tmp = cx_read(CLK_RST);
+       /* use external ALT_PLL_REF pin as its reference clock instead */
+       tmp |= FLD_USE_ALT_PLL_REF;
+       cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
+
+       mdelay(100);
+}
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+                              struct sram_channel *ch,
+                              unsigned int bpl, u32 risc)
+{
+       unsigned int i, lines;
+       u32 cdt;
+
+       if (ch->cmds_start == 0) {
+               cx_write(ch->ptr1_reg, 0);
+               cx_write(ch->ptr2_reg, 0);
+               cx_write(ch->cnt2_reg, 0);
+               cx_write(ch->cnt1_reg, 0);
+               return 0;
+       }
+
+       bpl = (bpl + 7) & ~7;   /* alignment */
+       cdt = ch->cdt;
+       lines = ch->fifo_size / bpl;
+
+       if (lines > 4)
+               lines = 4;
+
+       BUG_ON(lines < 2);
+
+       cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       cx_write(8 + 4, 8);
+       cx_write(8 + 8, 0);
+
+       /* write CDT */
+       for (i = 0; i < lines; i++) {
+               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+               cx_write(cdt + 16 * i + 4, 0);
+               cx_write(cdt + 16 * i + 8, 0);
+               cx_write(cdt + 16 * i + 12, 0);
+       }
+
+       /* init the first cdt buffer */
+       for (i = 0; i < 128; i++)
+               cx_write(ch->fifo_start + 4 * i, i);
+
+       /* write CMDS */
+       if (ch->jumponly)
+               cx_write(ch->cmds_start + 0, 8);
+       else
+               cx_write(ch->cmds_start + 0, risc);
+
+       cx_write(ch->cmds_start + 4, 0);        /* 64 bits 63-32 */
+       cx_write(ch->cmds_start + 8, cdt);
+       cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+       cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+       if (ch->jumponly)
+               cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+       else
+               cx_write(ch->cmds_start + 20, 64 >> 2);
+
+       for (i = 24; i < 80; i += 4)
+               cx_write(ch->cmds_start + i, 0);
+
+       /* fill registers */
+       cx_write(ch->ptr1_reg, ch->fifo_start);
+       cx_write(ch->ptr2_reg, cdt);
+       cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+       return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup);
+
+int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+                                    struct sram_channel *ch,
+                                    unsigned int bpl, u32 risc)
+{
+       unsigned int i, lines;
+       u32 cdt;
+
+       if (ch->cmds_start == 0) {
+               cx_write(ch->ptr1_reg, 0);
+               cx_write(ch->ptr2_reg, 0);
+               cx_write(ch->cnt2_reg, 0);
+               cx_write(ch->cnt1_reg, 0);
+               return 0;
+       }
+
+       bpl = (bpl + 7) & ~7;   /* alignment */
+       cdt = ch->cdt;
+       lines = ch->fifo_size / bpl;
+
+       if (lines > 3)
+               lines = 3;      /* for AUDIO */
+
+       BUG_ON(lines < 2);
+
+       cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       cx_write(8 + 4, 8);
+       cx_write(8 + 8, 0);
+
+       /* write CDT */
+       for (i = 0; i < lines; i++) {
+               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+               cx_write(cdt + 16 * i + 4, 0);
+               cx_write(cdt + 16 * i + 8, 0);
+               cx_write(cdt + 16 * i + 12, 0);
+       }
+
+       /* write CMDS */
+       if (ch->jumponly)
+               cx_write(ch->cmds_start + 0, 8);
+       else
+               cx_write(ch->cmds_start + 0, risc);
+
+       cx_write(ch->cmds_start + 4, 0);        /* 64 bits 63-32 */
+       cx_write(ch->cmds_start + 8, cdt);
+       cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+       cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+       /* IQ size */
+       if (ch->jumponly)
+               cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+       else
+               cx_write(ch->cmds_start + 20, 64 >> 2);
+
+       /* zero out */
+       for (i = 24; i < 80; i += 4)
+               cx_write(ch->cmds_start + i, 0);
+
+       /* fill registers */
+       cx_write(ch->ptr1_reg, ch->fifo_start);
+       cx_write(ch->ptr2_reg, cdt);
+       cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+       return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+       static char *name[] = {
+               "init risc lo",
+               "init risc hi",
+               "cdt base",
+               "cdt size",
+               "iq base",
+               "iq size",
+               "risc pc lo",
+               "risc pc hi",
+               "iq wr ptr",
+               "iq rd ptr",
+               "cdt current",
+               "pci target lo",
+               "pci target hi",
+               "line / byte",
+       };
+       u32 risc;
+       unsigned int i, j, n;
+
+       pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
+       for (i = 0; i < ARRAY_SIZE(name); i++)
+               pr_warn("cmds + 0x%2x:   %-15s: 0x%08x\n",
+                       i * 4, name[i], cx_read(ch->cmds_start + 4 * i));
+
+       j = i * 4;
+       for (i = 0; i < 4;) {
+               risc = cx_read(ch->cmds_start + 4 * (i + 14));
+               pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+               i += cx25821_risc_decode(risc);
+       }
+
+       for (i = 0; i < (64 >> 2); i += n) {
+               risc = cx_read(ch->ctrl_start + 4 * i);
+               /* No consideration for bits 63-32 */
+
+               pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+                       i * 4, ch->ctrl_start + 4 * i, i);
+               n = cx25821_risc_decode(risc);
+               for (j = 1; j < n; j++) {
+                       risc = cx_read(ch->ctrl_start + 4 * (i + j));
+                       pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+                               4 * (i + j), i + j, risc, j);
+               }
+       }
+
+       pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+               ch->fifo_start, ch->fifo_start + ch->fifo_size);
+       pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+               ch->ctrl_start, ch->ctrl_start + 6 * 16);
+       pr_warn("        :   ptr1_reg: 0x%08x\n",
+               cx_read(ch->ptr1_reg));
+       pr_warn("        :   ptr2_reg: 0x%08x\n",
+               cx_read(ch->ptr2_reg));
+       pr_warn("        :   cnt1_reg: 0x%08x\n",
+               cx_read(ch->cnt1_reg));
+       pr_warn("        :   cnt2_reg: 0x%08x\n",
+               cx_read(ch->cnt2_reg));
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump);
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+                                    struct sram_channel *ch)
+{
+       static const char * const name[] = {
+               "init risc lo",
+               "init risc hi",
+               "cdt base",
+               "cdt size",
+               "iq base",
+               "iq size",
+               "risc pc lo",
+               "risc pc hi",
+               "iq wr ptr",
+               "iq rd ptr",
+               "cdt current",
+               "pci target lo",
+               "pci target hi",
+               "line / byte",
+       };
+
+       u32 risc, value, tmp;
+       unsigned int i, j, n;
+
+       pr_info("\n%s: %s - dma Audio channel status dump\n",
+               dev->name, ch->name);
+
+       for (i = 0; i < ARRAY_SIZE(name); i++)
+               pr_info("%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
+                       dev->name, i * 4, name[i],
+                       cx_read(ch->cmds_start + 4 * i));
+
+       j = i * 4;
+       for (i = 0; i < 4;) {
+               risc = cx_read(ch->cmds_start + 4 * (i + 14));
+               pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+               i += cx25821_risc_decode(risc);
+       }
+
+       for (i = 0; i < (64 >> 2); i += n) {
+               risc = cx_read(ch->ctrl_start + 4 * i);
+               /* No consideration for bits 63-32 */
+
+               pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+                       i * 4, ch->ctrl_start + 4 * i, i);
+               n = cx25821_risc_decode(risc);
+
+               for (j = 1; j < n; j++) {
+                       risc = cx_read(ch->ctrl_start + 4 * (i + j));
+                       pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+                               4 * (i + j), i + j, risc, j);
+               }
+       }
+
+       pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+               ch->fifo_start, ch->fifo_start + ch->fifo_size);
+       pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+               ch->ctrl_start, ch->ctrl_start + 6 * 16);
+       pr_warn("        :   ptr1_reg: 0x%08x\n",
+               cx_read(ch->ptr1_reg));
+       pr_warn("        :   ptr2_reg: 0x%08x\n",
+               cx_read(ch->ptr2_reg));
+       pr_warn("        :   cnt1_reg: 0x%08x\n",
+               cx_read(ch->cnt1_reg));
+       pr_warn("        :   cnt2_reg: 0x%08x\n",
+               cx_read(ch->cnt2_reg));
+
+       for (i = 0; i < 4; i++) {
+               risc = cx_read(ch->cmds_start + 56 + (i * 4));
+               pr_warn("instruction %d = 0x%x\n", i, risc);
+       }
+
+       /* read data from the first cdt buffer */
+       risc = cx_read(AUD_A_CDT);
+       pr_warn("\nread cdt loc=0x%x\n", risc);
+       for (i = 0; i < 8; i++) {
+               n = cx_read(risc + i * 4);
+               pr_cont("0x%x ", n);
+       }
+       pr_cont("\n\n");
+
+       value = cx_read(CLK_RST);
+       CX25821_INFO(" CLK_RST = 0x%x\n\n", value);
+
+       value = cx_read(PLL_A_POST_STAT_BIST);
+       CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x\n\n", value);
+       value = cx_read(PLL_A_INT_FRAC);
+       CX25821_INFO(" PLL_A_INT_FRAC = 0x%x\n\n", value);
+
+       value = cx_read(PLL_B_POST_STAT_BIST);
+       CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x\n\n", value);
+       value = cx_read(PLL_B_INT_FRAC);
+       CX25821_INFO(" PLL_B_INT_FRAC = 0x%x\n\n", value);
+
+       value = cx_read(PLL_C_POST_STAT_BIST);
+       CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x\n\n", value);
+       value = cx_read(PLL_C_INT_FRAC);
+       CX25821_INFO(" PLL_C_INT_FRAC = 0x%x\n\n", value);
+
+       value = cx_read(PLL_D_POST_STAT_BIST);
+       CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x\n\n", value);
+       value = cx_read(PLL_D_INT_FRAC);
+       CX25821_INFO(" PLL_D_INT_FRAC = 0x%x\n\n", value);
+
+       value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+       CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x\n\n", value);
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+
+static void cx25821_shutdown(struct cx25821_dev *dev)
+{
+       int i;
+
+       /* disable RISC controller */
+       cx_write(DEV_CNTRL2, 0);
+
+       /* Disable Video A/B activity */
+       for (i = 0; i < VID_CHANNEL_NUM; i++) {
+               cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+               cx_write(dev->channels[i].sram_channels->int_msk, 0);
+       }
+
+       for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+               i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+               cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+               cx_write(dev->channels[i].sram_channels->int_msk, 0);
+       }
+
+       /* Disable Audio activity */
+       cx_write(AUD_INT_DMA_CTL, 0);
+
+       /* Disable Serial port */
+       cx_write(UART_CTL, 0);
+
+       /* Disable Interrupts */
+       cx_write(PCI_INT_MSK, 0);
+       cx_write(AUD_A_INT_MSK, 0);
+}
+
+void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
+                             u32 format)
+{
+       if (channel_select <= 7 && channel_select >= 0) {
+               cx_write(dev->channels[channel_select].sram_channels->pix_frmt,
+                               format);
+               dev->channels[channel_select].pixel_formats = format;
+       }
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev,
+                                struct sram_channel *ch)
+{
+       cx_write(ch->pix_frmt, PIXEL_FRMT_422);
+       cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
+}
+
+static void cx25821_initialize(struct cx25821_dev *dev)
+{
+       int i;
+
+       dprintk(1, "%s()\n", __func__);
+
+       cx25821_shutdown(dev);
+       cx_write(PCI_INT_STAT, 0xffffffff);
+
+       for (i = 0; i < VID_CHANNEL_NUM; i++)
+               cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+       cx_write(AUD_A_INT_STAT, 0xffffffff);
+       cx_write(AUD_B_INT_STAT, 0xffffffff);
+       cx_write(AUD_C_INT_STAT, 0xffffffff);
+       cx_write(AUD_D_INT_STAT, 0xffffffff);
+       cx_write(AUD_E_INT_STAT, 0xffffffff);
+
+       cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+       cx_write(PAD_CTRL, 0x12);       /* for I2C */
+       cx25821_registers_init(dev);    /* init Pecos registers */
+       mdelay(100);
+
+       for (i = 0; i < VID_CHANNEL_NUM; i++) {
+               cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+               cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels,
+                                               1440, 0);
+               dev->channels[i].pixel_formats = PIXEL_FRMT_422;
+               dev->channels[i].use_cif_resolution = FALSE;
+       }
+
+       /* Probably only affect Downstream */
+       for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+               i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+               cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+       }
+
+       cx25821_sram_channel_setup_audio(dev,
+                       dev->channels[SRAM_CH08].sram_channels, 128, 0);
+
+       cx25821_gpio_init(dev);
+}
+
+static int cx25821_get_resources(struct cx25821_dev *dev)
+{
+       if (request_mem_region(pci_resource_start(dev->pci, 0),
+                               pci_resource_len(dev->pci, 0), dev->name))
+               return 0;
+
+       pr_err("%s: can't get MMIO memory @ 0x%llx\n",
+               dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+       return -EBUSY;
+}
+
+static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
+{
+       dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
+
+       pr_info("%s(): Hardware revision = 0x%02x\n",
+               __func__, dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+       if (dev == NULL)
+               return;
+
+       /* Releasing IO memory */
+       if (dev->lmmio != NULL) {
+               CX25821_INFO("Releasing lmmio.\n");
+               iounmap(dev->lmmio);
+               dev->lmmio = NULL;
+       }
+}
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{
+       int i;
+
+       pr_info("\n***********************************\n");
+       pr_info("cx25821 set up\n");
+       pr_info("***********************************\n\n");
+
+       mutex_init(&dev->lock);
+
+       atomic_inc(&dev->refcount);
+
+       dev->nr = ++cx25821_devcount;
+       sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+       mutex_lock(&cx25821_devlist_mutex);
+       list_add_tail(&dev->devlist, &cx25821_devlist);
+       mutex_unlock(&cx25821_devlist_mutex);
+
+       if (dev->pci->device != 0x8210) {
+               pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
+                       __func__, dev->pci->device);
+               return -1;
+       } else {
+               pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
+       }
+
+       /* Apply a sensible clock frequency for the PCIe bridge */
+       dev->clk_freq = 28000000;
+       for (i = 0; i < MAX_VID_CHANNEL_NUM; i++)
+               dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+
+       if (dev->nr > 1)
+               CX25821_INFO("dev->nr > 1!");
+
+       /* board config */
+       dev->board = 1;         /* card[dev->nr]; */
+       dev->_max_num_decoders = MAX_DECODERS;
+
+       dev->pci_bus = dev->pci->bus->number;
+       dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+       dev->pci_irqmask = 0x001f00;
+
+       /* External Master 1 Bus */
+       dev->i2c_bus[0].nr = 0;
+       dev->i2c_bus[0].dev = dev;
+       dev->i2c_bus[0].reg_stat = I2C1_STAT;
+       dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
+       dev->i2c_bus[0].reg_addr = I2C1_ADDR;
+       dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+       dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+       dev->i2c_bus[0].i2c_period = (0x07 << 24);      /* 1.95MHz */
+
+       if (cx25821_get_resources(dev) < 0) {
+               pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
+                      dev->name, dev->pci->subsystem_vendor,
+                      dev->pci->subsystem_device);
+
+               cx25821_devcount--;
+               return -EBUSY;
+       }
+
+       /* PCIe stuff */
+       dev->base_io_addr = pci_resource_start(dev->pci, 0);
+
+       if (!dev->base_io_addr) {
+               CX25821_ERR("No PCI Memory resources, exiting!\n");
+               return -ENODEV;
+       }
+
+       dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+       if (!dev->lmmio) {
+               CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+               cx25821_iounmap(dev);
+               return -ENOMEM;
+       }
+
+       dev->bmmio = (u8 __iomem *) dev->lmmio;
+
+       pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+               dev->name, dev->pci->subsystem_vendor,
+               dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+               dev->board, card[dev->nr] == dev->board ?
+               "insmod option" : "autodetected");
+
+       /* init hardware */
+       cx25821_initialize(dev);
+
+       cx25821_i2c_register(&dev->i2c_bus[0]);
+/*  cx25821_i2c_register(&dev->i2c_bus[1]);
+ *  cx25821_i2c_register(&dev->i2c_bus[2]); */
+
+       CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
+                       dev->i2c_bus[0].i2c_rc);
+
+       cx25821_card_setup(dev);
+
+       if (medusa_video_init(dev) < 0)
+               CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
+
+       cx25821_video_register(dev);
+
+       /* register IOCTL device */
+       dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci,
+                       &cx25821_videoioctl_template, "video");
+
+       if (video_register_device
+           (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
+               cx25821_videoioctl_unregister(dev);
+               pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n",
+                      __func__);
+       }
+
+       cx25821_dev_checkrevision(dev);
+       CX25821_INFO("setup done!\n");
+
+       return 0;
+}
+
+void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+                                     struct upstream_user_struct *up_data)
+{
+       dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
+
+       dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+       medusa_set_videostandard(dev);
+
+       cx25821_vidupstream_init_ch1(dev, dev->channel_select,
+                                    dev->pixel_format);
+}
+
+void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+                                     struct upstream_user_struct *up_data)
+{
+       dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
+
+       dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+       medusa_set_videostandard(dev);
+
+       cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
+                                    dev->pixel_format_ch2);
+}
+
+void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+                                 struct upstream_user_struct *up_data)
+{
+       cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
+}
+
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+       int i;
+
+       if (!dev->base_io_addr)
+               return;
+
+       cx25821_free_mem_upstream_ch1(dev);
+       cx25821_free_mem_upstream_ch2(dev);
+       cx25821_free_mem_upstream_audio(dev);
+
+       release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+       if (!atomic_dec_and_test(&dev->refcount))
+               return;
+
+       for (i = 0; i < VID_CHANNEL_NUM; i++)
+               cx25821_video_unregister(dev, i);
+
+       for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+            i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
+               cx25821_video_unregister(dev, i);
+       }
+
+       cx25821_videoioctl_unregister(dev);
+
+       cx25821_i2c_unregister(&dev->i2c_bus[0]);
+       cx25821_iounmap(dev);
+}
+EXPORT_SYMBOL(cx25821_dev_unregister);
+
+static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
+                                 unsigned int offset, u32 sync_line,
+                                 unsigned int bpl, unsigned int padding,
+                                 unsigned int lines)
+{
+       struct scatterlist *sg;
+       unsigned int line, todo;
+
+       /* sync instruction */
+       if (sync_line != NO_SYNC_LINE)
+               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       /* scan lines */
+       sg = sglist;
+       for (line = 0; line < lines; line++) {
+               while (offset && offset >= sg_dma_len(sg)) {
+                       offset -= sg_dma_len(sg);
+                       sg++;
+               }
+               if (bpl <= sg_dma_len(sg) - offset) {
+                       /* fits into current chunk */
+                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL |
+                                       bpl);
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                       offset += bpl;
+               } else {
+                       /* scanline needs to be split */
+                       todo = bpl;
+                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL |
+                                       (sg_dma_len(sg) - offset));
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                       todo -= (sg_dma_len(sg) - offset);
+                       offset = 0;
+                       sg++;
+                       while (todo > sg_dma_len(sg)) {
+                               *(rp++) = cpu_to_le32(RISC_WRITE |
+                                               sg_dma_len(sg));
+                               *(rp++) = cpu_to_le32(sg_dma_address(sg));
+                               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                               todo -= sg_dma_len(sg);
+                               sg++;
+                       }
+                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg));
+                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                       offset += todo;
+               }
+
+               offset += padding;
+       }
+
+       return rp;
+}
+
+int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                       struct scatterlist *sglist, unsigned int top_offset,
+                       unsigned int bottom_offset, unsigned int bpl,
+                       unsigned int padding, unsigned int lines)
+{
+       u32 instructions;
+       u32 fields;
+       __le32 *rp;
+       int rc;
+
+       fields = 0;
+       if (UNSET != top_offset)
+               fields++;
+       if (UNSET != bottom_offset)
+               fields++;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Padding
+          can cause next bpl to start close to a page border.  First DMA
+          region may be smaller than PAGE_SIZE */
+       /* write and jump need and extra dword */
+       instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE +
+                       lines);
+       instructions += 2;
+       rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+
+       if (rc < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+
+       if (UNSET != top_offset) {
+               rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
+                                       lines);
+       }
+
+       if (UNSET != bottom_offset) {
+               rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
+                                       padding, lines);
+       }
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+
+       return 0;
+}
+
+static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
+                                       unsigned int offset, u32 sync_line,
+                                       unsigned int bpl, unsigned int padding,
+                                       unsigned int lines, unsigned int lpi)
+{
+       struct scatterlist *sg;
+       unsigned int line, todo, sol;
+
+       /* sync instruction */
+       if (sync_line != NO_SYNC_LINE)
+               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       /* scan lines */
+       sg = sglist;
+       for (line = 0; line < lines; line++) {
+               while (offset && offset >= sg_dma_len(sg)) {
+                       offset -= sg_dma_len(sg);
+                       sg++;
+               }
+
+               if (lpi && line > 0 && !(line % lpi))
+                       sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+               else
+                       sol = RISC_SOL;
+
+               if (bpl <= sg_dma_len(sg) - offset) {
+                       /* fits into current chunk */
+                       *(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL |
+                                       bpl);
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                       offset += bpl;
+               } else {
+                       /* scanline needs to be split */
+                       todo = bpl;
+                       *(rp++) = cpu_to_le32(RISC_WRITE | sol |
+                                       (sg_dma_len(sg) - offset));
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                       todo -= (sg_dma_len(sg) - offset);
+                       offset = 0;
+                       sg++;
+                       while (todo > sg_dma_len(sg)) {
+                               *(rp++) = cpu_to_le32(RISC_WRITE |
+                                               sg_dma_len(sg));
+                               *(rp++) = cpu_to_le32(sg_dma_address(sg));
+                               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                               todo -= sg_dma_len(sg);
+                               sg++;
+                       }
+                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+                       *(rp++) = cpu_to_le32(sg_dma_address(sg));
+                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+                       offset += todo;
+               }
+               offset += padding;
+       }
+
+       return rp;
+}
+
+int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+                                 struct btcx_riscmem *risc,
+                                 struct scatterlist *sglist,
+                                 unsigned int bpl,
+                                 unsigned int lines, unsigned int lpi)
+{
+       u32 instructions;
+       __le32 *rp;
+       int rc;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Here
+          there is no padding and no sync.  First DMA region may be smaller
+          than PAGE_SIZE */
+       /* Jump and write need an extra dword */
+       instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
+       instructions += 1;
+
+       rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+       if (rc < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
+                                     lines, lpi);
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+       return 0;
+}
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+
+int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+                        u32 reg, u32 mask, u32 value)
+{
+       __le32 *rp;
+       int rc;
+
+       rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
+
+       if (rc < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+
+       *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
+       *(rp++) = cpu_to_le32(reg);
+       *(rp++) = cpu_to_le32(value);
+       *(rp++) = cpu_to_le32(mask);
+       *(rp++) = cpu_to_le32(RISC_JUMP);
+       *(rp++) = cpu_to_le32(risc->dma);
+       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+       return 0;
+}
+
+void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+{
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+       BUG_ON(in_interrupt());
+       videobuf_waiton(q, &buf->vb, 0, 0);
+       videobuf_dma_unmap(q->dev, dma);
+       videobuf_dma_free(dma);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+       struct cx25821_dev *dev = dev_id;
+       u32 pci_status;
+       u32 vid_status;
+       int i, handled = 0;
+       u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+       pci_status = cx_read(PCI_INT_STAT);
+
+       if (pci_status == 0)
+               goto out;
+
+       for (i = 0; i < VID_CHANNEL_NUM; i++) {
+               if (pci_status & mask[i]) {
+                       vid_status = cx_read(dev->channels[i].
+                               sram_channels->int_stat);
+
+                       if (vid_status)
+                               handled += cx25821_video_irq(dev, i,
+                                               vid_status);
+
+                       cx_write(PCI_INT_STAT, mask[i]);
+               }
+       }
+
+out:
+       return IRQ_RETVAL(handled);
+}
+
+void cx25821_print_irqbits(char *name, char *tag, char **strings,
+                          int len, u32 bits, u32 mask)
+{
+       unsigned int i;
+
+       printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits);
+
+       for (i = 0; i < len; i++) {
+               if (!(bits & (1 << i)))
+                       continue;
+               if (strings[i])
+                       pr_cont(" %s", strings[i]);
+               else
+                       pr_cont(" %d", i);
+               if (!(mask & (1 << i)))
+                       continue;
+               pr_cont("*");
+       }
+       pr_cont("\n");
+}
+EXPORT_SYMBOL(cx25821_print_irqbits);
+
+struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
+{
+       struct cx25821_dev *dev = pci_get_drvdata(pci);
+       return dev;
+}
+EXPORT_SYMBOL(cx25821_dev_get);
+
+static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
+                                    const struct pci_device_id *pci_id)
+{
+       struct cx25821_dev *dev;
+       int err = 0;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (NULL == dev)
+               return -ENOMEM;
+
+       err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+       if (err < 0)
+               goto fail_free;
+
+       /* pci init */
+       dev->pci = pci_dev;
+       if (pci_enable_device(pci_dev)) {
+               err = -EIO;
+
+               pr_info("pci enable failed!\n");
+
+               goto fail_unregister_device;
+       }
+
+       pr_info("Athena pci enable !\n");
+
+       err = cx25821_dev_setup(dev);
+       if (err) {
+               if (err == -EBUSY)
+                       goto fail_unregister_device;
+               else
+                       goto fail_unregister_pci;
+       }
+
+       /* print pci info */
+       pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
+       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
+       pr_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)dev->base_io_addr);
+
+       pci_set_master(pci_dev);
+       if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+               pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+               err = -EIO;
+               goto fail_irq;
+       }
+
+       err = request_irq(pci_dev->irq, cx25821_irq,
+                       IRQF_SHARED, dev->name, dev);
+
+       if (err < 0) {
+               pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
+               goto fail_irq;
+       }
+
+       return 0;
+
+fail_irq:
+       pr_info("cx25821_initdev() can't get IRQ !\n");
+       cx25821_dev_unregister(dev);
+
+fail_unregister_pci:
+       pci_disable_device(pci_dev);
+fail_unregister_device:
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+fail_free:
+       kfree(dev);
+       return err;
+}
+
+static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct cx25821_dev *dev = get_cx25821(v4l2_dev);
+
+       cx25821_shutdown(dev);
+       pci_disable_device(pci_dev);
+
+       /* unregister stuff */
+       if (pci_dev->irq)
+               free_irq(pci_dev->irq, dev);
+
+       mutex_lock(&cx25821_devlist_mutex);
+       list_del(&dev->devlist);
+       mutex_unlock(&cx25821_devlist_mutex);
+
+       cx25821_dev_unregister(dev);
+       v4l2_device_unregister(v4l2_dev);
+       kfree(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = {
+       {
+               /* CX25821 Athena */
+               .vendor = 0x14f1,
+               .device = 0x8210,
+               .subvendor = 0x14f1,
+               .subdevice = 0x0920,
+       }, {
+               /* CX25821 No Brand */
+               .vendor = 0x14f1,
+               .device = 0x8210,
+               .subvendor = 0x0000,
+               .subdevice = 0x0000,
+       }, {
+               /* --- end of list --- */
+       }
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
+
+static struct pci_driver cx25821_pci_driver = {
+       .name = "cx25821",
+       .id_table = cx25821_pci_tbl,
+       .probe = cx25821_initdev,
+       .remove = __devexit_p(cx25821_finidev),
+       /* TODO */
+       .suspend = NULL,
+       .resume = NULL,
+};
+
+static int __init cx25821_init(void)
+{
+       pr_info("driver version %d.%d.%d loaded\n",
+               (CX25821_VERSION_CODE >> 16) & 0xff,
+               (CX25821_VERSION_CODE >> 8) & 0xff,
+               CX25821_VERSION_CODE & 0xff);
+       return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void __exit cx25821_fini(void)
+{
+       pci_unregister_driver(&cx25821_pci_driver);
+}
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
diff --git a/drivers/media/pci/cx25821/cx25821-gpio.c b/drivers/media/pci/cx25821/cx25821-gpio.c
new file mode 100644 (file)
index 0000000..29e43b0
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 "cx25821.h"
+
+/********************* GPIO stuffs *********************/
+void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+                                  int pin_number, int pin_logic_value)
+{
+       int bit = pin_number;
+       u32 gpio_oe_reg = GPIO_LO_OE;
+       u32 gpio_register = 0;
+       u32 value = 0;
+
+       /* Check for valid pinNumber */
+       if (pin_number >= 47)
+               return;
+
+       if (pin_number > 31) {
+               bit = pin_number - 31;
+               gpio_oe_reg = GPIO_HI_OE;
+       }
+       /* Here we will make sure that the GPIOs 0 and 1 are output. keep the
+        * rest as is */
+       gpio_register = cx_read(gpio_oe_reg);
+
+       if (pin_logic_value == 1)
+               value = gpio_register | Set_GPIO_Bit(bit);
+       else
+               value = gpio_register & Clear_GPIO_Bit(bit);
+
+       cx_write(gpio_oe_reg, value);
+}
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
+                                          int pin_number, int pin_logic_value)
+{
+       int bit = pin_number;
+       u32 gpio_reg = GPIO_LO;
+       u32 value = 0;
+
+       /* Check for valid pinNumber */
+       if (pin_number >= 47)
+               return;
+
+       /* change to output direction */
+       cx25821_set_gpiopin_direction(dev, pin_number, 0);
+
+       if (pin_number > 31) {
+               bit = pin_number - 31;
+               gpio_reg = GPIO_HI;
+       }
+
+       value = cx_read(gpio_reg);
+
+       if (pin_logic_value == 0)
+               value &= Clear_GPIO_Bit(bit);
+       else
+               value |= Set_GPIO_Bit(bit);
+
+       cx_write(gpio_reg, value);
+}
+
+void cx25821_gpio_init(struct cx25821_dev *dev)
+{
+       if (dev == NULL)
+               return;
+
+       switch (dev->board) {
+       case CX25821_BOARD_CONEXANT_ATHENA10:
+       default:
+               /* set GPIO 5 to select the path for Medusa/Athena */
+               cx25821_set_gpiopin_logicvalue(dev, 5, 1);
+               mdelay(20);
+               break;
+       }
+
+}
diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c
new file mode 100644 (file)
index 0000000..9844549
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *     Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include <linux/i2c.h>
+
+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;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)                                    \
+do {                                                                   \
+       if (i2c_debug >= level)                                         \
+               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);      \
+} while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       return cx_read(bus->reg_stat) & 0x02 ? 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;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg, int joined_rlen)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       u32 wdata, addr, ctrl;
+       int retval, cnt;
+
+       if (joined_rlen)
+               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+                       msg->len, joined_rlen);
+       else
+               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+       /* Deal with i2c probe functions with zero payload */
+       if (msg->len == 0) {
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+
+               if (!i2c_slave_did_ack(i2c_adap))
+                       return -EIO;
+
+               dprintk(1, "%s(): returns 0\n", __func__);
+               return 0;
+       }
+
+       /* dev, reg + first byte */
+       addr = (msg->addr << 25) | msg->buf[0];
+       wdata = msg->buf[0];
+
+       ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+       if (msg->len > 1)
+               ctrl |= I2C_NOSTOP | I2C_EXTEND;
+       else if (joined_rlen)
+               ctrl |= I2C_NOSTOP;
+
+       cx_write(bus->reg_addr, addr);
+       cx_write(bus->reg_wdata, wdata);
+       cx_write(bus->reg_ctrl, ctrl);
+
+       retval = i2c_wait_done(i2c_adap);
+       if (retval < 0)
+               goto err;
+
+       if (retval == 0)
+               goto eio;
+
+       if (i2c_debug) {
+               if (!(ctrl & I2C_NOSTOP))
+                       printk(" >\n");
+       }
+
+       for (cnt = 1; cnt < msg->len; cnt++) {
+               /* following bytes */
+               wdata = msg->buf[cnt];
+               ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+               if (cnt < msg->len - 1)
+                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
+               else if (joined_rlen)
+                       ctrl |= I2C_NOSTOP;
+
+               cx_write(bus->reg_addr, addr);
+               cx_write(bus->reg_wdata, wdata);
+               cx_write(bus->reg_ctrl, ctrl);
+
+               retval = i2c_wait_done(i2c_adap);
+               if (retval < 0)
+                       goto err;
+
+               if (retval == 0)
+                       goto eio;
+
+               if (i2c_debug) {
+                       dprintk(1, " %02x", msg->buf[cnt]);
+                       if (!(ctrl & I2C_NOSTOP))
+                               dprintk(1, " >\n");
+               }
+       }
+
+       return msg->len;
+
+eio:
+       retval = -EIO;
+err:
+       if (i2c_debug)
+               pr_err(" ERR: %d\n", retval);
+       return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+                        const struct i2c_msg *msg, int joined)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       u32 ctrl, cnt;
+       int retval;
+
+       if (i2c_debug && !joined)
+               dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
+
+       /* Deal with i2c probe functions with zero payload */
+       if (msg->len == 0) {
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+               if (!i2c_slave_did_ack(i2c_adap))
+                       return -EIO;
+
+               dprintk(1, "%s(): returns 0\n", __func__);
+               return 0;
+       }
+
+       if (i2c_debug) {
+               if (joined)
+                       dprintk(1, " R");
+               else
+                       dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+       }
+
+       for (cnt = 0; cnt < msg->len; cnt++) {
+
+               ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+               if (cnt < msg->len - 1)
+                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+               cx_write(bus->reg_addr, msg->addr << 25);
+               cx_write(bus->reg_ctrl, ctrl);
+
+               retval = i2c_wait_done(i2c_adap);
+               if (retval < 0)
+                       goto err;
+               if (retval == 0)
+                       goto eio;
+               msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+
+               if (i2c_debug) {
+                       dprintk(1, " %02x", msg->buf[cnt]);
+                       if (!(ctrl & I2C_NOSTOP))
+                               dprintk(1, " >\n");
+               }
+       }
+
+       return msg->len;
+eio:
+       retval = -EIO;
+err:
+       if (i2c_debug)
+               pr_err(" ERR: %d\n", retval);
+       return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+       struct cx25821_i2c *bus = i2c_adap->algo_data;
+       struct cx25821_dev *dev = bus->dev;
+       int i, retval = 0;
+
+       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",
+                       __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 u32 cx25821_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA |
+               I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static struct i2c_algorithm cx25821_i2c_algo_template = {
+       .master_xfer = i2c_xfer,
+       .functionality = cx25821_functionality,
+#ifdef NEED_ALGO_CONTROL
+       .algo_control = dummy_algo_control,
+#endif
+};
+
+static struct i2c_adapter cx25821_i2c_adap_template = {
+       .name = "cx25821",
+       .owner = THIS_MODULE,
+       .algo = &cx25821_i2c_algo_template,
+};
+
+static struct i2c_client cx25821_i2c_client_template = {
+       .name = "cx25821 internal",
+};
+
+/* init + register i2c adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+       struct cx25821_dev *dev = bus->dev;
+
+       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+       bus->i2c_adap = cx25821_i2c_adap_template;
+       bus->i2c_client = cx25821_i2c_client_template;
+       bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+       strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+       bus->i2c_adap.algo_data = bus;
+       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+       i2c_add_adapter(&bus->i2c_adap);
+
+       bus->i2c_client.adapter = &bus->i2c_adap;
+
+       /* set up the I2c */
+       bus->i2c_client.addr = (0x88 >> 1);
+
+       return bus->i2c_rc;
+}
+
+int cx25821_i2c_unregister(struct cx25821_i2c *bus)
+{
+       i2c_del_adapter(&bus->i2c_adap);
+       return 0;
+}
+
+void cx25821_av_clk(struct cx25821_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[0].i2c_adap, &msg, 1);
+}
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+       struct i2c_client *client = &bus->i2c_client;
+       int v = 0;
+       u8 addr[2] = { 0, 0 };
+       u8 buf[4] = { 0, 0, 0, 0 };
+
+       struct i2c_msg msgs[2] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 2,
+                       .buf = addr,
+               }, {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 4,
+                       .buf = buf,
+               }
+       };
+
+       addr[0] = (reg_addr >> 8);
+       addr[1] = (reg_addr & 0xff);
+       msgs[0].addr = 0x44;
+       msgs[1].addr = 0x44;
+
+       i2c_xfer(client->adapter, msgs, 2);
+
+       v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+       *value = v;
+
+       return v;
+}
+
+int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
+{
+       struct i2c_client *client = &bus->i2c_client;
+       int retval = 0;
+       u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+       struct i2c_msg msgs[1] = {
+               {
+                       .addr = client->addr,
+                       .flags = 0,
+                       .len = 6,
+                       .buf = buf,
+               }
+       };
+
+       buf[0] = reg_addr >> 8;
+       buf[1] = reg_addr & 0xff;
+       buf[5] = (value >> 24) & 0xff;
+       buf[4] = (value >> 16) & 0xff;
+       buf[3] = (value >> 8) & 0xff;
+       buf[2] = value & 0xff;
+       client->flags = 0;
+       msgs[0].addr = 0x44;
+
+       retval = i2c_xfer(client->adapter, msgs, 1);
+
+       return retval;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-defines.h b/drivers/media/pci/cx25821/cx25821-medusa-defines.h
new file mode 100644 (file)
index 0000000..7a9e647
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _MEDUSA_DEF_H_
+#define _MEDUSA_DEF_H_
+
+/* Video decoder that we supported */
+#define VDEC_A         0
+#define VDEC_B         1
+#define VDEC_C         2
+#define VDEC_D         3
+#define VDEC_E         4
+#define VDEC_F         5
+#define VDEC_G         6
+#define VDEC_H         7
+
+/* end of display sequence */
+#define END_OF_SEQ     0xF;
+
+/* registry string size */
+#define MAX_REGISTRY_SZ        40;
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-reg.h b/drivers/media/pci/cx25821/cx25821-medusa-reg.h
new file mode 100644 (file)
index 0000000..c98ac94
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __MEDUSA_REGISTERS__
+#define __MEDUSA_REGISTERS__
+
+/* Serial Slave Registers */
+#define        HOST_REGISTER1                          0x0000
+#define        HOST_REGISTER2                          0x0001
+
+/* Chip Configuration Registers */
+#define        CHIP_CTRL                               0x0100
+#define        AFE_AB_CTRL                             0x0104
+#define        AFE_CD_CTRL                             0x0108
+#define        AFE_EF_CTRL                             0x010C
+#define        AFE_GH_CTRL                             0x0110
+#define        DENC_AB_CTRL                            0x0114
+#define        BYP_AB_CTRL                             0x0118
+#define        MON_A_CTRL                              0x011C
+#define        DISP_SEQ_A                              0x0120
+#define        DISP_SEQ_B                              0x0124
+#define        DISP_AB_CNT                             0x0128
+#define        DISP_CD_CNT                             0x012C
+#define        DISP_EF_CNT                             0x0130
+#define        DISP_GH_CNT                             0x0134
+#define        DISP_IJ_CNT                             0x0138
+#define        PIN_OE_CTRL                             0x013C
+#define        PIN_SPD_CTRL                            0x0140
+#define        PIN_SPD_CTRL2                           0x0144
+#define        IRQ_STAT_CTRL                           0x0148
+#define        POWER_CTRL_AB                           0x014C
+#define        POWER_CTRL_CD                           0x0150
+#define        POWER_CTRL_EF                           0x0154
+#define        POWER_CTRL_GH                           0x0158
+#define        TUNE_CTRL                               0x015C
+#define        BIAS_CTRL                               0x0160
+#define        AFE_AB_DIAG_CTRL                        0x0164
+#define        AFE_CD_DIAG_CTRL                        0x0168
+#define        AFE_EF_DIAG_CTRL                        0x016C
+#define        AFE_GH_DIAG_CTRL                        0x0170
+#define        PLL_AB_DIAG_CTRL                        0x0174
+#define        PLL_CD_DIAG_CTRL                        0x0178
+#define        PLL_EF_DIAG_CTRL                        0x017C
+#define        PLL_GH_DIAG_CTRL                        0x0180
+#define        TEST_CTRL                               0x0184
+#define        BIST_STAT                               0x0188
+#define        BIST_STAT2                              0x018C
+#define        BIST_VID_PLL_AB_STAT                    0x0190
+#define        BIST_VID_PLL_CD_STAT                    0x0194
+#define        BIST_VID_PLL_EF_STAT                    0x0198
+#define        BIST_VID_PLL_GH_STAT                    0x019C
+#define        DLL_DIAG_CTRL                           0x01A0
+#define        DEV_CH_ID_CTRL                          0x01A4
+#define        ABIST_CTRL_STATUS                       0x01A8
+#define        ABIST_FREQ                              0x01AC
+#define        ABIST_GOERT_SHIFT                       0x01B0
+#define        ABIST_COEF12                            0x01B4
+#define        ABIST_COEF34                            0x01B8
+#define        ABIST_COEF56                            0x01BC
+#define        ABIST_COEF7_SNR                         0x01C0
+#define        ABIST_ADC_CAL                           0x01C4
+#define        ABIST_BIN1_VGA0                         0x01C8
+#define        ABIST_BIN2_VGA1                         0x01CC
+#define        ABIST_BIN3_VGA2                         0x01D0
+#define        ABIST_BIN4_VGA3                         0x01D4
+#define        ABIST_BIN5_VGA4                         0x01D8
+#define        ABIST_BIN6_VGA5                         0x01DC
+#define        ABIST_BIN7_VGA6                         0x0x1E0
+#define        ABIST_CLAMP_A                           0x0x1E4
+#define        ABIST_CLAMP_B                           0x0x1E8
+#define        ABIST_CLAMP_C                           0x01EC
+#define        ABIST_CLAMP_D                           0x01F0
+#define        ABIST_CLAMP_E                           0x01F4
+#define        ABIST_CLAMP_F                           0x01F8
+
+/* Digital Video Encoder A Registers */
+#define        DENC_A_REG_1                            0x0200
+#define        DENC_A_REG_2                            0x0204
+#define        DENC_A_REG_3                            0x0208
+#define        DENC_A_REG_4                            0x020C
+#define        DENC_A_REG_5                            0x0210
+#define        DENC_A_REG_6                            0x0214
+#define        DENC_A_REG_7                            0x0218
+#define        DENC_A_REG_8                            0x021C
+
+/* Digital Video Encoder B Registers */
+#define        DENC_B_REG_1                            0x0300
+#define        DENC_B_REG_2                            0x0304
+#define        DENC_B_REG_3                            0x0308
+#define        DENC_B_REG_4                            0x030C
+#define        DENC_B_REG_5                            0x0310
+#define        DENC_B_REG_6                            0x0314
+#define        DENC_B_REG_7                            0x0318
+#define        DENC_B_REG_8                            0x031C
+
+/* Video Decoder A Registers */
+#define        MODE_CTRL                               0x1000
+#define        OUT_CTRL1                               0x1004
+#define        OUT_CTRL_NS                             0x1008
+#define        GEN_STAT                                0x100C
+#define        INT_STAT_MASK                           0x1010
+#define        LUMA_CTRL                               0x1014
+#define        CHROMA_CTRL                             0x1018
+#define        CRUSH_CTRL                              0x101C
+#define        HORIZ_TIM_CTRL                          0x1020
+#define        VERT_TIM_CTRL                           0x1024
+#define        MISC_TIM_CTRL                           0x1028
+#define        FIELD_COUNT                             0x102C
+#define        HSCALE_CTRL                             0x1030
+#define        VSCALE_CTRL                             0x1034
+#define        MAN_VGA_CTRL                            0x1038
+#define        MAN_AGC_CTRL                            0x103C
+#define        DFE_CTRL1                               0x1040
+#define        DFE_CTRL2                               0x1044
+#define        DFE_CTRL3                               0x1048
+#define        PLL_CTRL                                0x104C
+#define        PLL_CTRL_FAST                           0x1050
+#define        HTL_CTRL                                0x1054
+#define        SRC_CFG                                 0x1058
+#define        SC_STEP_SIZE                            0x105C
+#define        SC_CONVERGE_CTRL                        0x1060
+#define        SC_LOOP_CTRL                            0x1064
+#define        COMB_2D_HFS_CFG                         0x1068
+#define        COMB_2D_HFD_CFG                         0x106C
+#define        COMB_2D_LF_CFG                          0x1070
+#define        COMB_2D_BLEND                           0x1074
+#define        COMB_MISC_CTRL                          0x1078
+#define        COMB_FLAT_THRESH_CTRL                   0x107C
+#define        COMB_TEST                               0x1080
+#define        BP_MISC_CTRL                            0x1084
+#define        VCR_DET_CTRL                            0x1088
+#define        NOISE_DET_CTRL                          0x108C
+#define        COMB_FLAT_NOISE_CTRL                    0x1090
+#define        VERSION                                 0x11F8
+#define        SOFT_RST_CTRL                           0x11FC
+
+/* Video Decoder B Registers */
+#define        VDEC_B_MODE_CTRL                        0x1200
+#define        VDEC_B_OUT_CTRL1                        0x1204
+#define        VDEC_B_OUT_CTRL_NS                      0x1208
+#define        VDEC_B_GEN_STAT                         0x120C
+#define        VDEC_B_INT_STAT_MASK                    0x1210
+#define        VDEC_B_LUMA_CTRL                        0x1214
+#define        VDEC_B_CHROMA_CTRL                      0x1218
+#define        VDEC_B_CRUSH_CTRL                       0x121C
+#define        VDEC_B_HORIZ_TIM_CTRL                   0x1220
+#define        VDEC_B_VERT_TIM_CTRL                    0x1224
+#define        VDEC_B_MISC_TIM_CTRL                    0x1228
+#define        VDEC_B_FIELD_COUNT                      0x122C
+#define        VDEC_B_HSCALE_CTRL                      0x1230
+#define        VDEC_B_VSCALE_CTRL                      0x1234
+#define        VDEC_B_MAN_VGA_CTRL                     0x1238
+#define        VDEC_B_MAN_AGC_CTRL                     0x123C
+#define        VDEC_B_DFE_CTRL1                        0x1240
+#define        VDEC_B_DFE_CTRL2                        0x1244
+#define        VDEC_B_DFE_CTRL3                        0x1248
+#define        VDEC_B_PLL_CTRL                         0x124C
+#define        VDEC_B_PLL_CTRL_FAST                    0x1250
+#define        VDEC_B_HTL_CTRL                         0x1254
+#define        VDEC_B_SRC_CFG                          0x1258
+#define        VDEC_B_SC_STEP_SIZE                     0x125C
+#define        VDEC_B_SC_CONVERGE_CTRL                 0x1260
+#define        VDEC_B_SC_LOOP_CTRL                     0x1264
+#define        VDEC_B_COMB_2D_HFS_CFG                  0x1268
+#define        VDEC_B_COMB_2D_HFD_CFG                  0x126C
+#define        VDEC_B_COMB_2D_LF_CFG                   0x1270
+#define        VDEC_B_COMB_2D_BLEND                    0x1274
+#define        VDEC_B_COMB_MISC_CTRL                   0x1278
+#define        VDEC_B_COMB_FLAT_THRESH_CTRL            0x127C
+#define        VDEC_B_COMB_TEST                        0x1280
+#define        VDEC_B_BP_MISC_CTRL                     0x1284
+#define        VDEC_B_VCR_DET_CTRL                     0x1288
+#define        VDEC_B_NOISE_DET_CTRL                   0x128C
+#define        VDEC_B_COMB_FLAT_NOISE_CTRL             0x1290
+#define        VDEC_B_VERSION                          0x13F8
+#define        VDEC_B_SOFT_RST_CTRL                    0x13FC
+
+/* Video Decoder C Registers */
+#define        VDEC_C_MODE_CTRL                        0x1400
+#define        VDEC_C_OUT_CTRL1                        0x1404
+#define        VDEC_C_OUT_CTRL_NS                      0x1408
+#define        VDEC_C_GEN_STAT                         0x140C
+#define        VDEC_C_INT_STAT_MASK                    0x1410
+#define VDEC_C_LUMA_CTRL                       0x1414
+#define VDEC_C_CHROMA_CTRL                     0x1418
+#define        VDEC_C_CRUSH_CTRL                       0x141C
+#define        VDEC_C_HORIZ_TIM_CTRL                   0x1420
+#define        VDEC_C_VERT_TIM_CTRL                    0x1424
+#define        VDEC_C_MISC_TIM_CTRL                    0x1428
+#define        VDEC_C_FIELD_COUNT                      0x142C
+#define        VDEC_C_HSCALE_CTRL                      0x1430
+#define        VDEC_C_VSCALE_CTRL                      0x1434
+#define        VDEC_C_MAN_VGA_CTRL                     0x1438
+#define        VDEC_C_MAN_AGC_CTRL                     0x143C
+#define        VDEC_C_DFE_CTRL1                        0x1440
+#define        VDEC_C_DFE_CTRL2                        0x1444
+#define        VDEC_C_DFE_CTRL3                        0x1448
+#define        VDEC_C_PLL_CTRL                         0x144C
+#define        VDEC_C_PLL_CTRL_FAST                    0x1450
+#define        VDEC_C_HTL_CTRL                         0x1454
+#define        VDEC_C_SRC_CFG                          0x1458
+#define        VDEC_C_SC_STEP_SIZE                     0x145C
+#define        VDEC_C_SC_CONVERGE_CTRL                 0x1460
+#define        VDEC_C_SC_LOOP_CTRL                     0x1464
+#define        VDEC_C_COMB_2D_HFS_CFG                  0x1468
+#define        VDEC_C_COMB_2D_HFD_CFG                  0x146C
+#define        VDEC_C_COMB_2D_LF_CFG                   0x1470
+#define        VDEC_C_COMB_2D_BLEND                    0x1474
+#define        VDEC_C_COMB_MISC_CTRL                   0x1478
+#define        VDEC_C_COMB_FLAT_THRESH_CTRL            0x147C
+#define        VDEC_C_COMB_TEST                        0x1480
+#define        VDEC_C_BP_MISC_CTRL                     0x1484
+#define        VDEC_C_VCR_DET_CTRL                     0x1488
+#define        VDEC_C_NOISE_DET_CTRL                   0x148C
+#define        VDEC_C_COMB_FLAT_NOISE_CTRL             0x1490
+#define        VDEC_C_VERSION                          0x15F8
+#define        VDEC_C_SOFT_RST_CTRL                    0x15FC
+
+/* Video Decoder D Registers */
+#define VDEC_D_MODE_CTRL                       0x1600
+#define VDEC_D_OUT_CTRL1                       0x1604
+#define VDEC_D_OUT_CTRL_NS                     0x1608
+#define VDEC_D_GEN_STAT                                0x160C
+#define VDEC_D_INT_STAT_MASK                   0x1610
+#define VDEC_D_LUMA_CTRL                       0x1614
+#define VDEC_D_CHROMA_CTRL                     0x1618
+#define VDEC_D_CRUSH_CTRL                      0x161C
+#define VDEC_D_HORIZ_TIM_CTRL                  0x1620
+#define VDEC_D_VERT_TIM_CTRL                   0x1624
+#define VDEC_D_MISC_TIM_CTRL                   0x1628
+#define VDEC_D_FIELD_COUNT                     0x162C
+#define VDEC_D_HSCALE_CTRL                     0x1630
+#define VDEC_D_VSCALE_CTRL                     0x1634
+#define VDEC_D_MAN_VGA_CTRL                    0x1638
+#define VDEC_D_MAN_AGC_CTRL                    0x163C
+#define VDEC_D_DFE_CTRL1                       0x1640
+#define VDEC_D_DFE_CTRL2                       0x1644
+#define VDEC_D_DFE_CTRL3                       0x1648
+#define VDEC_D_PLL_CTRL                                0x164C
+#define VDEC_D_PLL_CTRL_FAST                   0x1650
+#define VDEC_D_HTL_CTRL                                0x1654
+#define VDEC_D_SRC_CFG                         0x1658
+#define VDEC_D_SC_STEP_SIZE                    0x165C
+#define VDEC_D_SC_CONVERGE_CTRL                        0x1660
+#define VDEC_D_SC_LOOP_CTRL                    0x1664
+#define VDEC_D_COMB_2D_HFS_CFG                 0x1668
+#define VDEC_D_COMB_2D_HFD_CFG                 0x166C
+#define VDEC_D_COMB_2D_LF_CFG                  0x1670
+#define VDEC_D_COMB_2D_BLEND                   0x1674
+#define VDEC_D_COMB_MISC_CTRL                  0x1678
+#define VDEC_D_COMB_FLAT_THRESH_CTRL           0x167C
+#define VDEC_D_COMB_TEST                       0x1680
+#define VDEC_D_BP_MISC_CTRL                    0x1684
+#define VDEC_D_VCR_DET_CTRL                    0x1688
+#define VDEC_D_NOISE_DET_CTRL                  0x168C
+#define VDEC_D_COMB_FLAT_NOISE_CTRL            0x1690
+#define VDEC_D_VERSION                         0x17F8
+#define VDEC_D_SOFT_RST_CTRL                   0x17FC
+
+/* Video Decoder E Registers */
+#define        VDEC_E_MODE_CTRL                        0x1800
+#define        VDEC_E_OUT_CTRL1                        0x1804
+#define        VDEC_E_OUT_CTRL_NS                      0x1808
+#define        VDEC_E_GEN_STAT                         0x180C
+#define        VDEC_E_INT_STAT_MASK                    0x1810
+#define        VDEC_E_LUMA_CTRL                        0x1814
+#define        VDEC_E_CHROMA_CTRL                      0x1818
+#define        VDEC_E_CRUSH_CTRL                       0x181C
+#define        VDEC_E_HORIZ_TIM_CTRL                   0x1820
+#define        VDEC_E_VERT_TIM_CTRL                    0x1824
+#define        VDEC_E_MISC_TIM_CTRL                    0x1828
+#define        VDEC_E_FIELD_COUNT                      0x182C
+#define        VDEC_E_HSCALE_CTRL                      0x1830
+#define        VDEC_E_VSCALE_CTRL                      0x1834
+#define        VDEC_E_MAN_VGA_CTRL                     0x1838
+#define        VDEC_E_MAN_AGC_CTRL                     0x183C
+#define        VDEC_E_DFE_CTRL1                        0x1840
+#define        VDEC_E_DFE_CTRL2                        0x1844
+#define        VDEC_E_DFE_CTRL3                        0x1848
+#define        VDEC_E_PLL_CTRL                         0x184C
+#define        VDEC_E_PLL_CTRL_FAST                    0x1850
+#define        VDEC_E_HTL_CTRL                         0x1854
+#define        VDEC_E_SRC_CFG                          0x1858
+#define        VDEC_E_SC_STEP_SIZE                     0x185C
+#define        VDEC_E_SC_CONVERGE_CTRL                 0x1860
+#define        VDEC_E_SC_LOOP_CTRL                     0x1864
+#define        VDEC_E_COMB_2D_HFS_CFG                  0x1868
+#define        VDEC_E_COMB_2D_HFD_CFG                  0x186C
+#define        VDEC_E_COMB_2D_LF_CFG                   0x1870
+#define        VDEC_E_COMB_2D_BLEND                    0x1874
+#define        VDEC_E_COMB_MISC_CTRL                   0x1878
+#define        VDEC_E_COMB_FLAT_THRESH_CTRL            0x187C
+#define        VDEC_E_COMB_TEST                        0x1880
+#define        VDEC_E_BP_MISC_CTRL                     0x1884
+#define        VDEC_E_VCR_DET_CTRL                     0x1888
+#define        VDEC_E_NOISE_DET_CTRL                   0x188C
+#define        VDEC_E_COMB_FLAT_NOISE_CTRL             0x1890
+#define        VDEC_E_VERSION                          0x19F8
+#define        VDEC_E_SOFT_RST_CTRL                    0x19FC
+
+/* Video Decoder F Registers */
+#define        VDEC_F_MODE_CTRL                        0x1A00
+#define        VDEC_F_OUT_CTRL1                        0x1A04
+#define        VDEC_F_OUT_CTRL_NS                      0x1A08
+#define        VDEC_F_GEN_STAT                         0x1A0C
+#define        VDEC_F_INT_STAT_MASK                    0x1A10
+#define        VDEC_F_LUMA_CTRL                        0x1A14
+#define        VDEC_F_CHROMA_CTRL                      0x1A18
+#define        VDEC_F_CRUSH_CTRL                       0x1A1C
+#define        VDEC_F_HORIZ_TIM_CTRL                   0x1A20
+#define        VDEC_F_VERT_TIM_CTRL                    0x1A24
+#define        VDEC_F_MISC_TIM_CTRL                    0x1A28
+#define        VDEC_F_FIELD_COUNT                      0x1A2C
+#define        VDEC_F_HSCALE_CTRL                      0x1A30
+#define        VDEC_F_VSCALE_CTRL                      0x1A34
+#define        VDEC_F_MAN_VGA_CTRL                     0x1A38
+#define        VDEC_F_MAN_AGC_CTRL                     0x1A3C
+#define        VDEC_F_DFE_CTRL1                        0x1A40
+#define        VDEC_F_DFE_CTRL2                        0x1A44
+#define        VDEC_F_DFE_CTRL3                        0x1A48
+#define        VDEC_F_PLL_CTRL                         0x1A4C
+#define        VDEC_F_PLL_CTRL_FAST                    0x1A50
+#define        VDEC_F_HTL_CTRL                         0x1A54
+#define        VDEC_F_SRC_CFG                          0x1A58
+#define        VDEC_F_SC_STEP_SIZE                     0x1A5C
+#define        VDEC_F_SC_CONVERGE_CTRL                 0x1A60
+#define        VDEC_F_SC_LOOP_CTRL                     0x1A64
+#define        VDEC_F_COMB_2D_HFS_CFG                  0x1A68
+#define        VDEC_F_COMB_2D_HFD_CFG                  0x1A6C
+#define        VDEC_F_COMB_2D_LF_CFG                   0x1A70
+#define        VDEC_F_COMB_2D_BLEND                    0x1A74
+#define        VDEC_F_COMB_MISC_CTRL                   0x1A78
+#define        VDEC_F_COMB_FLAT_THRESH_CTRL            0x1A7C
+#define        VDEC_F_COMB_TEST                        0x1A80
+#define        VDEC_F_BP_MISC_CTRL                     0x1A84
+#define        VDEC_F_VCR_DET_CTRL                     0x1A88
+#define        VDEC_F_NOISE_DET_CTRL                   0x1A8C
+#define        VDEC_F_COMB_FLAT_NOISE_CTRL             0x1A90
+#define        VDEC_F_VERSION                          0x1BF8
+#define        VDEC_F_SOFT_RST_CTRL                    0x1BFC
+
+/* Video Decoder G Registers */
+#define        VDEC_G_MODE_CTRL                        0x1C00
+#define        VDEC_G_OUT_CTRL1                        0x1C04
+#define        VDEC_G_OUT_CTRL_NS                      0x1C08
+#define        VDEC_G_GEN_STAT                         0x1C0C
+#define        VDEC_G_INT_STAT_MASK                    0x1C10
+#define        VDEC_G_LUMA_CTRL                        0x1C14
+#define        VDEC_G_CHROMA_CTRL                      0x1C18
+#define        VDEC_G_CRUSH_CTRL                       0x1C1C
+#define        VDEC_G_HORIZ_TIM_CTRL                   0x1C20
+#define        VDEC_G_VERT_TIM_CTRL                    0x1C24
+#define        VDEC_G_MISC_TIM_CTRL                    0x1C28
+#define        VDEC_G_FIELD_COUNT                      0x1C2C
+#define        VDEC_G_HSCALE_CTRL                      0x1C30
+#define        VDEC_G_VSCALE_CTRL                      0x1C34
+#define        VDEC_G_MAN_VGA_CTRL                     0x1C38
+#define        VDEC_G_MAN_AGC_CTRL                     0x1C3C
+#define        VDEC_G_DFE_CTRL1                        0x1C40
+#define        VDEC_G_DFE_CTRL2                        0x1C44
+#define        VDEC_G_DFE_CTRL3                        0x1C48
+#define        VDEC_G_PLL_CTRL                         0x1C4C
+#define        VDEC_G_PLL_CTRL_FAST                    0x1C50
+#define        VDEC_G_HTL_CTRL                         0x1C54
+#define        VDEC_G_SRC_CFG                          0x1C58
+#define        VDEC_G_SC_STEP_SIZE                     0x1C5C
+#define        VDEC_G_SC_CONVERGE_CTRL                 0x1C60
+#define        VDEC_G_SC_LOOP_CTRL                     0x1C64
+#define        VDEC_G_COMB_2D_HFS_CFG                  0x1C68
+#define        VDEC_G_COMB_2D_HFD_CFG                  0x1C6C
+#define        VDEC_G_COMB_2D_LF_CFG                   0x1C70
+#define        VDEC_G_COMB_2D_BLEND                    0x1C74
+#define        VDEC_G_COMB_MISC_CTRL                   0x1C78
+#define        VDEC_G_COMB_FLAT_THRESH_CTRL            0x1C7C
+#define        VDEC_G_COMB_TEST                        0x1C80
+#define        VDEC_G_BP_MISC_CTRL                     0x1C84
+#define        VDEC_G_VCR_DET_CTRL                     0x1C88
+#define        VDEC_G_NOISE_DET_CTRL                   0x1C8C
+#define        VDEC_G_COMB_FLAT_NOISE_CTRL             0x1C90
+#define        VDEC_G_VERSION                          0x1DF8
+#define        VDEC_G_SOFT_RST_CTRL                    0x1DFC
+
+/* Video Decoder H Registers  */
+#define        VDEC_H_MODE_CTRL                        0x1E00
+#define        VDEC_H_OUT_CTRL1                        0x1E04
+#define        VDEC_H_OUT_CTRL_NS                      0x1E08
+#define        VDEC_H_GEN_STAT                         0x1E0C
+#define        VDEC_H_INT_STAT_MASK                    0x1E1E
+#define        VDEC_H_LUMA_CTRL                        0x1E14
+#define        VDEC_H_CHROMA_CTRL                      0x1E18
+#define        VDEC_H_CRUSH_CTRL                       0x1E1C
+#define        VDEC_H_HORIZ_TIM_CTRL                   0x1E20
+#define        VDEC_H_VERT_TIM_CTRL                    0x1E24
+#define        VDEC_H_MISC_TIM_CTRL                    0x1E28
+#define        VDEC_H_FIELD_COUNT                      0x1E2C
+#define        VDEC_H_HSCALE_CTRL                      0x1E30
+#define        VDEC_H_VSCALE_CTRL                      0x1E34
+#define        VDEC_H_MAN_VGA_CTRL                     0x1E38
+#define        VDEC_H_MAN_AGC_CTRL                     0x1E3C
+#define        VDEC_H_DFE_CTRL1                        0x1E40
+#define        VDEC_H_DFE_CTRL2                        0x1E44
+#define        VDEC_H_DFE_CTRL3                        0x1E48
+#define        VDEC_H_PLL_CTRL                         0x1E4C
+#define        VDEC_H_PLL_CTRL_FAST                    0x1E50
+#define        VDEC_H_HTL_CTRL                         0x1E54
+#define        VDEC_H_SRC_CFG                          0x1E58
+#define        VDEC_H_SC_STEP_SIZE                     0x1E5C
+#define        VDEC_H_SC_CONVERGE_CTRL                 0x1E60
+#define        VDEC_H_SC_LOOP_CTRL                     0x1E64
+#define        VDEC_H_COMB_2D_HFS_CFG                  0x1E68
+#define        VDEC_H_COMB_2D_HFD_CFG                  0x1E6C
+#define        VDEC_H_COMB_2D_LF_CFG                   0x1E70
+#define        VDEC_H_COMB_2D_BLEND                    0x1E74
+#define        VDEC_H_COMB_MISC_CTRL                   0x1E78
+#define        VDEC_H_COMB_FLAT_THRESH_CTRL            0x1E7C
+#define        VDEC_H_COMB_TEST                        0x1E80
+#define        VDEC_H_BP_MISC_CTRL                     0x1E84
+#define        VDEC_H_VCR_DET_CTRL                     0x1E88
+#define        VDEC_H_NOISE_DET_CTRL                   0x1E8C
+#define        VDEC_H_COMB_FLAT_NOISE_CTRL             0x1E90
+#define        VDEC_H_VERSION                          0x1FF8
+#define        VDEC_H_SOFT_RST_CTRL                    0x1FFC
+
+/*****************************************************************************/
+/* LUMA_CTRL register fields */
+#define VDEC_A_BRITE_CTRL                      0x1014
+#define VDEC_A_CNTRST_CTRL                     0x1015
+#define VDEC_A_PEAK_SEL                                0x1016
+
+/*****************************************************************************/
+/* CHROMA_CTRL register fields */
+#define VDEC_A_USAT_CTRL                       0x1018
+#define VDEC_A_VSAT_CTRL                       0x1019
+#define VDEC_A_HUE_CTRL                                0x101A
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.c b/drivers/media/pci/cx25821/cx25821-medusa-video.c
new file mode 100644 (file)
index 0000000..6a92e5c
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include "cx25821-medusa-video.h"
+#include "cx25821-biffuncs.h"
+
+/*
+ * medusa_enable_bluefield_output()
+ *
+ * Enable the generation of blue filed output if no video
+ *
+ */
+static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
+                                          int enable)
+{
+       u32 value = 0;
+       u32 tmp = 0;
+       int out_ctrl = OUT_CTRL1;
+       int out_ctrl_ns = OUT_CTRL_NS;
+
+       switch (channel) {
+       default:
+       case VDEC_A:
+               break;
+       case VDEC_B:
+               out_ctrl = VDEC_B_OUT_CTRL1;
+               out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
+               break;
+       case VDEC_C:
+               out_ctrl = VDEC_C_OUT_CTRL1;
+               out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
+               break;
+       case VDEC_D:
+               out_ctrl = VDEC_D_OUT_CTRL1;
+               out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
+               break;
+       case VDEC_E:
+               out_ctrl = VDEC_E_OUT_CTRL1;
+               out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
+               return;
+       case VDEC_F:
+               out_ctrl = VDEC_F_OUT_CTRL1;
+               out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
+               return;
+       case VDEC_G:
+               out_ctrl = VDEC_G_OUT_CTRL1;
+               out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
+               return;
+       case VDEC_H:
+               out_ctrl = VDEC_H_OUT_CTRL1;
+               out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
+               return;
+       }
+
+       value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
+       value &= 0xFFFFFF7F;    /* clear BLUE_FIELD_EN */
+       if (enable)
+               value |= 0x00000080;    /* set BLUE_FIELD_EN */
+       cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
+
+       value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
+       value &= 0xFFFFFF7F;
+       if (enable)
+               value |= 0x00000080;    /* set BLUE_FIELD_EN */
+       cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
+}
+
+static int medusa_initialize_ntsc(struct cx25821_dev *dev)
+{
+       int ret_val = 0;
+       int i = 0;
+       u32 value = 0;
+       u32 tmp = 0;
+
+       mutex_lock(&dev->lock);
+
+       for (i = 0; i < MAX_DECODERS; i++) {
+               /* set video format NTSC-M */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), &tmp);
+               value &= 0xFFFFFFF0;
+               /* enable the fast locking mode bit[16] */
+               value |= 0x10001;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), value);
+
+               /* resolution NTSC 720x480 */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+               value &= 0x00C00C00;
+               value |= 0x612D0074;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), value);
+
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), &tmp);
+               value &= 0x00C00C00;
+               value |= 0x1C1E001A;    /* vblank_cnt + 2 to get camera ID */
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), value);
+
+               /* chroma subcarrier step size */
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+
+               /* enable VIP optional active */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), &tmp);
+               value &= 0xFFFBFFFF;
+               value |= 0x00040000;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), value);
+
+               /* enable VIP optional active (VIP_OPT_AL) for direct output. */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), &tmp);
+               value &= 0xFFFBFFFF;
+               value |= 0x00040000;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), value);
+
+               /*
+                * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+                * when the input switching rate < 16 fields
+               */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), &tmp);
+               /* disable special play detection */
+               value = setBitAtPos(value, 14);
+               value = clearBitAtPos(value, 15);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), value);
+
+               /* set vbi_gate_en to 0 */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), &tmp);
+               value = clearBitAtPos(value, 29);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), value);
+
+               /* Enable the generation of blue field output if no video */
+               medusa_enable_bluefield_output(dev, i, 1);
+       }
+
+       for (i = 0; i < MAX_ENCODERS; i++) {
+               /* NTSC hclock */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), &tmp);
+               value &= 0xF000FC00;
+               value |= 0x06B402D0;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), value);
+
+               /* burst begin and burst end */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), &tmp);
+               value &= 0xFF000000;
+               value |= 0x007E9054;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), value);
+
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), &tmp);
+               value &= 0xFC00FE00;
+               value |= 0x00EC00F0;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), value);
+
+               /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), &tmp);
+               value &= 0x00FCFFFF;
+               value |= 0x13020000;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), value);
+
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), &tmp);
+               value &= 0xFFFF0000;
+               value |= 0x0000E575;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), value);
+
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+
+               /* Subcarrier Increment */
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+       }
+
+       /* set picture resolutions */
+       /* 0 - 720 */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+       /* 0 - 480 */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+       /* set Bypass input format to NTSC 525 lines */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+       value |= 0x00080200;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+       mutex_unlock(&dev->lock);
+
+       return ret_val;
+}
+
+static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
+{
+       int ret_val = -1;
+       u32 value = 0, tmp = 0;
+
+       /* Setup for 2D threshold */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861);
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023);
+
+       /* Setup flat chroma and luma thresholds */
+       value = cx25821_i2c_read(&dev->i2c_bus[0],
+                       COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+       value &= 0x06230000;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+
+       /* set comb 2D blend */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F);
+
+       /* COMB MISC CONTROL */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                       COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F);
+
+       return ret_val;
+}
+
+static int medusa_initialize_pal(struct cx25821_dev *dev)
+{
+       int ret_val = 0;
+       int i = 0;
+       u32 value = 0;
+       u32 tmp = 0;
+
+       mutex_lock(&dev->lock);
+
+       for (i = 0; i < MAX_DECODERS; i++) {
+               /* set video format PAL-BDGHI */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), &tmp);
+               value &= 0xFFFFFFF0;
+               /* enable the fast locking mode bit[16] */
+               value |= 0x10004;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MODE_CTRL + (0x200 * i), value);
+
+               /* resolution PAL 720x576 */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+               value &= 0x00C00C00;
+               value |= 0x632D007D;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               HORIZ_TIM_CTRL + (0x200 * i), value);
+
+               /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), &tmp);
+               value &= 0x00C00C00;
+               value |= 0x28240026;    /* vblank_cnt + 2 to get camera ID */
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               VERT_TIM_CTRL + (0x200 * i), value);
+
+               /* chroma subcarrier step size */
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+
+               /* enable VIP optional active */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), &tmp);
+               value &= 0xFFFBFFFF;
+               value |= 0x00040000;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL_NS + (0x200 * i), value);
+
+               /* enable VIP optional active (VIP_OPT_AL) for direct output. */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), &tmp);
+               value &= 0xFFFBFFFF;
+               value |= 0x00040000;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               OUT_CTRL1 + (0x200 * i), value);
+
+               /*
+                * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+                * when the input switching rate < 16 fields
+                */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), &tmp);
+               /* disable special play detection */
+               value = setBitAtPos(value, 14);
+               value = clearBitAtPos(value, 15);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               MISC_TIM_CTRL + (0x200 * i), value);
+
+               /* set vbi_gate_en to 0 */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), &tmp);
+               value = clearBitAtPos(value, 29);
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DFE_CTRL1 + (0x200 * i), value);
+
+               medusa_PALCombInit(dev, i);
+
+               /* Enable the generation of blue field output if no video */
+               medusa_enable_bluefield_output(dev, i, 1);
+       }
+
+       for (i = 0; i < MAX_ENCODERS; i++) {
+               /* PAL hclock */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), &tmp);
+               value &= 0xF000FC00;
+               value |= 0x06C002D0;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_1 + (0x100 * i), value);
+
+               /* burst begin and burst end */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), &tmp);
+               value &= 0xFF000000;
+               value |= 0x007E9754;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_2 + (0x100 * i), value);
+
+               /* hblank and vactive */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), &tmp);
+               value &= 0xFC00FE00;
+               value |= 0x00FC0120;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_3 + (0x100 * i), value);
+
+               /* set PAL vblank, phase alternation, 0 IRE pedestal */
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), &tmp);
+               value &= 0x00FCFFFF;
+               value |= 0x14010000;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_4 + (0x100 * i), value);
+
+               value = cx25821_i2c_read(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), &tmp);
+               value &= 0xFFFF0000;
+               value |= 0x0000F078;
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_5 + (0x100 * i), value);
+
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+
+               /* Subcarrier Increment */
+               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+                               DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+       }
+
+       /* set picture resolutions */
+       /* 0 - 720 */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+       /* 0 - 576 */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+       /* set Bypass input format to PAL 625 lines */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+       value &= 0xFFF7FDFF;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+       mutex_unlock(&dev->lock);
+
+       return ret_val;
+}
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+       int status = STATUS_SUCCESS;
+       u32 value = 0, tmp = 0;
+
+       if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+               status = medusa_initialize_pal(dev);
+       else
+               status = medusa_initialize_ntsc(dev);
+
+       /* Enable DENC_A output */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
+       value = setBitAtPos(value, 4);
+       status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
+
+       /* Enable DENC_B output */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
+       value = setBitAtPos(value, 4);
+       status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
+
+       return status;
+}
+
+void medusa_set_resolution(struct cx25821_dev *dev, int width,
+                          int decoder_select)
+{
+       int decoder = 0;
+       int decoder_count = 0;
+       u32 hscale = 0x0;
+       u32 vscale = 0x0;
+       const int MAX_WIDTH = 720;
+
+       mutex_lock(&dev->lock);
+
+       /* validate the width */
+       if (width > MAX_WIDTH) {
+               pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
+                       __func__, width, MAX_WIDTH);
+               width = MAX_WIDTH;
+       }
+
+       if (decoder_select <= 7 && decoder_select >= 0) {
+               decoder = decoder_select;
+               decoder_count = decoder_select + 1;
+       } else {
+               decoder = 0;
+               decoder_count = _num_decoders;
+       }
+
+       switch (width) {
+       case 320:
+               hscale = 0x13E34B;
+               vscale = 0x0;
+               break;
+
+       case 352:
+               hscale = 0x10A273;
+               vscale = 0x0;
+               break;
+
+       case 176:
+               hscale = 0x3115B2;
+               vscale = 0x1E00;
+               break;
+
+       case 160:
+               hscale = 0x378D84;
+               vscale = 0x1E00;
+               break;
+
+       default:                /* 720 */
+               hscale = 0x0;
+               vscale = 0x0;
+               break;
+       }
+
+       for (; decoder < decoder_count; decoder++) {
+               /* write scaling values for each decoder */
+               cx25821_i2c_write(&dev->i2c_bus[0],
+                               HSCALE_CTRL + (0x200 * decoder), hscale);
+               cx25821_i2c_write(&dev->i2c_bus[0],
+                               VSCALE_CTRL + (0x200 * decoder), vscale);
+       }
+
+       mutex_unlock(&dev->lock);
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
+                                      int duration)
+{
+       u32 fld_cnt = 0;
+       u32 tmp = 0;
+       u32 disp_cnt_reg = DISP_AB_CNT;
+
+       mutex_lock(&dev->lock);
+
+       /* no support */
+       if (decoder < VDEC_A || decoder > VDEC_H) {
+               mutex_unlock(&dev->lock);
+               return;
+       }
+
+       switch (decoder) {
+       default:
+               break;
+       case VDEC_C:
+       case VDEC_D:
+               disp_cnt_reg = DISP_CD_CNT;
+               break;
+       case VDEC_E:
+       case VDEC_F:
+               disp_cnt_reg = DISP_EF_CNT;
+               break;
+       case VDEC_G:
+       case VDEC_H:
+               disp_cnt_reg = DISP_GH_CNT;
+               break;
+       }
+
+       _display_field_cnt[decoder] = duration;
+
+       /* update hardware */
+       fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
+
+       if (!(decoder % 2)) {   /* EVEN decoder */
+               fld_cnt &= 0xFFFF0000;
+               fld_cnt |= duration;
+       } else {
+               fld_cnt &= 0x0000FFFF;
+               fld_cnt |= ((u32) duration) << 16;
+       }
+
+       cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+
+       mutex_unlock(&dev->lock);
+}
+
+/* Map to Medusa register setting */
+static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax,
+               int *dstVal)
+{
+       int numerator;
+       int denominator;
+       int quotient;
+
+       if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
+               return -1;
+       /*
+        * This is the overall expression used:
+        * *dstVal =
+        *   (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
+        * but we need to account for rounding so below we use the modulus
+        * operator to find the remainder and increment if necessary.
+        */
+       numerator = (srcVal - srcMin) * (dstMax - dstMin);
+       denominator = srcMax - srcMin;
+       quotient = numerator / denominator;
+
+       if (2 * (numerator % denominator) >= denominator)
+               quotient++;
+
+       *dstVal = quotient + dstMin;
+
+       return 0;
+}
+
+static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
+{
+       unsigned char temp;
+
+       if (numeric >= 0)
+               return numeric;
+       else {
+               temp = ~(abs(numeric) & 0xFF);
+               temp += 1;
+               return temp;
+       }
+}
+
+int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
+{
+       int ret_val = 0;
+       int value = 0;
+       u32 val = 0, tmp = 0;
+
+       mutex_lock(&dev->lock);
+       if ((brightness > VIDEO_PROCAMP_MAX) ||
+           (brightness < VIDEO_PROCAMP_MIN)) {
+               mutex_unlock(&dev->lock);
+               return -1;
+       }
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+                       SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+       value = convert_to_twos(value, 8);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+       val &= 0xFFFFFF00;
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value);
+       mutex_unlock(&dev->lock);
+       return ret_val;
+}
+
+int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
+{
+       int ret_val = 0;
+       int value = 0;
+       u32 val = 0, tmp = 0;
+
+       mutex_lock(&dev->lock);
+
+       if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
+               mutex_unlock(&dev->lock);
+               return -1;
+       }
+
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+                       UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+       val &= 0xFFFFFF00;
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value);
+
+       mutex_unlock(&dev->lock);
+       return ret_val;
+}
+
+int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
+{
+       int ret_val = 0;
+       int value = 0;
+       u32 val = 0, tmp = 0;
+
+       mutex_lock(&dev->lock);
+
+       if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
+               mutex_unlock(&dev->lock);
+               return -1;
+       }
+
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue,
+                       SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+
+       value = convert_to_twos(value, 8);
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+       val &= 0xFFFFFF00;
+
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+
+       mutex_unlock(&dev->lock);
+       return ret_val;
+}
+
+int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
+{
+       int ret_val = 0;
+       int value = 0;
+       u32 val = 0, tmp = 0;
+
+       mutex_lock(&dev->lock);
+
+       if ((saturation > VIDEO_PROCAMP_MAX) ||
+           (saturation < VIDEO_PROCAMP_MIN)) {
+               mutex_unlock(&dev->lock);
+               return -1;
+       }
+
+       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+                       UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+       val &= 0xFFFFFF00;
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_USAT_CTRL + (0x200 * decoder), val | value);
+
+       val = cx25821_i2c_read(&dev->i2c_bus[0],
+                       VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+       val &= 0xFFFFFF00;
+       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+                       VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value);
+
+       mutex_unlock(&dev->lock);
+       return ret_val;
+}
+
+/* Program the display sequence and monitor output. */
+
+int medusa_video_init(struct cx25821_dev *dev)
+{
+       u32 value = 0, tmp = 0;
+       int ret_val = 0;
+       int i = 0;
+
+       mutex_lock(&dev->lock);
+
+       _num_decoders = dev->_max_num_decoders;
+
+       /* disable Auto source selection on all video decoders */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+       value &= 0xFFFFF0FF;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+       if (ret_val < 0)
+               goto error;
+
+       /* Turn off Master source switch enable */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+       value &= 0xFFFFFFDF;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+       if (ret_val < 0)
+               goto error;
+
+       mutex_unlock(&dev->lock);
+
+       for (i = 0; i < _num_decoders; i++)
+               medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
+
+       mutex_lock(&dev->lock);
+
+       /* Select monitor as DENC A input, power up the DAC */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
+       value &= 0xFF70FF70;
+       value |= 0x00090008;    /* set en_active */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
+
+       if (ret_val < 0)
+               goto error;
+
+       /* enable input is VIP/656 */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+       value |= 0x00040100;    /* enable VIP */
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+       if (ret_val < 0)
+               goto error;
+
+       /* select AFE clock to output mode */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+       value &= 0x83FFFFFF;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+                       value | 0x10000000);
+
+       if (ret_val < 0)
+               goto error;
+
+       /* Turn on all of the data out and control output pins. */
+       value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
+       value &= 0xFEF0FE00;
+       if (_num_decoders == MAX_DECODERS) {
+               /*
+                * Note: The octal board does not support control pins(bit16-19)
+                * These bits are ignored in the octal board.
+                *
+                * disable VDEC A-C port, default to Mobilygen Interface
+                */
+               value |= 0x010001F8;
+       } else {
+               /* disable VDEC A-C port, default to Mobilygen Interface */
+               value |= 0x010F0108;
+       }
+
+       value |= 7;
+       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+
+       if (ret_val < 0)
+               goto error;
+
+
+       mutex_unlock(&dev->lock);
+
+       ret_val = medusa_set_videostandard(dev);
+
+       return ret_val;
+
+error:
+       mutex_unlock(&dev->lock);
+       return ret_val;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.h b/drivers/media/pci/cx25821/cx25821-medusa-video.h
new file mode 100644 (file)
index 0000000..6175e09
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _MEDUSA_VIDEO_H
+#define _MEDUSA_VIDEO_H
+
+#include "cx25821-medusa-defines.h"
+
+/* Color control constants */
+#define VIDEO_PROCAMP_MIN                 0
+#define VIDEO_PROCAMP_MAX                 10000
+#define UNSIGNED_BYTE_MIN                 0
+#define UNSIGNED_BYTE_MAX                 0xFF
+#define SIGNED_BYTE_MIN                   -128
+#define SIGNED_BYTE_MAX                   127
+
+/* Default video color settings */
+#define SHARPNESS_DEFAULT                 50
+#define SATURATION_DEFAULT              5000
+#define BRIGHTNESS_DEFAULT              6200
+#define CONTRAST_DEFAULT                5000
+#define HUE_DEFAULT                     5000
+
+unsigned short _num_decoders;
+unsigned short _num_cameras;
+
+unsigned int _video_standard;
+int _display_field_cnt[MAX_DECODERS];
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-reg.h b/drivers/media/pci/cx25821/cx25821-reg.h
new file mode 100644 (file)
index 0000000..a3fc25a
--- /dev/null
@@ -0,0 +1,1592 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __CX25821_REGISTERS__
+#define __CX25821_REGISTERS__
+
+/* Risc Instructions */
+#define RISC_CNT_INC    0x00010000
+#define RISC_CNT_RESET  0x00030000
+#define RISC_IRQ1               0x01000000
+#define RISC_IRQ2               0x02000000
+#define RISC_EOL                0x04000000
+#define RISC_SOL                0x08000000
+#define RISC_WRITE              0x10000000
+#define RISC_SKIP               0x20000000
+#define RISC_JUMP               0x70000000
+#define RISC_SYNC               0x80000000
+#define RISC_RESYNC             0x80008000
+#define RISC_READ               0x90000000
+#define RISC_WRITERM    0xB0000000
+#define RISC_WRITECM    0xC0000000
+#define RISC_WRITECR    0xD0000000
+#define RISC_WRITEC             0x50000000
+#define RISC_READC              0xA0000000
+
+#define RISC_SYNC_ODD           0x00000000
+#define RISC_SYNC_EVEN          0x00000200
+#define RISC_SYNC_ODD_VBI       0x00000006
+#define RISC_SYNC_EVEN_VBI      0x00000207
+#define RISC_NOOP                       0xF0000000
+
+/*****************************************************************************
+* ASB SRAM
+ *****************************************************************************/
+#define  TX_SRAM                   0x000000    /* Transmit SRAM */
+
+/*****************************************************************************/
+#define  RX_RAM                    0x010000    /* Receive SRAM */
+
+/*****************************************************************************
+* Application Layer (AL)
+ *****************************************************************************/
+#define  DEV_CNTRL2                0x040000    /* Device control */
+#define  FLD_RUN_RISC              0x00000020
+
+/* ***************************************************************************** */
+#define  PCI_INT_MSK               0x040010    /* PCI interrupt mask */
+#define  PCI_INT_STAT              0x040014    /* PCI interrupt status */
+#define  PCI_INT_MSTAT             0x040018    /* PCI interrupt masked status */
+#define  FLD_HAMMERHEAD_INT        (1 << 27)
+#define  FLD_UART_INT              (1 << 26)
+#define  FLD_IRQN_INT              (1 << 25)
+#define  FLD_TM_INT                (1 << 28)
+#define  FLD_I2C_3_RACK            (1 << 27)
+#define  FLD_I2C_3_INT             (1 << 26)
+#define  FLD_I2C_2_RACK            (1 << 25)
+#define  FLD_I2C_2_INT             (1 << 24)
+#define  FLD_I2C_1_RACK            (1 << 23)
+#define  FLD_I2C_1_INT             (1 << 22)
+
+#define  FLD_APB_DMA_BERR_INT      (1 << 21)
+#define  FLD_AL_WR_BERR_INT        (1 << 20)
+#define  FLD_AL_RD_BERR_INT        (1 << 19)
+#define  FLD_RISC_WR_BERR_INT      (1 << 18)
+#define  FLD_RISC_RD_BERR_INT      (1 << 17)
+
+#define  FLD_VID_I_INT             (1 << 8)
+#define  FLD_VID_H_INT             (1 << 7)
+#define  FLD_VID_G_INT             (1 << 6)
+#define  FLD_VID_F_INT             (1 << 5)
+#define  FLD_VID_E_INT             (1 << 4)
+#define  FLD_VID_D_INT             (1 << 3)
+#define  FLD_VID_C_INT             (1 << 2)
+#define  FLD_VID_B_INT             (1 << 1)
+#define  FLD_VID_A_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  VID_A_INT_MSK             0x040020    /* Video A interrupt mask */
+#define  VID_A_INT_STAT            0x040024    /* Video A interrupt status */
+#define  VID_A_INT_MSTAT           0x040028    /* Video A interrupt masked status */
+#define  VID_A_INT_SSTAT           0x04002C    /* Video A interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_B_INT_MSK             0x040030    /* Video B interrupt mask */
+#define  VID_B_INT_STAT            0x040034    /* Video B interrupt status */
+#define  VID_B_INT_MSTAT           0x040038    /* Video B interrupt masked status */
+#define  VID_B_INT_SSTAT           0x04003C    /* Video B interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_C_INT_MSK             0x040040    /* Video C interrupt mask */
+#define  VID_C_INT_STAT            0x040044    /* Video C interrupt status */
+#define  VID_C_INT_MSTAT           0x040048    /* Video C interrupt masked status */
+#define  VID_C_INT_SSTAT           0x04004C    /* Video C interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_D_INT_MSK             0x040050    /* Video D interrupt mask */
+#define  VID_D_INT_STAT            0x040054    /* Video D interrupt status */
+#define  VID_D_INT_MSTAT           0x040058    /* Video D interrupt masked status */
+#define  VID_D_INT_SSTAT           0x04005C    /* Video D interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_E_INT_MSK             0x040060    /* Video E interrupt mask */
+#define  VID_E_INT_STAT            0x040064    /* Video E interrupt status */
+#define  VID_E_INT_MSTAT           0x040068    /* Video E interrupt masked status */
+#define  VID_E_INT_SSTAT           0x04006C    /* Video E interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_F_INT_MSK             0x040070    /* Video F interrupt mask */
+#define  VID_F_INT_STAT            0x040074    /* Video F interrupt status */
+#define  VID_F_INT_MSTAT           0x040078    /* Video F interrupt masked status */
+#define  VID_F_INT_SSTAT           0x04007C    /* Video F interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_G_INT_MSK             0x040080    /* Video G interrupt mask */
+#define  VID_G_INT_STAT            0x040084    /* Video G interrupt status */
+#define  VID_G_INT_MSTAT           0x040088    /* Video G interrupt masked status */
+#define  VID_G_INT_SSTAT           0x04008C    /* Video G interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_H_INT_MSK             0x040090    /* Video H interrupt mask */
+#define  VID_H_INT_STAT            0x040094    /* Video H interrupt status */
+#define  VID_H_INT_MSTAT           0x040098    /* Video H interrupt masked status */
+#define  VID_H_INT_SSTAT           0x04009C    /* Video H interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_I_INT_MSK             0x0400A0    /* Video I interrupt mask */
+#define  VID_I_INT_STAT            0x0400A4    /* Video I interrupt status */
+#define  VID_I_INT_MSTAT           0x0400A8    /* Video I interrupt masked status */
+#define  VID_I_INT_SSTAT           0x0400AC    /* Video I interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_J_INT_MSK             0x0400B0    /* Video J interrupt mask */
+#define  VID_J_INT_STAT            0x0400B4    /* Video J interrupt status */
+#define  VID_J_INT_MSTAT           0x0400B8    /* Video J interrupt masked status */
+#define  VID_J_INT_SSTAT           0x0400BC    /* Video J interrupt set status */
+
+#define  FLD_VID_SRC_OPC_ERR       0x00020000
+#define  FLD_VID_DST_OPC_ERR       0x00010000
+#define  FLD_VID_SRC_SYNC          0x00002000
+#define  FLD_VID_DST_SYNC          0x00001000
+#define  FLD_VID_SRC_UF            0x00000200
+#define  FLD_VID_DST_OF            0x00000100
+#define  FLD_VID_SRC_RISC2         0x00000020
+#define  FLD_VID_DST_RISC2         0x00000010
+#define  FLD_VID_SRC_RISC1         0x00000002
+#define  FLD_VID_DST_RISC1         0x00000001
+#define  FLD_VID_SRC_ERRORS            (FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF)
+#define  FLD_VID_DST_ERRORS            (FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF)
+
+/* ***************************************************************************** */
+#define  AUD_A_INT_MSK             0x0400C0    /* Audio Int interrupt mask */
+#define  AUD_A_INT_STAT            0x0400C4    /* Audio Int interrupt status */
+#define  AUD_A_INT_MSTAT           0x0400C8    /* Audio Int interrupt masked status */
+#define  AUD_A_INT_SSTAT           0x0400CC    /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_B_INT_MSK             0x0400D0    /* Audio Int interrupt mask */
+#define  AUD_B_INT_STAT            0x0400D4    /* Audio Int interrupt status */
+#define  AUD_B_INT_MSTAT           0x0400D8    /* Audio Int interrupt masked status */
+#define  AUD_B_INT_SSTAT           0x0400DC    /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_C_INT_MSK             0x0400E0    /* Audio Int interrupt mask */
+#define  AUD_C_INT_STAT            0x0400E4    /* Audio Int interrupt status */
+#define  AUD_C_INT_MSTAT           0x0400E8    /* Audio Int interrupt masked status */
+#define  AUD_C_INT_SSTAT           0x0400EC    /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_D_INT_MSK             0x0400F0    /* Audio Int interrupt mask */
+#define  AUD_D_INT_STAT            0x0400F4    /* Audio Int interrupt status */
+#define  AUD_D_INT_MSTAT           0x0400F8    /* Audio Int interrupt masked status */
+#define  AUD_D_INT_SSTAT           0x0400FC    /* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_E_INT_MSK             0x040100    /* Audio Int interrupt mask */
+#define  AUD_E_INT_STAT            0x040104    /* Audio Int interrupt status */
+#define  AUD_E_INT_MSTAT           0x040108    /* Audio Int interrupt masked status */
+#define  AUD_E_INT_SSTAT           0x04010C    /* Audio Int interrupt set status */
+
+#define  FLD_AUD_SRC_OPC_ERR       0x00020000
+#define  FLD_AUD_DST_OPC_ERR       0x00010000
+#define  FLD_AUD_SRC_SYNC          0x00002000
+#define  FLD_AUD_DST_SYNC          0x00001000
+#define  FLD_AUD_SRC_OF            0x00000200
+#define  FLD_AUD_DST_OF            0x00000100
+#define  FLD_AUD_SRC_RISCI2        0x00000020
+#define  FLD_AUD_DST_RISCI2        0x00000010
+#define  FLD_AUD_SRC_RISCI1        0x00000002
+#define  FLD_AUD_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  MBIF_A_INT_MSK             0x040110   /* MBIF Int interrupt mask */
+#define  MBIF_A_INT_STAT            0x040114   /* MBIF Int interrupt status */
+#define  MBIF_A_INT_MSTAT           0x040118   /* MBIF Int interrupt masked status */
+#define  MBIF_A_INT_SSTAT           0x04011C   /* MBIF Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  MBIF_B_INT_MSK             0x040120   /* MBIF Int interrupt mask */
+#define  MBIF_B_INT_STAT            0x040124   /* MBIF Int interrupt status */
+#define  MBIF_B_INT_MSTAT           0x040128   /* MBIF Int interrupt masked status */
+#define  MBIF_B_INT_SSTAT           0x04012C   /* MBIF Int interrupt set status */
+
+#define  FLD_MBIF_DST_OPC_ERR       0x00010000
+#define  FLD_MBIF_DST_SYNC          0x00001000
+#define  FLD_MBIF_DST_OF            0x00000100
+#define  FLD_MBIF_DST_RISCI2        0x00000010
+#define  FLD_MBIF_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  AUD_EXT_INT_MSK           0x040060    /* Audio Ext interrupt mask */
+#define  AUD_EXT_INT_STAT          0x040064    /* Audio Ext interrupt status */
+#define  AUD_EXT_INT_MSTAT         0x040068    /* Audio Ext interrupt masked status */
+#define  AUD_EXT_INT_SSTAT         0x04006C    /* Audio Ext interrupt set status */
+#define  FLD_AUD_EXT_OPC_ERR       0x00010000
+#define  FLD_AUD_EXT_SYNC          0x00001000
+#define  FLD_AUD_EXT_OF            0x00000100
+#define  FLD_AUD_EXT_RISCI2        0x00000010
+#define  FLD_AUD_EXT_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  GPIO_LO                   0x110010    /* Lower  of GPIO pins [31:0] */
+#define  GPIO_HI                   0x110014    /* Upper WORD  of GPIO pins [47:31] */
+
+#define  GPIO_LO_OE                0x110018    /* Lower  of GPIO output enable [31:0] */
+#define  GPIO_HI_OE                0x11001C    /* Upper word  of GPIO output enable [47:32] */
+
+#define  GPIO_LO_INT_MSK           0x11003C    /* GPIO interrupt mask */
+#define  GPIO_LO_INT_STAT          0x110044    /* GPIO interrupt status */
+#define  GPIO_LO_INT_MSTAT         0x11004C    /* GPIO interrupt masked status */
+#define  GPIO_LO_ISM_SNS           0x110054    /* GPIO interrupt sensitivity */
+#define  GPIO_LO_ISM_POL           0x11005C    /* GPIO interrupt polarity */
+
+#define  GPIO_HI_INT_MSK           0x110040    /* GPIO interrupt mask */
+#define  GPIO_HI_INT_STAT          0x110048    /* GPIO interrupt status */
+#define  GPIO_HI_INT_MSTAT         0x110050    /* GPIO interrupt masked status */
+#define  GPIO_HI_ISM_SNS           0x110058    /* GPIO interrupt sensitivity */
+#define  GPIO_HI_ISM_POL           0x110060    /* GPIO interrupt polarity */
+
+#define  FLD_GPIO43_INT            (1 << 11)
+#define  FLD_GPIO42_INT            (1 << 10)
+#define  FLD_GPIO41_INT            (1 << 9)
+#define  FLD_GPIO40_INT            (1 << 8)
+
+#define  FLD_GPIO9_INT             (1 << 9)
+#define  FLD_GPIO8_INT             (1 << 8)
+#define  FLD_GPIO7_INT             (1 << 7)
+#define  FLD_GPIO6_INT             (1 << 6)
+#define  FLD_GPIO5_INT             (1 << 5)
+#define  FLD_GPIO4_INT             (1 << 4)
+#define  FLD_GPIO3_INT             (1 << 3)
+#define  FLD_GPIO2_INT             (1 << 2)
+#define  FLD_GPIO1_INT             (1 << 1)
+#define  FLD_GPIO0_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  TC_REQ                    0x040090    /* Rider PCI Express traFFic class request */
+
+/* ***************************************************************************** */
+#define  TC_REQ_SET                0x040094    /* Rider PCI Express traFFic class request set */
+
+/* ***************************************************************************** */
+/* Rider */
+/* ***************************************************************************** */
+
+/* PCI Compatible Header */
+/* ***************************************************************************** */
+#define  RDR_CFG0                  0x050000
+#define  RDR_VENDOR_DEVICE_ID_CFG  0x050000
+
+/* ***************************************************************************** */
+#define  RDR_CFG1                  0x050004
+
+/* ***************************************************************************** */
+#define  RDR_CFG2                  0x050008
+
+/* ***************************************************************************** */
+#define  RDR_CFG3                  0x05000C
+
+/* ***************************************************************************** */
+#define  RDR_CFG4                  0x050010
+
+/* ***************************************************************************** */
+#define  RDR_CFG5                  0x050014
+
+/* ***************************************************************************** */
+#define  RDR_CFG6                  0x050018
+
+/* ***************************************************************************** */
+#define  RDR_CFG7                  0x05001C
+
+/* ***************************************************************************** */
+#define  RDR_CFG8                  0x050020
+
+/* ***************************************************************************** */
+#define  RDR_CFG9                  0x050024
+
+/* ***************************************************************************** */
+#define  RDR_CFGA                  0x050028
+
+/* ***************************************************************************** */
+#define  RDR_CFGB                  0x05002C
+#define  RDR_SUSSYSTEM_ID_CFG      0x05002C
+
+/* ***************************************************************************** */
+#define  RDR_CFGC                  0x050030
+
+/* ***************************************************************************** */
+#define  RDR_CFGD                  0x050034
+
+/* ***************************************************************************** */
+#define  RDR_CFGE                  0x050038
+
+/* ***************************************************************************** */
+#define  RDR_CFGF                  0x05003C
+
+/* ***************************************************************************** */
+/* PCI-Express Capabilities */
+/* ***************************************************************************** */
+#define  RDR_PECAP                 0x050040
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVCAP              0x050044
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVSC               0x050048
+
+/* ***************************************************************************** */
+#define  RDR_PELINKCAP             0x05004C
+
+/* ***************************************************************************** */
+#define  RDR_PELINKSC              0x050050
+
+/* ***************************************************************************** */
+#define  RDR_PMICAP                0x050080
+
+/* ***************************************************************************** */
+#define  RDR_PMCSR                 0x050084
+
+/* ***************************************************************************** */
+#define  RDR_VPDCAP                0x050090
+
+/* ***************************************************************************** */
+#define  RDR_VPDDATA               0x050094
+
+/* ***************************************************************************** */
+#define  RDR_MSICAP                0x0500A0
+
+/* ***************************************************************************** */
+#define  RDR_MSIARL                0x0500A4
+
+/* ***************************************************************************** */
+#define  RDR_MSIARU                0x0500A8
+
+/* ***************************************************************************** */
+#define  RDR_MSIDATA               0x0500AC
+
+/* ***************************************************************************** */
+/* PCI Express Extended Capabilities */
+/* ***************************************************************************** */
+#define  RDR_AERXCAP               0x050100
+
+/* ***************************************************************************** */
+#define  RDR_AERUESTA              0x050104
+
+/* ***************************************************************************** */
+#define  RDR_AERUEMSK              0x050108
+
+/* ***************************************************************************** */
+#define  RDR_AERUESEV              0x05010C
+
+/* ***************************************************************************** */
+#define  RDR_AERCESTA              0x050110
+
+/* ***************************************************************************** */
+#define  RDR_AERCEMSK              0x050114
+
+/* ***************************************************************************** */
+#define  RDR_AERCC                 0x050118
+
+/* ***************************************************************************** */
+#define  RDR_AERHL0                0x05011C
+
+/* ***************************************************************************** */
+#define  RDR_AERHL1                0x050120
+
+/* ***************************************************************************** */
+#define  RDR_AERHL2                0x050124
+
+/* ***************************************************************************** */
+#define  RDR_AERHL3                0x050128
+
+/* ***************************************************************************** */
+#define  RDR_VCXCAP                0x050200
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP1                0x050204
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP2                0x050208
+
+/* ***************************************************************************** */
+#define  RDR_VCSC                  0x05020C
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CAP              0x050210
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CTRL             0x050214
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_STAT             0x050218
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CAP              0x05021C
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CTRL             0x050220
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_STAT             0x050224
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CAP              0x050228
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CTRL             0x05022C
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_STAT             0x050230
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CAP              0x050234
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CTRL             0x050238
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_STAT             0x05023C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB0                0x050240
+
+/* ***************************************************************************** */
+#define  RDR_VCARB1                0x050244
+
+/* ***************************************************************************** */
+#define  RDR_VCARB2                0x050248
+
+/* ***************************************************************************** */
+#define  RDR_VCARB3                0x05024C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB4                0x050250
+
+/* ***************************************************************************** */
+#define  RDR_VCARB5                0x050254
+
+/* ***************************************************************************** */
+#define  RDR_VCARB6                0x050258
+
+/* ***************************************************************************** */
+#define  RDR_VCARB7                0x05025C
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT0              0x050300
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT1              0x050304
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL0               0x050308
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL1               0x05030C
+
+/* ***************************************************************************** */
+/* Transaction Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_TLSTAT0               0x050310
+
+/* ***************************************************************************** */
+#define  RDR_TLSTAT1               0x050314
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL0                0x050318
+#define  FLD_CFG_UR_CPL_MODE       0x00000040
+#define  FLD_CFG_CORR_ERR_QUITE    0x00000020
+#define  FLD_CFG_RCB_CK_EN         0x00000010
+#define  FLD_CFG_BNDRY_CK_EN       0x00000008
+#define  FLD_CFG_BYTE_EN_CK_EN     0x00000004
+#define  FLD_CFG_RELAX_ORDER_MSK   0x00000002
+#define  FLD_CFG_TAG_ORDER_EN      0x00000001
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL1                0x05031C
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAL               0x050320
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAU               0x050324
+
+/* ***************************************************************************** */
+#define  RDR_REQEPA                0x050328
+
+/* ***************************************************************************** */
+#define  RDR_REQCTRL               0x05032C
+
+/* ***************************************************************************** */
+#define  RDR_REQSTAT               0x050330
+
+/* ***************************************************************************** */
+#define  RDR_TL_TEST               0x050334
+
+/* ***************************************************************************** */
+#define  RDR_VCR01_CTL             0x050348
+
+/* ***************************************************************************** */
+#define  RDR_VCR23_CTL             0x05034C
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR0_FC            0x050350
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR1_FC            0x050354
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR2_FC            0x050358
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR3_FC            0x05035C
+
+/* ***************************************************************************** */
+/* Data Link Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_DLLSTAT               0x050360
+
+/* ***************************************************************************** */
+#define  RDR_DLLCTRL               0x050364
+
+/* ***************************************************************************** */
+#define  RDR_REPLAYTO              0x050368
+
+/* ***************************************************************************** */
+#define  RDR_ACKLATTO              0x05036C
+
+/* ***************************************************************************** */
+/* MAC Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_MACSTAT0              0x050380
+
+/* ***************************************************************************** */
+#define  RDR_MACSTAT1              0x050384
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL0              0x050388
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL1              0x05038C
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL2              0x050390
+
+/* ***************************************************************************** */
+#define  RDR_MAC_LB_DATA           0x050394
+
+/* ***************************************************************************** */
+#define  RDR_L0S_EXIT_LAT          0x050398
+
+/* ***************************************************************************** */
+/* DMAC */
+/* ***************************************************************************** */
+#define  DMA1_PTR1                 0x100000    /* DMA Current Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR1                 0x100004    /* DMA Current Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR1                 0x100008    /* DMA Current Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR1                 0x10000C    /* DMA Current Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR1                 0x100010    /* DMA Current Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR1                 0x100014    /* DMA Current Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR1                 0x100018    /* DMA Current Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR1                 0x10001C    /* DMA Current Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR1                 0x100020    /* DMA Current Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR1                0x100024    /* DMA Current Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR1                0x100028    /* DMA Current Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR1                0x10002C    /* DMA Current Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR1                0x100030    /* DMA Current Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR1                0x100034    /* DMA Current Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR1                0x100038    /* DMA Current Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR1                0x10003C    /* DMA Current Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR1                0x100040    /* DMA Current Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR1                0x100044    /* DMA Current Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR1                0x100048    /* DMA Current Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR1                0x10004C    /* DMA Current Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR1                0x100050    /* DMA Current Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR1                0x100054    /* DMA Current Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR1                0x100058    /* DMA Current Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR1                0x10005C    /* DMA Current Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR1                0x100060    /* DMA Current Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR1                0x100064    /* DMA Current Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_PTR2                 0x100080    /* DMA Tab Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR2                 0x100084    /* DMA Tab Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR2                 0x100088    /* DMA Tab Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR2                 0x10008C    /* DMA Tab Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR2                 0x100090    /* DMA Tab Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR2                 0x100094    /* DMA Tab Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR2                 0x100098    /* DMA Tab Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR2                 0x10009C    /* DMA Tab Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR2                 0x1000A0    /* DMA Tab Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR2                0x1000A4    /* DMA Tab Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR2                0x1000A8    /* DMA Tab Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR2                0x1000AC    /* DMA Tab Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR2                0x1000B0    /* DMA Tab Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR2                0x1000B4    /* DMA Tab Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR2                0x1000B8    /* DMA Tab Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR2                0x1000BC    /* DMA Tab Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR2                0x1000C0    /* DMA Tab Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR2                0x1000C4    /* DMA Tab Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR2                0x1000C8    /* DMA Tab Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR2                0x1000CC    /* DMA Tab Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR2                0x1000D0    /* DMA Tab Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR2                0x1000D4    /* DMA Tab Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR2                0x1000D8    /* DMA Tab Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR2                0x1000DC    /* DMA Tab Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR2                0x1000E0    /* DMA Tab Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR2                0x1000E4    /* DMA Tab Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT1                 0x100100    /* DMA BuFFer Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT1                 0x100104    /* DMA BuFFer Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT1                 0x100108    /* DMA BuFFer Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT1                 0x10010C    /* DMA BuFFer Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT1                 0x100110    /* DMA BuFFer Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT1                 0x100114    /* DMA BuFFer Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT1                 0x100118    /* DMA BuFFer Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT1                 0x10011C    /* DMA BuFFer Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT1                 0x100120    /* DMA BuFFer Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT1                0x100124    /* DMA BuFFer Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT1                0x100128    /* DMA BuFFer Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT1                0x10012C    /* DMA BuFFer Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT1                0x100130    /* DMA BuFFer Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT1                0x100134    /* DMA BuFFer Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT1                0x100138    /* DMA BuFFer Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT1                0x10013C    /* DMA BuFFer Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT1                0x100140    /* DMA BuFFer Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT1                0x100144    /* DMA BuFFer Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT1                0x100148    /* DMA BuFFer Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT1                0x10014C    /* DMA BuFFer Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT1                0x100150    /* DMA BuFFer Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT1                0x100154    /* DMA BuFFer Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT1                0x100158    /* DMA BuFFer Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT1                0x10015C    /* DMA BuFFer Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT1                0x100160    /* DMA BuFFer Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT1                0x100164    /* DMA BuFFer Size : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT2                 0x100180    /* DMA Table Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT2                 0x100184    /* DMA Table Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT2                 0x100188    /* DMA Table Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT2                 0x10018C    /* DMA Table Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT2                 0x100190    /* DMA Table Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT2                 0x100194    /* DMA Table Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT2                 0x100198    /* DMA Table Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT2                 0x10019C    /* DMA Table Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT2                 0x1001A0    /* DMA Table Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT2                0x1001A4    /* DMA Table Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT2                0x1001A8    /* DMA Table Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT2                0x1001AC    /* DMA Table Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT2                0x1001B0    /* DMA Table Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT2                0x1001B4    /* DMA Table Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT2                0x1001B8    /* DMA Table Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT2                0x1001BC    /* DMA Table Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT2                0x1001C0    /* DMA Table Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT2                0x1001C4    /* DMA Table Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT2                0x1001C8    /* DMA Table Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT2                0x1001CC    /* DMA Table Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT2                0x1001D0    /* DMA Table Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT2                0x1001D4    /* DMA Table Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT2                0x1001D8    /* DMA Table Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT2                0x1001DC    /* DMA Table Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT2                0x1001E0    /* DMA Table Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT2                0x1001E4    /* DMA Table Size : Ch#26 */
+
+/* ***************************************************************************** */
+ /* ITG */
+/* ***************************************************************************** */
+#define  TM_CNT_LDW                0x110000    /* Timer : Counter low */
+
+/* ***************************************************************************** */
+#define  TM_CNT_UW                 0x110004    /* Timer : Counter high word */
+
+/* ***************************************************************************** */
+#define  TM_LMT_LDW                0x110008    /* Timer : Limit low */
+
+/* ***************************************************************************** */
+#define  TM_LMT_UW                 0x11000C    /* Timer : Limit high word */
+
+/* ***************************************************************************** */
+#define  GP0_IO                    0x110010    /* GPIO output enables data I/O */
+#define  FLD_GP_OE                 0x00FF0000  /* GPIO: GP_OE output enable */
+#define  FLD_GP_IN                 0x0000FF00  /* GPIO: GP_IN status */
+#define  FLD_GP_OUT                0x000000FF  /* GPIO: GP_OUT control */
+
+/* ***************************************************************************** */
+#define  GPIO_ISM                  0x110014    /* GPIO interrupt sensitivity mode */
+#define  FLD_GP_ISM_SNS            0x00000070
+#define  FLD_GP_ISM_POL            0x00000007
+
+/* ***************************************************************************** */
+#define  SOFT_RESET                0x11001C    /* Output system reset reg */
+#define  FLD_PECOS_SOFT_RESET      0x00000001
+
+/* ***************************************************************************** */
+#define  MC416_RWD                 0x110020    /* MC416 GPIO[18:3] pin */
+#define  MC416_OEN                 0x110024    /* Output enable of GPIO[18:3] */
+#define  MC416_CTL                 0x110028
+
+/* ***************************************************************************** */
+#define  ALT_PIN_OUT_SEL           0x11002C    /* Alternate GPIO output select */
+
+#define  FLD_ALT_GPIO_OUT_SEL      0xF0000000
+/* 0          Disabled <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+/* 8          ATT_IF */
+
+#define  FLD_AUX_PLL_CLK_ALT_SEL   0x0F000000
+/* 0          AUX_PLL_CLK<-- default */
+/* 1          GPIO[2] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_TX_ALT_SEL         0x00F00000
+/* 0          IR_TX <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_RX_ALT_SEL         0x000F0000
+/* 0          IR_RX <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO10_ALT_SEL        0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO2_ALT_SEL         0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO1_ALT_SEL         0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO0_ALT_SEL         0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  ALT_PIN_IN_SEL            0x110030    /* Alternate GPIO input select */
+
+#define  FLD_GPIO10_ALT_IN_SEL     0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+/* 5          GPIO[0] */
+/* 6          GPIO[1] */
+/* 7          GPIO[2] */
+
+#define  FLD_GPIO2_ALT_IN_SEL      0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO1_ALT_IN_SEL      0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO0_ALT_IN_SEL      0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL1             0x110040    /* Test bus control register #1 */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL2             0x110044    /* Test bus control register #2 */
+
+/* ***************************************************************************** */
+#define  CLK_DELAY                 0x110048    /* Clock delay */
+#define  FLD_MOE_CLK_DIS           0x80000000  /* Disable MoE clock */
+
+/* ***************************************************************************** */
+#define  PAD_CTRL                  0x110068    /* Pad drive strength control */
+
+/* ***************************************************************************** */
+#define  MBIST_CTRL                0x110050    /* SRAM memory built-in self test control */
+
+/* ***************************************************************************** */
+#define  MBIST_STAT                0x110054    /* SRAM memory built-in self test status */
+
+/* ***************************************************************************** */
+/* PLL registers */
+/* ***************************************************************************** */
+#define  PLL_A_INT_FRAC            0x110088
+#define  PLL_A_POST_STAT_BIST      0x11008C
+#define  PLL_B_INT_FRAC            0x110090
+#define  PLL_B_POST_STAT_BIST      0x110094
+#define  PLL_C_INT_FRAC            0x110098
+#define  PLL_C_POST_STAT_BIST      0x11009C
+#define  PLL_D_INT_FRAC            0x1100A0
+#define  PLL_D_POST_STAT_BIST      0x1100A4
+
+#define  CLK_RST                   0x11002C
+#define  FLD_VID_I_CLK_NOE         0x00001000
+#define  FLD_VID_J_CLK_NOE         0x00002000
+#define  FLD_USE_ALT_PLL_REF       0x00004000
+
+#define  VID_CH_MODE_SEL           0x110078
+#define  VID_CH_CLK_SEL            0x11007C
+
+/* ***************************************************************************** */
+#define  VBI_A_DMA                 0x130008    /* VBI A DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_A_VIP_CTL             0x130080    /* Video A VIP format control */
+#define  FLD_VIP_MODE              0x00000001
+
+/* ***************************************************************************** */
+#define  VID_A_PIXEL_FRMT          0x130084    /* Video A pixel format */
+#define  FLD_VID_A_GAMMA_DIS       0x00000008
+#define  FLD_VID_A_FORMAT          0x00000007
+#define  FLD_VID_A_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_A_VBI_CTL             0x130088    /* Video A VBI miscellaneous control */
+#define  FLD_VID_A_VIP_EXT         0x00000003
+
+/* ***************************************************************************** */
+#define  VID_B_DMA                 0x130100    /* Video B DMA data port */
+
+/* ***************************************************************************** */
+#define  VBI_B_DMA                 0x130108    /* VBI B DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_B_SRC_SEL             0x130144    /* Video B source select */
+#define  FLD_VID_B_SRC_SEL         0x00000000
+
+/* ***************************************************************************** */
+#define  VID_B_LNGTH               0x130150    /* Video B line length */
+#define  FLD_VID_B_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+#define  VID_B_VIP_CTL             0x130180    /* Video B VIP format control */
+
+/* ***************************************************************************** */
+#define  VID_B_PIXEL_FRMT          0x130184    /* Video B pixel format */
+#define  FLD_VID_B_GAMMA_DIS       0x00000008
+#define  FLD_VID_B_FORMAT          0x00000007
+#define  FLD_VID_B_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_C_DMA                 0x130200    /* Video C DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_C_LNGTH               0x130250    /* Video C line length */
+#define  FLD_VID_C_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+/* Video Destination Channels */
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT           0x130020    /* Video A general purpose counter */
+#define  VID_DST_B_GPCNT           0x130120    /* Video B general purpose counter */
+#define  VID_DST_C_GPCNT           0x130220    /* Video C general purpose counter */
+#define  VID_DST_D_GPCNT           0x130320    /* Video D general purpose counter */
+#define  VID_DST_E_GPCNT           0x130420    /* Video E general purpose counter */
+#define  VID_DST_F_GPCNT           0x130520    /* Video F general purpose counter */
+#define  VID_DST_G_GPCNT           0x130620    /* Video G general purpose counter */
+#define  VID_DST_H_GPCNT           0x130720    /* Video H general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT_CTL       0x130030    /* Video A general purpose control */
+#define  VID_DST_B_GPCNT_CTL       0x130130    /* Video B general purpose control */
+#define  VID_DST_C_GPCNT_CTL       0x130230    /* Video C general purpose control */
+#define  VID_DST_D_GPCNT_CTL       0x130330    /* Video D general purpose control */
+#define  VID_DST_E_GPCNT_CTL       0x130430    /* Video E general purpose control */
+#define  VID_DST_F_GPCNT_CTL       0x130530    /* Video F general purpose control */
+#define  VID_DST_G_GPCNT_CTL       0x130630    /* Video G general purpose control */
+#define  VID_DST_H_GPCNT_CTL       0x130730    /* Video H general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_DMA_CTL         0x130040    /* Video A DMA control */
+#define  VID_DST_B_DMA_CTL         0x130140    /* Video B DMA control */
+#define  VID_DST_C_DMA_CTL         0x130240    /* Video C DMA control */
+#define  VID_DST_D_DMA_CTL         0x130340    /* Video D DMA control */
+#define  VID_DST_E_DMA_CTL         0x130440    /* Video E DMA control */
+#define  VID_DST_F_DMA_CTL         0x130540    /* Video F DMA control */
+#define  VID_DST_G_DMA_CTL         0x130640    /* Video G DMA control */
+#define  VID_DST_H_DMA_CTL         0x130740    /* Video H DMA control */
+
+#define  FLD_VID_RISC_EN           0x00000010
+#define  FLD_VID_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_VIP_CTL         0x130080    /* Video A VIP control */
+#define  VID_DST_B_VIP_CTL         0x130180    /* Video B VIP control */
+#define  VID_DST_C_VIP_CTL         0x130280    /* Video C VIP control */
+#define  VID_DST_D_VIP_CTL         0x130380    /* Video D VIP control */
+#define  VID_DST_E_VIP_CTL         0x130480    /* Video E VIP control */
+#define  VID_DST_F_VIP_CTL         0x130580    /* Video F VIP control */
+#define  VID_DST_G_VIP_CTL         0x130680    /* Video G VIP control */
+#define  VID_DST_H_VIP_CTL         0x130780    /* Video H VIP control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_PIX_FRMT        0x130084    /* Video A Pixel format */
+#define  VID_DST_B_PIX_FRMT        0x130184    /* Video B Pixel format */
+#define  VID_DST_C_PIX_FRMT        0x130284    /* Video C Pixel format */
+#define  VID_DST_D_PIX_FRMT        0x130384    /* Video D Pixel format */
+#define  VID_DST_E_PIX_FRMT        0x130484    /* Video E Pixel format */
+#define  VID_DST_F_PIX_FRMT        0x130584    /* Video F Pixel format */
+#define  VID_DST_G_PIX_FRMT        0x130684    /* Video G Pixel format */
+#define  VID_DST_H_PIX_FRMT        0x130784    /* Video H Pixel format */
+
+/* ***************************************************************************** */
+/* Video Source Channels */
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT_CTL       0x130804    /* Video A general purpose control */
+#define  VID_SRC_B_GPCNT_CTL       0x130904    /* Video B general purpose control */
+#define  VID_SRC_C_GPCNT_CTL       0x130A04    /* Video C general purpose control */
+#define  VID_SRC_D_GPCNT_CTL       0x130B04    /* Video D general purpose control */
+#define  VID_SRC_E_GPCNT_CTL       0x130C04    /* Video E general purpose control */
+#define  VID_SRC_F_GPCNT_CTL       0x130D04    /* Video F general purpose control */
+#define  VID_SRC_I_GPCNT_CTL       0x130E04    /* Video I general purpose control */
+#define  VID_SRC_J_GPCNT_CTL       0x130F04    /* Video J general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT           0x130808    /* Video A general purpose counter */
+#define  VID_SRC_B_GPCNT           0x130908    /* Video B general purpose counter */
+#define  VID_SRC_C_GPCNT           0x130A08    /* Video C general purpose counter */
+#define  VID_SRC_D_GPCNT           0x130B08    /* Video D general purpose counter */
+#define  VID_SRC_E_GPCNT           0x130C08    /* Video E general purpose counter */
+#define  VID_SRC_F_GPCNT           0x130D08    /* Video F general purpose counter */
+#define  VID_SRC_I_GPCNT           0x130E08    /* Video I general purpose counter */
+#define  VID_SRC_J_GPCNT           0x130F08    /* Video J general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_DMA_CTL         0x13080C    /* Video A DMA control */
+#define  VID_SRC_B_DMA_CTL         0x13090C    /* Video B DMA control */
+#define  VID_SRC_C_DMA_CTL         0x130A0C    /* Video C DMA control */
+#define  VID_SRC_D_DMA_CTL         0x130B0C    /* Video D DMA control */
+#define  VID_SRC_E_DMA_CTL         0x130C0C    /* Video E DMA control */
+#define  VID_SRC_F_DMA_CTL         0x130D0C    /* Video F DMA control */
+#define  VID_SRC_I_DMA_CTL         0x130E0C    /* Video I DMA control */
+#define  VID_SRC_J_DMA_CTL         0x130F0C    /* Video J DMA control */
+
+#define  FLD_APB_RISC_EN           0x00000010
+#define  FLD_APB_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_FMT_CTL         0x130810    /* Video A format control */
+#define  VID_SRC_B_FMT_CTL         0x130910    /* Video B format control */
+#define  VID_SRC_C_FMT_CTL         0x130A10    /* Video C format control */
+#define  VID_SRC_D_FMT_CTL         0x130B10    /* Video D format control */
+#define  VID_SRC_E_FMT_CTL         0x130C10    /* Video E format control */
+#define  VID_SRC_F_FMT_CTL         0x130D10    /* Video F format control */
+#define  VID_SRC_I_FMT_CTL         0x130E10    /* Video I format control */
+#define  VID_SRC_J_FMT_CTL         0x130F10    /* Video J format control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL1     0x130814    /* Video A active control      1 */
+#define  VID_SRC_B_ACTIVE_CTL1     0x130914    /* Video B active control      1 */
+#define  VID_SRC_C_ACTIVE_CTL1     0x130A14    /* Video C active control      1 */
+#define  VID_SRC_D_ACTIVE_CTL1     0x130B14    /* Video D active control      1 */
+#define  VID_SRC_E_ACTIVE_CTL1     0x130C14    /* Video E active control      1 */
+#define  VID_SRC_F_ACTIVE_CTL1     0x130D14    /* Video F active control      1 */
+#define  VID_SRC_I_ACTIVE_CTL1     0x130E14    /* Video I active control      1 */
+#define  VID_SRC_J_ACTIVE_CTL1     0x130F14    /* Video J active control      1 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL2     0x130818    /* Video A active control      2 */
+#define  VID_SRC_B_ACTIVE_CTL2     0x130918    /* Video B active control      2 */
+#define  VID_SRC_C_ACTIVE_CTL2     0x130A18    /* Video C active control      2 */
+#define  VID_SRC_D_ACTIVE_CTL2     0x130B18    /* Video D active control      2 */
+#define  VID_SRC_E_ACTIVE_CTL2     0x130C18    /* Video E active control      2 */
+#define  VID_SRC_F_ACTIVE_CTL2     0x130D18    /* Video F active control      2 */
+#define  VID_SRC_I_ACTIVE_CTL2     0x130E18    /* Video I active control      2 */
+#define  VID_SRC_J_ACTIVE_CTL2     0x130F18    /* Video J active control      2 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_CDT_SZ          0x13081C    /* Video A CDT size */
+#define  VID_SRC_B_CDT_SZ          0x13091C    /* Video B CDT size */
+#define  VID_SRC_C_CDT_SZ          0x130A1C    /* Video C CDT size */
+#define  VID_SRC_D_CDT_SZ          0x130B1C    /* Video D CDT size */
+#define  VID_SRC_E_CDT_SZ          0x130C1C    /* Video E CDT size */
+#define  VID_SRC_F_CDT_SZ          0x130D1C    /* Video F CDT size */
+#define  VID_SRC_I_CDT_SZ          0x130E1C    /* Video I CDT size */
+#define  VID_SRC_J_CDT_SZ          0x130F1C    /* Video J CDT size */
+
+/* ***************************************************************************** */
+/* Audio I/F */
+/* ***************************************************************************** */
+#define  AUD_DST_A_DMA             0x140000    /* Audio Int A DMA data port */
+#define  AUD_SRC_A_DMA             0x140008    /* Audio Int A DMA data port */
+
+#define  AUD_A_GPCNT               0x140010    /* Audio Int A gp counter */
+#define  FLD_AUD_A_GP_CNT          0x0000FFFF
+
+#define  AUD_A_GPCNT_CTL           0x140014    /* Audio Int A gp control */
+
+#define  AUD_A_LNGTH               0x140018    /* Audio Int A line length */
+
+#define  AUD_A_CFG                 0x14001C    /* Audio Int A configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_B_DMA             0x140100    /* Audio Int B DMA data port */
+#define  AUD_SRC_B_DMA             0x140108    /* Audio Int B DMA data port */
+
+#define  AUD_B_GPCNT               0x140110    /* Audio Int B gp counter */
+#define  FLD_AUD_B_GP_CNT          0x0000FFFF
+
+#define  AUD_B_GPCNT_CTL           0x140114    /* Audio Int B gp control */
+
+#define  AUD_B_LNGTH               0x140118    /* Audio Int B line length */
+
+#define  AUD_B_CFG                 0x14011C    /* Audio Int B configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_C_DMA             0x140200    /* Audio Int C DMA data port */
+#define  AUD_SRC_C_DMA             0x140208    /* Audio Int C DMA data port */
+
+#define  AUD_C_GPCNT               0x140210    /* Audio Int C gp counter */
+#define  FLD_AUD_C_GP_CNT          0x0000FFFF
+
+#define  AUD_C_GPCNT_CTL           0x140214    /* Audio Int C gp control */
+
+#define  AUD_C_LNGTH               0x140218    /* Audio Int C line length */
+
+#define  AUD_C_CFG                 0x14021C    /* Audio Int C configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_D_DMA             0x140300    /* Audio Int D DMA data port */
+#define  AUD_SRC_D_DMA             0x140308    /* Audio Int D DMA data port */
+
+#define  AUD_D_GPCNT               0x140310    /* Audio Int D gp counter */
+#define  FLD_AUD_D_GP_CNT          0x0000FFFF
+
+#define  AUD_D_GPCNT_CTL           0x140314    /* Audio Int D gp control */
+
+#define  AUD_D_LNGTH               0x140318    /* Audio Int D line length */
+
+#define  AUD_D_CFG                 0x14031C    /* Audio Int D configuration */
+
+/* ***************************************************************************** */
+#define  AUD_SRC_E_DMA             0x140400    /* Audio Int E DMA data port */
+
+#define  AUD_E_GPCNT               0x140410    /* Audio Int E gp counter */
+#define  FLD_AUD_E_GP_CNT          0x0000FFFF
+
+#define  AUD_E_GPCNT_CTL           0x140414    /* Audio Int E gp control */
+
+#define  AUD_E_CFG                 0x14041C    /* Audio Int E configuration */
+
+/* ***************************************************************************** */
+
+#define  FLD_AUD_DST_LN_LNGTH      0x00000FFF
+
+#define  FLD_AUD_DST_PK_MODE       0x00004000
+
+#define  FLD_AUD_CLK_ENABLE        0x00000200
+
+#define  FLD_AUD_MASTER_MODE       0x00000002
+
+#define  FLD_AUD_SONY_MODE         0x00000001
+
+#define  FLD_AUD_CLK_SELECT_PLL_D  0x00001800
+
+#define  FLD_AUD_DST_ENABLE        0x00020000
+
+#define  FLD_AUD_SRC_ENABLE        0x00010000
+
+/* ***************************************************************************** */
+#define  AUD_INT_DMA_CTL           0x140500    /* Audio Int DMA control */
+
+#define  FLD_AUD_SRC_E_RISC_EN     0x00008000
+#define  FLD_AUD_SRC_C_RISC_EN     0x00004000
+#define  FLD_AUD_SRC_B_RISC_EN     0x00002000
+#define  FLD_AUD_SRC_A_RISC_EN     0x00001000
+
+#define  FLD_AUD_DST_D_RISC_EN     0x00000800
+#define  FLD_AUD_DST_C_RISC_EN     0x00000400
+#define  FLD_AUD_DST_B_RISC_EN     0x00000200
+#define  FLD_AUD_DST_A_RISC_EN     0x00000100
+
+#define  FLD_AUD_SRC_E_FIFO_EN     0x00000080
+#define  FLD_AUD_SRC_C_FIFO_EN     0x00000040
+#define  FLD_AUD_SRC_B_FIFO_EN     0x00000020
+#define  FLD_AUD_SRC_A_FIFO_EN     0x00000010
+
+#define  FLD_AUD_DST_D_FIFO_EN     0x00000008
+#define  FLD_AUD_DST_C_FIFO_EN     0x00000004
+#define  FLD_AUD_DST_B_FIFO_EN     0x00000002
+#define  FLD_AUD_DST_A_FIFO_EN     0x00000001
+
+/* ***************************************************************************** */
+/*  */
+/* Mobilygen Interface Registers */
+/*  */
+/* ***************************************************************************** */
+/* Mobilygen Interface A */
+/* ***************************************************************************** */
+#define  MB_IF_A_DMA               0x150000    /* MBIF A DMA data port */
+#define  MB_IF_A_GPCN              0x150008    /* MBIF A GP counter */
+#define  MB_IF_A_GPCN_CTRL         0x15000C
+#define  MB_IF_A_DMA_CTRL          0x150010
+#define  MB_IF_A_LENGTH            0x150014
+#define  MB_IF_A_HDMA_XFER_SZ      0x150018
+#define  MB_IF_A_HCMD              0x15001C
+#define  MB_IF_A_HCONFIG           0x150020
+#define  MB_IF_A_DATA_STRUCT_0     0x150024
+#define  MB_IF_A_DATA_STRUCT_1     0x150028
+#define  MB_IF_A_DATA_STRUCT_2     0x15002C
+#define  MB_IF_A_DATA_STRUCT_3     0x150030
+#define  MB_IF_A_DATA_STRUCT_4     0x150034
+#define  MB_IF_A_DATA_STRUCT_5     0x150038
+#define  MB_IF_A_DATA_STRUCT_6     0x15003C
+#define  MB_IF_A_DATA_STRUCT_7     0x150040
+#define  MB_IF_A_DATA_STRUCT_8     0x150044
+#define  MB_IF_A_DATA_STRUCT_9     0x150048
+#define  MB_IF_A_DATA_STRUCT_A     0x15004C
+#define  MB_IF_A_DATA_STRUCT_B     0x150050
+#define  MB_IF_A_DATA_STRUCT_C     0x150054
+#define  MB_IF_A_DATA_STRUCT_D     0x150058
+#define  MB_IF_A_DATA_STRUCT_E     0x15005C
+#define  MB_IF_A_DATA_STRUCT_F     0x150060
+/* ***************************************************************************** */
+/* Mobilygen Interface B */
+/* ***************************************************************************** */
+#define  MB_IF_B_DMA               0x160000    /* MBIF A DMA data port */
+#define  MB_IF_B_GPCN              0x160008    /* MBIF A GP counter */
+#define  MB_IF_B_GPCN_CTRL         0x16000C
+#define  MB_IF_B_DMA_CTRL          0x160010
+#define  MB_IF_B_LENGTH            0x160014
+#define  MB_IF_B_HDMA_XFER_SZ      0x160018
+#define  MB_IF_B_HCMD              0x16001C
+#define  MB_IF_B_HCONFIG           0x160020
+#define  MB_IF_B_DATA_STRUCT_0     0x160024
+#define  MB_IF_B_DATA_STRUCT_1     0x160028
+#define  MB_IF_B_DATA_STRUCT_2     0x16002C
+#define  MB_IF_B_DATA_STRUCT_3     0x160030
+#define  MB_IF_B_DATA_STRUCT_4     0x160034
+#define  MB_IF_B_DATA_STRUCT_5     0x160038
+#define  MB_IF_B_DATA_STRUCT_6     0x16003C
+#define  MB_IF_B_DATA_STRUCT_7     0x160040
+#define  MB_IF_B_DATA_STRUCT_8     0x160044
+#define  MB_IF_B_DATA_STRUCT_9     0x160048
+#define  MB_IF_B_DATA_STRUCT_A     0x16004C
+#define  MB_IF_B_DATA_STRUCT_B     0x160050
+#define  MB_IF_B_DATA_STRUCT_C     0x160054
+#define  MB_IF_B_DATA_STRUCT_D     0x160058
+#define  MB_IF_B_DATA_STRUCT_E     0x16005C
+#define  MB_IF_B_DATA_STRUCT_F     0x160060
+
+/* MB_DMA_CTRL */
+#define  FLD_MB_IF_RISC_EN         0x00000010
+#define  FLD_MB_IF_FIFO_EN         0x00000001
+
+/* MB_LENGTH */
+#define  FLD_MB_IF_LN_LNGTH        0x00000FFF
+
+/* MB_HCMD register */
+#define  FLD_MB_HCMD_H_GO          0x80000000
+#define  FLD_MB_HCMD_H_BUSY        0x40000000
+#define  FLD_MB_HCMD_H_DMA_HOLD    0x10000000
+#define  FLD_MB_HCMD_H_DMA_BUSY    0x08000000
+#define  FLD_MB_HCMD_H_DMA_TYPE    0x04000000
+#define  FLD_MB_HCMD_H_DMA_XACT    0x02000000
+#define  FLD_MB_HCMD_H_RW_N        0x01000000
+#define  FLD_MB_HCMD_H_ADDR        0x00FF0000
+#define  FLD_MB_HCMD_H_DATA        0x0000FFFF
+
+/* ***************************************************************************** */
+/* I2C #1 */
+/* ***************************************************************************** */
+#define  I2C1_ADDR                 0x180000    /* I2C #1 address */
+#define  FLD_I2C_DADDR             0xfe000000  /* RW [31:25] I2C Device Address */
+                                                /* RO [24] reserved */
+/* ***************************************************************************** */
+#define  FLD_I2C_SADDR             0x00FFFFFF  /* RW [23:0]  I2C Sub-address */
+
+/* ***************************************************************************** */
+#define  I2C1_WDATA                0x180004    /* I2C #1 write data */
+#define  FLD_I2C_WDATA             0xFFFFFFFF  /* RW [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_CTRL                 0x180008    /* I2C #1 control */
+#define  FLD_I2C_PERIOD            0xFF000000  /* RW [31:24] */
+#define  FLD_I2C_SCL_IN            0x00200000  /* RW [21] */
+#define  FLD_I2C_SDA_IN            0x00100000  /* RW [20] */
+                                                /* RO [19:18] reserved */
+#define  FLD_I2C_SCL_OUT           0x00020000  /* RW [17] */
+#define  FLD_I2C_SDA_OUT           0x00010000  /* RW [16] */
+                                                /* RO [15] reserved */
+#define  FLD_I2C_DATA_LEN          0x00007000  /* RW [14:12] */
+#define  FLD_I2C_SADDR_INC         0x00000800  /* RW [11] */
+                                                /* RO [10:9] reserved */
+#define  FLD_I2C_SADDR_LEN         0x00000300  /* RW [9:8] */
+                                                /* RO [7:6] reserved */
+#define  FLD_I2C_SOFT              0x00000020  /* RW [5] */
+#define  FLD_I2C_NOSTOP            0x00000010  /* RW [4] */
+#define  FLD_I2C_EXTEND            0x00000008  /* RW [3] */
+#define  FLD_I2C_SYNC              0x00000004  /* RW [2] */
+#define  FLD_I2C_READ_SA           0x00000002  /* RW [1] */
+#define  FLD_I2C_READ_WRN          0x00000001  /* RW [0] */
+
+/* ***************************************************************************** */
+#define  I2C1_RDATA                0x18000C    /* I2C #1 read data */
+#define  FLD_I2C_RDATA             0xFFFFFFFF  /* RO [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_STAT                 0x180010    /* I2C #1 status */
+#define  FLD_I2C_XFER_IN_PROG      0x00000002  /* RO [1] */
+#define  FLD_I2C_RACK              0x00000001  /* RO [0] */
+
+/* ***************************************************************************** */
+/* I2C #2 */
+/* ***************************************************************************** */
+#define  I2C2_ADDR                 0x190000    /* I2C #2 address */
+
+/* ***************************************************************************** */
+#define  I2C2_WDATA                0x190004    /* I2C #2 write data */
+
+/* ***************************************************************************** */
+#define  I2C2_CTRL                 0x190008    /* I2C #2 control */
+
+/* ***************************************************************************** */
+#define  I2C2_RDATA                0x19000C    /* I2C #2 read data */
+
+/* ***************************************************************************** */
+#define  I2C2_STAT                 0x190010    /* I2C #2 status */
+
+/* ***************************************************************************** */
+/* I2C #3 */
+/* ***************************************************************************** */
+#define  I2C3_ADDR                 0x1A0000    /* I2C #3 address */
+
+/* ***************************************************************************** */
+#define  I2C3_WDATA                0x1A0004    /* I2C #3 write data */
+
+/* ***************************************************************************** */
+#define  I2C3_CTRL                 0x1A0008    /* I2C #3 control */
+
+/* ***************************************************************************** */
+#define  I2C3_RDATA                0x1A000C    /* I2C #3 read data */
+
+/* ***************************************************************************** */
+#define  I2C3_STAT                 0x1A0010    /* I2C #3 status */
+
+/* ***************************************************************************** */
+/* UART */
+/* ***************************************************************************** */
+#define  UART_CTL                  0x1B0000    /* UART Control Register */
+#define  FLD_LOOP_BACK_EN          (1 << 7)    /* RW field - default 0 */
+#define  FLD_RX_TRG_SZ             (3 << 2)    /* RW field - default 0 */
+#define  FLD_RX_EN                 (1 << 1)    /* RW field - default 0 */
+#define  FLD_TX_EN                 (1 << 0)    /* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_BRD                  0x1B0004    /* UART Baud Rate Divisor */
+#define  FLD_BRD                   0x0000FFFF  /* RW field - default 0x197 */
+
+/* ***************************************************************************** */
+#define  UART_DBUF                 0x1B0008    /* UART Tx/Rx Data BuFFer */
+#define  FLD_DB                    0xFFFFFFFF  /* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_ISR                  0x1B000C    /* UART Interrupt Status */
+#define  FLD_RXD_TIMEOUT_EN        (1 << 7)    /* RW field - default 0 */
+#define  FLD_FRM_ERR_EN            (1 << 6)    /* RW field - default 0 */
+#define  FLD_RXD_RDY_EN            (1 << 5)    /* RW field - default 0 */
+#define  FLD_TXD_EMPTY_EN          (1 << 4)    /* RW field - default 0 */
+#define  FLD_RXD_OVERFLOW          (1 << 3)    /* RW field - default 0 */
+#define  FLD_FRM_ERR               (1 << 2)    /* RW field - default 0 */
+#define  FLD_RXD_RDY               (1 << 1)    /* RW field - default 0 */
+#define  FLD_TXD_EMPTY             (1 << 0)    /* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_CNT                  0x1B0010    /* UART Tx/Rx FIFO Byte Count */
+#define  FLD_TXD_CNT               (0x1F << 8) /* RW field - default 0 */
+#define  FLD_RXD_CNT               (0x1F << 0) /* RW field - default 0 */
+
+/* ***************************************************************************** */
+/* Motion Detection */
+#define  MD_CH0_GRID_BLOCK_YCNT    0x170014
+#define  MD_CH1_GRID_BLOCK_YCNT    0x170094
+#define  MD_CH2_GRID_BLOCK_YCNT    0x170114
+#define  MD_CH3_GRID_BLOCK_YCNT    0x170194
+#define  MD_CH4_GRID_BLOCK_YCNT    0x170214
+#define  MD_CH5_GRID_BLOCK_YCNT    0x170294
+#define  MD_CH6_GRID_BLOCK_YCNT    0x170314
+#define  MD_CH7_GRID_BLOCK_YCNT    0x170394
+
+#define PIXEL_FRMT_422    4
+#define PIXEL_FRMT_411    5
+#define PIXEL_FRMT_Y8     6
+
+#define PIXEL_ENGINE_VIP1 0
+#define PIXEL_ENGINE_VIP2 1
+
+#endif /* Athena_REGISTERS */
diff --git a/drivers/media/pci/cx25821/cx25821-sram.h b/drivers/media/pci/cx25821/cx25821-sram.h
new file mode 100644 (file)
index 0000000..5f05d15
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __ATHENA_SRAM_H__
+#define __ATHENA_SRAM_H__
+
+/* #define RX_SRAM_START_SIZE        = 0;  //  Start of reserved SRAM */
+#define VID_CMDS_SIZE             80   /* Video CMDS size in bytes */
+#define AUDIO_CMDS_SIZE           80   /* AUDIO CMDS size in bytes */
+#define MBIF_CMDS_SIZE            80   /* MBIF  CMDS size in bytes */
+
+/* #define RX_SRAM_POOL_START_SIZE   = 0;  //  Start of useable RX SRAM for buffers */
+#define VID_IQ_SIZE               64   /* VID instruction queue size in bytes */
+#define MBIF_IQ_SIZE              64
+#define AUDIO_IQ_SIZE             64   /* AUD instruction queue size in bytes */
+
+#define VID_CDT_SIZE              64   /* VID cluster descriptor table size in bytes */
+#define MBIF_CDT_SIZE             64   /* MBIF/HBI cluster descriptor table size in bytes */
+#define AUDIO_CDT_SIZE            48   /* AUD cluster descriptor table size in bytes */
+
+/* #define RX_SRAM_POOL_FREE_SIZE    = 16; //  Start of available RX SRAM */
+/* #define RX_SRAM_END_SIZE          = 0;  //  End of RX SRAM */
+
+/* #define TX_SRAM_POOL_START_SIZE   = 0;  //  Start of transmit pool SRAM */
+/* #define MSI_DATA_SIZE             = 64; //  Reserved (MSI Data, RISC working stora */
+
+#define VID_CLUSTER_SIZE          1440 /* VID cluster data line */
+#define AUDIO_CLUSTER_SIZE        128  /* AUDIO cluster data line */
+#define MBIF_CLUSTER_SIZE         1440 /* MBIF/HBI cluster data line */
+
+/* #define TX_SRAM_POOL_FREE_SIZE    = 704;    //  Start of available TX SRAM */
+/* #define TX_SRAM_END_SIZE          = 0;      //  End of TX SRAM */
+
+/* Receive SRAM */
+#define RX_SRAM_START             0x10000
+#define VID_A_DOWN_CMDS           0x10000
+#define VID_B_DOWN_CMDS           0x10050
+#define VID_C_DOWN_CMDS           0x100A0
+#define VID_D_DOWN_CMDS           0x100F0
+#define VID_E_DOWN_CMDS           0x10140
+#define VID_F_DOWN_CMDS           0x10190
+#define VID_G_DOWN_CMDS           0x101E0
+#define VID_H_DOWN_CMDS           0x10230
+#define VID_A_UP_CMDS             0x10280
+#define VID_B_UP_CMDS             0x102D0
+#define VID_C_UP_CMDS             0x10320
+#define VID_D_UP_CMDS             0x10370
+#define VID_E_UP_CMDS             0x103C0
+#define VID_F_UP_CMDS             0x10410
+#define VID_I_UP_CMDS             0x10460
+#define VID_J_UP_CMDS             0x104B0
+#define AUD_A_DOWN_CMDS           0x10500
+#define AUD_B_DOWN_CMDS           0x10550
+#define AUD_C_DOWN_CMDS           0x105A0
+#define AUD_D_DOWN_CMDS           0x105F0
+#define AUD_A_UP_CMDS             0x10640
+#define AUD_B_UP_CMDS             0x10690
+#define AUD_C_UP_CMDS             0x106E0
+#define AUD_E_UP_CMDS             0x10730
+#define MBIF_A_DOWN_CMDS          0x10780
+#define MBIF_B_DOWN_CMDS          0x107D0
+#define DMA_SCRATCH_PAD           0x10820      /* Scratch pad area from 0x10820 to 0x10B40 */
+
+/* #define RX_SRAM_POOL_START        = 0x105B0; */
+
+#define VID_A_IQ                  0x11000
+#define VID_B_IQ                  0x11040
+#define VID_C_IQ                  0x11080
+#define VID_D_IQ                  0x110C0
+#define VID_E_IQ                  0x11100
+#define VID_F_IQ                  0x11140
+#define VID_G_IQ                  0x11180
+#define VID_H_IQ                  0x111C0
+#define VID_I_IQ                  0x11200
+#define VID_J_IQ                  0x11240
+#define AUD_A_IQ                  0x11280
+#define AUD_B_IQ                  0x112C0
+#define AUD_C_IQ                  0x11300
+#define AUD_D_IQ                  0x11340
+#define AUD_E_IQ                  0x11380
+#define MBIF_A_IQ                 0x11000
+#define MBIF_B_IQ                 0x110C0
+
+#define VID_A_CDT                 0x10C00
+#define VID_B_CDT                 0x10C40
+#define VID_C_CDT                 0x10C80
+#define VID_D_CDT                 0x10CC0
+#define VID_E_CDT                 0x10D00
+#define VID_F_CDT                 0x10D40
+#define VID_G_CDT                 0x10D80
+#define VID_H_CDT                 0x10DC0
+#define VID_I_CDT                 0x10E00
+#define VID_J_CDT                 0x10E40
+#define AUD_A_CDT                 0x10E80
+#define AUD_B_CDT                 0x10EB0
+#define AUD_C_CDT                 0x10EE0
+#define AUD_D_CDT                 0x10F10
+#define AUD_E_CDT                 0x10F40
+#define MBIF_A_CDT                0x10C00
+#define MBIF_B_CDT                0x10CC0
+
+/* Cluster Buffer for RX */
+#define VID_A_UP_CLUSTER_1        0x11400
+#define VID_A_UP_CLUSTER_2        0x119A0
+#define VID_A_UP_CLUSTER_3        0x11F40
+#define VID_A_UP_CLUSTER_4        0x124E0
+
+#define VID_B_UP_CLUSTER_1        0x12A80
+#define VID_B_UP_CLUSTER_2        0x13020
+#define VID_B_UP_CLUSTER_3        0x135C0
+#define VID_B_UP_CLUSTER_4        0x13B60
+
+#define VID_C_UP_CLUSTER_1        0x14100
+#define VID_C_UP_CLUSTER_2        0x146A0
+#define VID_C_UP_CLUSTER_3        0x14C40
+#define VID_C_UP_CLUSTER_4        0x151E0
+
+#define VID_D_UP_CLUSTER_1        0x15780
+#define VID_D_UP_CLUSTER_2        0x15D20
+#define VID_D_UP_CLUSTER_3        0x162C0
+#define VID_D_UP_CLUSTER_4        0x16860
+
+#define VID_E_UP_CLUSTER_1        0x16E00
+#define VID_E_UP_CLUSTER_2        0x173A0
+#define VID_E_UP_CLUSTER_3        0x17940
+#define VID_E_UP_CLUSTER_4        0x17EE0
+
+#define VID_F_UP_CLUSTER_1        0x18480
+#define VID_F_UP_CLUSTER_2        0x18A20
+#define VID_F_UP_CLUSTER_3        0x18FC0
+#define VID_F_UP_CLUSTER_4        0x19560
+
+#define VID_I_UP_CLUSTER_1        0x19B00
+#define VID_I_UP_CLUSTER_2        0x1A0A0
+#define VID_I_UP_CLUSTER_3        0x1A640
+#define VID_I_UP_CLUSTER_4        0x1ABE0
+
+#define VID_J_UP_CLUSTER_1        0x1B180
+#define VID_J_UP_CLUSTER_2        0x1B720
+#define VID_J_UP_CLUSTER_3        0x1BCC0
+#define VID_J_UP_CLUSTER_4        0x1C260
+
+#define AUD_A_UP_CLUSTER_1        0x1C800
+#define AUD_A_UP_CLUSTER_2        0x1C880
+#define AUD_A_UP_CLUSTER_3        0x1C900
+
+#define AUD_B_UP_CLUSTER_1        0x1C980
+#define AUD_B_UP_CLUSTER_2        0x1CA00
+#define AUD_B_UP_CLUSTER_3        0x1CA80
+
+#define AUD_C_UP_CLUSTER_1        0x1CB00
+#define AUD_C_UP_CLUSTER_2        0x1CB80
+#define AUD_C_UP_CLUSTER_3        0x1CC00
+
+#define AUD_E_UP_CLUSTER_1        0x1CC80
+#define AUD_E_UP_CLUSTER_2        0x1CD00
+#define AUD_E_UP_CLUSTER_3        0x1CD80
+
+#define RX_SRAM_POOL_FREE         0x1CE00
+#define RX_SRAM_END               0x1D000
+
+/* Free Receive SRAM    144 Bytes */
+
+/* Transmit SRAM */
+#define TX_SRAM_POOL_START        0x00000
+
+#define VID_A_DOWN_CLUSTER_1      0x00040
+#define VID_A_DOWN_CLUSTER_2      0x005E0
+#define VID_A_DOWN_CLUSTER_3      0x00B80
+#define VID_A_DOWN_CLUSTER_4      0x01120
+
+#define VID_B_DOWN_CLUSTER_1      0x016C0
+#define VID_B_DOWN_CLUSTER_2      0x01C60
+#define VID_B_DOWN_CLUSTER_3      0x02200
+#define VID_B_DOWN_CLUSTER_4      0x027A0
+
+#define VID_C_DOWN_CLUSTER_1      0x02D40
+#define VID_C_DOWN_CLUSTER_2      0x032E0
+#define VID_C_DOWN_CLUSTER_3      0x03880
+#define VID_C_DOWN_CLUSTER_4      0x03E20
+
+#define VID_D_DOWN_CLUSTER_1      0x043C0
+#define VID_D_DOWN_CLUSTER_2      0x04960
+#define VID_D_DOWN_CLUSTER_3      0x04F00
+#define VID_D_DOWN_CLUSTER_4      0x054A0
+
+#define VID_E_DOWN_CLUSTER_1      0x05a40
+#define VID_E_DOWN_CLUSTER_2      0x05FE0
+#define VID_E_DOWN_CLUSTER_3      0x06580
+#define VID_E_DOWN_CLUSTER_4      0x06B20
+
+#define VID_F_DOWN_CLUSTER_1      0x070C0
+#define VID_F_DOWN_CLUSTER_2      0x07660
+#define VID_F_DOWN_CLUSTER_3      0x07C00
+#define VID_F_DOWN_CLUSTER_4      0x081A0
+
+#define VID_G_DOWN_CLUSTER_1      0x08740
+#define VID_G_DOWN_CLUSTER_2      0x08CE0
+#define VID_G_DOWN_CLUSTER_3      0x09280
+#define VID_G_DOWN_CLUSTER_4      0x09820
+
+#define VID_H_DOWN_CLUSTER_1      0x09DC0
+#define VID_H_DOWN_CLUSTER_2      0x0A360
+#define VID_H_DOWN_CLUSTER_3      0x0A900
+#define VID_H_DOWN_CLUSTER_4      0x0AEA0
+
+#define AUD_A_DOWN_CLUSTER_1      0x0B500
+#define AUD_A_DOWN_CLUSTER_2      0x0B580
+#define AUD_A_DOWN_CLUSTER_3      0x0B600
+
+#define AUD_B_DOWN_CLUSTER_1      0x0B680
+#define AUD_B_DOWN_CLUSTER_2      0x0B700
+#define AUD_B_DOWN_CLUSTER_3      0x0B780
+
+#define AUD_C_DOWN_CLUSTER_1      0x0B800
+#define AUD_C_DOWN_CLUSTER_2      0x0B880
+#define AUD_C_DOWN_CLUSTER_3      0x0B900
+
+#define AUD_D_DOWN_CLUSTER_1      0x0B980
+#define AUD_D_DOWN_CLUSTER_2      0x0BA00
+#define AUD_D_DOWN_CLUSTER_3      0x0BA80
+
+#define TX_SRAM_POOL_FREE         0x0BB00
+#define TX_SRAM_END               0x0C000
+
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
+
+#define VID_IQ_SIZE_DW             BYTES_TO_DWORDS(VID_IQ_SIZE)
+#define VID_CDT_SIZE_QW            BYTES_TO_QWORDS(VID_CDT_SIZE)
+#define VID_CLUSTER_SIZE_OW        BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
+
+#define AUDIO_IQ_SIZE_DW           BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
+#define AUDIO_CDT_SIZE_QW          BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
+#define AUDIO_CLUSTER_SIZE_QW      BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
+
+#define MBIF_IQ_SIZE_DW            BYTES_TO_DWORDS(MBIF_IQ_SIZE)
+#define MBIF_CDT_SIZE_QW           BYTES_TO_QWORDS(MBIF_CDT_SIZE)
+#define MBIF_CLUSTER_SIZE_OW       BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
new file mode 100644 (file)
index 0000000..c8c94fb
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream-ch2.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+                       FLD_VID_SRC_OPC_ERR;
+
+static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
+                                             __le32 *rp, unsigned int offset,
+                                             unsigned int bpl, u32 sync_line,
+                                             unsigned int lines,
+                                             int fifo_enable, int field_type)
+{
+       unsigned int line, i;
+       int dist_betwn_starts = bpl * 2;
+
+       *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       if (USE_RISC_NOOP_VIDEO) {
+               for (i = 0; i < NUM_NO_OPS; i++)
+                       *(rp++) = cpu_to_le32(RISC_NOOP);
+       }
+
+       /* scan lines */
+       for (line = 0; line < lines; line++) {
+               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+               *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
+               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+
+               if ((lines <= NTSC_FIELD_HEIGHT) ||
+                   (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
+                       offset += dist_betwn_starts;
+               }
+       }
+
+       return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
+                                              __le32 *rp,
+                                              dma_addr_t databuf_phys_addr,
+                                              unsigned int offset,
+                                              u32 sync_line, unsigned int bpl,
+                                              unsigned int lines,
+                                              int fifo_enable, int field_type)
+{
+       unsigned int line, i;
+       struct sram_channel *sram_ch =
+               dev->channels[dev->_channel2_upstream_select].sram_channels;
+       int dist_betwn_starts = bpl * 2;
+
+       /* sync instruction */
+       if (sync_line != NO_SYNC_LINE)
+               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       if (USE_RISC_NOOP_VIDEO) {
+               for (i = 0; i < NUM_NO_OPS; i++)
+                       *(rp++) = cpu_to_le32(RISC_NOOP);
+       }
+
+       /* scan lines */
+       for (line = 0; line < lines; line++) {
+               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+               *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+
+               if ((lines <= NTSC_FIELD_HEIGHT) ||
+                   (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
+                       offset += dist_betwn_starts;
+               }
+
+              /*
+                check if we need to enable the FIFO after the first 4 lines
+                 For the upstream video channel, the risc engine will enable
+                 the FIFO.
+              */
+               if (fifo_enable && line == 3) {
+                       *(rp++) = RISC_WRITECR;
+                       *(rp++) = sram_ch->dma_ctl;
+                       *(rp++) = FLD_VID_FIFO_EN;
+                       *(rp++) = 0x00000001;
+               }
+       }
+
+       return rp;
+}
+
+int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+                                    struct pci_dev *pci,
+                                    unsigned int top_offset, unsigned int bpl,
+                                    unsigned int lines)
+{
+       __le32 *rp;
+       int fifo_enable = 0;
+       int singlefield_lines = lines >> 1; /*get line count for single field */
+       int odd_num_lines = singlefield_lines;
+       int frame = 0;
+       int frame_size = 0;
+       int databuf_offset = 0;
+       int risc_program_size = 0;
+       int risc_flag = RISC_CNT_RESET;
+       unsigned int bottom_offset = bpl;
+       dma_addr_t risc_phys_jump_addr;
+
+       if (dev->_isNTSC_ch2) {
+               odd_num_lines = singlefield_lines + 1;
+               risc_program_size = FRAME1_VID_PROG_SIZE;
+               if (bpl == Y411_LINE_SZ)
+                       frame_size = FRAME_SIZE_NTSC_Y411;
+               else
+                       frame_size = FRAME_SIZE_NTSC_Y422;
+       } else {
+               risc_program_size = PAL_VID_PROG_SIZE;
+               if (bpl == Y411_LINE_SZ)
+                       frame_size = FRAME_SIZE_PAL_Y411;
+               else
+                       frame_size = FRAME_SIZE_PAL_Y422;
+       }
+
+       /* Virtual address of Risc buffer program */
+       rp = dev->_dma_virt_addr_ch2;
+
+       for (frame = 0; frame < NUM_FRAMES; frame++) {
+               databuf_offset = frame_size * frame;
+
+               if (UNSET != top_offset) {
+                       fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+                       rp = cx25821_risc_field_upstream_ch2(dev, rp,
+                               dev->_data_buf_phys_addr_ch2 + databuf_offset,
+                               top_offset, 0, bpl, odd_num_lines, fifo_enable,
+                               ODD_FIELD);
+               }
+
+               fifo_enable = FIFO_DISABLE;
+
+               /* Even field */
+               rp = cx25821_risc_field_upstream_ch2(dev, rp,
+                               dev->_data_buf_phys_addr_ch2 + databuf_offset,
+                               bottom_offset, 0x200, bpl, singlefield_lines,
+                               fifo_enable, EVEN_FIELD);
+
+               if (frame == 0) {
+                       risc_flag = RISC_CNT_RESET;
+                       risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 +
+                                       risc_program_size;
+               } else {
+                       risc_flag = RISC_CNT_INC;
+                       risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;
+               }
+
+              /*
+               * Loop to 2ndFrameRISC or to Start of
+               * Risc program & generate IRQ
+               */
+               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+               *(rp++) = cpu_to_le32(0);
+       }
+
+       return 0;
+}
+
+void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
+{
+       struct sram_channel *sram_ch =
+               dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
+       u32 tmp = 0;
+
+       if (!dev->_is_running_ch2) {
+               pr_info("No video file is currently running so return!\n");
+               return;
+       }
+       /* Disable RISC interrupts */
+       tmp = cx_read(sram_ch->int_msk);
+       cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+       /* Turn OFF risc and fifo */
+       tmp = cx_read(sram_ch->dma_ctl);
+       cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+       /* Clear data buffer memory */
+       if (dev->_data_buf_virt_addr_ch2)
+               memset(dev->_data_buf_virt_addr_ch2, 0,
+                      dev->_data_buf_size_ch2);
+
+       dev->_is_running_ch2 = 0;
+       dev->_is_first_frame_ch2 = 0;
+       dev->_frame_count_ch2 = 0;
+       dev->_file_status_ch2 = END_OF_FILE;
+
+       kfree(dev->_irq_queues_ch2);
+       dev->_irq_queues_ch2 = NULL;
+
+       kfree(dev->_filename_ch2);
+
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
+{
+       if (dev->_is_running_ch2)
+               cx25821_stop_upstream_video_ch2(dev);
+
+       if (dev->_dma_virt_addr_ch2) {
+               pci_free_consistent(dev->pci, dev->_risc_size_ch2,
+                                   dev->_dma_virt_addr_ch2,
+                                   dev->_dma_phys_addr_ch2);
+               dev->_dma_virt_addr_ch2 = NULL;
+       }
+
+       if (dev->_data_buf_virt_addr_ch2) {
+               pci_free_consistent(dev->pci, dev->_data_buf_size_ch2,
+                                   dev->_data_buf_virt_addr_ch2,
+                                   dev->_data_buf_phys_addr_ch2);
+               dev->_data_buf_virt_addr_ch2 = NULL;
+       }
+}
+
+int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+       struct file *myfile;
+       int frame_index_temp = dev->_frame_index_ch2;
+       int i = 0;
+       int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
+       int frame_size = 0;
+       int frame_offset = 0;
+       ssize_t vfs_read_retval = 0;
+       char mybuf[line_size];
+       loff_t file_offset;
+       loff_t pos;
+       mm_segment_t old_fs;
+
+       if (dev->_file_status_ch2 == END_OF_FILE)
+               return 0;
+
+       if (dev->_isNTSC_ch2) {
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+       } else {
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+       }
+
+       frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+       file_offset = dev->_frame_count_ch2 * frame_size;
+
+       myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+       if (IS_ERR(myfile)) {
+               const int open_errno = -PTR_ERR(myfile);
+               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+                      __func__, dev->_filename_ch2, open_errno);
+               return PTR_ERR(myfile);
+       } else {
+               if (!(myfile->f_op)) {
+                       pr_err("%s(): File has no file operations registered!\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               if (!myfile->f_op->read) {
+                       pr_err("%s(): File has no READ operations registered!\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               pos = myfile->f_pos;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               for (i = 0; i < dev->_lines_count_ch2; i++) {
+                       pos = file_offset;
+
+                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+                                       &pos);
+
+                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
+                           && dev->_data_buf_virt_addr_ch2 != NULL) {
+                               memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
+                                               frame_offset / 4), mybuf,
+                                               vfs_read_retval);
+                       }
+
+                       file_offset += vfs_read_retval;
+                       frame_offset += vfs_read_retval;
+
+                       if (vfs_read_retval < line_size) {
+                               pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+                                       __func__);
+                               break;
+                       }
+               }
+
+               if (i > 0)
+                       dev->_frame_count_ch2++;
+
+               dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
+
+               set_fs(old_fs);
+               filp_close(myfile, NULL);
+       }
+
+       return 0;
+}
+
+static void cx25821_vidups_handler_ch2(struct work_struct *work)
+{
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+                       _irq_work_entry_ch2);
+
+       if (!dev) {
+               pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+                      __func__);
+               return;
+       }
+
+       cx25821_get_frame_ch2(dev, dev->channels[dev->
+                       _channel2_upstream_select].sram_channels);
+}
+
+int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+       struct file *myfile;
+       int i = 0, j = 0;
+       int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
+       ssize_t vfs_read_retval = 0;
+       char mybuf[line_size];
+       loff_t pos;
+       loff_t offset = (unsigned long)0;
+       mm_segment_t old_fs;
+
+       myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+
+       if (IS_ERR(myfile)) {
+               const int open_errno = -PTR_ERR(myfile);
+               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+                      __func__, dev->_filename_ch2, open_errno);
+               return PTR_ERR(myfile);
+       } else {
+               if (!(myfile->f_op)) {
+                       pr_err("%s(): File has no file operations registered!\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               if (!myfile->f_op->read) {
+                       pr_err("%s(): File has no READ operations registered!  Returning\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               pos = myfile->f_pos;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               for (j = 0; j < NUM_FRAMES; j++) {
+                       for (i = 0; i < dev->_lines_count_ch2; i++) {
+                               pos = offset;
+
+                               vfs_read_retval = vfs_read(myfile, mybuf,
+                                               line_size, &pos);
+
+                               if (vfs_read_retval > 0 &&
+                                   vfs_read_retval == line_size &&
+                                   dev->_data_buf_virt_addr_ch2 != NULL) {
+                                       memcpy((void *)(dev->
+                                                       _data_buf_virt_addr_ch2
+                                                       + offset / 4), mybuf,
+                                                       vfs_read_retval);
+                               }
+
+                               offset += vfs_read_retval;
+
+                               if (vfs_read_retval < line_size) {
+                                       pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+                                               __func__);
+                                       break;
+                               }
+                       }
+
+                       if (i > 0)
+                               dev->_frame_count_ch2++;
+
+                       if (vfs_read_retval < line_size)
+                               break;
+               }
+
+               dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
+
+               set_fs(old_fs);
+               myfile->f_pos = 0;
+               filp_close(myfile, NULL);
+       }
+
+       return 0;
+}
+
+static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
+                                              struct sram_channel *sram_ch,
+                                              int bpl)
+{
+       int ret = 0;
+       dma_addr_t dma_addr;
+       dma_addr_t data_dma_addr;
+
+       if (dev->_dma_virt_addr_ch2 != NULL) {
+               pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+                                   dev->_dma_virt_addr_ch2,
+                                   dev->_dma_phys_addr_ch2);
+       }
+
+       dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+                       dev->upstream_riscbuf_size_ch2, &dma_addr);
+       dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
+       dev->_dma_phys_start_addr_ch2 = dma_addr;
+       dev->_dma_phys_addr_ch2 = dma_addr;
+       dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
+
+       if (!dev->_dma_virt_addr_ch2) {
+               pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+               return -ENOMEM;
+       }
+
+       /* Iniitize at this address until n bytes to 0 */
+       memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2);
+
+       if (dev->_data_buf_virt_addr_ch2 != NULL) {
+               pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+                                   dev->_data_buf_virt_addr_ch2,
+                                   dev->_data_buf_phys_addr_ch2);
+       }
+       /* For Video Data buffer allocation */
+       dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+                       dev->upstream_databuf_size_ch2, &data_dma_addr);
+       dev->_data_buf_phys_addr_ch2 = data_dma_addr;
+       dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
+
+       if (!dev->_data_buf_virt_addr_ch2) {
+               pr_err("FAILED to allocate memory for data buffer! Returning\n");
+               return -ENOMEM;
+       }
+
+       /* Initialize at this address until n bytes to 0 */
+       memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2);
+
+       ret = cx25821_openfile_ch2(dev, sram_ch);
+       if (ret < 0)
+               return ret;
+
+       /* Creating RISC programs */
+       ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
+                                               dev->_lines_count_ch2);
+       if (ret < 0) {
+               pr_info("Failed creating Video Upstream Risc programs!\n");
+               goto error;
+       }
+
+       return 0;
+
+error:
+       return ret;
+}
+
+int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
+                                  u32 status)
+{
+       u32 int_msk_tmp;
+       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+       int singlefield_lines = NTSC_FIELD_HEIGHT;
+       int line_size_in_bytes = Y422_LINE_SZ;
+       int odd_risc_prog_size = 0;
+       dma_addr_t risc_phys_jump_addr;
+       __le32 *rp;
+
+       if (status & FLD_VID_SRC_RISC1) {
+               /* We should only process one program per call */
+               u32 prog_cnt = cx_read(channel->gpcnt);
+
+               /*
+                *  Since we've identified our IRQ, clear our bits from the
+                *  interrupt mask and interrupt status registers
+                */
+               int_msk_tmp = cx_read(channel->int_msk);
+               cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+               cx_write(channel->int_stat, _intr_msk);
+
+               spin_lock(&dev->slock);
+
+               dev->_frame_index_ch2 = prog_cnt;
+
+               queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);
+
+               if (dev->_is_first_frame_ch2) {
+                       dev->_is_first_frame_ch2 = 0;
+
+                       if (dev->_isNTSC_ch2) {
+                               singlefield_lines += 1;
+                               odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+                       } else {
+                               singlefield_lines = PAL_FIELD_HEIGHT;
+                               odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+                       }
+
+                       if (dev->_dma_virt_start_addr_ch2 != NULL) {
+                               if (dev->_pixel_format_ch2 == PIXEL_FRMT_411)
+                                       line_size_in_bytes = Y411_LINE_SZ;
+                               else
+                                       line_size_in_bytes = Y422_LINE_SZ;
+                               risc_phys_jump_addr =
+                                       dev->_dma_phys_start_addr_ch2 +
+                                       odd_risc_prog_size;
+
+                               rp = cx25821_update_riscprogram_ch2(dev,
+                                               dev->_dma_virt_start_addr_ch2,
+                                               TOP_OFFSET, line_size_in_bytes,
+                                               0x0, singlefield_lines,
+                                               FIFO_DISABLE, ODD_FIELD);
+
+                              /* Jump to Even Risc program of 1st Frame */
+                               *(rp++) = cpu_to_le32(RISC_JUMP);
+                               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+                               *(rp++) = cpu_to_le32(0);
+                       }
+               }
+
+               spin_unlock(&dev->slock);
+       }
+
+       if (dev->_file_status_ch2 == END_OF_FILE) {
+               pr_info("EOF Channel 2 Framecount = %d\n",
+                       dev->_frame_count_ch2);
+               return -1;
+       }
+       /* ElSE, set the interrupt mask register, re-enable irq. */
+       int_msk_tmp = cx_read(channel->int_msk);
+       cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+       return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
+{
+       struct cx25821_dev *dev = dev_id;
+       u32 vid_status;
+       int handled = 0;
+       int channel_num = 0;
+       struct sram_channel *sram_ch;
+
+       if (!dev)
+               return -1;
+
+       channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;
+       sram_ch = dev->channels[channel_num].sram_channels;
+
+       vid_status = cx_read(sram_ch->int_stat);
+
+       /* Only deal with our interrupt */
+       if (vid_status)
+               handled = cx25821_video_upstream_irq_ch2(dev, channel_num,
+                               vid_status);
+
+       if (handled < 0)
+               cx25821_stop_upstream_video_ch2(dev);
+       else
+               handled += handled;
+
+       return IRQ_RETVAL(handled);
+}
+
+static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
+                                       struct sram_channel *ch, int pix_format)
+{
+       int width = WIDTH_D1;
+       int height = dev->_lines_count_ch2;
+       int num_lines, odd_num_lines;
+       u32 value;
+       int vip_mode = PIXEL_ENGINE_VIP1;
+
+       value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+       value &= 0xFFFFFFEF;
+       value |= dev->_isNTSC_ch2 ? 0 : 0x10;
+       cx_write(ch->vid_fmt_ctl, value);
+
+       /*
+        *  set number of active pixels in each line. Default is 720
+        * pixels in both NTSC and PAL format
+        */
+       cx_write(ch->vid_active_ctl1, width);
+
+       num_lines = (height / 2) & 0x3FF;
+       odd_num_lines = num_lines;
+
+       if (dev->_isNTSC_ch2)
+               odd_num_lines += 1;
+
+       value = (num_lines << 16) | odd_num_lines;
+
+       /* set number of active lines in field 0 (top) and field 1 (bottom) */
+       cx_write(ch->vid_active_ctl2, value);
+
+       cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+                                        struct sram_channel *sram_ch)
+{
+       u32 tmp = 0;
+       int err = 0;
+
+       /*
+        *  656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface
+        * for channel A-C
+        */
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+       /*
+        *  Set the physical start address of the RISC program in the initial
+        *  program counter(IPC) member of the cmds.
+        */
+       cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);
+       cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+       /* reset counter */
+       cx_write(sram_ch->gpcnt_ctl, 3);
+
+       /* Clear our bits from the interrupt status register. */
+       cx_write(sram_ch->int_stat, _intr_msk);
+
+       /* Set the interrupt mask register, enable irq. */
+       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+       tmp = cx_read(sram_ch->int_msk);
+       cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+       err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+                       IRQF_SHARED, dev->name, dev);
+       if (err < 0) {
+               pr_err("%s: can't get upstream IRQ %d\n",
+                      dev->name, dev->pci->irq);
+               goto fail_irq;
+       }
+       /* Start the DMA  engine */
+       tmp = cx_read(sram_ch->dma_ctl);
+       cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+       dev->_is_running_ch2 = 1;
+       dev->_is_first_frame_ch2 = 1;
+
+       return 0;
+
+fail_irq:
+       cx25821_dev_unregister(dev);
+       return err;
+}
+
+int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
+                                int pixel_format)
+{
+       struct sram_channel *sram_ch;
+       u32 tmp;
+       int retval = 0;
+       int err = 0;
+       int data_frame_size = 0;
+       int risc_buffer_size = 0;
+       int str_length = 0;
+
+       if (dev->_is_running_ch2) {
+               pr_info("Video Channel is still running so return!\n");
+               return 0;
+       }
+
+       dev->_channel2_upstream_select = channel_select;
+       sram_ch = dev->channels[channel_select].sram_channels;
+
+       INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);
+       dev->_irq_queues_ch2 =
+           create_singlethread_workqueue("cx25821_workqueue2");
+
+       if (!dev->_irq_queues_ch2) {
+               pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+               return -ENOMEM;
+       }
+       /*
+        * 656/VIP SRC Upstream Channel I & J and 7 -
+        * Host Bus Interface for channel A-C
+        */
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+       dev->_is_running_ch2 = 0;
+       dev->_frame_count_ch2 = 0;
+       dev->_file_status_ch2 = RESET_STATUS;
+       dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
+       dev->_pixel_format_ch2 = pixel_format;
+       dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ?
+               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+       data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+       risc_buffer_size = dev->_isNTSC_ch2 ?
+               NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+       if (dev->input_filename_ch2) {
+               str_length = strlen(dev->input_filename_ch2);
+               dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
+                                            str_length + 1, GFP_KERNEL);
+
+               if (!dev->_filename_ch2)
+                       goto error;
+       } else {
+               str_length = strlen(dev->_defaultname_ch2);
+               dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
+                                            str_length + 1, GFP_KERNEL);
+
+               if (!dev->_filename_ch2)
+                       goto error;
+       }
+
+       /* Default if filename is empty string */
+       if (strcmp(dev->input_filename_ch2, "") == 0) {
+               if (dev->_isNTSC_ch2) {
+                       dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+                               PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+                               "/root/vidtest.yuv";
+               } else {
+                       dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+                               PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+                               "/root/pal422.yuv";
+               }
+       }
+
+       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+                                               dev->_line_size_ch2, 0);
+
+       /* setup fifo + format */
+       cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);
+
+       dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;
+       dev->upstream_databuf_size_ch2 = data_frame_size * 2;
+
+       /* Allocating buffers and prepare RISC program */
+       retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+                                               dev->_line_size_ch2);
+       if (retval < 0) {
+               pr_err("%s: Failed to set up Video upstream buffers!\n",
+                      dev->name);
+               goto error;
+       }
+
+       cx25821_start_video_dma_upstream_ch2(dev, sram_ch);
+
+       return 0;
+
+error:
+       cx25821_dev_unregister(dev);
+
+       return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h
new file mode 100644 (file)
index 0000000..d42dab5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
+#include <linux/workqueue.h>
+
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE                                           \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +   \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE         (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE                                              \
+       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
+        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+        JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE                                          \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE                                          \
+       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
+        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +        \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE                                             \
+       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE                                           \
+       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *                     \
+        3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +              \
+        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +        \
+        2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE                                         \
+       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
+        NUM_NO_OPS * DWORD_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE                                           \
+       ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE +                      \
+        RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE                                              \
+       (2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE))
+
+#define PAL_VID_PROG_SIZE                                              \
+       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
+        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+        JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE                                          \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE                                         \
+       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE                                          \
+       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
+        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE                                             \
+       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE                                           \
+       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *                     \
+        3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +              \
+        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c
new file mode 100644 (file)
index 0000000..52c13e0
--- /dev/null
@@ -0,0 +1,856 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+                       FLD_VID_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+                                       struct sram_channel *ch,
+                                       unsigned int bpl, u32 risc)
+{
+       unsigned int i, lines;
+       u32 cdt;
+
+       if (ch->cmds_start == 0) {
+               cx_write(ch->ptr1_reg, 0);
+               cx_write(ch->ptr2_reg, 0);
+               cx_write(ch->cnt2_reg, 0);
+               cx_write(ch->cnt1_reg, 0);
+               return 0;
+       }
+
+       bpl = (bpl + 7) & ~7;   /* alignment */
+       cdt = ch->cdt;
+       lines = ch->fifo_size / bpl;
+
+       if (lines > 4)
+               lines = 4;
+
+       BUG_ON(lines < 2);
+
+       /* write CDT */
+       for (i = 0; i < lines; i++) {
+               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+               cx_write(cdt + 16 * i + 4, 0);
+               cx_write(cdt + 16 * i + 8, 0);
+               cx_write(cdt + 16 * i + 12, 0);
+       }
+
+       /* write CMDS */
+       cx_write(ch->cmds_start + 0, risc);
+
+       cx_write(ch->cmds_start + 4, 0);
+       cx_write(ch->cmds_start + 8, cdt);
+       cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+       cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+       cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
+
+       for (i = 24; i < 80; i += 4)
+               cx_write(ch->cmds_start + i, 0);
+
+       /* fill registers */
+       cx_write(ch->ptr1_reg, ch->fifo_start);
+       cx_write(ch->ptr2_reg, cdt);
+       cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+       return 0;
+}
+
+static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
+                                         __le32 *rp, unsigned int offset,
+                                         unsigned int bpl, u32 sync_line,
+                                         unsigned int lines, int fifo_enable,
+                                         int field_type)
+{
+       unsigned int line, i;
+       int dist_betwn_starts = bpl * 2;
+
+       *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       if (USE_RISC_NOOP_VIDEO) {
+               for (i = 0; i < NUM_NO_OPS; i++)
+                       *(rp++) = cpu_to_le32(RISC_NOOP);
+       }
+
+       /* scan lines */
+       for (line = 0; line < lines; line++) {
+               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+               *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
+               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+
+               if ((lines <= NTSC_FIELD_HEIGHT)
+                   || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
+                       offset += dist_betwn_starts;
+               }
+       }
+
+       return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
+                                          dma_addr_t databuf_phys_addr,
+                                          unsigned int offset, u32 sync_line,
+                                          unsigned int bpl, unsigned int lines,
+                                          int fifo_enable, int field_type)
+{
+       unsigned int line, i;
+       struct sram_channel *sram_ch =
+               dev->channels[dev->_channel_upstream_select].sram_channels;
+       int dist_betwn_starts = bpl * 2;
+
+       /* sync instruction */
+       if (sync_line != NO_SYNC_LINE)
+               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       if (USE_RISC_NOOP_VIDEO) {
+               for (i = 0; i < NUM_NO_OPS; i++)
+                       *(rp++) = cpu_to_le32(RISC_NOOP);
+       }
+
+       /* scan lines */
+       for (line = 0; line < lines; line++) {
+               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+               *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
+
+               if ((lines <= NTSC_FIELD_HEIGHT)
+                   || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC))
+                       /* to skip the other field line */
+                       offset += dist_betwn_starts;
+
+               /* check if we need to enable the FIFO after the first 4 lines
+                * For the upstream video channel, the risc engine will enable
+                * the FIFO. */
+               if (fifo_enable && line == 3) {
+                       *(rp++) = RISC_WRITECR;
+                       *(rp++) = sram_ch->dma_ctl;
+                       *(rp++) = FLD_VID_FIFO_EN;
+                       *(rp++) = 0x00000001;
+               }
+       }
+
+       return rp;
+}
+
+int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+                                struct pci_dev *pci,
+                                unsigned int top_offset,
+                                unsigned int bpl, unsigned int lines)
+{
+       __le32 *rp;
+       int fifo_enable = 0;
+       /* get line count for single field */
+       int singlefield_lines = lines >> 1;
+       int odd_num_lines = singlefield_lines;
+       int frame = 0;
+       int frame_size = 0;
+       int databuf_offset = 0;
+       int risc_program_size = 0;
+       int risc_flag = RISC_CNT_RESET;
+       unsigned int bottom_offset = bpl;
+       dma_addr_t risc_phys_jump_addr;
+
+       if (dev->_isNTSC) {
+               odd_num_lines = singlefield_lines + 1;
+               risc_program_size = FRAME1_VID_PROG_SIZE;
+               frame_size = (bpl == Y411_LINE_SZ) ?
+                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+       } else {
+               risc_program_size = PAL_VID_PROG_SIZE;
+               frame_size = (bpl == Y411_LINE_SZ) ?
+                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+       }
+
+       /* Virtual address of Risc buffer program */
+       rp = dev->_dma_virt_addr;
+
+       for (frame = 0; frame < NUM_FRAMES; frame++) {
+               databuf_offset = frame_size * frame;
+
+               if (UNSET != top_offset) {
+                       fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+                       rp = cx25821_risc_field_upstream(dev, rp,
+                                       dev->_data_buf_phys_addr +
+                                       databuf_offset, top_offset, 0, bpl,
+                                       odd_num_lines, fifo_enable, ODD_FIELD);
+               }
+
+               fifo_enable = FIFO_DISABLE;
+
+               /* Even Field */
+               rp = cx25821_risc_field_upstream(dev, rp,
+                                                dev->_data_buf_phys_addr +
+                                                databuf_offset, bottom_offset,
+                                                0x200, bpl, singlefield_lines,
+                                                fifo_enable, EVEN_FIELD);
+
+               if (frame == 0) {
+                       risc_flag = RISC_CNT_RESET;
+                       risc_phys_jump_addr = dev->_dma_phys_start_addr +
+                               risc_program_size;
+               } else {
+                       risc_phys_jump_addr = dev->_dma_phys_start_addr;
+                       risc_flag = RISC_CNT_INC;
+               }
+
+               /* Loop to 2ndFrameRISC or to Start of Risc
+                * program & generate IRQ
+                */
+               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+               *(rp++) = cpu_to_le32(0);
+       }
+
+       return 0;
+}
+
+void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
+{
+       struct sram_channel *sram_ch =
+               dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
+       u32 tmp = 0;
+
+       if (!dev->_is_running) {
+               pr_info("No video file is currently running so return!\n");
+               return;
+       }
+       /* Disable RISC interrupts */
+       tmp = cx_read(sram_ch->int_msk);
+       cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+       /* Turn OFF risc and fifo enable */
+       tmp = cx_read(sram_ch->dma_ctl);
+       cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+       /* Clear data buffer memory */
+       if (dev->_data_buf_virt_addr)
+               memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+       dev->_is_running = 0;
+       dev->_is_first_frame = 0;
+       dev->_frame_count = 0;
+       dev->_file_status = END_OF_FILE;
+
+       kfree(dev->_irq_queues);
+       dev->_irq_queues = NULL;
+
+       kfree(dev->_filename);
+
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
+{
+       if (dev->_is_running)
+               cx25821_stop_upstream_video_ch1(dev);
+
+       if (dev->_dma_virt_addr) {
+               pci_free_consistent(dev->pci, dev->_risc_size,
+                                   dev->_dma_virt_addr, dev->_dma_phys_addr);
+               dev->_dma_virt_addr = NULL;
+       }
+
+       if (dev->_data_buf_virt_addr) {
+               pci_free_consistent(dev->pci, dev->_data_buf_size,
+                                   dev->_data_buf_virt_addr,
+                                   dev->_data_buf_phys_addr);
+               dev->_data_buf_virt_addr = NULL;
+       }
+}
+
+int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+       struct file *myfile;
+       int frame_index_temp = dev->_frame_index;
+       int i = 0;
+       int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
+       int frame_size = 0;
+       int frame_offset = 0;
+       ssize_t vfs_read_retval = 0;
+       char mybuf[line_size];
+       loff_t file_offset;
+       loff_t pos;
+       mm_segment_t old_fs;
+
+       if (dev->_file_status == END_OF_FILE)
+               return 0;
+
+       if (dev->_isNTSC)
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+       else
+               frame_size = (line_size == Y411_LINE_SZ) ?
+                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+
+       frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+       file_offset = dev->_frame_count * frame_size;
+
+       myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+       if (IS_ERR(myfile)) {
+               const int open_errno = -PTR_ERR(myfile);
+               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+                      __func__, dev->_filename, open_errno);
+               return PTR_ERR(myfile);
+       } else {
+               if (!(myfile->f_op)) {
+                       pr_err("%s(): File has no file operations registered!\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               if (!myfile->f_op->read) {
+                       pr_err("%s(): File has no READ operations registered!\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               pos = myfile->f_pos;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               for (i = 0; i < dev->_lines_count; i++) {
+                       pos = file_offset;
+
+                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+                                       &pos);
+
+                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
+                           && dev->_data_buf_virt_addr != NULL) {
+                               memcpy((void *)(dev->_data_buf_virt_addr +
+                                               frame_offset / 4), mybuf,
+                                      vfs_read_retval);
+                       }
+
+                       file_offset += vfs_read_retval;
+                       frame_offset += vfs_read_retval;
+
+                       if (vfs_read_retval < line_size) {
+                               pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+                                       __func__);
+                               break;
+                       }
+               }
+
+               if (i > 0)
+                       dev->_frame_count++;
+
+               dev->_file_status = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
+
+               set_fs(old_fs);
+               filp_close(myfile, NULL);
+       }
+
+       return 0;
+}
+
+static void cx25821_vidups_handler(struct work_struct *work)
+{
+       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+                       _irq_work_entry);
+
+       if (!dev) {
+               pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+                      __func__);
+               return;
+       }
+
+       cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select].
+                       sram_channels);
+}
+
+int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+       struct file *myfile;
+       int i = 0, j = 0;
+       int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+               Y411_LINE_SZ : Y422_LINE_SZ;
+       ssize_t vfs_read_retval = 0;
+       char mybuf[line_size];
+       loff_t pos;
+       loff_t offset = (unsigned long)0;
+       mm_segment_t old_fs;
+
+       myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+       if (IS_ERR(myfile)) {
+               const int open_errno = -PTR_ERR(myfile);
+               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+                      __func__, dev->_filename, open_errno);
+               return PTR_ERR(myfile);
+       } else {
+               if (!(myfile->f_op)) {
+                       pr_err("%s(): File has no file operations registered!\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               if (!myfile->f_op->read) {
+                       pr_err("%s(): File has no READ operations registered!  Returning\n",
+                              __func__);
+                       filp_close(myfile, NULL);
+                       return -EIO;
+               }
+
+               pos = myfile->f_pos;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+
+               for (j = 0; j < NUM_FRAMES; j++) {
+                       for (i = 0; i < dev->_lines_count; i++) {
+                               pos = offset;
+
+                               vfs_read_retval = vfs_read(myfile, mybuf,
+                                               line_size, &pos);
+
+                               if (vfs_read_retval > 0
+                                   && vfs_read_retval == line_size
+                                   && dev->_data_buf_virt_addr != NULL) {
+                                       memcpy((void *)(dev->
+                                                       _data_buf_virt_addr +
+                                                       offset / 4), mybuf,
+                                              vfs_read_retval);
+                               }
+
+                               offset += vfs_read_retval;
+
+                               if (vfs_read_retval < line_size) {
+                                       pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+                                               __func__);
+                                       break;
+                               }
+                       }
+
+                       if (i > 0)
+                               dev->_frame_count++;
+
+                       if (vfs_read_retval < line_size)
+                               break;
+               }
+
+               dev->_file_status = (vfs_read_retval == line_size) ?
+                       IN_PROGRESS : END_OF_FILE;
+
+               set_fs(old_fs);
+               myfile->f_pos = 0;
+               filp_close(myfile, NULL);
+       }
+
+       return 0;
+}
+
+int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+                                   struct sram_channel *sram_ch, int bpl)
+{
+       int ret = 0;
+       dma_addr_t dma_addr;
+       dma_addr_t data_dma_addr;
+
+       if (dev->_dma_virt_addr != NULL)
+               pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
+                               dev->_dma_virt_addr, dev->_dma_phys_addr);
+
+       dev->_dma_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->upstream_riscbuf_size, &dma_addr);
+       dev->_dma_virt_start_addr = dev->_dma_virt_addr;
+       dev->_dma_phys_start_addr = dma_addr;
+       dev->_dma_phys_addr = dma_addr;
+       dev->_risc_size = dev->upstream_riscbuf_size;
+
+       if (!dev->_dma_virt_addr) {
+               pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+               return -ENOMEM;
+       }
+
+       /* Clear memory at address */
+       memset(dev->_dma_virt_addr, 0, dev->_risc_size);
+
+       if (dev->_data_buf_virt_addr != NULL)
+               pci_free_consistent(dev->pci, dev->upstream_databuf_size,
+                               dev->_data_buf_virt_addr,
+                               dev->_data_buf_phys_addr);
+       /* For Video Data buffer allocation */
+       dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci,
+                       dev->upstream_databuf_size, &data_dma_addr);
+       dev->_data_buf_phys_addr = data_dma_addr;
+       dev->_data_buf_size = dev->upstream_databuf_size;
+
+       if (!dev->_data_buf_virt_addr) {
+               pr_err("FAILED to allocate memory for data buffer! Returning\n");
+               return -ENOMEM;
+       }
+
+       /* Clear memory at address */
+       memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+       ret = cx25821_openfile(dev, sram_ch);
+       if (ret < 0)
+               return ret;
+
+       /* Create RISC programs */
+       ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+                       dev->_lines_count);
+       if (ret < 0) {
+               pr_info("Failed creating Video Upstream Risc programs!\n");
+               goto error;
+       }
+
+       return 0;
+
+error:
+       return ret;
+}
+
+int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+                              u32 status)
+{
+       u32 int_msk_tmp;
+       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+       int singlefield_lines = NTSC_FIELD_HEIGHT;
+       int line_size_in_bytes = Y422_LINE_SZ;
+       int odd_risc_prog_size = 0;
+       dma_addr_t risc_phys_jump_addr;
+       __le32 *rp;
+
+       if (status & FLD_VID_SRC_RISC1) {
+               /* We should only process one program per call */
+               u32 prog_cnt = cx_read(channel->gpcnt);
+
+               /* Since we've identified our IRQ, clear our bits from the
+                * interrupt mask and interrupt status registers */
+               int_msk_tmp = cx_read(channel->int_msk);
+               cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+               cx_write(channel->int_stat, _intr_msk);
+
+               spin_lock(&dev->slock);
+
+               dev->_frame_index = prog_cnt;
+
+               queue_work(dev->_irq_queues, &dev->_irq_work_entry);
+
+               if (dev->_is_first_frame) {
+                       dev->_is_first_frame = 0;
+
+                       if (dev->_isNTSC) {
+                               singlefield_lines += 1;
+                               odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+                       } else {
+                               singlefield_lines = PAL_FIELD_HEIGHT;
+                               odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+                       }
+
+                       if (dev->_dma_virt_start_addr != NULL) {
+                               line_size_in_bytes =
+                                   (dev->_pixel_format ==
+                                    PIXEL_FRMT_411) ? Y411_LINE_SZ :
+                                   Y422_LINE_SZ;
+                               risc_phys_jump_addr =
+                                   dev->_dma_phys_start_addr +
+                                   odd_risc_prog_size;
+
+                               rp = cx25821_update_riscprogram(dev,
+                                       dev->_dma_virt_start_addr, TOP_OFFSET,
+                                       line_size_in_bytes, 0x0,
+                                       singlefield_lines, FIFO_DISABLE,
+                                       ODD_FIELD);
+
+                               /* Jump to Even Risc program of 1st Frame */
+                               *(rp++) = cpu_to_le32(RISC_JUMP);
+                               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
+                               *(rp++) = cpu_to_le32(0);
+                       }
+               }
+
+               spin_unlock(&dev->slock);
+       } else {
+               if (status & FLD_VID_SRC_UF)
+                       pr_err("%s(): Video Received Underflow Error Interrupt!\n",
+                              __func__);
+
+               if (status & FLD_VID_SRC_SYNC)
+                       pr_err("%s(): Video Received Sync Error Interrupt!\n",
+                              __func__);
+
+               if (status & FLD_VID_SRC_OPC_ERR)
+                       pr_err("%s(): Video Received OpCode Error Interrupt!\n",
+                              __func__);
+       }
+
+       if (dev->_file_status == END_OF_FILE) {
+               pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
+               return -1;
+       }
+       /* ElSE, set the interrupt mask register, re-enable irq. */
+       int_msk_tmp = cx_read(channel->int_msk);
+       cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+       return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
+{
+       struct cx25821_dev *dev = dev_id;
+       u32 vid_status;
+       int handled = 0;
+       int channel_num = 0;
+       struct sram_channel *sram_ch;
+
+       if (!dev)
+               return -1;
+
+       channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
+
+       sram_ch = dev->channels[channel_num].sram_channels;
+
+       vid_status = cx_read(sram_ch->int_stat);
+
+       /* Only deal with our interrupt */
+       if (vid_status)
+               handled = cx25821_video_upstream_irq(dev, channel_num,
+                               vid_status);
+
+       if (handled < 0)
+               cx25821_stop_upstream_video_ch1(dev);
+       else
+               handled += handled;
+
+       return IRQ_RETVAL(handled);
+}
+
+void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
+                            int pix_format)
+{
+       int width = WIDTH_D1;
+       int height = dev->_lines_count;
+       int num_lines, odd_num_lines;
+       u32 value;
+       int vip_mode = OUTPUT_FRMT_656;
+
+       value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+       value &= 0xFFFFFFEF;
+       value |= dev->_isNTSC ? 0 : 0x10;
+       cx_write(ch->vid_fmt_ctl, value);
+
+       /* set number of active pixels in each line.
+        * Default is 720 pixels in both NTSC and PAL format */
+       cx_write(ch->vid_active_ctl1, width);
+
+       num_lines = (height / 2) & 0x3FF;
+       odd_num_lines = num_lines;
+
+       if (dev->_isNTSC)
+               odd_num_lines += 1;
+
+       value = (num_lines << 16) | odd_num_lines;
+
+       /* set number of active lines in field 0 (top) and field 1 (bottom) */
+       cx_write(ch->vid_active_ctl2, value);
+
+       cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+                                    struct sram_channel *sram_ch)
+{
+       u32 tmp = 0;
+       int err = 0;
+
+       /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+        * channel A-C
+        */
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+       /* Set the physical start address of the RISC program in the initial
+        * program counter(IPC) member of the cmds.
+        */
+       cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
+       /* Risc IPC High 64 bits 63-32 */
+       cx_write(sram_ch->cmds_start + 4, 0);
+
+       /* reset counter */
+       cx_write(sram_ch->gpcnt_ctl, 3);
+
+       /* Clear our bits from the interrupt status register. */
+       cx_write(sram_ch->int_stat, _intr_msk);
+
+       /* Set the interrupt mask register, enable irq. */
+       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+       tmp = cx_read(sram_ch->int_msk);
+       cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+       err = request_irq(dev->pci->irq, cx25821_upstream_irq,
+                       IRQF_SHARED, dev->name, dev);
+       if (err < 0) {
+               pr_err("%s: can't get upstream IRQ %d\n",
+                      dev->name, dev->pci->irq);
+               goto fail_irq;
+       }
+
+       /* Start the DMA  engine */
+       tmp = cx_read(sram_ch->dma_ctl);
+       cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+       dev->_is_running = 1;
+       dev->_is_first_frame = 1;
+
+       return 0;
+
+fail_irq:
+       cx25821_dev_unregister(dev);
+       return err;
+}
+
+int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
+                                int pixel_format)
+{
+       struct sram_channel *sram_ch;
+       u32 tmp;
+       int retval = 0;
+       int err = 0;
+       int data_frame_size = 0;
+       int risc_buffer_size = 0;
+       int str_length = 0;
+
+       if (dev->_is_running) {
+               pr_info("Video Channel is still running so return!\n");
+               return 0;
+       }
+
+       dev->_channel_upstream_select = channel_select;
+       sram_ch = dev->channels[channel_select].sram_channels;
+
+       INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
+       dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
+
+       if (!dev->_irq_queues) {
+               pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+               return -ENOMEM;
+       }
+       /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+        * channel A-C
+        */
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+       dev->_is_running = 0;
+       dev->_frame_count = 0;
+       dev->_file_status = RESET_STATUS;
+       dev->_lines_count = dev->_isNTSC ? 480 : 576;
+       dev->_pixel_format = pixel_format;
+       dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+       data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+       risc_buffer_size = dev->_isNTSC ?
+               NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+       if (dev->input_filename) {
+               str_length = strlen(dev->input_filename);
+               dev->_filename = kmemdup(dev->input_filename, str_length + 1,
+                                        GFP_KERNEL);
+
+               if (!dev->_filename)
+                       goto error;
+       } else {
+               str_length = strlen(dev->_defaultname);
+               dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
+                                        GFP_KERNEL);
+
+               if (!dev->_filename)
+                       goto error;
+       }
+
+       /* Default if filename is empty string */
+       if (strcmp(dev->input_filename, "") == 0) {
+               if (dev->_isNTSC) {
+                       dev->_filename =
+                               (dev->_pixel_format == PIXEL_FRMT_411) ?
+                               "/root/vid411.yuv" : "/root/vidtest.yuv";
+               } else {
+                       dev->_filename =
+                               (dev->_pixel_format == PIXEL_FRMT_411) ?
+                               "/root/pal411.yuv" : "/root/pal422.yuv";
+               }
+       }
+
+       dev->_is_running = 0;
+       dev->_frame_count = 0;
+       dev->_file_status = RESET_STATUS;
+       dev->_lines_count = dev->_isNTSC ? 480 : 576;
+       dev->_pixel_format = pixel_format;
+       dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+
+       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+                       dev->_line_size, 0);
+
+       /* setup fifo + format */
+       cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
+
+       dev->upstream_riscbuf_size = risc_buffer_size * 2;
+       dev->upstream_databuf_size = data_frame_size * 2;
+
+       /* Allocating buffers and prepare RISC program */
+       retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+       if (retval < 0) {
+               pr_err("%s: Failed to set up Video upstream buffers!\n",
+                      dev->name);
+               goto error;
+       }
+
+       cx25821_start_video_dma_upstream(dev, sram_ch);
+
+       return 0;
+
+error:
+       cx25821_dev_unregister(dev);
+
+       return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.h b/drivers/media/pci/cx25821/cx25821-video-upstream.h
new file mode 100644 (file)
index 0000000..268ec8a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
+#include <linux/workqueue.h>
+
+#define OUTPUT_FRMT_656       0
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE                                           \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +   \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE                                              \
+       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
+        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+        JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE                                          \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE                                         \
+       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE                                          \
+       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
+        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +        \
+        NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE                                             \
+       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE                                           \
+       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +    \
+        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+        JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE                                           \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +   \
+        JUMP_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE              (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE                                              \
+       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
+        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+        JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE                                          \
+       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE                                         \
+       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
+        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE                                          \
+       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
+        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE                                             \
+       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE                                           \
+       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +    \
+        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+        JUMP_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
new file mode 100644 (file)
index 0000000..b38d437
--- /dev/null
@@ -0,0 +1,1990 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *  Parts adapted/taken from Eduardo Moscoso Rubino
+ *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug = VIDEO_DEBUG;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num);
+
+static const struct v4l2_file_operations video_fops;
+static const struct v4l2_ioctl_ops video_ioctl_ops;
+
+#define FORMAT_FLAGS_PACKED       0x01
+
+struct cx25821_fmt formats[] = {
+       {
+               .name = "8 bpp, gray",
+               .fourcc = V4L2_PIX_FMT_GREY,
+               .depth = 8,
+               .flags = FORMAT_FLAGS_PACKED,
+        }, {
+               .name = "4:1:1, packed, Y41P",
+               .fourcc = V4L2_PIX_FMT_Y41P,
+               .depth = 12,
+               .flags = FORMAT_FLAGS_PACKED,
+       }, {
+               .name = "4:2:2, packed, YUYV",
+               .fourcc = V4L2_PIX_FMT_YUYV,
+               .depth = 16,
+               .flags = FORMAT_FLAGS_PACKED,
+       }, {
+               .name = "4:2:2, packed, UYVY",
+               .fourcc = V4L2_PIX_FMT_UYVY,
+               .depth = 16,
+               .flags = FORMAT_FLAGS_PACKED,
+       }, {
+               .name = "4:2:0, YUV",
+               .fourcc = V4L2_PIX_FMT_YUV420,
+               .depth = 12,
+               .flags = FORMAT_FLAGS_PACKED,
+       },
+};
+
+int cx25821_get_format_size(void)
+{
+       return ARRAY_SIZE(formats);
+}
+
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P)
+               return formats + 1;
+
+       for (i = 0; i < ARRAY_SIZE(formats); i++)
+               if (formats[i].fourcc == fourcc)
+                       return formats + i;
+
+       pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+       return NULL;
+}
+
+void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
+                         u32 count)
+{
+       struct cx25821_buffer *buf;
+       int bc;
+
+       for (bc = 0;; bc++) {
+               if (list_empty(&q->active)) {
+                       dprintk(1, "bc=%d (=0: active empty)\n", bc);
+                       break;
+               }
+
+               buf = list_entry(q->active.next, struct cx25821_buffer,
+                               vb.queue);
+
+               /* count comes from the hw and it is 16bit wide --
+                * this trick handles wrap-arounds correctly for
+                * up to 32767 buffers in flight... */
+               if ((s16) (count - buf->count) < 0)
+                       break;
+
+               do_gettimeofday(&buf->vb.ts);
+               buf->vb.state = VIDEOBUF_DONE;
+               list_del(&buf->vb.queue);
+               wake_up(&buf->vb.done);
+       }
+
+       if (list_empty(&q->active))
+               del_timer(&q->timeout);
+       else
+               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+       if (bc != 1)
+               pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
+{
+       dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+               __func__, (unsigned int)norm, v4l2_norm_to_name(norm));
+
+       dev->tvnorm = norm;
+
+       /* Tell the internal A/V decoder */
+       cx25821_call_all(dev, core, s_std, norm);
+
+       return 0;
+}
+#endif
+
+struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+                                      struct pci_dev *pci,
+                                      struct video_device *template,
+                                      char *type)
+{
+       struct video_device *vfd;
+       dprintk(1, "%s()\n", __func__);
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+       vfd->release = video_device_release;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
+                cx25821_boards[dev->board].name);
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+/*
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+       int i;
+
+       if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       for (i = 0; i < CX25821_CTLS; i++)
+               if (cx25821_ctls[i].v.id == qctrl->id)
+                       break;
+       if (i == CX25821_CTLS) {
+               *qctrl = no_ctl;
+               return 0;
+       }
+       *qctrl = cx25821_ctls[i].v;
+       return 0;
+}
+*/
+
+/* resource management */
+int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+                   unsigned int bit)
+{
+       dprintk(1, "%s()\n", __func__);
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       /* is it free? */
+       mutex_lock(&dev->lock);
+       if (dev->channels[fh->channel_id].resources & bit) {
+               /* no, someone else uses it */
+               mutex_unlock(&dev->lock);
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources |= bit;
+       dev->channels[fh->channel_id].resources |= bit;
+       dprintk(1, "res: get %d\n", bit);
+       mutex_unlock(&dev->lock);
+       return 1;
+}
+
+int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit)
+{
+       return fh->resources & bit;
+}
+
+int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit)
+{
+       return fh->dev->channels[fh->channel_id].resources & bit;
+}
+
+void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+                     unsigned int bits)
+{
+       BUG_ON((fh->resources & bits) != bits);
+       dprintk(1, "%s()\n", __func__);
+
+       mutex_lock(&dev->lock);
+       fh->resources &= ~bits;
+       dev->channels[fh->channel_id].resources &= ~bits;
+       dprintk(1, "res: put %d\n", bits);
+       mutex_unlock(&dev->lock);
+}
+
+int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
+{
+       struct v4l2_routing route;
+       memset(&route, 0, sizeof(route));
+
+       dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+               __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
+               INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
+       dev->input = input;
+
+       route.input = INPUT(input)->vmux;
+
+       /* Tell the internal A/V decoder */
+       cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);
+
+       return 0;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+                           struct cx25821_dmaqueue *q,
+                           struct cx25821_buffer *buf,
+                           struct sram_channel *channel)
+{
+       int tmp = 0;
+
+       /* setup fifo + format */
+       cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
+
+       /* reset counter */
+       cx_write(channel->gpcnt_ctl, 3);
+       q->count = 1;
+
+       /* enable irq */
+       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
+       cx_set(channel->int_msk, 0x11);
+
+       /* start dma */
+       cx_write(channel->dma_ctl, 0x11);       /* FIFO and RISC enable */
+
+       /* make sure upstream setting if any is reversed */
+       tmp = cx_read(VID_CH_MODE_SEL);
+       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+       return 0;
+}
+
+int cx25821_restart_video_queue(struct cx25821_dev *dev,
+                               struct cx25821_dmaqueue *q,
+                               struct sram_channel *channel)
+{
+       struct cx25821_buffer *buf, *prev;
+       struct list_head *item;
+
+       if (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx25821_buffer,
+                               vb.queue);
+
+               cx25821_start_video_dma(dev, q, buf, channel);
+
+               list_for_each(item, &q->active) {
+                       buf = list_entry(item, struct cx25821_buffer, vb.queue);
+                       buf->count = q->count++;
+               }
+
+               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+               return 0;
+       }
+
+       prev = NULL;
+       for (;;) {
+               if (list_empty(&q->queued))
+                       return 0;
+
+               buf = list_entry(q->queued.next, struct cx25821_buffer,
+                               vb.queue);
+
+               if (NULL == prev) {
+                       list_move_tail(&buf->vb.queue, &q->active);
+                       cx25821_start_video_dma(dev, q, buf, channel);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count = q->count++;
+                       mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+               } else if (prev->vb.width == buf->vb.width &&
+                          prev->vb.height == buf->vb.height &&
+                          prev->fmt == buf->fmt) {
+                       list_move_tail(&buf->vb.queue, &q->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count = q->count++;
+                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                       prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+               } else {
+                       return 0;
+               }
+               prev = buf;
+       }
+}
+
+void cx25821_vid_timeout(unsigned long data)
+{
+       struct cx25821_data *timeout_data = (struct cx25821_data *)data;
+       struct cx25821_dev *dev = timeout_data->dev;
+       struct sram_channel *channel = timeout_data->channel;
+       struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq;
+       struct cx25821_buffer *buf;
+       unsigned long flags;
+
+       /* cx25821_sram_channel_dump(dev, channel); */
+       cx_clear(channel->dma_ctl, 0x11);
+
+       spin_lock_irqsave(&dev->slock, flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx25821_buffer,
+                               vb.queue);
+               list_del(&buf->vb.queue);
+
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+       }
+
+       cx25821_restart_video_queue(dev, q, channel);
+       spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+       u32 count = 0;
+       int handled = 0;
+       u32 mask;
+       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+
+       mask = cx_read(channel->int_msk);
+       if (0 == (status & mask))
+               return handled;
+
+       cx_write(channel->int_stat, status);
+
+       /* risc op code error */
+       if (status & (1 << 16)) {
+               pr_warn("%s, %s: video risc op code error\n",
+                       dev->name, channel->name);
+               cx_clear(channel->dma_ctl, 0x11);
+               cx25821_sram_channel_dump(dev, channel);
+       }
+
+       /* risc1 y */
+       if (status & FLD_VID_DST_RISC1) {
+               spin_lock(&dev->slock);
+               count = cx_read(channel->gpcnt);
+               cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq,
+                               count);
+               spin_unlock(&dev->slock);
+               handled++;
+       }
+
+       /* risc2 y */
+       if (status & 0x10) {
+               dprintk(2, "stopper video\n");
+               spin_lock(&dev->slock);
+               cx25821_restart_video_queue(dev,
+                               &dev->channels[channel->i].vidq, channel);
+               spin_unlock(&dev->slock);
+               handled++;
+       }
+       return handled;
+}
+
+void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
+{
+       if (dev->ioctl_dev) {
+               if (video_is_registered(dev->ioctl_dev))
+                       video_unregister_device(dev->ioctl_dev);
+               else
+                       video_device_release(dev->ioctl_dev);
+
+               dev->ioctl_dev = NULL;
+       }
+}
+
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+       cx_clear(PCI_INT_MSK, 1);
+
+       if (dev->channels[chan_num].video_dev) {
+               if (video_is_registered(dev->channels[chan_num].video_dev))
+                       video_unregister_device(
+                                       dev->channels[chan_num].video_dev);
+               else
+                       video_device_release(
+                                       dev->channels[chan_num].video_dev);
+
+               dev->channels[chan_num].video_dev = NULL;
+
+               btcx_riscmem_free(dev->pci,
+                               &dev->channels[chan_num].vidq.stopper);
+
+               pr_warn("device %d released!\n", chan_num);
+       }
+
+}
+
+int cx25821_video_register(struct cx25821_dev *dev)
+{
+       int err;
+       int i;
+
+       struct video_device cx25821_video_device = {
+               .name = "cx25821-video",
+               .fops = &video_fops,
+               .minor = -1,
+               .ioctl_ops = &video_ioctl_ops,
+               .tvnorms = CX25821_NORMS,
+               .current_norm = V4L2_STD_NTSC_M,
+       };
+
+       spin_lock_init(&dev->slock);
+
+       for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+               cx25821_init_controls(dev, i);
+
+               cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
+                       dev->channels[i].sram_channels->dma_ctl, 0x11, 0);
+
+               dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+               dev->channels[i].video_dev = NULL;
+               dev->channels[i].resources = 0;
+
+               cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+               INIT_LIST_HEAD(&dev->channels[i].vidq.active);
+               INIT_LIST_HEAD(&dev->channels[i].vidq.queued);
+
+               dev->channels[i].timeout_data.dev = dev;
+               dev->channels[i].timeout_data.channel =
+                       &cx25821_sram_channels[i];
+               dev->channels[i].vidq.timeout.function = cx25821_vid_timeout;
+               dev->channels[i].vidq.timeout.data =
+                       (unsigned long)&dev->channels[i].timeout_data;
+               init_timer(&dev->channels[i].vidq.timeout);
+
+               /* register v4l devices */
+               dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci,
+                               &cx25821_video_device, "video");
+
+               err = video_register_device(dev->channels[i].video_dev,
+                               VFL_TYPE_GRABBER, video_nr[dev->nr]);
+
+               if (err < 0)
+                       goto fail_unreg;
+
+       }
+
+       /* set PCI interrupt */
+       cx_set(PCI_INT_MSK, 0xff);
+
+       /* initial device configuration */
+       mutex_lock(&dev->lock);
+#ifdef TUNER_FLAG
+       dev->tvnorm = cx25821_video_device.current_norm;
+       cx25821_set_tvnorm(dev, dev->tvnorm);
+#endif
+       mutex_unlock(&dev->lock);
+
+       return 0;
+
+fail_unreg:
+       cx25821_video_unregister(dev, i);
+       return err;
+}
+
+int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+                unsigned int *size)
+{
+       struct cx25821_fh *fh = q->priv_data;
+
+       *size = fh->fmt->depth * fh->width * fh->height >> 3;
+
+       if (0 == *count)
+               *count = 32;
+
+       if (*size * *count > vid_limit * 1024 * 1024)
+               *count = (vid_limit * 1024 * 1024) / *size;
+
+       return 0;
+}
+
+int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+                  enum v4l2_field field)
+{
+       struct cx25821_fh *fh = q->priv_data;
+       struct cx25821_dev *dev = fh->dev;
+       struct cx25821_buffer *buf =
+               container_of(vb, struct cx25821_buffer, vb);
+       int rc, init_buffer = 0;
+       u32 line0_offset;
+       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+       int bpl_local = LINE_SIZE_D1;
+       int channel_opened = fh->channel_id;
+
+       BUG_ON(NULL == fh->fmt);
+       if (fh->width < 48 || fh->width > 720 ||
+           fh->height < 32 || fh->height > 576)
+               return -EINVAL;
+
+       buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+
+       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;
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               init_buffer = 1;
+               rc = videobuf_iolock(q, &buf->vb, NULL);
+               if (0 != rc) {
+                       printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
+                       goto fail;
+               }
+       }
+
+       dprintk(1, "init_buffer=%d\n", init_buffer);
+
+       if (init_buffer) {
+
+               channel_opened = dev->channel_opened;
+               if (channel_opened < 0 || channel_opened > 7)
+                       channel_opened = 7;
+
+               if (dev->channels[channel_opened].pixel_formats ==
+                               PIXEL_FRMT_411)
+                       buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
+               else
+                       buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
+
+               if (dev->channels[channel_opened].pixel_formats ==
+                               PIXEL_FRMT_411) {
+                       bpl_local = buf->bpl;
+               } else {
+                       bpl_local = buf->bpl;   /* Default */
+
+                       if (channel_opened >= 0 && channel_opened <= 7) {
+                               if (dev->channels[channel_opened]
+                                               .use_cif_resolution) {
+                                       if (dev->tvnorm & V4L2_STD_PAL_BG ||
+                                           dev->tvnorm & V4L2_STD_PAL_DK)
+                                               bpl_local = 352 << 1;
+                                       else
+                                               bpl_local = dev->channels[
+                                                       channel_opened].
+                                                       cif_width << 1;
+                               }
+                       }
+               }
+
+               switch (buf->vb.field) {
+               case V4L2_FIELD_TOP:
+                       cx25821_risc_buffer(dev->pci, &buf->risc,
+                                           dma->sglist, 0, UNSET,
+                                           buf->bpl, 0, buf->vb.height);
+                       break;
+               case V4L2_FIELD_BOTTOM:
+                       cx25821_risc_buffer(dev->pci, &buf->risc,
+                                           dma->sglist, UNSET, 0,
+                                           buf->bpl, 0, buf->vb.height);
+                       break;
+               case V4L2_FIELD_INTERLACED:
+                       /* All other formats are top field first */
+                       line0_offset = 0;
+                       dprintk(1, "top field first\n");
+
+                       cx25821_risc_buffer(dev->pci, &buf->risc,
+                                           dma->sglist, line0_offset,
+                                           bpl_local, bpl_local, bpl_local,
+                                           buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_TB:
+                       cx25821_risc_buffer(dev->pci, &buf->risc,
+                                           dma->sglist,
+                                           0, buf->bpl * (buf->vb.height >> 1),
+                                           buf->bpl, 0, buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_BT:
+                       cx25821_risc_buffer(dev->pci, &buf->risc,
+                                           dma->sglist,
+                                           buf->bpl * (buf->vb.height >> 1), 0,
+                                           buf->bpl, 0, buf->vb.height >> 1);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+
+       dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+               buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth,
+               fh->fmt->name, (unsigned long)buf->risc.dma);
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+
+       return 0;
+
+fail:
+       cx25821_free_buffer(q, buf);
+       return rc;
+}
+
+void cx25821_buffer_release(struct videobuf_queue *q,
+                           struct videobuf_buffer *vb)
+{
+       struct cx25821_buffer *buf =
+               container_of(vb, struct cx25821_buffer, vb);
+
+       cx25821_free_buffer(q, buf);
+}
+
+struct videobuf_queue *get_queue(struct cx25821_fh *fh)
+{
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &fh->vidq;
+       default:
+               BUG();
+               return NULL;
+       }
+}
+
+int cx25821_get_resource(struct cx25821_fh *fh, int resource)
+{
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return resource;
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cx25821_fh *fh = file->private_data;
+
+       return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx25821_buffer *buf =
+               container_of(vb, struct cx25821_buffer, vb);
+       struct cx25821_buffer *prev;
+       struct cx25821_fh *fh = vq->priv_data;
+       struct cx25821_dev *dev = fh->dev;
+       struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq;
+
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+       buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
+
+       dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+       if (!list_empty(&q->queued)) {
+               list_add_tail(&buf->vb.queue, &q->queued);
+               buf->vb.state = VIDEOBUF_QUEUED;
+               dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+                               buf->vb.i);
+
+       } else if (list_empty(&q->active)) {
+               list_add_tail(&buf->vb.queue, &q->active);
+               cx25821_start_video_dma(dev, q, buf,
+                               dev->channels[fh->channel_id].sram_channels);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count = q->count++;
+               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+               dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+                               buf, buf->vb.i, buf->count, q->count);
+       } else {
+               prev = list_entry(q->active.prev, struct cx25821_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, &q->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count = q->count++;
+                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+                       /* 64 bit bits 63-32 */
+                       prev->risc.jmp[2] = cpu_to_le32(0);
+                       dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+                                       buf, buf->vb.i, buf->count);
+
+               } else {
+                       list_add_tail(&buf->vb.queue, &q->queued);
+                       buf->vb.state = VIDEOBUF_QUEUED;
+                       dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+                                       buf->vb.i);
+               }
+       }
+
+       if (list_empty(&q->active))
+               dprintk(2, "active queue empty!\n");
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+       .buf_setup = cx25821_buffer_setup,
+       .buf_prepare = cx25821_buffer_prepare,
+       .buf_queue = buffer_queue,
+       .buf_release = cx25821_buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx25821_dev *h, *dev = video_drvdata(file);
+       struct cx25821_fh *fh;
+       struct list_head *list;
+       int minor = video_devdata(file)->minor;
+       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       u32 pix_format;
+       int ch_id = 0;
+       int i;
+
+       dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev),
+                       v4l2_type_names[type]);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       mutex_lock(&cx25821_devlist_mutex);
+
+       list_for_each(list, &cx25821_devlist)
+       {
+               h = list_entry(list, struct cx25821_dev, devlist);
+
+               for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
+                       if (h->channels[i].video_dev &&
+                           h->channels[i].video_dev->minor == minor) {
+                               dev = h;
+                               ch_id = i;
+                               type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       }
+               }
+       }
+
+       if (NULL == dev) {
+               mutex_unlock(&cx25821_devlist_mutex);
+               kfree(fh);
+               return -ENODEV;
+       }
+
+       file->private_data = fh;
+       fh->dev = dev;
+       fh->type = type;
+       fh->width = 720;
+       fh->channel_id = ch_id;
+
+       if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+               fh->height = 576;
+       else
+               fh->height = 480;
+
+       dev->channel_opened = fh->channel_id;
+       if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411)
+               pix_format = V4L2_PIX_FMT_Y41P;
+       else
+               pix_format = V4L2_PIX_FMT_YUYV;
+       fh->fmt = cx25821_format_by_fourcc(pix_format);
+
+       v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
+
+       videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev,
+                       &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                       V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer),
+                       fh, NULL);
+
+       dprintk(1, "post videobuf_queue_init()\n");
+       mutex_unlock(&cx25821_devlist_mutex);
+
+       return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+                        loff_t *ppos)
+{
+       struct cx25821_fh *fh = file->private_data;
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (cx25821_res_locked(fh, RESOURCE_VIDEO0))
+                       return -EBUSY;
+
+               return videobuf_read_one(&fh->vidq, data, count, ppos,
+                                       file->f_flags & O_NONBLOCK);
+
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static unsigned int video_poll(struct file *file,
+                             struct poll_table_struct *wait)
+{
+       struct cx25821_fh *fh = file->private_data;
+       struct cx25821_buffer *buf;
+
+       if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+               /* streaming capture */
+               if (list_empty(&fh->vidq.stream))
+                       return POLLERR;
+               buf = list_entry(fh->vidq.stream.next,
+                               struct cx25821_buffer, vb.stream);
+       } else {
+               /* read() capture */
+               buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+               if (NULL == buf)
+                       return POLLERR;
+       }
+
+       poll_wait(file, &buf->vb.done, wait);
+       if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+               if (buf->vb.state == VIDEOBUF_DONE) {
+                       struct cx25821_dev *dev = fh->dev;
+
+                       if (dev && dev->channels[fh->channel_id]
+                                       .use_cif_resolution) {
+                               u8 cam_id = *((char *)buf->vb.baddr + 3);
+                               memcpy((char *)buf->vb.baddr,
+                                     (char *)buf->vb.baddr + (fh->width * 2),
+                                     (fh->width * 2));
+                               *((char *)buf->vb.baddr + 3) = cam_id;
+                       }
+               }
+
+               return POLLIN | POLLRDNORM;
+       }
+
+       return 0;
+}
+
+static int video_release(struct file *file)
+{
+       struct cx25821_fh *fh = file->private_data;
+       struct cx25821_dev *dev = fh->dev;
+
+       /* stop the risc engine and fifo */
+       cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
+
+       /* stop video capture */
+       if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+               videobuf_queue_cancel(&fh->vidq);
+               cx25821_res_free(dev, fh, RESOURCE_VIDEO0);
+       }
+
+       if (fh->vidq.read_buf) {
+               cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf);
+               kfree(fh->vidq.read_buf);
+       }
+
+       videobuf_mmap_free(&fh->vidq);
+
+       v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio);
+       file->private_data = NULL;
+       kfree(fh);
+
+       return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = fh->dev;
+
+       if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+               return -EINVAL;
+
+       if (unlikely(i != fh->type))
+               return -EINVAL;
+
+       if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh,
+                                               RESOURCE_VIDEO0))))
+               return -EBUSY;
+
+       return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = fh->dev;
+       int err, res;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
+
+       res = cx25821_get_resource(fh, RESOURCE_VIDEO0);
+       err = videobuf_streamoff(get_queue(fh));
+       if (err < 0)
+               return err;
+       cx25821_res_free(dev, fh, res);
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int err;
+       int pix_format = PIXEL_FRMT_422;
+
+       if (fh) {
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       dprintk(2, "%s()\n", __func__);
+       err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
+
+       if (0 != err)
+               return err;
+
+       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->vidq.field = f->fmt.pix.field;
+
+       /* check if width and height is valid based on set standard */
+       if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm))
+               fh->width = f->fmt.pix.width;
+
+       if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm))
+               fh->height = f->fmt.pix.height;
+
+       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+               pix_format = PIXEL_FRMT_411;
+       else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+               pix_format = PIXEL_FRMT_422;
+       else
+               return -EINVAL;
+
+       cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
+
+       /* check if cif resolution */
+       if (fh->width == 320 || fh->width == 352)
+               dev->channels[fh->channel_id].use_cif_resolution = 1;
+       else
+               dev->channels[fh->channel_id].use_cif_resolution = 0;
+
+       dev->channels[fh->channel_id].cif_width = fh->width;
+       medusa_set_resolution(dev, fh->width, SRAM_CH00);
+
+       dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width,
+               fh->height, fh->vidq.field);
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+
+       return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       int ret_val = 0;
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+       ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+       p->sequence = dev->channels[fh->channel_id].vidq.count;
+
+       return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       struct cx25821_fh *fh = priv;
+       char name[32 + 2];
+
+       struct sram_channel *sram_ch = dev->channels[fh->channel_id]
+                                                               .sram_channels;
+       u32 tmp = 0;
+
+       snprintf(name, sizeof(name), "%s/2", dev->name);
+       pr_info("%s/2: ============  START LOG STATUS  ============\n",
+               dev->name);
+       cx25821_call_all(dev, core, log_status);
+       tmp = cx_read(sram_ch->dma_ctl);
+       pr_info("Video input 0 is %s\n",
+               (tmp & 0x11) ? "streaming" : "stopped");
+       pr_info("%s/2: =============  END LOG STATUS  =============\n",
+               dev->name);
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                       struct v4l2_control *ctl)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       int err;
+
+       if (fh) {
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       return cx25821_set_control(dev, ctl, fh->channel_id);
+}
+
+/* VIDEO IOCTLS */
+int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                struct v4l2_format *f)
+{
+       struct cx25821_fh *fh = priv;
+
+       f->fmt.pix.width = fh->width;
+       f->fmt.pix.height = fh->height;
+       f->fmt.pix.field = fh->vidq.field;
+       f->fmt.pix.pixelformat = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_format *f)
+{
+       struct cx25821_fmt *fmt;
+       enum v4l2_field field;
+       unsigned int maxw, maxh;
+
+       fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       maxw = 720;
+       maxh = 576;
+
+       if (V4L2_FIELD_ANY == field) {
+               if (f->fmt.pix.height > maxh / 2)
+                       field = V4L2_FIELD_INTERLACED;
+               else
+                       field = V4L2_FIELD_TOP;
+       }
+
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       f->fmt.pix.field = field;
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
+       if (f->fmt.pix.height > maxh)
+               f->fmt.pix.height = maxh;
+       if (f->fmt.pix.width < 48)
+               f->fmt.pix.width = 48;
+       if (f->fmt.pix.width > maxw)
+               f->fmt.pix.width = maxw;
+       f->fmt.pix.width &= ~0x03;
+       f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+int cx25821_vidioc_querycap(struct file *file, void *priv,
+                           struct v4l2_capability *cap)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+       strcpy(cap->driver, "cx25821");
+       strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+       sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+       cap->version = CX25821_VERSION_CODE;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING;
+       if (UNSET != dev->tuner_type)
+               cap->capabilities |= V4L2_CAP_TUNER;
+       return 0;
+}
+
+int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                           struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(formats)))
+               return -EINVAL;
+
+       strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+       f->pixelformat = formats[f->index].fourcc;
+
+       return 0;
+}
+
+int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+                          struct v4l2_requestbuffers *p)
+{
+       struct cx25821_fh *fh = priv;
+       return videobuf_reqbufs(get_queue(fh), p);
+}
+
+int cx25821_vidioc_querybuf(struct file *file, void *priv,
+                           struct v4l2_buffer *p)
+{
+       struct cx25821_fh *fh = priv;
+       return videobuf_querybuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx25821_fh *fh = priv;
+       return videobuf_qbuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+       struct cx25821_fh *fh = f;
+
+       *p = v4l2_prio_max(&dev->channels[fh->channel_id].prio);
+
+       return 0;
+}
+
+int cx25821_vidioc_s_priority(struct file *file, void *f,
+                             enum v4l2_priority prio)
+{
+       struct cx25821_fh *fh = f;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+       return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio,
+                       prio);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       int err;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (fh) {
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       if (dev->tvnorm == *tvnorms)
+               return 0;
+
+       mutex_lock(&dev->lock);
+       cx25821_set_tvnorm(dev, *tvnorms);
+       mutex_unlock(&dev->lock);
+
+       medusa_set_videostandard(dev);
+
+       return 0;
+}
+#endif
+
+int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
+{
+       static const char * const iname[] = {
+               [CX25821_VMUX_COMPOSITE] = "Composite",
+               [CX25821_VMUX_SVIDEO] = "S-Video",
+               [CX25821_VMUX_DEBUG] = "for debug only",
+       };
+       unsigned int n;
+       dprintk(1, "%s()\n", __func__);
+
+       n = i->index;
+       if (n >= 2)
+               return -EINVAL;
+
+       if (0 == INPUT(n)->type)
+               return -EINVAL;
+
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(i->name, iname[INPUT(n)->type]);
+
+       i->std = CX25821_NORMS;
+       return 0;
+}
+
+int cx25821_vidioc_enum_input(struct file *file, void *priv,
+                             struct v4l2_input *i)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       dprintk(1, "%s()\n", __func__);
+       return cx25821_enum_input(dev, i);
+}
+
+int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+       *i = dev->input;
+       dprintk(1, "%s(): returns %d\n", __func__, *i);
+       return 0;
+}
+
+int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       int err;
+
+       dprintk(1, "%s(%d)\n", __func__, i);
+
+       if (fh) {
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       if (i >= CX25821_NR_INPUT) {
+               dprintk(1, "%s(): -EINVAL\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&dev->lock);
+       cx25821_video_mux(dev, i);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+                              struct v4l2_frequency *f)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev = fh->dev;
+
+       f->frequency = dev->freq;
+
+       cx25821_call_all(dev, tuner, g_frequency, f);
+
+       return 0;
+}
+
+int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+{
+       mutex_lock(&dev->lock);
+       dev->freq = f->frequency;
+
+       cx25821_call_all(dev, tuner, s_frequency, f);
+
+       /* When changing channels it is required to reset TVAUDIO */
+       msleep(10);
+
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+                              struct v4l2_frequency *f)
+{
+       struct cx25821_fh *fh = priv;
+       struct cx25821_dev *dev;
+       int err;
+
+       if (fh) {
+               dev = fh->dev;
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       } else {
+               pr_err("Invalid fh pointer!\n");
+               return -EINVAL;
+       }
+
+       return cx25821_set_freq(dev, f);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx25821_vidioc_g_register(struct file *file, void *fh,
+                     struct v4l2_dbg_register *reg)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+
+       cx25821_call_all(dev, core, g_register, reg);
+
+       return 0;
+}
+
+int cx25821_vidioc_s_register(struct file *file, void *fh,
+                     struct v4l2_dbg_register *reg)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+
+       cx25821_call_all(dev, core, s_register, reg);
+
+       return 0;
+}
+
+#endif
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+       t->type = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh = 0xffffffffUL;
+
+       t->signal = 0xffff;     /* LOCKED */
+       return 0;
+}
+
+int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       struct cx25821_fh *fh = priv;
+       int err;
+
+       if (fh) {
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       }
+
+       dprintk(1, "%s()\n", __func__);
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       return 0;
+}
+
+#endif
+/*****************************************************************************/
+static const struct v4l2_queryctrl no_ctl = {
+       .name = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct v4l2_queryctrl cx25821_ctls[] = {
+       /* --- video --- */
+       {
+               .id = V4L2_CID_BRIGHTNESS,
+               .name = "Brightness",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 6200,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }, {
+               .id = V4L2_CID_CONTRAST,
+               .name = "Contrast",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 5000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }, {
+               .id = V4L2_CID_SATURATION,
+               .name = "Saturation",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 5000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }, {
+               .id = V4L2_CID_HUE,
+               .name = "Hue",
+               .minimum = 0,
+               .maximum = 10000,
+               .step = 1,
+               .default_value = 5000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
+
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+       int i;
+
+       if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       for (i = 0; i < CX25821_CTLS; i++)
+               if (cx25821_ctls[i].id == qctrl->id)
+                       break;
+       if (i == CX25821_CTLS) {
+               *qctrl = no_ctl;
+               return 0;
+       }
+       *qctrl = cx25821_ctls[i];
+       return 0;
+}
+
+int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+                    struct v4l2_queryctrl *qctrl)
+{
+       return cx25821_ctrl_query(qctrl);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+       unsigned int i;
+
+       for (i = 0; i < CX25821_CTLS; i++)
+               if (cx25821_ctls[i].id == id)
+                       return cx25821_ctls + i;
+       return NULL;
+}
+
+int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+                         struct v4l2_control *ctl)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       struct cx25821_fh *fh = priv;
+
+       const struct v4l2_queryctrl *ctrl;
+
+       ctrl = ctrl_by_id(ctl->id);
+
+       if (NULL == ctrl)
+               return -EINVAL;
+       switch (ctl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctl->value = dev->channels[fh->channel_id].ctl_bright;
+               break;
+       case V4L2_CID_HUE:
+               ctl->value = dev->channels[fh->channel_id].ctl_hue;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctl->value = dev->channels[fh->channel_id].ctl_contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               ctl->value = dev->channels[fh->channel_id].ctl_saturation;
+               break;
+       }
+       return 0;
+}
+
+int cx25821_set_control(struct cx25821_dev *dev,
+                       struct v4l2_control *ctl, int chan_num)
+{
+       int err;
+       const struct v4l2_queryctrl *ctrl;
+
+       err = -EINVAL;
+
+       ctrl = ctrl_by_id(ctl->id);
+
+       if (NULL == ctrl)
+               return err;
+
+       switch (ctrl->type) {
+       case V4L2_CTRL_TYPE_BOOLEAN:
+       case V4L2_CTRL_TYPE_MENU:
+       case V4L2_CTRL_TYPE_INTEGER:
+               if (ctl->value < ctrl->minimum)
+                       ctl->value = ctrl->minimum;
+               if (ctl->value > ctrl->maximum)
+                       ctl->value = ctrl->maximum;
+               break;
+       default:
+               /* nothing */ ;
+       }
+
+       switch (ctl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               dev->channels[chan_num].ctl_bright = ctl->value;
+               medusa_set_brightness(dev, ctl->value, chan_num);
+               break;
+       case V4L2_CID_HUE:
+               dev->channels[chan_num].ctl_hue = ctl->value;
+               medusa_set_hue(dev, ctl->value, chan_num);
+               break;
+       case V4L2_CID_CONTRAST:
+               dev->channels[chan_num].ctl_contrast = ctl->value;
+               medusa_set_contrast(dev, ctl->value, chan_num);
+               break;
+       case V4L2_CID_SATURATION:
+               dev->channels[chan_num].ctl_saturation = ctl->value;
+               medusa_set_saturation(dev, ctl->value, chan_num);
+               break;
+       }
+
+       err = 0;
+
+       return err;
+}
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num)
+{
+       struct v4l2_control ctrl;
+       int i;
+       for (i = 0; i < CX25821_CTLS; i++) {
+               ctrl.id = cx25821_ctls[i].id;
+               ctrl.value = cx25821_ctls[i].default_value;
+
+               cx25821_set_control(dev, &ctrl, chan_num);
+       }
+}
+
+int cx25821_vidioc_cropcap(struct file *file, void *priv,
+                          struct v4l2_cropcap *cropcap)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       cropcap->bounds.top = 0;
+       cropcap->bounds.left = 0;
+       cropcap->bounds.width = 720;
+       cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
+       cropcap->pixelaspect.numerator =
+               dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
+       cropcap->pixelaspect.denominator =
+               dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
+       cropcap->defrect = cropcap->bounds;
+       return 0;
+}
+
+int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+       struct cx25821_fh *fh = priv;
+       int err;
+
+       if (fh) {
+               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+                                     fh->prio);
+               if (0 != err)
+                       return err;
+       }
+       /* cx25821_vidioc_s_crop not supported */
+       return -EINVAL;
+}
+
+int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+       /* cx25821_vidioc_g_crop not supported */
+       return -EINVAL;
+}
+
+int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm)
+{
+       /* medusa does not support video standard sensing of current input */
+       *norm = CX25821_NORMS;
+
+       return 0;
+}
+
+int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm)
+{
+       if (tvnorm == V4L2_STD_PAL_BG) {
+               if (width == 352 || width == 720)
+                       return 1;
+               else
+                       return 0;
+       }
+
+       if (tvnorm == V4L2_STD_NTSC_M) {
+               if (width == 320 || width == 352 || width == 720)
+                       return 1;
+               else
+                       return 0;
+       }
+       return 0;
+}
+
+int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm)
+{
+       if (tvnorm == V4L2_STD_PAL_BG) {
+               if (height == 576 || height == 288)
+                       return 1;
+               else
+                       return 0;
+       }
+
+       if (tvnorm == V4L2_STD_NTSC_M) {
+               if (height == 480 || height == 240)
+                       return 1;
+               else
+                       return 0;
+       }
+
+       return 0;
+}
+
+static long video_ioctl_upstream9(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+{
+       struct cx25821_fh *fh = file->private_data;
+       struct cx25821_dev *dev = fh->dev;
+       int command = 0;
+       struct upstream_user_struct *data_from_user;
+
+       data_from_user = (struct upstream_user_struct *)arg;
+
+       if (!data_from_user) {
+               pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+               return 0;
+       }
+
+       command = data_from_user->command;
+
+       if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+               return 0;
+
+       dev->input_filename = data_from_user->input_filename;
+       dev->input_audiofilename = data_from_user->input_filename;
+       dev->vid_stdname = data_from_user->vid_stdname;
+       dev->pixel_format = data_from_user->pixel_format;
+       dev->channel_select = data_from_user->channel_select;
+       dev->command = data_from_user->command;
+
+       switch (command) {
+       case UPSTREAM_START_VIDEO:
+               cx25821_start_upstream_video_ch1(dev, data_from_user);
+               break;
+
+       case UPSTREAM_STOP_VIDEO:
+               cx25821_stop_upstream_video_ch1(dev);
+               break;
+       }
+
+       return 0;
+}
+
+static long video_ioctl_upstream10(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       struct cx25821_fh *fh = file->private_data;
+       struct cx25821_dev *dev = fh->dev;
+       int command = 0;
+       struct upstream_user_struct *data_from_user;
+
+       data_from_user = (struct upstream_user_struct *)arg;
+
+       if (!data_from_user) {
+               pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+               return 0;
+       }
+
+       command = data_from_user->command;
+
+       if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+               return 0;
+
+       dev->input_filename_ch2 = data_from_user->input_filename;
+       dev->input_audiofilename = data_from_user->input_filename;
+       dev->vid_stdname_ch2 = data_from_user->vid_stdname;
+       dev->pixel_format_ch2 = data_from_user->pixel_format;
+       dev->channel_select_ch2 = data_from_user->channel_select;
+       dev->command_ch2 = data_from_user->command;
+
+       switch (command) {
+       case UPSTREAM_START_VIDEO:
+               cx25821_start_upstream_video_ch2(dev, data_from_user);
+               break;
+
+       case UPSTREAM_STOP_VIDEO:
+               cx25821_stop_upstream_video_ch2(dev);
+               break;
+       }
+
+       return 0;
+}
+
+static long video_ioctl_upstream11(struct file *file, unsigned int cmd,
+                                 unsigned long arg)
+{
+       struct cx25821_fh *fh = file->private_data;
+       struct cx25821_dev *dev = fh->dev;
+       int command = 0;
+       struct upstream_user_struct *data_from_user;
+
+       data_from_user = (struct upstream_user_struct *)arg;
+
+       if (!data_from_user) {
+               pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+               return 0;
+       }
+
+       command = data_from_user->command;
+
+       if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO)
+               return 0;
+
+       dev->input_filename = data_from_user->input_filename;
+       dev->input_audiofilename = data_from_user->input_filename;
+       dev->vid_stdname = data_from_user->vid_stdname;
+       dev->pixel_format = data_from_user->pixel_format;
+       dev->channel_select = data_from_user->channel_select;
+       dev->command = data_from_user->command;
+
+       switch (command) {
+       case UPSTREAM_START_AUDIO:
+               cx25821_start_upstream_audio(dev, data_from_user);
+               break;
+
+       case UPSTREAM_STOP_AUDIO:
+               cx25821_stop_upstream_audio(dev);
+               break;
+       }
+
+       return 0;
+}
+
+static long video_ioctl_set(struct file *file, unsigned int cmd,
+                          unsigned long arg)
+{
+       struct cx25821_fh *fh = file->private_data;
+       struct cx25821_dev *dev = fh->dev;
+       struct downstream_user_struct *data_from_user;
+       int command;
+       int width = 720;
+       int selected_channel = 0;
+       int pix_format = 0;
+       int i = 0;
+       int cif_enable = 0;
+       int cif_width = 0;
+
+       data_from_user = (struct downstream_user_struct *)arg;
+
+       if (!data_from_user) {
+               pr_err("%s(): User data is INVALID. Returning\n", __func__);
+               return 0;
+       }
+
+       command = data_from_user->command;
+
+       if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT
+          && command != ENABLE_CIF_RESOLUTION && command != REG_READ
+          && command != REG_WRITE && command != MEDUSA_READ
+          && command != MEDUSA_WRITE) {
+               return 0;
+       }
+
+       switch (command) {
+       case SET_VIDEO_STD:
+               if (!strcmp(data_from_user->vid_stdname, "PAL"))
+                       dev->tvnorm = V4L2_STD_PAL_BG;
+               else
+                       dev->tvnorm = V4L2_STD_NTSC_M;
+               medusa_set_videostandard(dev);
+               break;
+
+       case SET_PIXEL_FORMAT:
+               selected_channel = data_from_user->decoder_select;
+               pix_format = data_from_user->pixel_format;
+
+               if (!(selected_channel <= 7 && selected_channel >= 0)) {
+                       selected_channel -= 4;
+                       selected_channel = selected_channel % 8;
+               }
+
+               if (selected_channel >= 0)
+                       cx25821_set_pixel_format(dev, selected_channel,
+                                               pix_format);
+
+               break;
+
+       case ENABLE_CIF_RESOLUTION:
+               selected_channel = data_from_user->decoder_select;
+               cif_enable = data_from_user->cif_resolution_enable;
+               cif_width = data_from_user->cif_width;
+
+               if (cif_enable) {
+                       if (dev->tvnorm & V4L2_STD_PAL_BG
+                           || dev->tvnorm & V4L2_STD_PAL_DK) {
+                               width = 352;
+                       } else {
+                               width = cif_width;
+                               if (cif_width != 320 && cif_width != 352)
+                                       width = 320;
+                       }
+               }
+
+               if (!(selected_channel <= 7 && selected_channel >= 0)) {
+                       selected_channel -= 4;
+                       selected_channel = selected_channel % 8;
+               }
+
+               if (selected_channel <= 7 && selected_channel >= 0) {
+                       dev->channels[selected_channel].use_cif_resolution =
+                               cif_enable;
+                       dev->channels[selected_channel].cif_width = width;
+               } else {
+                       for (i = 0; i < VID_CHANNEL_NUM; i++) {
+                               dev->channels[i].use_cif_resolution =
+                                       cif_enable;
+                               dev->channels[i].cif_width = width;
+                       }
+               }
+
+               medusa_set_resolution(dev, width, selected_channel);
+               break;
+       case REG_READ:
+               data_from_user->reg_data = cx_read(data_from_user->reg_address);
+               break;
+       case REG_WRITE:
+               cx_write(data_from_user->reg_address, data_from_user->reg_data);
+               break;
+       case MEDUSA_READ:
+               cx25821_i2c_read(&dev->i2c_bus[0],
+                                        (u16) data_from_user->reg_address,
+                                        &data_from_user->reg_data);
+               break;
+       case MEDUSA_WRITE:
+               cx25821_i2c_write(&dev->i2c_bus[0],
+                                 (u16) data_from_user->reg_address,
+                                 data_from_user->reg_data);
+               break;
+       }
+
+       return 0;
+}
+
+static long cx25821_video_ioctl(struct file *file,
+                               unsigned int cmd, unsigned long arg)
+{
+       int ret = 0;
+
+       struct cx25821_fh *fh = file->private_data;
+
+       /* check to see if it's the video upstream */
+       if (fh->channel_id == SRAM_CH09) {
+               ret = video_ioctl_upstream9(file, cmd, arg);
+               return ret;
+       } else if (fh->channel_id == SRAM_CH10) {
+               ret = video_ioctl_upstream10(file, cmd, arg);
+               return ret;
+       } else if (fh->channel_id == SRAM_CH11) {
+               ret = video_ioctl_upstream11(file, cmd, arg);
+               ret = video_ioctl_set(file, cmd, arg);
+               return ret;
+       }
+
+       return video_ioctl2(file, cmd, arg);
+}
+
+/* exported stuff */
+static const struct v4l2_file_operations video_fops = {
+       .owner = THIS_MODULE,
+       .open = video_open,
+       .release = video_release,
+       .read = video_read,
+       .poll = video_poll,
+       .mmap = cx25821_video_mmap,
+       .ioctl = cx25821_video_ioctl,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap = cx25821_vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+       .vidioc_reqbufs = cx25821_vidioc_reqbufs,
+       .vidioc_querybuf = cx25821_vidioc_querybuf,
+       .vidioc_qbuf = cx25821_vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+       .vidioc_s_std = cx25821_vidioc_s_std,
+       .vidioc_querystd = cx25821_vidioc_querystd,
+#endif
+       .vidioc_cropcap = cx25821_vidioc_cropcap,
+       .vidioc_s_crop = cx25821_vidioc_s_crop,
+       .vidioc_g_crop = cx25821_vidioc_g_crop,
+       .vidioc_enum_input = cx25821_vidioc_enum_input,
+       .vidioc_g_input = cx25821_vidioc_g_input,
+       .vidioc_s_input = cx25821_vidioc_s_input,
+       .vidioc_g_ctrl = cx25821_vidioc_g_ctrl,
+       .vidioc_s_ctrl = vidioc_s_ctrl,
+       .vidioc_queryctrl = cx25821_vidioc_queryctrl,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_log_status = vidioc_log_status,
+       .vidioc_g_priority = cx25821_vidioc_g_priority,
+       .vidioc_s_priority = cx25821_vidioc_s_priority,
+#ifdef TUNER_FLAG
+       .vidioc_g_tuner = cx25821_vidioc_g_tuner,
+       .vidioc_s_tuner = cx25821_vidioc_s_tuner,
+       .vidioc_g_frequency = cx25821_vidioc_g_frequency,
+       .vidioc_s_frequency = cx25821_vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register = cx25821_vidioc_g_register,
+       .vidioc_s_register = cx25821_vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_videoioctl_template = {
+       .name = "cx25821-videoioctl",
+       .fops = &video_fops,
+       .ioctl_ops = &video_ioctl_ops,
+       .tvnorms = CX25821_NORMS,
+       .current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/media/pci/cx25821/cx25821-video.h b/drivers/media/pci/cx25821/cx25821-video.h
new file mode 100644 (file)
index 0000000..9652a5e
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  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 CX25821_VIDEO_H_
+#define CX25821_VIDEO_H_
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx25821.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#define TUNER_FLAG
+
+#define VIDEO_DEBUG 0
+
+#define dprintk(level, fmt, arg...)                                    \
+do {                                                                   \
+       if (VIDEO_DEBUG >= level)                                       \
+               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);      \
+} while (0)
+
+/* For IOCTL to identify running upstream */
+#define UPSTREAM_START_VIDEO        700
+#define UPSTREAM_STOP_VIDEO         701
+#define UPSTREAM_START_AUDIO        702
+#define UPSTREAM_STOP_AUDIO         703
+#define UPSTREAM_DUMP_REGISTERS     702
+#define SET_VIDEO_STD               800
+#define SET_PIXEL_FORMAT            1000
+#define ENABLE_CIF_RESOLUTION       1001
+
+#define REG_READ                   900
+#define REG_WRITE                  901
+#define MEDUSA_READ                910
+#define MEDUSA_WRITE               911
+
+extern struct sram_channel *channel0;
+extern struct sram_channel *channel1;
+extern struct sram_channel *channel2;
+extern struct sram_channel *channel3;
+extern struct sram_channel *channel4;
+extern struct sram_channel *channel5;
+extern struct sram_channel *channel6;
+extern struct sram_channel *channel7;
+extern struct sram_channel *channel9;
+extern struct sram_channel *channel10;
+extern struct sram_channel *channel11;
+extern struct video_device cx25821_videoioctl_template;
+/* extern const u32 *ctrl_classes[]; */
+
+extern unsigned int vid_limit;
+
+#define FORMAT_FLAGS_PACKED       0x01
+extern struct cx25821_fmt formats[];
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+extern void cx25821_video_wakeup(struct cx25821_dev *dev,
+                                struct cx25821_dmaqueue *q, u32 count);
+
+#ifdef TUNER_FLAG
+extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
+#endif
+
+extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+                          unsigned int bit);
+extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit);
+extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit);
+extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+                            unsigned int bits);
+extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+                                  struct cx25821_dmaqueue *q,
+                                  struct cx25821_buffer *buf,
+                                  struct sram_channel *channel);
+
+extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width,
+                            unsigned int height, enum v4l2_field field);
+extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
+extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
+extern int cx25821_video_register(struct cx25821_dev *dev);
+extern int cx25821_get_format_size(void);
+
+extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+                               unsigned int *size);
+extern int cx25821_buffer_prepare(struct videobuf_queue *q,
+                                 struct videobuf_buffer *vb,
+                                 enum v4l2_field field);
+extern void cx25821_buffer_release(struct videobuf_queue *q,
+                                  struct videobuf_buffer *vb);
+extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
+extern int cx25821_get_resource(struct cx25821_fh *fh, int resource);
+extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma);
+extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                         struct v4l2_format *f);
+extern int cx25821_vidioc_querycap(struct file *file, void *priv,
+                                  struct v4l2_capability *cap);
+extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                          struct v4l2_fmtdesc *f);
+extern int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+                                 struct v4l2_requestbuffers *p);
+extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
+                                  struct v4l2_buffer *p);
+extern int cx25821_vidioc_qbuf(struct file *file, void *priv,
+                              struct v4l2_buffer *p);
+extern int cx25821_vidioc_s_std(struct file *file, void *priv,
+                               v4l2_std_id *tvnorms);
+extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
+extern int cx25821_vidioc_enum_input(struct file *file, void *priv,
+                                    struct v4l2_input *i);
+extern int cx25821_vidioc_g_input(struct file *file, void *priv,
+                                 unsigned int *i);
+extern int cx25821_vidioc_s_input(struct file *file, void *priv,
+                                 unsigned int i);
+extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+                                struct v4l2_control *ctl);
+extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f);
+extern int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+                                     struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+                                     struct v4l2_frequency *f);
+extern int cx25821_vidioc_g_register(struct file *file, void *fh,
+                                    struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_s_register(struct file *file, void *fh,
+                                    struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_g_tuner(struct file *file, void *priv,
+                                 struct v4l2_tuner *t);
+extern int cx25821_vidioc_s_tuner(struct file *file, void *priv,
+                                 struct v4l2_tuner *t);
+
+extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm);
+extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm);
+
+extern int cx25821_vidioc_g_priority(struct file *file, void *f,
+                                    enum v4l2_priority *p);
+extern int cx25821_vidioc_s_priority(struct file *file, void *f,
+                                    enum v4l2_priority prio);
+
+extern int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+                                   struct v4l2_queryctrl *qctrl);
+extern int cx25821_set_control(struct cx25821_dev *dev,
+                              struct v4l2_control *ctrl, int chan_num);
+
+extern int cx25821_vidioc_cropcap(struct file *file, void *fh,
+                                 struct v4l2_cropcap *cropcap);
+extern int cx25821_vidioc_s_crop(struct file *file, void *priv,
+                                struct v4l2_crop *crop);
+extern int cx25821_vidioc_g_crop(struct file *file, void *priv,
+                                struct v4l2_crop *crop);
+
+extern int cx25821_vidioc_querystd(struct file *file, void *priv,
+                                  v4l2_std_id *norm);
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
new file mode 100644 (file)
index 0000000..8a9c0c8
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  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 CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+
+#include "btcx-risc.h"
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+#include "media/cx2341x.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#define TRUE    1
+#define FALSE   0
+#define LINE_SIZE_D1    1440
+
+/* Number of decoders and encoders */
+#define MAX_DECODERS            8
+#define MAX_ENCODERS            2
+#define QUAD_DECODERS           4
+#define MAX_CAMERAS             16
+
+/* Max number of inputs by card */
+#define MAX_CX25821_INPUT     8
+#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
+#define RESOURCE_VIDEO0       1
+#define RESOURCE_VIDEO1       2
+#define RESOURCE_VIDEO2       4
+#define RESOURCE_VIDEO3       8
+#define RESOURCE_VIDEO4       16
+#define RESOURCE_VIDEO5       32
+#define RESOURCE_VIDEO6       64
+#define RESOURCE_VIDEO7       128
+#define RESOURCE_VIDEO8       256
+#define RESOURCE_VIDEO9       512
+#define RESOURCE_VIDEO10      1024
+#define RESOURCE_VIDEO11      2048
+#define RESOURCE_VIDEO_IOCTL  4096
+
+#define BUFFER_TIMEOUT     (HZ)        /* 0.5 seconds */
+
+#define UNKNOWN_BOARD        0
+#define CX25821_BOARD        1
+
+/* Currently supported by the driver */
+#define CX25821_NORMS (\
+       V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
+       V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+       V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_H    | \
+       V4L2_STD_PAL_Nc)
+
+#define CX25821_BOARD_CONEXANT_ATHENA10 1
+#define MAX_VID_CHANNEL_NUM     12
+#define VID_CHANNEL_NUM 8
+#define CX25821_NR_INPUT 2
+
+struct cx25821_fmt {
+       char *name;
+       u32 fourcc;             /* v4l2 format id */
+       int depth;
+       int flags;
+       u32 cxformat;
+};
+
+struct cx25821_ctrl {
+       struct v4l2_queryctrl v;
+       u32 off;
+       u32 reg;
+       u32 mask;
+       u32 shift;
+};
+
+struct cx25821_tvnorm {
+       char *name;
+       v4l2_std_id id;
+       u32 cxiformat;
+       u32 cxoformat;
+};
+
+struct cx25821_fh {
+       struct cx25821_dev *dev;
+       enum v4l2_buf_type type;
+       int radio;
+       u32 resources;
+
+       enum v4l2_priority prio;
+
+       /* video overlay */
+       struct v4l2_window win;
+       struct v4l2_clip *clips;
+       unsigned int nclips;
+
+       /* video capture */
+       struct cx25821_fmt *fmt;
+       unsigned int width, height;
+       int channel_id;
+
+       /* vbi capture */
+       struct videobuf_queue vidq;
+       struct videobuf_queue vbiq;
+
+       /* H264 Encoder specifics ONLY */
+       struct videobuf_queue mpegq;
+       atomic_t v4l_reading;
+};
+
+enum cx25821_itype {
+       CX25821_VMUX_COMPOSITE = 1,
+       CX25821_VMUX_SVIDEO,
+       CX25821_VMUX_DEBUG,
+       CX25821_RADIO,
+};
+
+enum cx25821_src_sel_type {
+       CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+       CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       /* cx25821 specific */
+       unsigned int bpl;
+       struct btcx_riscmem risc;
+       struct cx25821_fmt *fmt;
+       u32 count;
+};
+
+struct cx25821_input {
+       enum cx25821_itype type;
+       unsigned int vmux;
+       u32 gpio0, gpio1, gpio2, gpio3;
+};
+
+enum port {
+       CX25821_UNDEFINED = 0,
+       CX25821_RAW,
+       CX25821_264
+};
+
+struct cx25821_board {
+       const char *name;
+       enum port porta;
+       enum port portb;
+       enum port portc;
+       unsigned int tuner_type;
+       unsigned int radio_type;
+       unsigned char tuner_addr;
+       unsigned char radio_addr;
+
+       u32 clk_freq;
+       struct cx25821_input input[CX25821_NR_INPUT];
+};
+
+struct cx25821_subid {
+       u16 subvendor;
+       u16 subdevice;
+       u32 card;
+};
+
+struct cx25821_i2c {
+       struct cx25821_dev *dev;
+
+       int nr;
+
+       /* i2c i/o */
+       struct i2c_adapter i2c_adap;
+       struct i2c_client i2c_client;
+       u32 i2c_rc;
+
+       /* cx25821 registers used for raw addess */
+       u32 i2c_period;
+       u32 reg_ctrl;
+       u32 reg_stat;
+       u32 reg_addr;
+       u32 reg_rdata;
+       u32 reg_wdata;
+};
+
+struct cx25821_dmaqueue {
+       struct list_head active;
+       struct list_head queued;
+       struct timer_list timeout;
+       struct btcx_riscmem stopper;
+       u32 count;
+};
+
+struct cx25821_data {
+       struct cx25821_dev *dev;
+       struct sram_channel *channel;
+};
+
+struct cx25821_channel {
+       struct v4l2_prio_state prio;
+
+       int ctl_bright;
+       int ctl_contrast;
+       int ctl_hue;
+       int ctl_saturation;
+       struct cx25821_data timeout_data;
+
+       struct video_device *video_dev;
+       struct cx25821_dmaqueue vidq;
+
+       struct sram_channel *sram_channels;
+
+       struct mutex lock;
+       int resources;
+
+       int pixel_formats;
+       int use_cif_resolution;
+       int cif_width;
+};
+
+struct cx25821_dev {
+       struct list_head devlist;
+       atomic_t refcount;
+       struct v4l2_device v4l2_dev;
+
+       /* pci stuff */
+       struct pci_dev *pci;
+       unsigned char pci_rev, pci_lat;
+       int pci_bus, pci_slot;
+       u32 base_io_addr;
+       u32 __iomem *lmmio;
+       u8 __iomem *bmmio;
+       int pci_irqmask;
+       int hwrevision;
+
+       u32 clk_freq;
+
+       /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+       struct cx25821_i2c i2c_bus[3];
+
+       int nr;
+       struct mutex lock;
+
+       struct cx25821_channel channels[MAX_VID_CHANNEL_NUM];
+
+       /* board details */
+       unsigned int board;
+       char name[32];
+
+       /* Analog video */
+       u32 resources;
+       unsigned int input;
+       u32 tvaudio;
+       v4l2_std_id tvnorm;
+       unsigned int tuner_type;
+       unsigned char tuner_addr;
+       unsigned int radio_type;
+       unsigned char radio_addr;
+       unsigned int has_radio;
+       unsigned int videc_type;
+       unsigned char videc_addr;
+       unsigned short _max_num_decoders;
+
+       /* Analog Audio Upstream */
+       int _audio_is_running;
+       int _audiopixel_format;
+       int _is_first_audio_frame;
+       int _audiofile_status;
+       int _audio_lines_count;
+       int _audioframe_count;
+       int _audio_upstream_channel;
+       int _last_index_irq;    /* The last interrupt index processed. */
+
+       __le32 *_risc_audio_jmp_addr;
+       __le32 *_risc_virt_start_addr;
+       __le32 *_risc_virt_addr;
+       dma_addr_t _risc_phys_addr;
+       dma_addr_t _risc_phys_start_addr;
+
+       unsigned int _audiorisc_size;
+       unsigned int _audiodata_buf_size;
+       __le32 *_audiodata_buf_virt_addr;
+       dma_addr_t _audiodata_buf_phys_addr;
+       char *_audiofilename;
+
+       /* V4l */
+       u32 freq;
+       struct video_device *vbi_dev;
+       struct video_device *radio_dev;
+       struct video_device *ioctl_dev;
+
+       spinlock_t slock;
+
+       /* Video Upstream */
+       int _line_size;
+       int _prog_cnt;
+       int _pixel_format;
+       int _is_first_frame;
+       int _is_running;
+       int _file_status;
+       int _lines_count;
+       int _frame_count;
+       int _channel_upstream_select;
+       unsigned int _risc_size;
+
+       __le32 *_dma_virt_start_addr;
+       __le32 *_dma_virt_addr;
+       dma_addr_t _dma_phys_addr;
+       dma_addr_t _dma_phys_start_addr;
+
+       unsigned int _data_buf_size;
+       __le32 *_data_buf_virt_addr;
+       dma_addr_t _data_buf_phys_addr;
+       char *_filename;
+       char *_defaultname;
+
+       int _line_size_ch2;
+       int _prog_cnt_ch2;
+       int _pixel_format_ch2;
+       int _is_first_frame_ch2;
+       int _is_running_ch2;
+       int _file_status_ch2;
+       int _lines_count_ch2;
+       int _frame_count_ch2;
+       int _channel2_upstream_select;
+       unsigned int _risc_size_ch2;
+
+       __le32 *_dma_virt_start_addr_ch2;
+       __le32 *_dma_virt_addr_ch2;
+       dma_addr_t _dma_phys_addr_ch2;
+       dma_addr_t _dma_phys_start_addr_ch2;
+
+       unsigned int _data_buf_size_ch2;
+       __le32 *_data_buf_virt_addr_ch2;
+       dma_addr_t _data_buf_phys_addr_ch2;
+       char *_filename_ch2;
+       char *_defaultname_ch2;
+
+       /* MPEG Encoder ONLY settings */
+       u32 cx23417_mailbox;
+       struct cx2341x_mpeg_params mpeg_params;
+       struct video_device *v4l_device;
+       atomic_t v4l_reader_count;
+       struct cx25821_tvnorm encodernorm;
+
+       u32 upstream_riscbuf_size;
+       u32 upstream_databuf_size;
+       u32 upstream_riscbuf_size_ch2;
+       u32 upstream_databuf_size_ch2;
+       u32 audio_upstream_riscbuf_size;
+       u32 audio_upstream_databuf_size;
+       int _isNTSC;
+       int _frame_index;
+       int _audioframe_index;
+       struct workqueue_struct *_irq_queues;
+       struct work_struct _irq_work_entry;
+       struct workqueue_struct *_irq_queues_ch2;
+       struct work_struct _irq_work_entry_ch2;
+       struct workqueue_struct *_irq_audio_queues;
+       struct work_struct _audio_work_entry;
+       char *input_filename;
+       char *input_filename_ch2;
+       int _frame_index_ch2;
+       int _isNTSC_ch2;
+       char *vid_stdname_ch2;
+       int pixel_format_ch2;
+       int channel_select_ch2;
+       int command_ch2;
+       char *input_audiofilename;
+       char *vid_stdname;
+       int pixel_format;
+       int channel_select;
+       int command;
+       int channel_opened;
+};
+
+struct upstream_user_struct {
+       char *input_filename;
+       char *vid_stdname;
+       int pixel_format;
+       int channel_select;
+       int command;
+};
+
+struct downstream_user_struct {
+       char *vid_stdname;
+       int pixel_format;
+       int cif_resolution_enable;
+       int cif_width;
+       int decoder_select;
+       int command;
+       int reg_address;
+       int reg_data;
+};
+
+extern struct upstream_user_struct *up_data;
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+#define cx25821_call_all(dev, o, f, args...) \
+       v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
+extern struct list_head cx25821_devlist;
+extern struct mutex cx25821_devlist_mutex;
+
+extern struct cx25821_board cx25821_boards[];
+extern struct cx25821_subid cx25821_subids[];
+
+#define SRAM_CH00  0           /* Video A */
+#define SRAM_CH01  1           /* Video B */
+#define SRAM_CH02  2           /* Video C */
+#define SRAM_CH03  3           /* Video D */
+#define SRAM_CH04  4           /* Video E */
+#define SRAM_CH05  5           /* Video F */
+#define SRAM_CH06  6           /* Video G */
+#define SRAM_CH07  7           /* Video H */
+
+#define SRAM_CH08  8           /* Audio A */
+#define SRAM_CH09  9           /* Video Upstream I */
+#define SRAM_CH10  10          /* Video Upstream J */
+#define SRAM_CH11  11          /* Audio Upstream AUD_CHANNEL_B */
+
+#define VID_UPSTREAM_SRAM_CHANNEL_I     SRAM_CH09
+#define VID_UPSTREAM_SRAM_CHANNEL_J     SRAM_CH10
+#define AUDIO_UPSTREAM_SRAM_CHANNEL_B   SRAM_CH11
+#define VIDEO_IOCTL_CH  11
+
+struct sram_channel {
+       char *name;
+       u32 i;
+       u32 cmds_start;
+       u32 ctrl_start;
+       u32 cdt;
+       u32 fifo_start;
+       u32 fifo_size;
+       u32 ptr1_reg;
+       u32 ptr2_reg;
+       u32 cnt1_reg;
+       u32 cnt2_reg;
+       u32 int_msk;
+       u32 int_stat;
+       u32 int_mstat;
+       u32 dma_ctl;
+       u32 gpcnt_ctl;
+       u32 gpcnt;
+       u32 aud_length;
+       u32 aud_cfg;
+       u32 fld_aud_fifo_en;
+       u32 fld_aud_risc_en;
+
+       /* For Upstream Video */
+       u32 vid_fmt_ctl;
+       u32 vid_active_ctl1;
+       u32 vid_active_ctl2;
+       u32 vid_cdt_size;
+
+       u32 vip_ctl;
+       u32 pix_frmt;
+       u32 jumponly;
+       u32 irq_bit;
+};
+extern struct sram_channel cx25821_sram_channels[];
+
+#define STATUS_SUCCESS         0
+#define STATUS_UNSUCCESSFUL    -1
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+       writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+       ((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+#define Set_GPIO_Bit(Bit)                       (1 << Bit)
+#define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
+
+#define CX25821_ERR(fmt, args...)                      \
+       pr_err("(%d): " fmt, dev->board, ##args)
+#define CX25821_WARN(fmt, args...)                     \
+       pr_warn("(%d): " fmt, dev->board, ##args)
+#define CX25821_INFO(fmt, args...)                     \
+       pr_info("(%d): " fmt, dev->board, ##args)
+
+extern int cx25821_i2c_register(struct cx25821_i2c *bus);
+extern void cx25821_card_setup(struct cx25821_dev *dev);
+extern int cx25821_ir_init(struct cx25821_dev *dev);
+extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
+extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
+extern int cx25821_i2c_unregister(struct cx25821_i2c *bus);
+extern void cx25821_gpio_init(struct cx25821_dev *dev);
+extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+                                         int pin_number, int pin_logic_value);
+
+extern int medusa_video_init(struct cx25821_dev *dev);
+extern int medusa_set_videostandard(struct cx25821_dev *dev);
+extern void medusa_set_resolution(struct cx25821_dev *dev, int width,
+                                 int decoder_select);
+extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness,
+                                int decoder);
+extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast,
+                              int decoder);
+extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
+extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation,
+                                int decoder);
+
+extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+                                     struct sram_channel *ch, unsigned int bpl,
+                                     u32 risc);
+
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                              struct scatterlist *sglist,
+                              unsigned int top_offset,
+                              unsigned int bottom_offset,
+                              unsigned int bpl,
+                              unsigned int padding, unsigned int lines);
+extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+                                        struct btcx_riscmem *risc,
+                                        struct scatterlist *sglist,
+                                        unsigned int bpl,
+                                        unsigned int lines, unsigned int lpi);
+extern void cx25821_free_buffer(struct videobuf_queue *q,
+                               struct cx25821_buffer *buf);
+extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+                               u32 reg, u32 mask, u32 value);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
+                                     struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+                                           struct sram_channel *ch);
+
+extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci);
+extern void cx25821_print_irqbits(char *name, char *tag, char **strings,
+                                 int len, u32 bits, u32 mask);
+extern void cx25821_dev_unregister(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+                                           struct sram_channel *ch,
+                                           unsigned int bpl, u32 risc);
+
+extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev,
+                                       int channel_select, int pixel_format);
+extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev,
+                                       int channel_select, int pixel_format);
+extern int cx25821_audio_upstream_init(struct cx25821_dev *dev,
+                                      int channel_select);
+extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);
+extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+                                            struct upstream_user_struct
+                                            *up_data);
+extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+                                            struct upstream_user_struct
+                                            *up_data);
+extern void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+                                        struct upstream_user_struct *up_data);
+extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+                                              struct sram_channel *ch,
+                                              unsigned int bpl, u32 risc);
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
+                                    u32 format);
+extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
+extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+                                             struct pci_dev *pci,
+                                             struct video_device *template,
+                                             char *type);
+#endif
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
new file mode 100644 (file)
index 0000000..3598dc0
--- /dev/null
@@ -0,0 +1,86 @@
+config VIDEO_CX88
+       tristate "Conexant 2388x (bt878 successor) support"
+       depends on VIDEO_DEV && PCI && I2C && RC_CORE
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEOBUF_DMA_SG
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
+       ---help---
+         This is a video4linux driver for Conexant 2388x based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx8800
+
+config VIDEO_CX88_ALSA
+       tristate "Conexant 2388x DMA audio support"
+       depends on VIDEO_CX88 && SND
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio on
+         Conexant 2388x based TV cards using ALSA.
+
+         It only works with boards with function 01 enabled.
+         To check if your board supports, use lspci -n.
+         If supported, you should see 14f1:8801 or 14f1:8811
+         PCI device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx88-alsa.
+
+config VIDEO_CX88_BLACKBIRD
+       tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
+       depends on VIDEO_CX88
+       select VIDEO_CX2341X
+       ---help---
+         This adds support for MPEG encoder cards based on the
+         Blackbird reference design, using the Conexant 2388x
+         and 23416 chips.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx88-blackbird.
+
+config VIDEO_CX88_DVB
+       tristate "DVB/ATSC Support for cx2388x based TV cards"
+       depends on VIDEO_CX88 && DVB_CORE
+       select VIDEOBUF_DVB
+       select DVB_PLL if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_OR51132 if !DVB_FE_CUSTOMISE
+       select DVB_CX22702 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_NXT200X if !DVB_FE_CUSTOMISE
+       select DVB_CX24123 if !DVB_FE_CUSTOMISE
+       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+       select DVB_CX24116 if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_STV0288 if !DVB_FE_CUSTOMISE
+       select DVB_STB6000 if !DVB_FE_CUSTOMISE
+       select DVB_STV0900 if !DVB_FE_CUSTOMISE
+       select DVB_STB6100 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+       ---help---
+         This adds support for DVB/ATSC cards based on the
+         Conexant 2388x chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx88-dvb.
+
+config VIDEO_CX88_VP3054
+       tristate "VP-3054 Secondary I2C Bus Support"
+       default m
+       depends on VIDEO_CX88_DVB && DVB_MT352
+       ---help---
+         This adds DVB-T support for cards based on the
+         Conexant 2388x chip and the MT352 demodulator,
+         which also require support for the VP-3054
+         Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
+config VIDEO_CX88_MPEG
+       tristate
+       depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
+       default y
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile
new file mode 100644 (file)
index 0000000..884b4cd
--- /dev/null
@@ -0,0 +1,16 @@
+cx88xx-objs    := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
+                  cx88-dsp.o cx88-input.o
+cx8800-objs    := cx88-video.o cx88-vbi.o
+cx8802-objs    := cx88-mpeg.o
+
+obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o
+obj-$(CONFIG_VIDEO_CX88_MPEG) += cx8802.o
+obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
+obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
+
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
new file mode 100644 (file)
index 0000000..3aa6856
--- /dev/null
@@ -0,0 +1,975 @@
+/*
+ *
+ *  Support for audio capture
+ *  PCI function #1 of the cx2388x.
+ *
+ *    (c) 2007 Trent Piepho <xyzzy@speakeasy.org>
+ *    (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
+ *    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *    Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
+ *    Based on dummy.c by Jaroslav Kysela <perex@perex.cz>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  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/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <media/wm8775.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define dprintk(level,fmt, arg...)     if (debug >= level) \
+       printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
+
+#define dprintk_core(level,fmt, arg...)        if (debug >= level) \
+       printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
+
+/****************************************************************************
+       Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+struct cx88_audio_buffer {
+       unsigned int               bpl;
+       struct btcx_riscmem        risc;
+       struct videobuf_dmabuf     dma;
+};
+
+struct cx88_audio_dev {
+       struct cx88_core           *core;
+       struct cx88_dmaqueue       q;
+
+       /* pci i/o */
+       struct pci_dev             *pci;
+
+       /* audio controls */
+       int                        irq;
+
+       struct snd_card            *card;
+
+       spinlock_t                 reg_lock;
+       atomic_t                   count;
+
+       unsigned int               dma_size;
+       unsigned int               period_size;
+       unsigned int               num_periods;
+
+       struct videobuf_dmabuf     *dma_risc;
+
+       struct cx88_audio_buffer   *buf;
+
+       struct snd_pcm_substream   *substream;
+};
+typedef struct cx88_audio_dev snd_cx88_card_t;
+
+
+
+/****************************************************************************
+                       Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;        /* ID for this card */
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
+
+
+/****************************************************************************
+                               Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Ricardo Cerqueira");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
+                       "{{Conexant,23882},"
+                       "{{Conexant,23883}");
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages");
+
+/****************************************************************************
+                       Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+{
+       struct cx88_audio_buffer *buf = chip->buf;
+       struct cx88_core *core=chip->core;
+       const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
+
+       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+       cx_clear(MO_AUD_DMACNTRL, 0x11);
+
+       /* setup fifo + format - out channel */
+       cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma);
+
+       /* sets bpl size */
+       cx_write(MO_AUDD_LNGTH, buf->bpl);
+
+       /* reset counter */
+       cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
+       atomic_set(&chip->count, 0);
+
+       dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+               "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1,
+               chip->num_periods, buf->bpl * chip->num_periods);
+
+       /* Enables corresponding bits at AUD_INT_STAT */
+       cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+                               AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+       /* Clean any pending interrupt bits already set */
+       cx_write(MO_AUD_INTSTAT, ~0);
+
+       /* enable audio irqs */
+       cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
+
+       /* start dma */
+       cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+       cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
+
+       if (debug)
+               cx88_sram_channel_dump(chip->core, audio_ch);
+
+       return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+{
+       struct cx88_core *core=chip->core;
+       dprintk(1, "Stopping audio DMA\n");
+
+       /* stop dma */
+       cx_clear(MO_AUD_DMACNTRL, 0x11);
+
+       /* disable irqs */
+       cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
+       cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+                               AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+       if (debug)
+               cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+
+       return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static const char *cx88_aud_irqs[32] = {
+       "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
+       NULL,                                     /* reserved */
+       "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
+       NULL,                                     /* reserved */
+       "dnf_of", "upf_uf", "rds_dnf_uf",         /* 8-10 */
+       NULL,                                     /* reserved */
+       "dn_sync", "up_sync", "rds_dn_sync",      /* 12-14 */
+       NULL,                                     /* reserved */
+       "opc_err", "par_err", "rip_err",          /* 16-18 */
+       "pci_abort", "ber_irq", "mchg_irq"        /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx8801_aud_irq(snd_cx88_card_t *chip)
+{
+       struct cx88_core *core = chip->core;
+       u32 status, mask;
+
+       status = cx_read(MO_AUD_INTSTAT);
+       mask   = cx_read(MO_AUD_INTMSK);
+       if (0 == (status & mask))
+               return;
+       cx_write(MO_AUD_INTSTAT, status);
+       if (debug > 1  ||  (status & mask & ~0xff))
+               cx88_print_irqbits(core->name, "irq aud",
+                                  cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
+                                  status, mask);
+       /* risc op code error */
+       if (status & AUD_INT_OPC_ERR) {
+               printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name);
+               cx_clear(MO_AUD_DMACNTRL, 0x11);
+               cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
+       }
+       if (status & AUD_INT_DN_SYNC) {
+               dprintk(1, "Downstream sync error\n");
+               cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
+               return;
+       }
+       /* risc1 downstream */
+       if (status & AUD_INT_DN_RISCI1) {
+               atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT));
+               snd_pcm_period_elapsed(chip->substream);
+       }
+       /* FIXME: Any other status should deserve a special handling? */
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx8801_irq(int irq, void *dev_id)
+{
+       snd_cx88_card_t *chip = dev_id;
+       struct cx88_core *core = chip->core;
+       u32 status;
+       int loop, handled = 0;
+
+       for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
+               status = cx_read(MO_PCI_INTSTAT) &
+                       (core->pci_irqmask | PCI_INT_AUDINT);
+               if (0 == status)
+                       goto out;
+               dprintk(3, "cx8801_irq loop %d/%d, status %x\n",
+                       loop, MAX_IRQ_LOOP, status);
+               handled = 1;
+               cx_write(MO_PCI_INTSTAT, status);
+
+               if (status & core->pci_irqmask)
+                       cx88_core_irq(core, status);
+               if (status & PCI_INT_AUDINT)
+                       cx8801_aud_irq(chip);
+       }
+
+       if (MAX_IRQ_LOOP == loop) {
+               printk(KERN_ERR
+                      "%s/1: IRQ loop detected, disabling interrupts\n",
+                      core->name);
+               cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
+       }
+
+ out:
+       return IRQ_RETVAL(handled);
+}
+
+
+static int dsp_buffer_free(snd_cx88_card_t *chip)
+{
+       BUG_ON(!chip->dma_size);
+
+       dprintk(2,"Freeing buffer\n");
+       videobuf_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);
+
+       chip->dma_risc = NULL;
+       chip->dma_size = 0;
+
+       return 0;
+}
+
+/****************************************************************************
+                               ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE      4096
+static const struct snd_pcm_hardware snd_cx88_digital_hw = {
+       .info = SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates =                SNDRV_PCM_RATE_48000,
+       .rate_min =             48000,
+       .rate_max =             48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       /* Analog audio output will be full of clicks and pops if there
+          are not exactly four lines in the SRAM FIFO buffer.  */
+       .period_bytes_min = DEFAULT_FIFO_SIZE/4,
+       .period_bytes_max = DEFAULT_FIFO_SIZE/4,
+       .periods_min = 1,
+       .periods_max = 1024,
+       .buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
+{
+       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
+
+       if (!chip) {
+               printk(KERN_ERR "BUG: cx88 can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               goto _error;
+
+       chip->substream = substream;
+
+       runtime->hw = snd_cx88_digital_hw;
+
+       if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) {
+               unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
+               bpl &= ~7; /* must be multiple of 8 */
+               runtime->hw.period_bytes_min = bpl;
+               runtime->hw.period_bytes_max = bpl;
+       }
+
+       return 0;
+_error:
+       dprintk(1,"Error opening PCM!\n");
+       return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx88_close(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
+                             struct snd_pcm_hw_params * hw_params)
+{
+       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+       struct videobuf_dmabuf *dma;
+
+       struct cx88_audio_buffer *buf;
+       int ret;
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       chip->period_size = params_period_bytes(hw_params);
+       chip->num_periods = params_periods(hw_params);
+       chip->dma_size = chip->period_size * params_periods(hw_params);
+
+       BUG_ON(!chip->dma_size);
+       BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+       if (NULL == buf)
+               return -ENOMEM;
+
+       buf->bpl = chip->period_size;
+
+       dma = &buf->dma;
+       videobuf_dma_init(dma);
+       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+       if (ret < 0)
+               goto error;
+
+       ret = videobuf_dma_map(&chip->pci->dev, dma);
+       if (ret < 0)
+               goto error;
+
+       ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+                                  chip->period_size, chip->num_periods, 1);
+       if (ret < 0)
+               goto error;
+
+       /* Loop back to start of program */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+       chip->buf = buf;
+       chip->dma_risc = dma;
+
+       substream->runtime->dma_area = chip->dma_risc->vaddr;
+       substream->runtime->dma_bytes = chip->dma_size;
+       substream->runtime->dma_addr = 0;
+       return 0;
+
+error:
+       kfree(buf);
+       return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx88_hw_free(struct snd_pcm_substream * substream)
+{
+
+       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+
+       if (substream->runtime->dma_area) {
+               dsp_buffer_free(chip);
+               substream->runtime->dma_area = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx88_prepare(struct snd_pcm_substream *substream)
+{
+       return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+       int err;
+
+       /* Local interrupts are already disabled by ALSA */
+       spin_lock(&chip->reg_lock);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               err=_cx88_start_audio_dma(chip);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               err=_cx88_stop_audio_dma(chip);
+               break;
+       default:
+               err=-EINVAL;
+               break;
+       }
+
+       spin_unlock(&chip->reg_lock);
+
+       return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
+{
+       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       u16 count;
+
+       count = atomic_read(&chip->count);
+
+//     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));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx88_page(struct snd_pcm_substream *substream,
+                               unsigned long offset)
+{
+       void *pageptr = substream->runtime->dma_area + offset;
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx88_pcm_ops = {
+       .open = snd_cx88_pcm_open,
+       .close = snd_cx88_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_cx88_hw_params,
+       .hw_free = snd_cx88_hw_free,
+       .prepare = snd_cx88_prepare,
+       .trigger = snd_cx88_card_trigger,
+       .pointer = snd_cx88_pointer,
+       .page = snd_cx88_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
+{
+       int err;
+       struct snd_pcm *pcm;
+
+       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+       if (err < 0)
+               return err;
+       pcm->private_data = chip;
+       strcpy(pcm->name, name);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);
+
+       return 0;
+}
+
+/****************************************************************************
+                               CONTROL INTERFACE
+ ****************************************************************************/
+static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *info)
+{
+       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       info->count = 2;
+       info->value.integer.min = 0;
+       info->value.integer.max = 0x3f;
+
+       return 0;
+}
+
+static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core=chip->core;
+       int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
+           bal = cx_read(AUD_BAL_CTL);
+
+       value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol;
+       vol -= (bal & 0x3f);
+       value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol;
+
+       return 0;
+}
+
+static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core = chip->core;
+       int left = value->value.integer.value[0];
+       int right = value->value.integer.value[1];
+       int v, b;
+
+       /* Pass volume & balance onto any WM8775 */
+       if (left >= right) {
+               v = left << 10;
+               b = left ? (0x8000 * right) / left : 0x8000;
+       } else {
+               v = right << 10;
+               b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
+       }
+       wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
+       wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
+}
+
+/* OK - TODO: test it */
+static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core=chip->core;
+       int left, right, v, b;
+       int changed = 0;
+       u32 old;
+
+       if (core->board.audio_chip == V4L2_IDENT_WM8775)
+               snd_cx88_wm8775_volume_put(kcontrol, value);
+
+       left = value->value.integer.value[0] & 0x3f;
+       right = value->value.integer.value[1] & 0x3f;
+       b = right - left;
+       if (b < 0) {
+               v = 0x3f - left;
+               b = (-b) | 0x40;
+       } else {
+               v = 0x3f - right;
+       }
+       /* Do we really know this will always be called with IRQs on? */
+       spin_lock_irq(&chip->reg_lock);
+       old = cx_read(AUD_VOL_CTL);
+       if (v != (old & 0x3f)) {
+               cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
+               changed = 1;
+       }
+       if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
+               cx_write(AUD_BAL_CTL, b);
+               changed = 1;
+       }
+       spin_unlock_irq(&chip->reg_lock);
+
+       return changed;
+}
+
+static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
+
+static const struct snd_kcontrol_new snd_cx88_volume = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+       .name = "Analog-TV Volume",
+       .info = snd_cx88_volume_info,
+       .get = snd_cx88_volume_get,
+       .put = snd_cx88_volume_put,
+       .tlv.p = snd_cx88_db_scale,
+};
+
+static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core = chip->core;
+       u32 bit = kcontrol->private_value;
+
+       value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit);
+       return 0;
+}
+
+static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core = chip->core;
+       u32 bit = kcontrol->private_value;
+       int ret = 0;
+       u32 vol;
+
+       spin_lock_irq(&chip->reg_lock);
+       vol = cx_read(AUD_VOL_CTL);
+       if (value->value.integer.value[0] != !(vol & bit)) {
+               vol ^= bit;
+               cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
+               /* Pass mute onto any WM8775 */
+               if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
+                   ((1<<6) == bit))
+                       wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
+               ret = 1;
+       }
+       spin_unlock_irq(&chip->reg_lock);
+       return ret;
+}
+
+static const struct snd_kcontrol_new snd_cx88_dac_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Audio-Out Switch",
+       .info = snd_ctl_boolean_mono_info,
+       .get = snd_cx88_switch_get,
+       .put = snd_cx88_switch_put,
+       .private_value = (1<<8),
+};
+
+static const struct snd_kcontrol_new snd_cx88_source_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Analog-TV Switch",
+       .info = snd_ctl_boolean_mono_info,
+       .get = snd_cx88_switch_get,
+       .put = snd_cx88_switch_put,
+       .private_value = (1<<6),
+};
+
+static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core = chip->core;
+       s32 val;
+
+       val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
+       value->value.integer.value[0] = val ? 1 : 0;
+       return 0;
+}
+
+static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
+                                      struct snd_ctl_elem_value *value)
+{
+       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+       struct cx88_core *core = chip->core;
+       struct v4l2_control client_ctl;
+
+       memset(&client_ctl, 0, sizeof(client_ctl));
+       client_ctl.value = 0 != value->value.integer.value[0];
+       client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
+       call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+
+       return 0;
+}
+
+static struct snd_kcontrol_new snd_cx88_alc_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Line-In ALC Switch",
+       .info = snd_ctl_boolean_mono_info,
+       .get = snd_cx88_alc_get,
+       .put = snd_cx88_alc_put,
+};
+
+/****************************************************************************
+                       Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
+       {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+       {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+       {0, }
+};
+MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
+
+/*
+ * Chip-specific destructor
+ */
+
+static int snd_cx88_free(snd_cx88_card_t *chip)
+{
+
+       if (chip->irq >= 0)
+               free_irq(chip->irq, chip);
+
+       cx88_core_put(chip->core,chip->pci);
+
+       pci_disable_device(chip->pci);
+       return 0;
+}
+
+/*
+ * Component Destructor
+ */
+static void snd_cx88_dev_free(struct snd_card * card)
+{
+       snd_cx88_card_t *chip = card->private_data;
+
+       snd_cx88_free(chip);
+}
+
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+static int devno;
+static int __devinit snd_cx88_create(struct snd_card *card,
+                                    struct pci_dev *pci,
+                                    snd_cx88_card_t **rchip,
+                                    struct cx88_core **core_ptr)
+{
+       snd_cx88_card_t   *chip;
+       struct cx88_core  *core;
+       int               err;
+       unsigned char     pci_lat;
+
+       *rchip = NULL;
+
+       err = pci_enable_device(pci);
+       if (err < 0)
+               return err;
+
+       pci_set_master(pci);
+
+       chip = card->private_data;
+
+       core = cx88_core_get(pci);
+       if (NULL == core) {
+               err = -EINVAL;
+               return err;
+       }
+
+       if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
+               dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
+               err = -EIO;
+               cx88_core_put(core, pci);
+               return err;
+       }
+
+
+       /* pci init */
+       chip->card = card;
+       chip->pci = pci;
+       chip->irq = -1;
+       spin_lock_init(&chip->reg_lock);
+
+       chip->core = core;
+
+       /* get irq */
+       err = request_irq(chip->pci->irq, cx8801_irq,
+                         IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip);
+       if (err < 0) {
+               dprintk(0, "%s: can't get IRQ %d\n",
+                      chip->core->name, chip->pci->irq);
+               return err;
+       }
+
+       /* print pci info */
+       pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat);
+
+       dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
+              "latency: %d, mmio: 0x%llx\n", core->name, devno,
+              pci_name(pci), pci->revision, pci->irq,
+              pci_lat, (unsigned long long)pci_resource_start(pci,0));
+
+       chip->irq = pci->irq;
+       synchronize_irq(chip->irq);
+
+       snd_card_set_dev(card, &pci->dev);
+
+       *rchip = chip;
+       *core_ptr = core;
+
+       return 0;
+}
+
+static int __devinit cx88_audio_initdev(struct pci_dev *pci,
+                                   const struct pci_device_id *pci_id)
+{
+       struct snd_card  *card;
+       snd_cx88_card_t  *chip;
+       struct cx88_core *core = NULL;
+       int              err;
+
+       if (devno >= SNDRV_CARDS)
+               return (-ENODEV);
+
+       if (!enable[devno]) {
+               ++devno;
+               return (-ENOENT);
+       }
+
+       err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+                             sizeof(snd_cx88_card_t), &card);
+       if (err < 0)
+               return err;
+
+       card->private_free = snd_cx88_dev_free;
+
+       err = snd_cx88_create(card, pci, &chip, &core);
+       if (err < 0)
+               goto error;
+
+       err = snd_cx88_pcm(chip, 0, "CX88 Digital");
+       if (err < 0)
+               goto error;
+
+       err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip));
+       if (err < 0)
+               goto error;
+       err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip));
+       if (err < 0)
+               goto error;
+       err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
+       if (err < 0)
+               goto error;
+
+       /* If there's a wm8775 then add a Line-In ALC switch */
+       if (core->board.audio_chip == V4L2_IDENT_WM8775)
+               snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
+
+       strcpy (card->driver, "CX88x");
+       sprintf(card->shortname, "Conexant CX%x", pci->device);
+       sprintf(card->longname, "%s at %#llx",
+               card->shortname,(unsigned long long)pci_resource_start(pci, 0));
+       strcpy (card->mixername, "CX88");
+
+       dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
+              card->driver,devno);
+
+       err = snd_card_register(card);
+       if (err < 0)
+               goto error;
+       pci_set_drvdata(pci,card);
+
+       devno++;
+       return 0;
+
+error:
+       snd_card_free(card);
+       return err;
+}
+/*
+ * ALSA destructor
+ */
+static void __devexit cx88_audio_finidev(struct pci_dev *pci)
+{
+       struct cx88_audio_dev *card = pci_get_drvdata(pci);
+
+       snd_card_free((void *)card);
+
+       pci_set_drvdata(pci, NULL);
+
+       devno--;
+}
+
+/*
+ * PCI driver definition
+ */
+
+static struct pci_driver cx88_audio_pci_driver = {
+       .name     = "cx88_audio",
+       .id_table = cx88_audio_pci_tbl,
+       .probe    = cx88_audio_initdev,
+       .remove   = __devexit_p(cx88_audio_finidev),
+};
+
+/****************************************************************************
+                               LINUX MODULE INIT
+ ****************************************************************************/
+
+/*
+ * module init
+ */
+static int __init cx88_audio_init(void)
+{
+       printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
+              CX88_VERSION);
+       return pci_register_driver(&cx88_audio_pci_driver);
+}
+
+/*
+ * module remove
+ */
+static void __exit cx88_audio_fini(void)
+{
+       pci_unregister_driver(&cx88_audio_pci_driver);
+}
+
+module_init(cx88_audio_init);
+module_exit(cx88_audio_fini);
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
new file mode 100644 (file)
index 0000000..843ffd9
--- /dev/null
@@ -0,0 +1,1299 @@
+/*
+ *
+ *  Support for a cx23416 mpeg encoder via cx2388x host port.
+ *  "blackbird" reference design.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *
+ *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *        - video_ioctl2 conversion
+ *
+ *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
+ *
+ *  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/slab.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/cx2341x.h>
+
+#include "cx88.h"
+
+MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
+MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+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;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
+
+#define dprintk(level,fmt, arg...)     if (debug >= level) \
+       printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
+
+
+/* ------------------------------------------------------------------ */
+
+#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
+
+/* defines below are from ivtv-driver.h */
+
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+enum blackbird_capture_type {
+       BLACKBIRD_MPEG_CAPTURE,
+       BLACKBIRD_RAW_CAPTURE,
+       BLACKBIRD_RAW_PASSTHRU_CAPTURE
+};
+enum blackbird_capture_bits {
+       BLACKBIRD_RAW_BITS_NONE             = 0x00,
+       BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
+       BLACKBIRD_RAW_BITS_PCM_CAPTURE      = 0x02,
+       BLACKBIRD_RAW_BITS_VBI_CAPTURE      = 0x04,
+       BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+       BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
+};
+enum blackbird_capture_end {
+       BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
+       BLACKBIRD_END_NOW, /* stop immediately, no irq */
+};
+enum blackbird_framerate {
+       BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+       BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
+};
+enum blackbird_stream_port {
+       BLACKBIRD_OUTPUT_PORT_MEMORY,
+       BLACKBIRD_OUTPUT_PORT_STREAMING,
+       BLACKBIRD_OUTPUT_PORT_SERIAL
+};
+enum blackbird_data_xfer_status {
+       BLACKBIRD_MORE_BUFFERS_FOLLOW,
+       BLACKBIRD_LAST_BUFFER,
+};
+enum blackbird_picture_mask {
+       BLACKBIRD_PICTURE_MASK_NONE,
+       BLACKBIRD_PICTURE_MASK_I_FRAMES,
+       BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
+       BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum blackbird_vbi_mode_bits {
+       BLACKBIRD_VBI_BITS_SLICED,
+       BLACKBIRD_VBI_BITS_RAW,
+};
+enum blackbird_vbi_insertion_bits {
+       BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+       BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+       BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+       BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+       BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum blackbird_dma_unit {
+       BLACKBIRD_DMA_BYTES,
+       BLACKBIRD_DMA_FRAMES,
+};
+enum blackbird_dma_transfer_status_bits {
+       BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
+       BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
+       BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum blackbird_pause {
+       BLACKBIRD_PAUSE_ENCODING,
+       BLACKBIRD_RESUME_ENCODING,
+};
+enum blackbird_copyright {
+       BLACKBIRD_COPYRIGHT_OFF,
+       BLACKBIRD_COPYRIGHT_ON,
+};
+enum blackbird_notification_type {
+       BLACKBIRD_NOTIFICATION_REFRESH,
+};
+enum blackbird_notification_status {
+       BLACKBIRD_NOTIFICATION_OFF,
+       BLACKBIRD_NOTIFICATION_ON,
+};
+enum blackbird_notification_mailbox {
+       BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum blackbird_field1_lines {
+       BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
+       BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
+       BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum blackbird_field2_lines {
+       BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
+       BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
+       BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum blackbird_custom_data_type {
+       BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+       BLACKBIRD_CUSTOM_PRIVATE_PACKET,
+};
+enum blackbird_mute {
+       BLACKBIRD_UNMUTE,
+       BLACKBIRD_MUTE,
+};
+enum blackbird_mute_video_mask {
+       BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
+       BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
+       BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum blackbird_mute_video_shift {
+       BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
+       BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
+       BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* Registers */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
+
+/* ------------------------------------------------------------------ */
+
+static void host_setup(struct cx88_core *core)
+{
+       /* toggle reset of the host */
+       cx_write(MO_GPHST_SOFT_RST, 1);
+       udelay(100);
+       cx_write(MO_GPHST_SOFT_RST, 0);
+       udelay(100);
+
+       /* host port setup */
+       cx_write(MO_GPHST_WSC, 0x44444444U);
+       cx_write(MO_GPHST_XFR, 0);
+       cx_write(MO_GPHST_WDTH, 15);
+       cx_write(MO_GPHST_HDSHK, 0);
+       cx_write(MO_GPHST_MUX16, 0x44448888U);
+       cx_write(MO_GPHST_MODE, 0);
+}
+
+/* ------------------------------------------------------------------ */
+
+#define P1_MDATA0 0x390000
+#define P1_MDATA1 0x390001
+#define P1_MDATA2 0x390002
+#define P1_MDATA3 0x390003
+#define P1_MADDR2 0x390004
+#define P1_MADDR1 0x390005
+#define P1_MADDR0 0x390006
+#define P1_RDATA0 0x390008
+#define P1_RDATA1 0x390009
+#define P1_RDATA2 0x39000A
+#define P1_RDATA3 0x39000B
+#define P1_RADDR0 0x39000C
+#define P1_RADDR1 0x39000D
+#define P1_RRDWR  0x39000E
+
+static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
+       u32 gpio0,need;
+
+       need = state ? 2 : 0;
+       for (;;) {
+               gpio0 = cx_read(MO_GP0_IO) & 2;
+               if (need == gpio0)
+                       return 0;
+               if (time_after(jiffies,timeout))
+                       return -1;
+               udelay(1);
+       }
+}
+
+static int memory_write(struct cx88_core *core, u32 address, u32 value)
+{
+       /* Warning: address is dword address (4 bytes) */
+       cx_writeb(P1_MDATA0, (unsigned int)value);
+       cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
+       cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
+       cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
+       cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
+       cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
+       cx_writeb(P1_MADDR0, (unsigned int)address);
+       cx_read(P1_MDATA0);
+       cx_read(P1_MADDR0);
+
+       return wait_ready_gpio0_bit1(core,1);
+}
+
+static int memory_read(struct cx88_core *core, u32 address, u32 *value)
+{
+       int retval;
+       u32 val;
+
+       /* Warning: address is dword address (4 bytes) */
+       cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
+       cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
+       cx_writeb(P1_MADDR0, (unsigned int)address);
+       cx_read(P1_MADDR0);
+
+       retval = wait_ready_gpio0_bit1(core,1);
+
+       cx_writeb(P1_MDATA3, 0);
+       val     = (unsigned char)cx_read(P1_MDATA3) << 24;
+       cx_writeb(P1_MDATA2, 0);
+       val    |= (unsigned char)cx_read(P1_MDATA2) << 16;
+       cx_writeb(P1_MDATA1, 0);
+       val    |= (unsigned char)cx_read(P1_MDATA1) << 8;
+       cx_writeb(P1_MDATA0, 0);
+       val    |= (unsigned char)cx_read(P1_MDATA0);
+
+       *value  = val;
+       return retval;
+}
+
+static int register_write(struct cx88_core *core, u32 address, u32 value)
+{
+       cx_writeb(P1_RDATA0, (unsigned int)value);
+       cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
+       cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
+       cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
+       cx_writeb(P1_RADDR0, (unsigned int)address);
+       cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
+       cx_writeb(P1_RRDWR, 1);
+       cx_read(P1_RDATA0);
+       cx_read(P1_RADDR0);
+
+       return wait_ready_gpio0_bit1(core,1);
+}
+
+
+static int register_read(struct cx88_core *core, u32 address, u32 *value)
+{
+       int retval;
+       u32 val;
+
+       cx_writeb(P1_RADDR0, (unsigned int)address);
+       cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
+       cx_writeb(P1_RRDWR, 0);
+       cx_read(P1_RADDR0);
+
+       retval  = wait_ready_gpio0_bit1(core,1);
+       val     = (unsigned char)cx_read(P1_RDATA0);
+       val    |= (unsigned char)cx_read(P1_RDATA1) << 8;
+       val    |= (unsigned char)cx_read(P1_RDATA2) << 16;
+       val    |= (unsigned char)cx_read(P1_RDATA3) << 24;
+
+       *value  = val;
+       return retval;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct cx8802_dev *dev = priv;
+       unsigned long timeout;
+       u32 value, flag, retval;
+       int i;
+
+       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 */
+       memory_read(dev->core, dev->mailbox - 4, &value);
+       if (value != 0x12345678) {
+               dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
+               return -1;
+       }
+
+       memory_read(dev->core, dev->mailbox, &flag);
+       if (flag) {
+               dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
+               return -1;
+       }
+
+       flag |= 1; /* tell 'em we're working on it */
+       memory_write(dev->core, dev->mailbox, flag);
+
+       /* write command + args + fill remaining with zeros */
+       memory_write(dev->core, dev->mailbox + 1, command); /* command code */
+       memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
+       for (i = 0; i < in; i++) {
+               memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
+               dprintk(1, "API Input %d = %d\n", i, data[i]);
+       }
+       for (; i < CX2341X_MBOX_MAX_DATA; i++)
+               memory_write(dev->core, dev->mailbox + 4 + i, 0);
+
+       flag |= 3; /* tell 'em we're done writing */
+       memory_write(dev->core, dev->mailbox, flag);
+
+       /* wait for firmware to handle the API command */
+       timeout = jiffies + msecs_to_jiffies(10);
+       for (;;) {
+               memory_read(dev->core, dev->mailbox, &flag);
+               if (0 != (flag & 4))
+                       break;
+               if (time_after(jiffies,timeout)) {
+                       dprintk(0, "ERROR: API Mailbox timeout\n");
+                       return -1;
+               }
+               udelay(10);
+       }
+
+       /* read output values */
+       for (i = 0; i < out; i++) {
+               memory_read(dev->core, dev->mailbox + 4 + i, data + i);
+               dprintk(1, "API Output %d = %d\n", i, data[i]);
+       }
+
+       memory_read(dev->core, dev->mailbox + 2, &retval);
+       dprintk(1, "API result = %d\n",retval);
+
+       flag = 0;
+       memory_write(dev->core, dev->mailbox, flag);
+       return retval;
+}
+/* ------------------------------------------------------------------ */
+
+/* We don't need to call the API often, so using just one mailbox will probably suffice */
+static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
+                            u32 inputcnt, u32 outputcnt, ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i, err;
+
+       va_start(vargs, outputcnt);
+
+       for (i = 0; i < inputcnt; i++) {
+               data[i] = va_arg(vargs, int);
+       }
+       err = blackbird_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 blackbird_find_mailbox(struct cx8802_dev *dev)
+{
+       u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
+       int signaturecnt=0;
+       u32 value;
+       int i;
+
+       for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
+               memory_read(dev->core, i, &value);
+               if (value == signature[signaturecnt])
+                       signaturecnt++;
+               else
+                       signaturecnt = 0;
+               if (4 == signaturecnt) {
+                       dprintk(1, "Mailbox signature found\n");
+                       return i+1;
+               }
+       }
+       dprintk(0, "Mailbox signature values not found!\n");
+       return -1;
+}
+
+static int blackbird_load_firmware(struct cx8802_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 checksum = 0;
+       u32 *dataptr;
+
+       retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
+       retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+       retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
+       retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+       msleep(1);
+       retval |= register_write(dev->core, IVTV_REG_APU, 0);
+
+       if (retval < 0)
+               dprintk(0, "Error with register_write\n");
+
+       retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
+                                 &dev->pci->dev);
+
+
+       if (retval != 0) {
+               dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
+                       CX2341X_FIRM_ENC_FILENAME);
+               dprintk(0, "Please fix your hotplug setup, the board will "
+                       "not work without firmware loaded!\n");
+               return -1;
+       }
+
+       if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
+               dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
+                       firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
+               release_firmware(firmware);
+               return -1;
+       }
+
+       if (0 != memcmp(firmware->data, magic, 8)) {
+               dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
+               release_firmware(firmware);
+               return -1;
+       }
+
+       /* transfer to the chip */
+       dprintk(1,"Loading firmware ...\n");
+       dataptr = (u32*)firmware->data;
+       for (i = 0; i < (firmware->size >> 2); i++) {
+               value = le32_to_cpu(*dataptr);
+               checksum += ~value;
+               memory_write(dev->core, i, value);
+               dataptr++;
+       }
+
+       /* read back to verify with the checksum */
+       for (i--; i >= 0; i--) {
+               memory_read(dev->core, i, &value);
+               checksum -= ~value;
+       }
+       if (checksum) {
+               dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
+               release_firmware(firmware);
+               return -1;
+       }
+       release_firmware(firmware);
+       dprintk(0, "Firmware upload successful.\n");
+
+       retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+       retval |= register_read(dev->core, IVTV_REG_SPU, &value);
+       retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
+       msleep(1);
+
+       retval |= register_read(dev->core, IVTV_REG_VPU, &value);
+       retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+       if (retval < 0)
+               dprintk(0, "Error with register_write\n");
+       return 0;
+}
+
+/**
+ Settings used by the windows tv app for PVR2000:
+=================================================================================================================
+Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
+-----------------------------------------------------------------------------------------------------------------
+MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+=================================================================================================================
+*DB: "DirectBurn"
+*/
+
+static void blackbird_codec_settings(struct cx8802_dev *dev)
+{
+       /* assign frame size */
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               dev->height, dev->width);
+
+       dev->cxhdl.width = dev->width;
+       dev->cxhdl.height = dev->height;
+       cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
+       cx2341x_handler_setup(&dev->cxhdl);
+}
+
+static int blackbird_initialize_codec(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       int version;
+       int retval;
+
+       dprintk(1,"Initialize codec\n");
+       retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+       if (retval < 0) {
+
+               dev->mpeg_active = 0;
+
+               /* ping was not successful, reset and upload firmware */
+               cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
+               cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
+               retval = blackbird_load_firmware(dev);
+               if (retval < 0)
+                       return retval;
+
+               retval = blackbird_find_mailbox(dev);
+               if (retval < 0)
+                       return -1;
+
+               dev->mailbox = retval;
+
+               retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+               if (retval < 0) {
+                       dprintk(0, "ERROR: Firmware ping failed!\n");
+                       return -1;
+               }
+
+               retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
+               if (retval < 0) {
+                       dprintk(0, "ERROR: Firmware get encoder version failed!\n");
+                       return -1;
+               }
+               dprintk(0, "Firmware version is 0x%08x\n", version);
+       }
+
+       cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
+       cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
+       cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
+       cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
+
+       blackbird_codec_settings(dev);
+
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+                       BLACKBIRD_FIELD1_SAA7115,
+                       BLACKBIRD_FIELD2_SAA7115
+               );
+
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+                       BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+       return 0;
+}
+
+static int blackbird_start_codec(struct file *file, void *priv)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx88_core *core = dev->core;
+       /* start capturing to the host interface */
+       u32 reg;
+
+       int i;
+       int lastchange = -1;
+       int lastval = 0;
+
+       for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) {
+               reg = cx_read(AUD_STATUS);
+
+               dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg);
+               if ((reg & 0x0F) != lastval) {
+                       lastval = reg & 0x0F;
+                       lastchange = i;
+               }
+               msleep(100);
+       }
+
+       /* unmute audio source */
+       cx_clear(AUD_VOL_CTL, (1 << 6));
+
+       blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0);
+
+       /* initialize the video input */
+       blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+
+       cx2341x_handler_set_busy(&dev->cxhdl, 1);
+
+       /* start capturing to the host interface */
+       blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+                       BLACKBIRD_MPEG_CAPTURE,
+                       BLACKBIRD_RAW_BITS_NONE
+               );
+
+       dev->mpeg_active = 1;
+       return 0;
+}
+
+static int blackbird_stop_codec(struct cx8802_dev *dev)
+{
+       blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                       BLACKBIRD_END_NOW,
+                       BLACKBIRD_MPEG_CAPTURE,
+                       BLACKBIRD_RAW_BITS_NONE
+               );
+
+       cx2341x_handler_set_busy(&dev->cxhdl, 0);
+
+       dev->mpeg_active = 0;
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+                       unsigned int *count, unsigned int *size)
+{
+       struct cx8802_fh *fh = q->priv_data;
+
+       fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
+       fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
+
+       *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
+       *count = fh->dev->ts_packet_count;
+       return 0;
+}
+
+static int
+bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+              enum v4l2_field field)
+{
+       struct cx8802_fh *fh = q->priv_data;
+       return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
+}
+
+static void
+bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx8802_fh *fh = q->priv_data;
+       cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
+}
+
+static void
+bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       cx88_free_buffer(q, (struct cx88_buffer*)vb);
+}
+
+static struct videobuf_queue_ops blackbird_qops = {
+       .buf_setup    = bb_buf_setup,
+       .buf_prepare  = bb_buf_prepare,
+       .buf_queue    = bb_buf_queue,
+       .buf_release  = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx88_core  *core = dev->core;
+
+       strcpy(cap->driver, "cx88_blackbird");
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+       cx88_querycap(file, core, cap);
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "MPEG", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+       f->fmt.pix.width        = dev->width;
+       f->fmt.pix.height       = dev->height;
+       f->fmt.pix.field        = fh->mpegq.field;
+       dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+               dev->width, dev->height, fh->mpegq.field );
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+       dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+               dev->width, dev->height, fh->mpegq.field );
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+       struct cx88_core  *core = dev->core;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+       dev->width              = f->fmt.pix.width;
+       dev->height             = f->fmt.pix.height;
+       fh->mpegq.field         = f->fmt.pix.field;
+       cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+       blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               f->fmt.pix.height, f->fmt.pix.width);
+       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;
+}
+
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_reqbufs(&fh->mpegq, p));
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_querybuf(&fh->mpegq, p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_qbuf(&fh->mpegq, p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct cx8802_fh  *fh   = priv;
+       return (videobuf_dqbuf(&fh->mpegq, p,
+                               file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+
+       if (!dev->mpeg_active)
+               blackbird_start_codec(file, fh);
+       return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+
+       if (dev->mpeg_active)
+               blackbird_stop_codec(dev);
+       return videobuf_streamoff(&fh->mpegq);
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx8802_dev *dev  = fh->dev;
+       struct cx88_core  *core = dev->core;
+
+       if (unlikely(UNSET == core->board.tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+       if (dev->mpeg_active)
+               blackbird_stop_codec(dev);
+
+       cx88_set_freq (core,f);
+       blackbird_initialize_codec(dev);
+       cx88_set_scale(dev->core, dev->width, dev->height,
+                       fh->mpegq.field);
+       return 0;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+       struct cx88_core  *core = dev->core;
+       char name[32 + 2];
+
+       snprintf(name, sizeof(name), "%s/2", core->name);
+       call_all(core, core, log_status);
+       v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
+       return 0;
+}
+
+static int vidioc_enum_input (struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+       return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8802_fh  *fh   = priv;
+       struct cx88_core  *core = fh->dev->core;
+
+       if (unlikely(UNSET == core->board.tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+
+       f->frequency = core->freq;
+       call_all(core, tuner, g_frequency, f);
+
+       return 0;
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       *i = core->input;
+       return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       if (i >= 4)
+               return -EINVAL;
+       if (0 == INPUT(i).type)
+               return -EINVAL;
+
+       mutex_lock(&core->lock);
+       cx88_newstation(core);
+       cx88_video_mux(core,i);
+       mutex_unlock(&core->lock);
+       return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+       u32 reg;
+
+       if (unlikely(UNSET == core->board.tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh  = 0xffffffffUL;
+       call_all(core, tuner, g_tuner, t);
+
+       cx88_get_stereo(core ,t);
+       reg = cx_read(MO_DEVICE_STATUS);
+       t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+       return 0;
+}
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       if (UNSET == core->board.tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       cx88_set_stereo(core, t->audmode, 1);
+       return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
+{
+       struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       *tvnorm = core->tvnorm;
+       return 0;
+}
+
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+       mutex_lock(&core->lock);
+       cx88_set_tvnorm(core,*id);
+       mutex_unlock(&core->lock);
+       return 0;
+}
+
+/* FIXME: cx88_ioctl_hook not implemented */
+
+static int mpeg_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8802_dev *dev = video_drvdata(file);
+       struct cx8802_fh *fh;
+       struct cx8802_driver *drv = NULL;
+       int err;
+
+       dprintk( 1, "%s\n", __func__);
+
+       mutex_lock(&dev->core->lock);
+
+       /* Make sure we can acquire the hardware */
+       drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+       if (!drv) {
+               dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
+               mutex_unlock(&dev->core->lock);
+               return -ENODEV;
+       }
+
+       err = drv->request_acquire(drv);
+       if (err != 0) {
+               dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+               mutex_unlock(&dev->core->lock);
+               return err;
+       }
+
+       if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
+               drv->request_release(drv);
+               mutex_unlock(&dev->core->lock);
+               return -EINVAL;
+       }
+       dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+       if (NULL == fh) {
+               drv->request_release(drv);
+               mutex_unlock(&dev->core->lock);
+               return -ENOMEM;
+       }
+       v4l2_fh_init(&fh->fh, vdev);
+       file->private_data = fh;
+       fh->dev      = dev;
+
+       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),
+                           fh, NULL);
+
+       /* FIXME: locking against other video device */
+       cx88_set_scale(dev->core, dev->width, dev->height,
+                       fh->mpegq.field);
+
+       dev->core->mpeg_users++;
+       mutex_unlock(&dev->core->lock);
+       v4l2_fh_add(&fh->fh);
+       return 0;
+}
+
+static int mpeg_release(struct file *file)
+{
+       struct cx8802_fh  *fh  = file->private_data;
+       struct cx8802_dev *dev = fh->dev;
+       struct cx8802_driver *drv = NULL;
+
+       mutex_lock(&dev->core->lock);
+
+       if (dev->mpeg_active && dev->core->mpeg_users == 1)
+               blackbird_stop_codec(dev);
+
+       cx8802_cancel_buffers(fh->dev);
+       /* stop mpeg capture */
+       videobuf_stop(&fh->mpegq);
+
+       videobuf_mmap_free(&fh->mpegq);
+
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+       file->private_data = NULL;
+       kfree(fh);
+
+       /* Make sure we release the hardware */
+       drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+       WARN_ON(!drv);
+       if (drv)
+               drv->request_release(drv);
+
+       dev->core->mpeg_users--;
+
+       mutex_unlock(&dev->core->lock);
+
+       return 0;
+}
+
+static ssize_t
+mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+       struct cx8802_fh *fh = file->private_data;
+       struct cx8802_dev *dev = fh->dev;
+
+       if (!dev->mpeg_active)
+               blackbird_start_codec(file, fh);
+
+       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)
+{
+       unsigned long req_events = poll_requested_events(wait);
+       struct cx8802_fh *fh = file->private_data;
+       struct cx8802_dev *dev = fh->dev;
+
+       if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
+               blackbird_start_codec(file, fh);
+
+       return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int
+mpeg_mmap(struct file *file, struct vm_area_struct * vma)
+{
+       struct cx8802_fh *fh = file->private_data;
+
+       return videobuf_mmap_mapper(&fh->mpegq, vma);
+}
+
+static const struct v4l2_file_operations mpeg_fops =
+{
+       .owner         = THIS_MODULE,
+       .open          = mpeg_open,
+       .release       = mpeg_release,
+       .read          = mpeg_read,
+       .poll          = mpeg_poll,
+       .mmap          = mpeg_mmap,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_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_s_frequency   = vidioc_s_frequency,
+       .vidioc_log_status    = vidioc_log_status,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+};
+
+static struct video_device cx8802_mpeg_template = {
+       .name                 = "cx8802",
+       .fops                 = &mpeg_fops,
+       .ioctl_ops            = &mpeg_ioctl_ops,
+       .tvnorms              = CX88_NORMS,
+};
+
+/* ------------------------------------------------------------------ */
+
+/* The CX8802 MPEG API will call this when we can use the hardware */
+static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* By default, core setup will leave the cx22702 out of reset, on the bus.
+                * We left the hardware on power up with the cx22702 active.
+                * We're being given access to re-arrange the GPIOs.
+                * Take the bus off the cx22702 and put the cx23416 on it.
+                */
+               /* Toggle reset on cx22702 leaving i2c active */
+               cx_set(MO_GP0_IO, 0x00000080);
+               udelay(1000);
+               cx_clear(MO_GP0_IO, 0x00000080);
+               udelay(50);
+               cx_set(MO_GP0_IO, 0x00000080);
+               udelay(1000);
+               /* tri-state the cx22702 pins */
+               cx_set(MO_GP0_IO, 0x00000004);
+               udelay(1000);
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+/* The CX8802 MPEG API will call this when we need to release the hardware */
+static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* Exit leaving the cx23416 on the bus */
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+static void blackbird_unregister_video(struct cx8802_dev *dev)
+{
+       if (dev->mpeg_dev) {
+               if (video_is_registered(dev->mpeg_dev))
+                       video_unregister_device(dev->mpeg_dev);
+               else
+                       video_device_release(dev->mpeg_dev);
+               dev->mpeg_dev = NULL;
+       }
+}
+
+static int blackbird_register_video(struct cx8802_dev *dev)
+{
+       int err;
+
+       dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
+                                      &cx8802_mpeg_template,"mpeg");
+       dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
+       video_set_drvdata(dev->mpeg_dev, dev);
+       err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
+       if (err < 0) {
+               printk(KERN_INFO "%s/2: can't register mpeg device\n",
+                      dev->core->name);
+               return err;
+       }
+       printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
+              dev->core->name, video_device_node_name(dev->mpeg_dev));
+       return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+static int cx8802_blackbird_probe(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       struct cx8802_dev *dev = core->dvbdev;
+       int err;
+
+       dprintk( 1, "%s\n", __func__);
+       dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+               core->boardnr,
+               core->name,
+               core->pci_bus,
+               core->pci_slot);
+
+       err = -ENODEV;
+       if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
+               goto fail_core;
+
+       dev->width = 720;
+       if (core->tvnorm & V4L2_STD_525_60) {
+               dev->height = 480;
+       } else {
+               dev->height = 576;
+       }
+       dev->cxhdl.port = CX2341X_PORT_STREAMING;
+       dev->cxhdl.width = dev->width;
+       dev->cxhdl.height = dev->height;
+       dev->cxhdl.func = blackbird_mbox_func;
+       dev->cxhdl.priv = dev;
+       err = cx2341x_handler_init(&dev->cxhdl, 36);
+       if (err)
+               goto fail_core;
+       v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl);
+
+       /* blackbird stuff */
+       printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
+              core->name);
+       host_setup(dev->core);
+
+       blackbird_initialize_codec(dev);
+
+       /* initial device configuration: needed ? */
+//     init_controls(core);
+       cx88_set_tvnorm(core,core->tvnorm);
+       cx88_video_mux(core,0);
+       cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
+       cx2341x_handler_setup(&dev->cxhdl);
+       blackbird_register_video(dev);
+
+       return 0;
+
+ fail_core:
+       return err;
+}
+
+static int cx8802_blackbird_remove(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       struct cx8802_dev *dev = core->dvbdev;
+
+       /* blackbird */
+       blackbird_unregister_video(drv->core->dvbdev);
+       v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
+
+       return 0;
+}
+
+static struct cx8802_driver cx8802_blackbird_driver = {
+       .type_id        = CX88_MPEG_BLACKBIRD,
+       .hw_access      = CX8802_DRVCTL_SHARED,
+       .probe          = cx8802_blackbird_probe,
+       .remove         = cx8802_blackbird_remove,
+       .advise_acquire = cx8802_blackbird_advise_acquire,
+       .advise_release = cx8802_blackbird_advise_release,
+};
+
+static int __init blackbird_init(void)
+{
+       printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
+              CX88_VERSION);
+       return cx8802_register_driver(&cx8802_blackbird_driver);
+}
+
+static void __exit blackbird_fini(void)
+{
+       cx8802_unregister_driver(&cx8802_blackbird_driver);
+}
+
+module_init(blackbird_init);
+module_exit(blackbird_fini);
+
+module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [video]");
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
new file mode 100644 (file)
index 0000000..4e9d4f7
--- /dev/null
@@ -0,0 +1,3811 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * card-specific stuff.
+ *
+ * (c) 2003 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, 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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "cx88.h"
+#include "tea5767.h"
+#include "xc4000.h"
+
+static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int card[]  = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(tuner, int, NULL, 0444);
+module_param_array(radio, int, NULL, 0444);
+module_param_array(card,  int, NULL, 0444);
+
+MODULE_PARM_DESC(tuner,"tuner type");
+MODULE_PARM_DESC(radio,"radio tuner type");
+MODULE_PARM_DESC(card,"card type");
+
+static unsigned int latency = UNSET;
+module_param(latency,int,0444);
+MODULE_PARM_DESC(latency,"pci latency timer");
+
+static int disable_ir;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir, "Disable IR support");
+
+#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                                                  */
+
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
+static const struct cx88_board cx88_boards[] = {
+       [CX88_BOARD_UNKNOWN] = {
+               .name           = "UNKNOWN/GENERIC",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE2,
+                       .vmux   = 1,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE3,
+                       .vmux   = 2,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE4,
+                       .vmux   = 3,
+               }},
+       },
+       [CX88_BOARD_HAUPPAUGE] = {
+               .name           = "Hauppauge WinTV 34xxx models",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xff00,  // internal decoder
+               },{
+                       .type   = CX88_VMUX_DEBUG,
+                       .vmux   = 0,
+                       .gpio0  = 0xff01,  // mono from tuner chip
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xff02,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xff02,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0xff01,
+               },
+       },
+       [CX88_BOARD_GDI] = {
+               .name           = "GDI Black Gold",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               }},
+       },
+       [CX88_BOARD_PIXELVIEW] = {
+               .name           = "PixelView",
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xff00,  // internal decoder
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0xff10,
+               },
+       },
+       [CX88_BOARD_ATI_WONDER_PRO] = {
+               .name           = "ATI TV Wonder Pro",
+               .tuner_type     = TUNER_PHILIPS_4IN1,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x03ff,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x03fe,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x03fe,
+               }},
+       },
+       [CX88_BOARD_WINFAST2000XP_EXPERT] = {
+               .name           = "Leadtek Winfast 2000XP Expert",
+               .tuner_type     = TUNER_PHILIPS_4IN1,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00F5e700,
+                       .gpio1  = 0x00003004,
+                       .gpio2  = 0x00F5e700,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00F5c700,
+                       .gpio1  = 0x00003004,
+                       .gpio2  = 0x00F5c700,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00F5c700,
+                       .gpio1  = 0x00003004,
+                       .gpio2  = 0x00F5c700,
+                       .gpio3  = 0x02000000,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x00F5d700,
+                       .gpio1  = 0x00003004,
+                       .gpio2  = 0x00F5d700,
+                       .gpio3  = 0x02000000,
+               },
+       },
+       [CX88_BOARD_AVERTV_STUDIO_303] = {
+               .name           = "AverTV Studio 303 (M126)",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio1  = 0xe09f,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio1  = 0xe05f,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio1  = 0xe05f,
+               }},
+               .radio = {
+                       .gpio1  = 0xe0df,
+                       .type   = CX88_RADIO,
+               },
+       },
+       [CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
+               // added gpio values thanks to Michal
+               // values for PAL from DScaler
+               .name           = "MSI TV-@nywhere Master",
+               .tuner_type     = TUNER_MT2032,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x000040bf,
+                       .gpio1  = 0x000080c0,
+                       .gpio2  = 0x0000ff40,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000040bf,
+                       .gpio1  = 0x000080c0,
+                       .gpio2  = 0x0000ff40,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000040bf,
+                       .gpio1  = 0x000080c0,
+                       .gpio2  = 0x0000ff40,
+               }},
+               .radio = {
+                        .type   = CX88_RADIO,
+                        .vmux   = 3,
+                        .gpio0  = 0x000040bf,
+                        .gpio1  = 0x000080c0,
+                        .gpio2  = 0x0000ff20,
+               },
+       },
+       [CX88_BOARD_WINFAST_DV2000] = {
+               .name           = "Leadtek Winfast DV2000",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0035e700,
+                       .gpio1  = 0x00003004,
+                       .gpio2  = 0x0035e700,
+                       .gpio3  = 0x02000000,
+               },{
+
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0035c700,
+                       .gpio1  = 0x00003004,
+                       .gpio2  = 0x0035c700,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0035c700,
+                       .gpio1  = 0x0035c700,
+                       .gpio2  = 0x02000000,
+                       .gpio3  = 0x02000000,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0035d700,
+                       .gpio1  = 0x00007004,
+                       .gpio2  = 0x0035d700,
+                       .gpio3  = 0x02000000,
+               },
+       },
+       [CX88_BOARD_LEADTEK_PVR2000] = {
+               // gpio values for PAL version from regspy by DScaler
+               .name           = "Leadtek PVR 2000",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0000bde2,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0000bde6,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0000bde6,
+                       .audioroute = 1,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0000bd62,
+                       .audioroute = 1,
+               },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_IODATA_GVVCP3PCI] = {
+               .name           = "IODATA GV-VCP3/PCI",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE2,
+                       .vmux   = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               }},
+       },
+       [CX88_BOARD_PROLINK_PLAYTVPVR] = {
+               .name           = "Prolink PlayTV PVR",
+               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xbff0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xbff3,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xbff3,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0xbff0,
+               },
+       },
+       [CX88_BOARD_ASUS_PVR_416] = {
+               .name           = "ASUS PVR-416",
+               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0000fde6,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
+                       .audioroute = 1,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0000fde2,
+               },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_MSI_TVANYWHERE] = {
+               .name           = "MSI TV-@nywhere",
+               .tuner_type     = TUNER_MT2032,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00000fbf,
+                       .gpio2  = 0x0000fc08,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00000fbf,
+                       .gpio2  = 0x0000fc68,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00000fbf,
+                       .gpio2  = 0x0000fc68,
+               }},
+       },
+       [CX88_BOARD_KWORLD_DVB_T] = {
+               .name           = "KWorld/VStream XPert DVB-T",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
+               .name           = "DViCO FusionHDTV DVB-T1",
+               .tuner_type     = TUNER_ABSENT, /* No analog tuner */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000027df,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000027df,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_KWORLD_LTV883] = {
+               .name           = "KWorld LTV883RF",
+               .tuner_type     = TUNER_TNF_8831BGFF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x07f8,
+               },{
+                       .type   = CX88_VMUX_DEBUG,
+                       .vmux   = 0,
+                       .gpio0  = 0x07f9,  // mono from tuner chip
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000007fa,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000007fa,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x000007f8,
+               },
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = {
+               .name           = "DViCO FusionHDTV 3 Gold-Q",
+               .tuner_type     = TUNER_MICROTUNE_4042FI5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /*
+                  GPIO[0] resets DT3302 DTV receiver
+                   0 - reset asserted
+                   1 - normal operation
+                  GPIO[1] mutes analog audio output connector
+                   0 - enable selected source
+                   1 - mute
+                  GPIO[2] selects source for analog audio output connector
+                   0 - analog audio input connector on tab
+                   1 - analog DAC output from CX23881 chip
+                  GPIO[3] selects RF input connector on tuner module
+                   0 - RF connector labeled CABLE
+                   1 - RF connector labeled ANT
+                  GPIO[4] selects high RF for QAM256 mode
+                   0 - normal RF
+                   1 - high RF
+               */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0f0d,
+               },{
+                       .type   = CX88_VMUX_CABLE,
+                       .vmux   = 0,
+                       .gpio0  = 0x0f05,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0f00,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0f00,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
+               .name           = "Hauppauge Nova-T DVB-T",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_CONEXANT_DVB_T1] = {
+               .name           = "Conexant DVB-T reference design",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PROVIDEO_PV259] = {
+               .name           = "Provideo PV259",
+               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .audioroute = 1,
+               }},
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
+               .name           = "DViCO FusionHDTV DVB-T Plus",
+               .tuner_type     = TUNER_ABSENT, /* No analog tuner */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x000027df,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x000027df,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DNTV_LIVE_DVB_T] = {
+               .name           = "digitalnow DNTV Live! DVB-T",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00000700,
+                       .gpio2  = 0x00000101,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00000700,
+                       .gpio2  = 0x00000101,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PCHDTV_HD3000] = {
+               .name           = "pcHDTV HD3000 HDTV",
+               .tuner_type     = TUNER_THOMSON_DTT761X,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               /* GPIO[2] = audio source for analog audio out connector
+                *  0 = analog audio input connector
+                *  1 = CX88 audio DACs
+                *
+                * GPIO[7] = input to CX88's audio/chroma ADC
+                *  0 = FM 10.7 MHz IF
+                *  1 = Sound 4.5 MHz IF
+                *
+                * GPIO[1,5,6] = Oren 51132 pins 27,35,28 respectively
+                *
+                * GPIO[16] = Remote control input
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00008484,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00008400,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00008400,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x00008404,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
+               // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
+               // GPIO values obtained from regspy, courtesy Sean Covel
+               .name           = "Hauppauge WinTV 28xxx (Roslyn) models",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xed1a,
+                       .gpio2  = 0x00ff,
+               },{
+                       .type   = CX88_VMUX_DEBUG,
+                       .vmux   = 0,
+                       .gpio0  = 0xff01,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xff02,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xed92,
+                       .gpio2  = 0x00ff,
+               }},
+               .radio = {
+                        .type   = CX88_RADIO,
+                        .gpio0  = 0xed96,
+                        .gpio2  = 0x00ff,
+                },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_DIGITALLOGIC_MEC] = {
+               .name           = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00009d80,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00009d76,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00009d76,
+                       .audioroute = 1,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x00009d00,
+                       .audioroute = 1,
+               },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_IODATA_GVBCTV7E] = {
+               .name           = "IODATA GV/BCTV7E",
+               .tuner_type     = TUNER_PHILIPS_FQ1286,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 1,
+                       .gpio1  = 0x0000e03f,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 2,
+                       .gpio1  = 0x0000e07f,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 3,
+                       .gpio1  = 0x0000e07f,
+               }}
+       },
+       [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
+               .name           = "PixelView PlayTV Ultra Pro (Stereo)",
+               /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               /* Some variants use a tda9874 and so need the tvaudio module. */
+               .audio_chip     = V4L2_IDENT_TVAUDIO,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xbf61,  /* internal decoder */
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xbf63,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xbf63,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0xbf60,
+                },
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
+               .name           = "DViCO FusionHDTV 3 Gold-T",
+               .tuner_type     = TUNER_THOMSON_DTT761X,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x97ed,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x97e9,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x97e9,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_ADSTECH_DVB_T_PCI] = {
+               .name           = "ADS Tech Instant TV DVB-T PCI",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
+               .name           = "TerraTec Cinergy 1400 DVB-T",
+               .tuner_type     = TUNER_ABSENT,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 2,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
+               .name           = "DViCO FusionHDTV 5 Gold",
+               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x87fd,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x87f9,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x87f9,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = {
+               .name           = "AverMedia UltraTV Media Center PCI 550",
+               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 0,
+                       .gpio0  = 0x0000cd73,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 1,
+                       .gpio0  = 0x0000cd73,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 3,
+                       .gpio0  = 0x0000cdb3,
+                       .audioroute = 1,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0000cdf3,
+                       .audioroute = 1,
+               },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
+                /* Alexander Wold <awold@bigfoot.com> */
+                .name           = "Kworld V-Stream Xpert DVD",
+                .tuner_type     = UNSET,
+                .input          = {{
+                        .type   = CX88_VMUX_COMPOSITE1,
+                        .vmux   = 1,
+                        .gpio0  = 0x03000000,
+                        .gpio1  = 0x01000000,
+                        .gpio2  = 0x02000000,
+                        .gpio3  = 0x00100000,
+                },{
+                        .type   = CX88_VMUX_SVIDEO,
+                        .vmux   = 2,
+                        .gpio0  = 0x03000000,
+                        .gpio1  = 0x01000000,
+                        .gpio2  = 0x02000000,
+                        .gpio3  = 0x00100000,
+                }},
+       },
+       [CX88_BOARD_ATI_HDTVWONDER] = {
+               .name           = "ATI HDTV Wonder",
+               .tuner_type     = TUNER_PHILIPS_TUV1236D,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00000ff7,
+                       .gpio1  = 0x000000ff,
+                       .gpio2  = 0x00000001,
+                       .gpio3  = 0x00000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00000ffe,
+                       .gpio1  = 0x000000ff,
+                       .gpio2  = 0x00000001,
+                       .gpio3  = 0x00000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00000ffe,
+                       .gpio1  = 0x000000ff,
+                       .gpio2  = 0x00000001,
+                       .gpio3  = 0x00000000,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_WINFAST_DTV1000] = {
+               .name           = "WinFast DTV1000-T",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_AVERTV_303] = {
+               .name           = "AVerTV 303 (M126)",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00ff,
+                       .gpio1  = 0xe09f,
+                       .gpio2  = 0x0010,
+                       .gpio3  = 0x0000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00ff,
+                       .gpio1  = 0xe05f,
+                       .gpio2  = 0x0010,
+                       .gpio3  = 0x0000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00ff,
+                       .gpio1  = 0xe05f,
+                       .gpio2  = 0x0010,
+                       .gpio3  = 0x0000,
+               }},
+       },
+       [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
+               .name           = "Hauppauge Nova-S-Plus DVB-S",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .audio_chip     = V4L2_IDENT_WM8775,
+               .i2sinputcntl   = 2,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
+               .name           = "Hauppauge Nova-SE2 DVB-S",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_KWORLD_DVBS_100] = {
+               .name           = "KWorld DVB-S 100",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .audio_chip = V4L2_IDENT_WM8775,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR1100] = {
+               .name           = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+               }},
+               /* fixme: Add radio support */
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
+               .name           = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+               }},
+               /* fixme: Add radio support */
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
+               .name           = "digitalnow DNTV Live! DVB-T Pro",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+                                 TDA9887_PORT2_ACTIVE,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xf80808,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xf80808,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xf80808,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0xf80808,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_KWORLD_DVB_T_CX22702] = {
+               /* Kworld V-stream Xpert DVB-T with Thomson tuner */
+               /* DTT 7579 Conexant CX22702-19 Conexant CX2388x  */
+               /* Manenti Marco <marco_manenti@colman.it> */
+               .name           = "KWorld/VStream XPert DVB-T with cx22702",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0700,
+                       .gpio2  = 0x0101,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
+               .name           = "DViCO FusionHDTV DVB-T Dual Digital",
+               .tuner_type     = TUNER_ABSENT, /* No analog tuner */
+               .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_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
+               .name           = "KWorld HardwareMpegTV XPert",
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x3de2,
+                       .gpio2  = 0x00ff,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x3de6,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x3de6,
+                       .audioroute = 1,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x3de6,
+                       .gpio2  = 0x00ff,
+               },
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
+               .name           = "DViCO FusionHDTV DVB-T Hybrid",
+               .tuner_type     = TUNER_THOMSON_FE6600,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0000a75f,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0000a75b,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0000a75b,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PCHDTV_HD5500] = {
+               .name           = "pcHDTV HD5500 HDTV",
+               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x87fd,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x87f9,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x87f9,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_KWORLD_MCE200_DELUXE] = {
+               /* FIXME: tested TV input only, disabled composite,
+                  svideo and radio until they can be tested also. */
+               .name           = "Kworld MCE 200 Deluxe",
+               .tuner_type     = TUNER_TENA_9533_DI,
+               .radio_type     = UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0000BDE6
+               }},
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
+               /* FIXME: SVideo, Composite and FM inputs are untested */
+               .name           = "PixelView PlayTV P7000",
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+                                 TDA9887_PORT2_ACTIVE,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x5da6,
+               }},
+               .mpeg           = CX88_MPEG_BLACKBIRD,
+       },
+       [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
+               .name           = "NPG Tech Real TV FM Top 10",
+               .tuner_type     = TUNER_TNF_5335MF, /* Actually a TNF9535 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0788,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x078b,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x078b,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0x074a,
+               },
+       },
+       [CX88_BOARD_WINFAST_DTV2000H] = {
+               .name           = "WinFast DTV2000 H",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00017304,
+                       .gpio1  = 0x00008203,
+                       .gpio2  = 0x00017304,
+                       .gpio3  = 0x02000000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0001d701,
+                       .gpio1  = 0x0000b207,
+                       .gpio2  = 0x0001d701,
+                       .gpio3  = 0x02000000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE2,
+                       .vmux   = 2,
+                       .gpio0  = 0x0001d503,
+                       .gpio1  = 0x0000b207,
+                       .gpio2  = 0x0001d503,
+                       .gpio3  = 0x02000000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 3,
+                       .gpio0  = 0x0001d701,
+                       .gpio1  = 0x0000b207,
+                       .gpio2  = 0x0001d701,
+                       .gpio3  = 0x02000000,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0x00015702,
+                        .gpio1 = 0x0000f207,
+                        .gpio2 = 0x00015702,
+                        .gpio3 = 0x02000000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_WINFAST_DTV2000H_J] = {
+               .name           = "WinFast DTV2000 H rev. J",
+               .tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00017300,
+                       .gpio1  = 0x00008207,
+                       .gpio2  = 0x00000000,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x00018300,
+                       .gpio1  = 0x0000f207,
+                       .gpio2  = 0x00017304,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x00018301,
+                       .gpio1  = 0x0000f207,
+                       .gpio2  = 0x00017304,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x00018301,
+                       .gpio1  = 0x0000f207,
+                       .gpio2  = 0x00017304,
+                       .gpio3  = 0x02000000,
+               }},
+               .radio = {
+                        .type  = CX88_RADIO,
+                        .gpio0 = 0x00015702,
+                        .gpio1 = 0x0000f207,
+                        .gpio2 = 0x00015702,
+                        .gpio3 = 0x02000000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_GENIATECH_DVBS] = {
+               .name          = "Geniatech DVB-S",
+               .tuner_type    = TUNER_ABSENT,
+               .radio_type    = UNSET,
+               .tuner_addr    = ADDR_UNSET,
+               .radio_addr    = ADDR_UNSET,
+               .input  = {{
+                       .type  = CX88_VMUX_DVB,
+                       .vmux  = 0,
+               },{
+                       .type  = CX88_VMUX_COMPOSITE1,
+                       .vmux  = 1,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR3000] = {
+               .name           = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .audio_chip     = V4L2_IDENT_WM8775,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x84bf,
+                       /* 1: TV Audio / FM Mono */
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x84bf,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x84bf,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x84bf,
+                       /* 4: FM Stereo (untested) */
+                       .audioroute = 8,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+               .num_frontends  = 2,
+       },
+       [CX88_BOARD_NORWOOD_MICRO] = {
+               .name           = "Norwood Micro TV Tuner",
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0709,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x070b,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x070b,
+               }},
+       },
+       [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
+               .name           = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x003fffff,
+                       .gpio1  = 0x00e00000,
+                       .gpio2  = 0x003fffff,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x003fffff,
+                       .gpio1  = 0x00e00000,
+                       .gpio2  = 0x003fffff,
+                       .gpio3  = 0x02000000,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x003fffff,
+                       .gpio1  = 0x00e00000,
+                       .gpio2  = 0x003fffff,
+                       .gpio3  = 0x02000000,
+               }},
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR1300] = {
+               .name           = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .audio_chip     = V4L2_IDENT_WM8775,
+               /*
+                * gpio0 as reported by Mike Crash <mike AT mikecrash.com>
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xef88,
+                       /* 1: TV Audio / FM Mono */
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xef88,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xef88,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               }},
+               .mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0xef88,
+                       /* 4: FM Stereo (untested) */
+                       .audioroute = 8,
+               },
+       },
+       [CX88_BOARD_SAMSUNG_SMT_7020] = {
+               .name           = "Samsung SMT 7020 DVB-S",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_ADSTECH_PTV_390] = {
+               .name           = "ADS Tech Instant Video PCI",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DEBUG,
+                       .vmux   = 3,
+                       .gpio0  = 0x04ff,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x07fa,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x07fa,
+               }},
+       },
+       [CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
+               .name           = "Pinnacle PCTV HD 800i",
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x04fb,
+                       .gpio1  = 0x10ff,
+               },{
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x04fb,
+                       .gpio1  = 0x10ef,
+                       .audioroute = 1,
+               },{
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x04fb,
+                       .gpio1  = 0x10ef,
+                       .audioroute = 1,
+               }},
+               .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,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x00001,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x004fb,
+                       .gpio1  = 0x010ef,
+                       .audioroute = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x004fb,
+                       .gpio1  = 0x010ef,
+                       .audioroute = 1,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x0ff,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       /* Terry Wu <terrywu2009@gmail.com> */
+       /* TV Audio :      set GPIO 2, 18, 19 value to 0, 1, 0 */
+       /* FM Audio :      set GPIO 2, 18, 19 value to 0, 0, 0 */
+       /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */
+       /* Mute Audio :    set GPIO 2 value to 1               */
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
+               .name           = "Leadtek TV2000 XP Global",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+                       .gpio3  = 0x0000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,        /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
+                       .gpio3  = 0x0000,
+               },
+       },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = {
+               .name           = "Leadtek TV2000 XP Global (SC4100)",
+               .tuner_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+                       .gpio3  = 0x0000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,        /* pin 2 = 0 */
+                       .gpio1  = 0x0000,
+                       .gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
+                       .gpio3  = 0x0000,
+               },
+       },
+       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = {
+               .name           = "Leadtek TV2000 XP Global (XC4100)",
+               .tuner_type     = TUNER_XC4000,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6040,       /* pin 14 = 1, pin 13 = 0 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,        /* pin 2 = 0 */
+                       .gpio1  = 0x6000,        /* pin 14 = 1, pin 13 = 0 */
+                       .gpio2  = 0x0000,
+                       .gpio3  = 0x0000,
+               },
+       },
+       [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
+               .name           = "PowerColor RA330",   /* Long names may confuse LIRC. */
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_DEBUG,
+                       .vmux   = 3,            /* Due to the way the cx88 driver is written,   */
+                       .gpio0 = 0x00ff,        /* there is no way to deactivate audio pass-    */
+                       .gpio1 = 0xf39d,        /* through without this entry. Furthermore, if  */
+                       .gpio3 = 0x0000,        /* the TV mux entry is first, you get audio     */
+               }, {                            /* from the tuner on boot for a little while.   */
+                       .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_XC2028,
+               .tuner_addr     = 0x61,
+               .radio_type     = 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,
+               }},
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [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,
+               },
+       },
+       [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
+               .name           = "Prolink Pixelview Global Extreme",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0 = 0x04fb,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cf7,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0 = 0x04fb,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cfb,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0 = 0x04fb,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cfb,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0 = 0x04ff,
+                       .gpio1 = 0x04080,
+                       .gpio2 = 0x0cf7,
+               },
+       },
+       /* 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,
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR4000] = {
+               .name           = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .audio_chip     = V4L2_IDENT_WM8775,
+               /*
+                * GPIO0 (WINTV2000)
+                *
+                * Analogue     SAT     DVB-T
+                * Antenna      0xc4bf  0xc4bb
+                * Composite    0xc4bf  0xc4bb
+                * S-Video      0xc4bf  0xc4bb
+                * Composite1   0xc4ff  0xc4fb
+                * S-Video1     0xc4ff  0xc4fb
+                *
+                * BIT  VALUE   FUNCTION GP{x}_IO
+                * 0    1       I:?
+                * 1    1       I:?
+                * 2    1       O:MPEG PORT 0=DVB-T 1=DVB-S
+                * 3    1       I:?
+                * 4    1       I:?
+                * 5    1       I:?
+                * 6    0       O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
+                * 7    1       O:DVB-T DEMOD RESET LOW
+                *
+                * BIT  VALUE   FUNCTION GP{x}_OE
+                * 8    0       I
+                * 9    0       I
+                * a    1       O
+                * b    0       I
+                * c    0       I
+                * d    0       I
+                * e    1       O
+                * f    1       O
+                *
+                * WM8775 ADC
+                *
+                * 1: TV Audio / FM Mono
+                * 2: Line-In
+                * 3: Line-In Expansion
+                * 4: FM Stereo
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0xc4bf,
+                       /* 1: TV Audio / FM Mono */
+                       .audioroute = 1,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0xc4bf,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0xc4bf,
+                       /* 2: Line-In */
+                       .audioroute = 2,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0xc4bf,
+                       /* 4: FM Stereo */
+                       .audioroute = 8,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+               .num_frontends  = 2,
+       },
+       [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
+               .name           = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TEVII_S420] = {
+               .name           = "TeVii S420 DVB-S",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TEVII_S460] = {
+               .name           = "TeVii S460 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TEVII_S464] = {
+               .name           = "TeVii S464 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_OMICOM_SS4_PCI] = {
+               .name           = "Omicom SS4 DVB-S/S2 PCI",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TBS_8910] = {
+               .name           = "TBS 8910 DVB-S",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TBS_8920] = {
+               .name           = "TBS 8920 DVB-S/S2",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+                       .gpio0  = 0x8080,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PROF_6200] = {
+               .name           = "Prof 6200 DVB-S",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PROF_7300] = {
+               .name           = "PROF 7300 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_SATTRADE_ST4200] = {
+               .name           = "SATTRADE ST4200 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = {
+               .name           = "Terratec Cinergy HT PCI MKII",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_addr     = 0x61,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x00001,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x004fb,
+                       .gpio1  = 0x010ef,
+                       .audioroute = 1,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x004fb,
+                       .gpio1  = 0x010ef,
+                       .audioroute = 1,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x004ff,
+                       .gpio1  = 0x010ff,
+                       .gpio2  = 0x0ff,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_HAUPPAUGE_IRONLY] = {
+               .name           = "Hauppauge WinTV-IR Only",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+       },
+       [CX88_BOARD_WINFAST_DTV1800H] = {
+               .name           = "Leadtek WinFast DTV1800 Hybrid",
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
+               /*
+                * GPIO setting
+                *
+                *  2: mute (0=off,1=on)
+                * 12: tuner reset pin
+                * 13: audio source (0=tuner audio,1=line in)
+                * 14: FM (0=on,1=off ???)
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               } },
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
+                       .gpio2  = 0x0000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
+               .name           = "Leadtek WinFast DTV1800 H (XC4000)",
+               .tuner_type     = TUNER_XC4000,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
+               /*
+                * GPIO setting
+                *
+                *  2: mute (0=off,1=on)
+                * 12: tuner reset pin
+                * 13: audio source (0=tuner audio,1=line in)
+                * 14: FM (0=on,1=off ???)
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+                       .gpio2  = 0x0000,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0400,       /* pin 2 = 0 */
+                       .gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
+                       .gpio2  = 0x0000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
+               .name           = "Leadtek WinFast DTV2000 H PLUS",
+               .tuner_type     = TUNER_XC4000,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
+               /*
+                * GPIO
+                *   2: 1: mute audio
+                *  12: 0: reset XC4000
+                *  13: 1: audio input is line in (0: tuner)
+                *  14: 0: FM radio
+                *  16: 0: RF input is cable
+                */
+               .input          = {{
+                       .type   = CX88_VMUX_TELEVISION,
+                       .vmux   = 0,
+                       .gpio0  = 0x0403,
+                       .gpio1  = 0xF0D7,
+                       .gpio2  = 0x0101,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_CABLE,
+                       .vmux   = 0,
+                       .gpio0  = 0x0403,
+                       .gpio1  = 0xF0D7,
+                       .gpio2  = 0x0100,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_COMPOSITE1,
+                       .vmux   = 1,
+                       .gpio0  = 0x0403,       /* was 0x0407 */
+                       .gpio1  = 0xF0F7,
+                       .gpio2  = 0x0101,
+                       .gpio3  = 0x0000,
+               }, {
+                       .type   = CX88_VMUX_SVIDEO,
+                       .vmux   = 2,
+                       .gpio0  = 0x0403,       /* was 0x0407 */
+                       .gpio1  = 0xF0F7,
+                       .gpio2  = 0x0101,
+                       .gpio3  = 0x0000,
+               }},
+               .radio = {
+                       .type   = CX88_RADIO,
+                       .gpio0  = 0x0403,
+                       .gpio1  = 0xF097,
+                       .gpio2  = 0x0100,
+                       .gpio3  = 0x0000,
+               },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_PROF_7301] = {
+               .name           = "Prof 7301 DVB-S/S2",
+               .tuner_type     = UNSET,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = { {
+                       .type   = CX88_VMUX_DVB,
+                       .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+       [CX88_BOARD_TWINHAN_VP1027_DVBS] = {
+               .name           = "Twinhan VP-1027 DVB-S",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .input          = {{
+                      .type   = CX88_VMUX_DVB,
+                      .vmux   = 0,
+               } },
+               .mpeg           = CX88_MPEG_DVB,
+       },
+};
+
+/* ------------------------------------------------------------------ */
+/* PCI subsystem IDs                                                  */
+
+static const struct cx88_subid cx88_subids[] = {
+       {
+               .subvendor = 0x0070,
+               .subdevice = 0x3400,
+               .card      = CX88_BOARD_HAUPPAUGE,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x3401,
+               .card      = CX88_BOARD_HAUPPAUGE,
+       },{
+               .subvendor = 0x14c7,
+               .subdevice = 0x0106,
+               .card      = CX88_BOARD_GDI,
+       },{
+               .subvendor = 0x14c7,
+               .subdevice = 0x0107, /* with mpeg encoder */
+               .card      = CX88_BOARD_GDI,
+       },{
+               .subvendor = PCI_VENDOR_ID_ATI,
+               .subdevice = 0x00f8,
+               .card      = CX88_BOARD_ATI_WONDER_PRO,
+       }, {
+               .subvendor = PCI_VENDOR_ID_ATI,
+               .subdevice = 0x00f9,
+               .card      = CX88_BOARD_ATI_WONDER_PRO,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6611,
+               .card      = CX88_BOARD_WINFAST2000XP_EXPERT,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x6613,    /* NTSC */
+               .card      = CX88_BOARD_WINFAST2000XP_EXPERT,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x6620,
+               .card      = CX88_BOARD_WINFAST_DV2000,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x663b,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x663c,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       },{
+               .subvendor = 0x1461,
+               .subdevice = 0x000b,
+               .card      = CX88_BOARD_AVERTV_STUDIO_303,
+       },{
+               .subvendor = 0x1462,
+               .subdevice = 0x8606,
+               .card      = CX88_BOARD_MSI_TVANYWHERE_MASTER,
+       },{
+               .subvendor = 0x10fc,
+               .subdevice = 0xd003,
+               .card      = CX88_BOARD_IODATA_GVVCP3PCI,
+       },{
+               .subvendor = 0x1043,
+               .subdevice = 0x4823,  /* with mpeg encoder */
+               .card      = CX88_BOARD_ASUS_PVR_416,
+       },{
+               .subvendor = 0x17de,
+               .subdevice = 0x08a6,
+               .card      = CX88_BOARD_KWORLD_DVB_T,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xd810,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xd820,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb00,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9002,
+               .card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+       },{
+               .subvendor = 0x14f1,
+               .subdevice = 0x0187,
+               .card      = CX88_BOARD_CONEXANT_DVB_T1,
+       },{
+               .subvendor = 0x1540,
+               .subdevice = 0x2580,
+               .card      = CX88_BOARD_PROVIDEO_PV259,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb10,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+       },{
+               .subvendor = 0x1554,
+               .subdevice = 0x4811,
+               .card      = CX88_BOARD_PIXELVIEW,
+       },{
+               .subvendor = 0x7063,
+               .subdevice = 0x3000, /* HD-3000 card */
+               .card      = CX88_BOARD_PCHDTV_HD3000,
+       },{
+               .subvendor = 0x17de,
+               .subdevice = 0xa8a6,
+               .card      = CX88_BOARD_DNTV_LIVE_DVB_T,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x2801,
+               .card      = CX88_BOARD_HAUPPAUGE_ROSLYN,
+       },{
+               .subvendor = 0x14f1,
+               .subdevice = 0x0342,
+               .card      = CX88_BOARD_DIGITALLOGIC_MEC,
+       },{
+               .subvendor = 0x10fc,
+               .subdevice = 0xd035,
+               .card      = CX88_BOARD_IODATA_GVBCTV7E,
+       },{
+               .subvendor = 0x1421,
+               .subdevice = 0x0334,
+               .card      = CX88_BOARD_ADSTECH_DVB_T_PCI,
+       },{
+               .subvendor = 0x153b,
+               .subdevice = 0x1166,
+               .card      = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xd500,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
+       },{
+               .subvendor = 0x1461,
+               .subdevice = 0x8011,
+               .card      = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550,
+       },{
+               .subvendor = PCI_VENDOR_ID_ATI,
+               .subdevice = 0xa101,
+               .card      = CX88_BOARD_ATI_HDTVWONDER,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x665f,
+               .card      = CX88_BOARD_WINFAST_DTV1000,
+       },{
+               .subvendor = 0x1461,
+               .subdevice = 0x000a,
+               .card      = CX88_BOARD_AVERTV_303,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9200,
+               .card      = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9201,
+               .card      = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9202,
+               .card      = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+       },{
+               .subvendor = 0x17de,
+               .subdevice = 0x08b2,
+               .card      = CX88_BOARD_KWORLD_DVBS_100,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9400,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1100,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9402,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1100,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9800,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9802,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9001,
+               .card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+       },{
+               .subvendor = 0x1822,
+               .subdevice = 0x0025,
+               .card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+       },{
+               .subvendor = 0x17de,
+               .subdevice = 0x08a1,
+               .card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb50,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb54,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+               /* Re-branded DViCO: DigitalNow DVB-T Dual */
+       },{
+               .subvendor = 0x18ac,
+               .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,
+       },{
+               .subvendor = 0x1421,
+               .subdevice = 0x0305,
+               .card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb40,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xdb44,
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+       },{
+               .subvendor = 0x7063,
+               .subdevice = 0x5500,
+               .card      = CX88_BOARD_PCHDTV_HD5500,
+       },{
+               .subvendor = 0x17de,
+               .subdevice = 0x0841,
+               .card      = CX88_BOARD_KWORLD_MCE200_DELUXE,
+       },{
+               .subvendor = 0x1822,
+               .subdevice = 0x0019,
+               .card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+       },{
+               .subvendor = 0x1554,
+               .subdevice = 0x4813,
+               .card      = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
+       },{
+               .subvendor = 0x14f1,
+               .subdevice = 0x0842,
+               .card      = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x665e,
+               .card      = CX88_BOARD_WINFAST_DTV2000H,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x6f2b,
+               .card      = CX88_BOARD_WINFAST_DTV2000H_J,
+       },{
+               .subvendor = 0x18ac,
+               .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
+               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
+       },{
+               .subvendor = 0x14f1,
+               .subdevice = 0x0084,
+               .card      = CX88_BOARD_GENIATECH_DVBS,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x1404,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xdc00,
+               .card      = CX88_BOARD_SAMSUNG_SMT_7020,
+       }, {
+               .subvendor = 0x18ac,
+               .subdevice = 0xdccd,
+               .card      = CX88_BOARD_SAMSUNG_SMT_7020,
+       },{
+               .subvendor = 0x1461,
+               .subdevice = 0xc111, /* AverMedia M150-D */
+               /* This board is known to work with the ASUS PVR416 config */
+               .card      = CX88_BOARD_ASUS_PVR_416,
+       },{
+               .subvendor = 0xc180,
+               .subdevice = 0xc980,
+               .card      = CX88_BOARD_TE_DTV_250_OEM_SWANN,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9600,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9601,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9602,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+       },{
+               .subvendor = 0x107d,
+               .subdevice = 0x6632,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       },{
+               .subvendor = 0x12ab,
+               .subdevice = 0x2300, /* Club3D Zap TV2100 */
+               .card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x9000,
+               .card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x1400,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x1401,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+       },{
+               .subvendor = 0x0070,
+               .subdevice = 0x1402,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+       },{
+               .subvendor = 0x1421,
+               .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */
+               .card      = CX88_BOARD_KWORLD_DVBS_100,
+       },{
+               .subvendor = 0x1421,
+               .subdevice = 0x0390,
+               .card      = CX88_BOARD_ADSTECH_PTV_390,
+       },{
+               .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 = 0x1554,
+               .subdevice = 0x4976,
+               .card      = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
+       }, {
+               .subvendor = 0x17de,
+               .subdevice = 0x08c1,
+               .card      = CX88_BOARD_KWORLD_ATSC_120,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6900,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6904,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6902,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6905,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x6906,
+               .card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+       }, {
+               .subvendor = 0xd420,
+               .subdevice = 0x9022,
+               .card      = CX88_BOARD_TEVII_S420,
+       }, {
+               .subvendor = 0xd460,
+               .subdevice = 0x9022,
+               .card      = CX88_BOARD_TEVII_S460,
+       }, {
+               .subvendor = 0xd464,
+               .subdevice = 0x9022,
+               .card      = CX88_BOARD_TEVII_S464,
+       }, {
+               .subvendor = 0xA044,
+               .subdevice = 0x2011,
+               .card      = CX88_BOARD_OMICOM_SS4_PCI,
+       }, {
+               .subvendor = 0x8910,
+               .subdevice = 0x8888,
+               .card      = CX88_BOARD_TBS_8910,
+       }, {
+               .subvendor = 0x8920,
+               .subdevice = 0x8888,
+               .card      = CX88_BOARD_TBS_8920,
+       }, {
+               .subvendor = 0xb022,
+               .subdevice = 0x3022,
+               .card      = CX88_BOARD_PROF_6200,
+       }, {
+               .subvendor = 0xB033,
+               .subdevice = 0x3033,
+               .card      = CX88_BOARD_PROF_7300,
+       }, {
+               .subvendor = 0xb200,
+               .subdevice = 0x4200,
+               .card      = CX88_BOARD_SATTRADE_ST4200,
+       }, {
+               .subvendor = 0x153b,
+               .subdevice = 0x1177,
+               .card      = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x9290,
+               .card      = CX88_BOARD_HAUPPAUGE_IRONLY,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6654,
+               .card      = CX88_BOARD_WINFAST_DTV1800H,
+       }, {
+               /* WinFast DTV1800 H with XC4000 tuner */
+               .subvendor = 0x107d,
+               .subdevice = 0x6f38,
+               .card      = CX88_BOARD_WINFAST_DTV1800H_XC4000,
+       }, {
+               .subvendor = 0x107d,
+               .subdevice = 0x6f42,
+               .card      = CX88_BOARD_WINFAST_DTV2000H_PLUS,
+       }, {
+               /* PVR2000 PAL Model [107d:6630] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6630,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       }, {
+               /* PVR2000 PAL Model [107d:6638] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6638,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       }, {
+               /* PVR2000 NTSC Model [107d:6631] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6631,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       }, {
+               /* PVR2000 NTSC Model [107d:6637] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6637,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       }, {
+               /* PVR2000 NTSC Model [107d:663d] */
+               .subvendor = 0x107d,
+               .subdevice = 0x663d,
+               .card      = CX88_BOARD_LEADTEK_PVR2000,
+       }, {
+               /* DV2000 NTSC Model [107d:6621] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6621,
+               .card      = CX88_BOARD_WINFAST_DV2000,
+       }, {
+               /* TV2000 XP Global [107d:6618]  */
+               .subvendor = 0x107d,
+               .subdevice = 0x6618,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               /* TV2000 XP Global [107d:6618] */
+               .subvendor = 0x107d,
+               .subdevice = 0x6619,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+       }, {
+               /* WinFast TV2000 XP Global with XC4000 tuner */
+               .subvendor = 0x107d,
+               .subdevice = 0x6f36,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36,
+       }, {
+               /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */
+               .subvendor = 0x107d,
+               .subdevice = 0x6f43,
+               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43,
+       }, {
+               .subvendor = 0xb034,
+               .subdevice = 0x3034,
+               .card      = CX88_BOARD_PROF_7301,
+       }, {
+               .subvendor = 0x1822,
+               .subdevice = 0x0023,
+               .card      = CX88_BOARD_TWINHAN_VP1027_DVBS,
+       },
+};
+
+/* ----------------------------------------------------------------------- */
+/* some leadtek specific stuff                                             */
+
+static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
+{
+       if (eeprom_data[4] != 0x7d ||
+           eeprom_data[5] != 0x10 ||
+           eeprom_data[7] != 0x66) {
+               warn_printk(core, "Leadtek eeprom invalid.\n");
+               return;
+       }
+
+       /* Terry Wu <terrywu2009@gmail.com> */
+       switch (eeprom_data[6]) {
+       case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
+       case 0x21: /* SSID 6621 for DV2000 NTSC Model */
+       case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
+       case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
+       case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
+               core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
+               break;
+       default:
+               core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+               break;
+       }
+
+       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)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
+       core->board.tuner_type = tv.tuner_type;
+       core->tuner_formats = tv.tuner_formats;
+       core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
+
+       /* Make sure we support the board model */
+       switch (tv.model)
+       {
+       case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
+       case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
+       case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
+       case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */
+       case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */
+       case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */
+       case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
+       case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */
+       case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
+       case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
+       case 34519: /* WinTV-PCI-FM */
+       case 69009:
+               /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
+       case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
+       case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
+       case 69559:
+               /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
+       case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
+       case 90002: /* Nova-T-PCI (9002) */
+       case 92001: /* Nova-S-Plus (Video and IR) */
+       case 92002: /* Nova-S-Plus (Video and IR) */
+       case 90003: /* Nova-T-PCI (9002 No RF out) */
+       case 90500: /* Nova-T-PCI (oem) */
+       case 90501: /* Nova-T-PCI (oem/IR) */
+       case 92000: /* Nova-SE2 (OEM, No Video or IR) */
+       case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
+       case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
+       case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
+       case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
+       case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */
+       case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */
+       case 96569: /* WinTV-HVR1300 () */
+       case 96659: /* WinTV-HVR1300 () */
+       case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
+               /* known */
+               break;
+       case CX88_BOARD_SAMSUNG_SMT_7020:
+               cx_set(MO_GP0_IO, 0x008989FF);
+               break;
+       default:
+               warn_printk(core, "warning: unknown hauppauge model #%d\n",
+                           tv.model);
+               break;
+       }
+
+       info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
+}
+
+/* ----------------------------------------------------------------------- */
+/* some GDI (was: Modular Technology) specific stuff                       */
+
+static const struct {
+       int  id;
+       int  fm;
+       const char *name;
+} gdi_tuner[] = {
+       [ 0x01 ] = { .id   = TUNER_ABSENT,
+                    .name = "NTSC_M" },
+       [ 0x02 ] = { .id   = TUNER_ABSENT,
+                    .name = "PAL_B" },
+       [ 0x03 ] = { .id   = TUNER_ABSENT,
+                    .name = "PAL_I" },
+       [ 0x04 ] = { .id   = TUNER_ABSENT,
+                    .name = "PAL_D" },
+       [ 0x05 ] = { .id   = TUNER_ABSENT,
+                    .name = "SECAM" },
+
+       [ 0x10 ] = { .id   = TUNER_ABSENT,
+                    .fm   = 1,
+                    .name = "TEMIC_4049" },
+       [ 0x11 ] = { .id   = TUNER_TEMIC_4136FY5,
+                    .name = "TEMIC_4136" },
+       [ 0x12 ] = { .id   = TUNER_ABSENT,
+                    .name = "TEMIC_4146" },
+
+       [ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME,
+                    .fm   = 1,
+                    .name = "PHILIPS_FQ1216_MK3" },
+       [ 0x21 ] = { .id   = TUNER_ABSENT, .fm = 1,
+                    .name = "PHILIPS_FQ1236_MK3" },
+       [ 0x22 ] = { .id   = TUNER_ABSENT,
+                    .name = "PHILIPS_FI1236_MK3" },
+       [ 0x23 ] = { .id   = TUNER_ABSENT,
+                    .name = "PHILIPS_FI1216_MK3" },
+};
+
+static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+{
+       const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
+               ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
+
+       info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
+       if (NULL == name)
+               return;
+       core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
+       core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
+               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:
+               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;
+               default:
+                       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;
+}
+
+static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
+                                            int command, int arg)
+{
+       switch (command) {
+       case XC2028_TUNER_RESET:
+               /* GPIO 12 (xc3028 tuner reset) */
+               cx_set(MO_GP1_IO, 0x1010);
+               mdelay(50);
+               cx_clear(MO_GP1_IO, 0x10);
+               mdelay(50);
+               cx_set(MO_GP1_IO, 0x10);
+               mdelay(50);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
+                                                 int command, int arg)
+{
+       switch (command) {
+       case XC4000_TUNER_RESET:
+               /* GPIO 12 (xc4000 tuner reset) */
+               cx_set(MO_GP1_IO, 0x1010);
+               mdelay(50);
+               cx_clear(MO_GP1_IO, 0x10);
+               mdelay(75);
+               cx_set(MO_GP1_IO, 0x10);
+               mdelay(75);
+               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                                               */
+
+static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
+{
+       struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
+       int i, err;
+       static u8 init_bufs[13][5] = {
+               { 0x10, 0x00, 0x20, 0x01, 0x03 },
+               { 0x10, 0x10, 0x01, 0x00, 0x21 },
+               { 0x10, 0x10, 0x10, 0x00, 0xCA },
+               { 0x10, 0x10, 0x12, 0x00, 0x08 },
+               { 0x10, 0x10, 0x13, 0x00, 0x0A },
+               { 0x10, 0x10, 0x16, 0x01, 0xC0 },
+               { 0x10, 0x10, 0x22, 0x01, 0x3D },
+               { 0x10, 0x10, 0x73, 0x01, 0x2E },
+               { 0x10, 0x10, 0x72, 0x00, 0xC5 },
+               { 0x10, 0x10, 0x71, 0x01, 0x97 },
+               { 0x10, 0x10, 0x70, 0x00, 0x0F },
+               { 0x10, 0x10, 0xB0, 0x00, 0x01 },
+               { 0x03, 0x0C },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(init_bufs); i++) {
+               msg.buf = init_bufs[i];
+               msg.len = (i != 12 ? 5 : 2);
+               err = i2c_transfer(&core->i2c_adap, &msg, 1);
+               if (err != 1) {
+                       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_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:
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+               return cx88_pv_8000gt_callback(core, command, arg);
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               return cx88_dvico_xc2028_callback(core, command, arg);
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_WINFAST_DTV1800H:
+               return cx88_xc3028_winfast1800h_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;
+}
+
+static int cx88_xc4000_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       /* Board-specific callbacks */
+       switch (core->boardnr) {
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+               return cx88_xc4000_winfast2000h_plus_callback(core,
+                                                             command, arg);
+       }
+       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)    */
+
+static int cx88_xc5000_tuner_callback(struct cx88_core *core,
+                                     int command, int arg)
+{
+       switch (core->boardnr) {
+       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+               if (command == 0) { /* This is the reset command from xc5000 */
+
+                       /* djh - According to the engineer at PCTV Systems,
+                          the xc5000 reset pin is supposed to be on GPIO12.
+                          However, despite three nights of effort, pulling
+                          that GPIO low didn't reset the xc5000.  While
+                          pulling MO_SRST_IO low does reset the xc5000, this
+                          also resets in the s5h1409 being reset as well.
+                          This causes tuning to always fail since the internal
+                          state of the s5h1409 does not match the driver's
+                          state.  Given that the only two conditions in which
+                          the driver performs a reset is during firmware load
+                          and powering down the chip, I am taking out the
+                          reset.  We know that the chip is being reset
+                          when the cx88 comes online, and not being able to
+                          do power management for this board is worse than
+                          not having any tuning at all. */
+                       return 0;
+               } else {
+                       err_printk(core, "xc5000: unknown tuner "
+                                  "callback command.\n");
+                       return -EINVAL;
+               }
+               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;
+               }
+               break;
+       }
+       return 0; /* Should never be here */
+}
+
+int cx88_tuner_callback(void *priv, int component, 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;
+       }
+
+       if (component != DVB_FRONTEND_COMPONENT_TUNER)
+               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_XC4000:
+                       info_printk(core, "Calling XC4000 callback\n");
+                       return cx88_xc4000_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);
+
+/* ----------------------------------------------------------------------- */
+
+static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+{
+       int i;
+
+       if (0 == pci->subsystem_vendor &&
+           0 == pci->subsystem_device) {
+               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(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);
+       }
+       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(KERN_ERR "%s:    card=%d -> %s\n",
+                      core->name, i, cx88_boards[i].name);
+}
+
+static void cx88_card_setup_pre_i2c(struct cx88_core *core)
+{
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /*
+                * Bring the 702 demod up before i2c scanning/attach or devices are hidden
+                * We leave here with the 702 on the bus
+                *
+                * "reset the IR receiver on GPIO[3]"
+                * Reported by Mike Crash <mike AT mikecrash.com>
+                */
+               cx_write(MO_GP0_IO, 0x0000ef88);
+               udelay(1000);
+               cx_clear(MO_GP0_IO, 0x00000088);
+               udelay(50);
+               cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
+               udelay(1000);
+               break;
+
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+       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;
+
+       case CX88_BOARD_WINFAST_DTV2000H_J:
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+               /* Init GPIO */
+               cx_write(MO_GP0_IO, core->board.input[0].gpio0);
+               udelay(1000);
+               cx_clear(MO_GP0_IO, 0x00000080);
+               udelay(50);
+               cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+               udelay(1000);
+               break;
+
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_WINFAST_DTV1800H:
+               cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
+               break;
+
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+               cx88_xc4000_winfast2000h_plus_callback(core,
+                                                      XC4000_TUNER_RESET, 0);
+               break;
+
+       case CX88_BOARD_TWINHAN_VP1027_DVBS:
+               cx_write(MO_GP0_IO, 0x00003230);
+               cx_write(MO_GP0_IO, 0x00003210);
+               msleep(1);
+               cx_write(MO_GP0_IO, 0x00001230);
+               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:
+               /* Now works with firmware version 2.7 */
+               if (core->i2c_algo.udelay < 16)
+                       core->i2c_algo.udelay = 16;
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+       case CX88_BOARD_WINFAST_DTV1800H:
+               ctl->demod = 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_GENIATECH_X8000_MT:
+               /* FIXME: For this board, the xc3028 never recovers after being
+                  powered down (the reset GPIO probably is not set properly).
+                  We don't have access to the hardware so we cannot determine
+                  which GPIO is used for xc3028, so just disable power xc3028
+                  power management for now */
+               ctl->disable_power_mgmt = 1;
+               break;
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+       case CX88_BOARD_PROLINK_PV_8000GT:
+               /*
+                * Those boards uses non-MTS firmware
+                */
+               break;
+       case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+       case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
+               ctl->demod = XC3028_FE_ZARLINK456;
+               ctl->mts = 1;
+               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];
+       struct tuner_setup tun_setup;
+       unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
+
+       if (0 == core->i2c_rc) {
+               core->i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
+       }
+
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE:
+       case CX88_BOARD_HAUPPAUGE_ROSLYN:
+               if (0 == core->i2c_rc)
+                       hauppauge_eeprom(core, eeprom+8);
+               break;
+       case CX88_BOARD_GDI:
+               if (0 == core->i2c_rc)
+                       gdi_eeprom(core, eeprom);
+               break;
+       case CX88_BOARD_LEADTEK_PVR2000:
+       case CX88_BOARD_WINFAST_DV2000:
+       case CX88_BOARD_WINFAST2000XP_EXPERT:
+               if (0 == core->i2c_rc)
+                       leadtek_eeprom(core, eeprom);
+               break;
+       case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+       case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+       case CX88_BOARD_HAUPPAUGE_DVB_T1:
+       case CX88_BOARD_HAUPPAUGE_HVR1100:
+       case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+       case CX88_BOARD_HAUPPAUGE_IRONLY:
+               if (0 == core->i2c_rc)
+                       hauppauge_eeprom(core, eeprom);
+               break;
+       case CX88_BOARD_KWORLD_DVBS_100:
+               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);
+               cx_clear(MO_GP0_IO, 0x00000040);
+               msleep(1000);
+               cx_set(MO_GP0_IO, 0x00004040);
+               /* FALLTHROUGH */
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+               /* GPIO0:0 is hooked to mt352 reset pin */
+               cx_set(MO_GP0_IO, 0x00000101);
+               cx_clear(MO_GP0_IO, 0x00000001);
+               msleep(1);
+               cx_set(MO_GP0_IO, 0x00000101);
+               if (0 == core->i2c_rc &&
+                   core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
+                       dvico_fusionhdtv_hybrid_init(core);
+               break;
+       case CX88_BOARD_KWORLD_DVB_T:
+       case CX88_BOARD_DNTV_LIVE_DVB_T:
+               cx_set(MO_GP0_IO, 0x00000707);
+               cx_set(MO_GP2_IO, 0x00000101);
+               cx_clear(MO_GP2_IO, 0x00000001);
+               msleep(1);
+               cx_clear(MO_GP0_IO, 0x00000007);
+               cx_set(MO_GP2_IO, 0x00000101);
+               break;
+       case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+               cx_write(MO_GP0_IO, 0x00080808);
+               break;
+       case CX88_BOARD_ATI_HDTVWONDER:
+               if (0 == core->i2c_rc) {
+                       /* enable tuner */
+                       int i;
+                       static const u8 buffer [][2] = {
+                               {0x10,0x12},
+                               {0x13,0x04},
+                               {0x16,0x00},
+                               {0x14,0x04},
+                               {0x17,0x00}
+                       };
+                       core->i2c_client.addr = 0x0a;
+
+                       for (i = 0; i < ARRAY_SIZE(buffer); i++)
+                               if (2 != i2c_master_send(&core->i2c_client,
+                                                       buffer[i],2))
+                                       warn_printk(core, "Unable to enable "
+                                                   "tuner(%i).\n", i);
+               }
+               break;
+       case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+       {
+               struct v4l2_priv_tun_config tea5767_cfg;
+               struct tea5767_ctrl ctl;
+
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.high_cut  = 1;
+               ctl.st_noise  = 1;
+               ctl.deemph_75 = 1;
+               ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
+
+               tea5767_cfg.tuner = TUNER_TEA5767;
+               tea5767_cfg.priv  = &ctl;
+
+               call_all(core, tuner, s_config, &tea5767_cfg);
+               break;
+       }
+       case  CX88_BOARD_TEVII_S420:
+       case  CX88_BOARD_TEVII_S460:
+       case  CX88_BOARD_TEVII_S464:
+       case  CX88_BOARD_OMICOM_SS4_PCI:
+       case  CX88_BOARD_TBS_8910:
+       case  CX88_BOARD_TBS_8920:
+       case  CX88_BOARD_PROF_6200:
+       case  CX88_BOARD_PROF_7300:
+       case  CX88_BOARD_PROF_7301:
+       case  CX88_BOARD_SATTRADE_ST4200:
+               cx_write(MO_GP0_IO, 0x8000);
+               msleep(100);
+               cx_write(MO_SRST_IO, 0);
+               msleep(10);
+               cx_write(MO_GP0_IO, 0x8080);
+               msleep(100);
+               cx_write(MO_SRST_IO, 1);
+               msleep(100);
+               break;
+       } /*end switch() */
+
+
+       /* Setup tuners */
+       if ((core->board.radio_type != UNSET)) {
+               tun_setup.mode_mask      = T_RADIO;
+               tun_setup.type           = core->board.radio_type;
+               tun_setup.addr           = core->board.radio_addr;
+               tun_setup.tuner_callback = cx88_tuner_callback;
+               call_all(core, tuner, s_type_addr, &tun_setup);
+               mode_mask &= ~T_RADIO;
+       }
+
+       if (core->board.tuner_type != TUNER_ABSENT) {
+               tun_setup.mode_mask      = mode_mask;
+               tun_setup.type           = core->board.tuner_type;
+               tun_setup.addr           = core->board.tuner_addr;
+               tun_setup.tuner_callback = cx88_tuner_callback;
+
+               call_all(core, tuner, s_type_addr, &tun_setup);
+       }
+
+       if (core->board.tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv  = &core->board.tda9887_conf;
+
+               call_all(core, tuner, s_config, &tda9887_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);
+               call_all(core, tuner, s_config, &xc2028_cfg);
+       }
+       call_all(core, core, s_power, 0);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int cx88_pci_quirks(const char *name, struct pci_dev *pci)
+{
+       unsigned int lat = UNSET;
+       u8 ctrl = 0;
+       u8 value;
+
+       /* check pci quirks */
+       if (pci_pci_problems & PCIPCI_TRITON) {
+               printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
+                      name);
+               ctrl |= CX88X_EN_TBFX;
+       }
+       if (pci_pci_problems & PCIPCI_NATOMA) {
+               printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
+                      name);
+               ctrl |= CX88X_EN_TBFX;
+       }
+       if (pci_pci_problems & PCIPCI_VIAETBF) {
+               printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
+                      name);
+               ctrl |= CX88X_EN_TBFX;
+       }
+       if (pci_pci_problems & PCIPCI_VSFX) {
+               printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
+                      name);
+               ctrl |= CX88X_EN_VSFX;
+       }
+#ifdef PCIPCI_ALIMAGIK
+       if (pci_pci_problems & PCIPCI_ALIMAGIK) {
+               printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
+                      name);
+               lat = 0x0A;
+       }
+#endif
+
+       /* check insmod options */
+       if (UNSET != latency)
+               lat = latency;
+
+       /* apply stuff */
+       if (ctrl) {
+               pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
+               value |= ctrl;
+               pci_write_config_byte(pci, CX88X_DEVCTRL, value);
+       }
+       if (UNSET != lat) {
+               printk(KERN_INFO "%s: setting pci latency timer to %d\n",
+                      name, latency);
+               pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
+       }
+       return 0;
+}
+
+int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci)
+{
+       if (request_mem_region(pci_resource_start(pci,0),
+                              pci_resource_len(pci,0),
+                              core->name))
+               return 0;
+       printk(KERN_ERR
+              "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
+              core->name, PCI_FUNC(pci->devfn),
+              (unsigned long long)pci_resource_start(pci, 0),
+              pci->subsystem_vendor, pci->subsystem_device);
+       return -EBUSY;
+}
+
+/* Allocate and initialize the cx88 core struct.  One should hold the
+ * devlist mutex before calling this.  */
+struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+{
+       struct cx88_core *core;
+       int i;
+
+       core = kzalloc(sizeof(*core), GFP_KERNEL);
+       if (core == NULL)
+               return NULL;
+
+       atomic_inc(&core->refcount);
+       core->pci_bus  = pci->bus->number;
+       core->pci_slot = PCI_SLOT(pci->devfn);
+       core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT |
+                           PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT |
+                           PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT;
+       mutex_init(&core->lock);
+
+       core->nr = nr;
+       sprintf(core->name, "cx88[%d]", core->nr);
+
+       strcpy(core->v4l2_dev.name, core->name);
+       if (v4l2_device_register(NULL, &core->v4l2_dev)) {
+               kfree(core);
+               return NULL;
+       }
+
+       if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
+               v4l2_device_unregister(&core->v4l2_dev);
+               kfree(core);
+               return NULL;
+       }
+
+       if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
+               v4l2_ctrl_handler_free(&core->video_hdl);
+               v4l2_device_unregister(&core->v4l2_dev);
+               kfree(core);
+               return NULL;
+       }
+
+       if (0 != cx88_get_resources(core, pci)) {
+               v4l2_ctrl_handler_free(&core->video_hdl);
+               v4l2_ctrl_handler_free(&core->audio_hdl);
+               v4l2_device_unregister(&core->v4l2_dev);
+               kfree(core);
+               return NULL;
+       }
+
+       /* PCI stuff */
+       cx88_pci_quirks(core->name, pci);
+       core->lmmio = ioremap(pci_resource_start(pci, 0),
+                             pci_resource_len(pci, 0));
+       core->bmmio = (u8 __iomem *)core->lmmio;
+
+       if (core->lmmio == NULL) {
+               release_mem_region(pci_resource_start(pci, 0),
+                          pci_resource_len(pci, 0));
+               v4l2_ctrl_handler_free(&core->video_hdl);
+               v4l2_ctrl_handler_free(&core->audio_hdl);
+               v4l2_device_unregister(&core->v4l2_dev);
+               kfree(core);
+               return NULL;
+       }
+
+       /* board config */
+       core->boardnr = UNSET;
+       if (card[core->nr] < ARRAY_SIZE(cx88_boards))
+               core->boardnr = card[core->nr];
+       for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++)
+               if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
+                   pci->subsystem_device == cx88_subids[i].subdevice)
+                       core->boardnr = cx88_subids[i].card;
+       if (UNSET == core->boardnr) {
+               core->boardnr = CX88_BOARD_UNKNOWN;
+               cx88_card_list(core, pci);
+       }
+
+       memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
+
+       if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
+               core->board.num_frontends = 1;
+
+       info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
+               pci->subsystem_vendor, pci->subsystem_device, core->board.name,
+               core->boardnr, card[core->nr] == core->boardnr ?
+               "insmod option" : "autodetected",
+               core->board.num_frontends);
+
+       if (tuner[core->nr] != UNSET)
+               core->board.tuner_type = tuner[core->nr];
+       if (radio[core->nr] != UNSET)
+               core->board.radio_type = radio[core->nr];
+
+       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);
+       cx88_card_setup_pre_i2c(core);
+       cx88_i2c_init(core, pci);
+
+       /* load tuner module, if needed */
+       if (TUNER_ABSENT != core->board.tuner_type) {
+               /* Ignore 0x6b and 0x6f on cx88 boards.
+                * FusionHDTV5 RT Gold has an ir receiver at 0x6b
+                * and an RTC at 0x6f which can get corrupted if probed. */
+               static const unsigned short tv_addrs[] = {
+                       0x42, 0x43, 0x4a, 0x4b,         /* tda8290 */
+                       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+                       0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e,
+                       I2C_CLIENT_END
+               };
+               int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
+
+               /* I don't trust the radio_type as is stored in the card
+                  definitions, so we just probe for it.
+                  The radio_type is sometimes missing, or set to UNSET but
+                  later code configures a tea5767.
+                */
+               v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
+                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+               if (has_demod)
+                       v4l2_i2c_new_subdev(&core->v4l2_dev,
+                               &core->i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+               if (core->board.tuner_addr == ADDR_UNSET) {
+                       v4l2_i2c_new_subdev(&core->v4l2_dev,
+                               &core->i2c_adap, "tuner",
+                               0, has_demod ? tv_addrs + 4 : tv_addrs);
+               } else {
+                       v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
+                               "tuner", core->board.tuner_addr, NULL);
+               }
+       }
+
+       cx88_card_setup(core);
+       if (!disable_ir) {
+               cx88_i2c_init_ir(core);
+               cx88_ir_init(core, pci);
+       }
+
+       return core;
+}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
new file mode 100644 (file)
index 0000000..c97b174
--- /dev/null
@@ -0,0 +1,1131 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * driver core
+ *
+ * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     - Multituner support
+ *     - video_ioctl2 conversion
+ *     - PAL/M fixes
+ *
+ *  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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/sound.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+
+#include "cx88.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int core_debug;
+module_param(core_debug,int,0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+static unsigned int nicam;
+module_param(nicam,int,0644);
+MODULE_PARM_DESC(nicam,"tv audio is nicam");
+
+static unsigned int nocomb;
+module_param(nocomb,int,0644);
+MODULE_PARM_DESC(nocomb,"disable comb filter");
+
+#define dprintk(level,fmt, arg...)     if (core_debug >= level)        \
+       printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
+
+static unsigned int cx88_devcount;
+static LIST_HEAD(cx88_devlist);
+static DEFINE_MUTEX(devlist);
+
+#define NO_SYNC_LINE (-1U)
+
+/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
+        generated _after_ lpi lines are transferred. */
+static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
+                           unsigned int offset, u32 sync_line,
+                           unsigned int bpl, unsigned int padding,
+                           unsigned int lines, unsigned int lpi)
+{
+       struct scatterlist *sg;
+       unsigned int line,todo,sol;
+
+       /* sync instruction */
+       if (sync_line != NO_SYNC_LINE)
+               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+       /* scan lines */
+       sg = sglist;
+       for (line = 0; line < lines; line++) {
+               while (offset && offset >= sg_dma_len(sg)) {
+                       offset -= sg_dma_len(sg);
+                       sg++;
+               }
+               if (lpi && line>0 && !(line % lpi))
+                       sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+               else
+                       sol = RISC_SOL;
+               if (bpl <= sg_dma_len(sg)-offset) {
+                       /* fits into current chunk */
+                       *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+                       offset+=bpl;
+               } else {
+                       /* scanline needs to be split */
+                       todo = bpl;
+                       *(rp++)=cpu_to_le32(RISC_WRITE|sol|
+                                           (sg_dma_len(sg)-offset));
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+                       todo -= (sg_dma_len(sg)-offset);
+                       offset = 0;
+                       sg++;
+                       while (todo > sg_dma_len(sg)) {
+                               *(rp++)=cpu_to_le32(RISC_WRITE|
+                                                   sg_dma_len(sg));
+                               *(rp++)=cpu_to_le32(sg_dma_address(sg));
+                               todo -= sg_dma_len(sg);
+                               sg++;
+                       }
+                       *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+                       *(rp++)=cpu_to_le32(sg_dma_address(sg));
+                       offset += todo;
+               }
+               offset += padding;
+       }
+
+       return rp;
+}
+
+int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                    struct scatterlist *sglist,
+                    unsigned int top_offset, unsigned int bottom_offset,
+                    unsigned int bpl, unsigned int padding, unsigned int lines)
+{
+       u32 instructions,fields;
+       __le32 *rp;
+       int rc;
+
+       fields = 0;
+       if (UNSET != top_offset)
+               fields++;
+       if (UNSET != bottom_offset)
+               fields++;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Padding
+          can cause next bpl to start close to a page border.  First DMA
+          region may be smaller than PAGE_SIZE */
+       instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+       instructions += 2;
+       if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       if (UNSET != top_offset)
+               rp = cx88_risc_field(rp, sglist, top_offset, 0,
+                                    bpl, padding, lines, 0);
+       if (UNSET != bottom_offset)
+               rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
+                                    bpl, padding, lines, 0);
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+       return 0;
+}
+
+int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                        struct scatterlist *sglist, unsigned int bpl,
+                        unsigned int lines, unsigned int lpi)
+{
+       u32 instructions;
+       __le32 *rp;
+       int rc;
+
+       /* estimate risc mem: worst case is one write per page border +
+          one write per scan line + syncs + jump (all 2 dwords).  Here
+          there is no padding and no sync.  First DMA region may be smaller
+          than PAGE_SIZE */
+       instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
+       instructions += 1;
+       if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
+
+       /* save pointer to jmp instruction address */
+       risc->jmp = rp;
+       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+       return 0;
+}
+
+int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+                     u32 reg, u32 mask, u32 value)
+{
+       __le32 *rp;
+       int rc;
+
+       if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+               return rc;
+
+       /* write risc instructions */
+       rp = risc->cpu;
+       *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
+       *(rp++) = cpu_to_le32(reg);
+       *(rp++) = cpu_to_le32(value);
+       *(rp++) = cpu_to_le32(mask);
+       *(rp++) = cpu_to_le32(RISC_JUMP);
+       *(rp++) = cpu_to_le32(risc->dma);
+       return 0;
+}
+
+void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+{
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+       BUG_ON(in_interrupt());
+       videobuf_waiton(q, &buf->vb, 0, 0);
+       videobuf_dma_unmap(q->dev, dma);
+       videobuf_dma_free(dma);
+       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+/* ------------------------------------------------------------------ */
+/* our SRAM memory layout                                             */
+
+/* we are going to put all thr risc programs into host memory, so we
+ * can use the whole SDRAM for the DMA fifos.  To simplify things, we
+ * use a static memory layout.  That surely will waste memory in case
+ * we don't use all DMA channels at the same time (which will be the
+ * case most of the time).  But that still gives us enough FIFO space
+ * to be able to deal with insane long pci latencies ...
+ *
+ * FIFO space allocations:
+ *    channel  21    (y video)  - 10.0k
+ *    channel  22    (u video)  -  2.0k
+ *    channel  23    (v video)  -  2.0k
+ *    channel  24    (vbi)      -  4.0k
+ *    channels 25+26 (audio)    -  4.0k
+ *    channel  28    (mpeg)     -  4.0k
+ *    channel  27    (audio rds)-  3.0k
+ *    TOTAL                     = 29.0k
+ *
+ * Every channel has 160 bytes control data (64 bytes instruction
+ * queue and 6 CDT entries), which is close to 2k total.
+ *
+ * Address layout:
+ *    0x0000 - 0x03ff    CMDs / reserved
+ *    0x0400 - 0x0bff    instruction queues + CDs
+ *    0x0c00 -           FIFOs
+ */
+
+const struct sram_channel cx88_sram_channels[] = {
+       [SRAM_CH21] = {
+               .name       = "video y / packed",
+               .cmds_start = 0x180040,
+               .ctrl_start = 0x180400,
+               .cdt        = 0x180400 + 64,
+               .fifo_start = 0x180c00,
+               .fifo_size  = 0x002800,
+               .ptr1_reg   = MO_DMA21_PTR1,
+               .ptr2_reg   = MO_DMA21_PTR2,
+               .cnt1_reg   = MO_DMA21_CNT1,
+               .cnt2_reg   = MO_DMA21_CNT2,
+       },
+       [SRAM_CH22] = {
+               .name       = "video u",
+               .cmds_start = 0x180080,
+               .ctrl_start = 0x1804a0,
+               .cdt        = 0x1804a0 + 64,
+               .fifo_start = 0x183400,
+               .fifo_size  = 0x000800,
+               .ptr1_reg   = MO_DMA22_PTR1,
+               .ptr2_reg   = MO_DMA22_PTR2,
+               .cnt1_reg   = MO_DMA22_CNT1,
+               .cnt2_reg   = MO_DMA22_CNT2,
+       },
+       [SRAM_CH23] = {
+               .name       = "video v",
+               .cmds_start = 0x1800c0,
+               .ctrl_start = 0x180540,
+               .cdt        = 0x180540 + 64,
+               .fifo_start = 0x183c00,
+               .fifo_size  = 0x000800,
+               .ptr1_reg   = MO_DMA23_PTR1,
+               .ptr2_reg   = MO_DMA23_PTR2,
+               .cnt1_reg   = MO_DMA23_CNT1,
+               .cnt2_reg   = MO_DMA23_CNT2,
+       },
+       [SRAM_CH24] = {
+               .name       = "vbi",
+               .cmds_start = 0x180100,
+               .ctrl_start = 0x1805e0,
+               .cdt        = 0x1805e0 + 64,
+               .fifo_start = 0x184400,
+               .fifo_size  = 0x001000,
+               .ptr1_reg   = MO_DMA24_PTR1,
+               .ptr2_reg   = MO_DMA24_PTR2,
+               .cnt1_reg   = MO_DMA24_CNT1,
+               .cnt2_reg   = MO_DMA24_CNT2,
+       },
+       [SRAM_CH25] = {
+               .name       = "audio from",
+               .cmds_start = 0x180140,
+               .ctrl_start = 0x180680,
+               .cdt        = 0x180680 + 64,
+               .fifo_start = 0x185400,
+               .fifo_size  = 0x001000,
+               .ptr1_reg   = MO_DMA25_PTR1,
+               .ptr2_reg   = MO_DMA25_PTR2,
+               .cnt1_reg   = MO_DMA25_CNT1,
+               .cnt2_reg   = MO_DMA25_CNT2,
+       },
+       [SRAM_CH26] = {
+               .name       = "audio to",
+               .cmds_start = 0x180180,
+               .ctrl_start = 0x180720,
+               .cdt        = 0x180680 + 64,  /* same as audio IN */
+               .fifo_start = 0x185400,       /* same as audio IN */
+               .fifo_size  = 0x001000,       /* same as audio IN */
+               .ptr1_reg   = MO_DMA26_PTR1,
+               .ptr2_reg   = MO_DMA26_PTR2,
+               .cnt1_reg   = MO_DMA26_CNT1,
+               .cnt2_reg   = MO_DMA26_CNT2,
+       },
+       [SRAM_CH28] = {
+               .name       = "mpeg",
+               .cmds_start = 0x180200,
+               .ctrl_start = 0x1807C0,
+               .cdt        = 0x1807C0 + 64,
+               .fifo_start = 0x186400,
+               .fifo_size  = 0x001000,
+               .ptr1_reg   = MO_DMA28_PTR1,
+               .ptr2_reg   = MO_DMA28_PTR2,
+               .cnt1_reg   = MO_DMA28_CNT1,
+               .cnt2_reg   = MO_DMA28_CNT2,
+       },
+       [SRAM_CH27] = {
+               .name       = "audio rds",
+               .cmds_start = 0x1801C0,
+               .ctrl_start = 0x180860,
+               .cdt        = 0x180860 + 64,
+               .fifo_start = 0x187400,
+               .fifo_size  = 0x000C00,
+               .ptr1_reg   = MO_DMA27_PTR1,
+               .ptr2_reg   = MO_DMA27_PTR2,
+               .cnt1_reg   = MO_DMA27_CNT1,
+               .cnt2_reg   = MO_DMA27_CNT2,
+       },
+};
+
+int cx88_sram_channel_setup(struct cx88_core *core,
+                           const struct sram_channel *ch,
+                           unsigned int bpl, u32 risc)
+{
+       unsigned int i,lines;
+       u32 cdt;
+
+       bpl   = (bpl + 7) & ~7; /* alignment */
+       cdt   = ch->cdt;
+       lines = ch->fifo_size / bpl;
+       if (lines > 6)
+               lines = 6;
+       BUG_ON(lines < 2);
+
+       /* write CDT */
+       for (i = 0; i < lines; i++)
+               cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+
+       /* write CMDS */
+       cx_write(ch->cmds_start +  0, risc);
+       cx_write(ch->cmds_start +  4, cdt);
+       cx_write(ch->cmds_start +  8, (lines*16) >> 3);
+       cx_write(ch->cmds_start + 12, ch->ctrl_start);
+       cx_write(ch->cmds_start + 16, 64 >> 2);
+       for (i = 20; i < 64; i += 4)
+               cx_write(ch->cmds_start + i, 0);
+
+       /* fill registers */
+       cx_write(ch->ptr1_reg, ch->fifo_start);
+       cx_write(ch->ptr2_reg, cdt);
+       cx_write(ch->cnt1_reg, (bpl >> 3) -1);
+       cx_write(ch->cnt2_reg, (lines*16) >> 3);
+
+       dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* debug helper code                                                  */
+
+static int cx88_risc_decode(u32 risc)
+{
+       static const char * const 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",
+       };
+       static int const incr[16] = {
+               [ RISC_WRITE   >> 28 ] = 2,
+               [ RISC_JUMP    >> 28 ] = 2,
+               [ RISC_WRITERM >> 28 ] = 3,
+               [ RISC_WRITECM >> 28 ] = 3,
+               [ RISC_WRITECR >> 28 ] = 4,
+       };
+       static const char * const bits[] = {
+               "12",   "13",   "14",   "resync",
+               "cnt0", "cnt1", "18",   "19",
+               "20",   "21",   "22",   "23",
+               "irq1", "irq2", "eol",  "sol",
+       };
+       int i;
+
+       printk("0x%08x [ %s", risc,
+              instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+       for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
+               if (risc & (1 << (i + 12)))
+                       printk(" %s",bits[i]);
+       printk(" count=%d ]\n", risc & 0xfff);
+       return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+
+void cx88_sram_channel_dump(struct cx88_core *core,
+                           const struct sram_channel *ch)
+{
+       static const char * const name[] = {
+               "initial risc",
+               "cdt base",
+               "cdt size",
+               "iq base",
+               "iq size",
+               "risc pc",
+               "iq wr ptr",
+               "iq rd ptr",
+               "cdt current",
+               "pci target",
+               "line / byte",
+       };
+       u32 risc;
+       unsigned int i,j,n;
+
+       printk("%s: %s - dma channel status dump\n",
+              core->name,ch->name);
+       for (i = 0; i < ARRAY_SIZE(name); i++)
+               printk("%s:   cmds: %-12s: 0x%08x\n",
+                      core->name,name[i],
+                      cx_read(ch->cmds_start + 4*i));
+       for (n = 1, i = 0; i < 4; i++) {
+               risc = cx_read(ch->cmds_start + 4 * (i+11));
+               printk("%s:   risc%d: ", core->name, i);
+               if (--n)
+                       printk("0x%08x [ arg #%d ]\n", risc, n);
+               else
+                       n = cx88_risc_decode(risc);
+       }
+       for (i = 0; i < 16; i += n) {
+               risc = cx_read(ch->ctrl_start + 4 * i);
+               printk("%s:   iq %x: ", core->name, i);
+               n = cx88_risc_decode(risc);
+               for (j = 1; j < n; j++) {
+                       risc = cx_read(ch->ctrl_start + 4 * (i+j));
+                       printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
+                              core->name, i+j, risc, j);
+               }
+       }
+
+       printk("%s: fifo: 0x%08x -> 0x%x\n",
+              core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
+       printk("%s: ctrl: 0x%08x -> 0x%x\n",
+              core->name, ch->ctrl_start, ch->ctrl_start+6*16);
+       printk("%s:   ptr1_reg: 0x%08x\n",
+              core->name,cx_read(ch->ptr1_reg));
+       printk("%s:   ptr2_reg: 0x%08x\n",
+              core->name,cx_read(ch->ptr2_reg));
+       printk("%s:   cnt1_reg: 0x%08x\n",
+              core->name,cx_read(ch->cnt1_reg));
+       printk("%s:   cnt2_reg: 0x%08x\n",
+              core->name,cx_read(ch->cnt2_reg));
+}
+
+static const char *cx88_pci_irqs[32] = {
+       "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
+       "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
+       "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
+       "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
+};
+
+void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
+                       int len, u32 bits, u32 mask)
+{
+       unsigned int i;
+
+       printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
+       for (i = 0; i < len; i++) {
+               if (!(bits & (1 << i)))
+                       continue;
+               if (strings[i])
+                       printk(" %s", strings[i]);
+               else
+                       printk(" %d", i);
+               if (!(mask & (1 << i)))
+                       continue;
+               printk("*");
+       }
+       printk("\n");
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx88_core_irq(struct cx88_core *core, u32 status)
+{
+       int handled = 0;
+
+       if (status & PCI_INT_IR_SMPINT) {
+               cx88_ir_irq(core);
+               handled++;
+       }
+       if (!handled)
+               cx88_print_irqbits(core->name, "irq pci",
+                                  cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
+                                  status, core->pci_irqmask);
+       return handled;
+}
+
+void cx88_wakeup(struct cx88_core *core,
+                struct cx88_dmaqueue *q, u32 count)
+{
+       struct cx88_buffer *buf;
+       int bc;
+
+       for (bc = 0;; bc++) {
+               if (list_empty(&q->active))
+                       break;
+               buf = list_entry(q->active.next,
+                                struct cx88_buffer, vb.queue);
+               /* count comes from the hw and is is 16bit wide --
+                * this trick handles wrap-arounds correctly for
+                * up to 32767 buffers in flight... */
+               if ((s16) (count - buf->count) < 0)
+                       break;
+               do_gettimeofday(&buf->vb.ts);
+               dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
+                       count, buf->count);
+               buf->vb.state = VIDEOBUF_DONE;
+               list_del(&buf->vb.queue);
+               wake_up(&buf->vb.done);
+       }
+       if (list_empty(&q->active)) {
+               del_timer(&q->timeout);
+       } else {
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+       }
+       if (bc != 1)
+               dprintk(2, "%s: %d buffers handled (should be 1)\n",
+                       __func__, bc);
+}
+
+void cx88_shutdown(struct cx88_core *core)
+{
+       /* disable RISC controller + IRQs */
+       cx_write(MO_DEV_CNTRL2, 0);
+
+       /* stop dma transfers */
+       cx_write(MO_VID_DMACNTRL, 0x0);
+       cx_write(MO_AUD_DMACNTRL, 0x0);
+       cx_write(MO_TS_DMACNTRL, 0x0);
+       cx_write(MO_VIP_DMACNTRL, 0x0);
+       cx_write(MO_GPHST_DMACNTRL, 0x0);
+
+       /* stop interrupts */
+       cx_write(MO_PCI_INTMSK, 0x0);
+       cx_write(MO_VID_INTMSK, 0x0);
+       cx_write(MO_AUD_INTMSK, 0x0);
+       cx_write(MO_TS_INTMSK, 0x0);
+       cx_write(MO_VIP_INTMSK, 0x0);
+       cx_write(MO_GPHST_INTMSK, 0x0);
+
+       /* stop capturing */
+       cx_write(VID_CAPTURE_CONTROL, 0);
+}
+
+int cx88_reset(struct cx88_core *core)
+{
+       dprintk(1,"%s\n",__func__);
+       cx88_shutdown(core);
+
+       /* clear irq status */
+       cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
+       cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
+       cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int
+
+       /* wait a bit */
+       msleep(100);
+
+       /* init sram */
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
+
+       /* misc init ... */
+       cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
+                                  (1 << 12) |   // agc gain
+                                  (1 << 11) |   // adaptibe agc
+                                  (0 << 10) |   // chroma agc
+                                  (0 <<  9) |   // ckillen
+                                  (7)));
+
+       /* setup image format */
+       cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
+
+       /* setup FIFO Thresholds */
+       cx_write(MO_PDMA_STHRSH,   0x0807);
+       cx_write(MO_PDMA_DTHRSH,   0x0807);
+
+       /* fixes flashing of image */
+       cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
+       cx_write(MO_AGC_BACK_VBI,  0x00E00555);
+
+       cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int
+       cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
+       cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
+
+       /* Reset on-board parts */
+       cx_write(MO_SRST_IO, 0);
+       msleep(10);
+       cx_write(MO_SRST_IO, 1);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int inline norm_swidth(v4l2_std_id norm)
+{
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
+}
+
+static unsigned int inline norm_hdelay(v4l2_std_id norm)
+{
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
+}
+
+static unsigned int inline norm_vdelay(v4l2_std_id norm)
+{
+       return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
+}
+
+static unsigned int inline norm_fsc8(v4l2_std_id norm)
+{
+       if (norm & V4L2_STD_PAL_M)
+               return 28604892;      // 3.575611 MHz
+
+       if (norm & (V4L2_STD_PAL_Nc))
+               return 28656448;      // 3.582056 MHz
+
+       if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
+               return 28636360;      // 3.57954545 MHz +/- 10 Hz
+
+       /* SECAM have also different sub carrier for chroma,
+          but step_db and step_dr, at cx88_set_tvnorm already handles that.
+
+          The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
+        */
+
+       return 35468950;      // 4.43361875 MHz +/- 5 Hz
+}
+
+static unsigned int inline norm_htotal(v4l2_std_id norm)
+{
+
+       unsigned int fsc4=norm_fsc8(norm)/2;
+
+       /* returns 4*FSC / vtotal / frames per seconds */
+       return (norm & V4L2_STD_625_50) ?
+                               ((fsc4+312)/625+12)/25 :
+                               ((fsc4+262)/525*1001+15000)/30000;
+}
+
+static unsigned int inline norm_vbipack(v4l2_std_id norm)
+{
+       return (norm & V4L2_STD_625_50) ? 511 : 400;
+}
+
+int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
+                  enum v4l2_field field)
+{
+       unsigned int swidth  = norm_swidth(core->tvnorm);
+       unsigned int sheight = norm_maxh(core->tvnorm);
+       u32 value;
+
+       dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
+               V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
+               V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
+               v4l2_norm_to_name(core->tvnorm));
+       if (!V4L2_FIELD_HAS_BOTH(field))
+               height *= 2;
+
+       // recalc H delay and scale registers
+       value = (width * norm_hdelay(core->tvnorm)) / swidth;
+       value &= 0x3fe;
+       cx_write(MO_HDELAY_EVEN,  value);
+       cx_write(MO_HDELAY_ODD,   value);
+       dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
+
+       value = (swidth * 4096 / width) - 4096;
+       cx_write(MO_HSCALE_EVEN,  value);
+       cx_write(MO_HSCALE_ODD,   value);
+       dprintk(1,"set_scale: hscale  0x%04x\n", value);
+
+       cx_write(MO_HACTIVE_EVEN, width);
+       cx_write(MO_HACTIVE_ODD,  width);
+       dprintk(1,"set_scale: hactive 0x%04x\n", width);
+
+       // recalc V scale Register (delay is constant)
+       cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
+       cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
+       dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
+
+       value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
+       cx_write(MO_VSCALE_EVEN,  value);
+       cx_write(MO_VSCALE_ODD,   value);
+       dprintk(1,"set_scale: vscale  0x%04x\n", value);
+
+       cx_write(MO_VACTIVE_EVEN, sheight);
+       cx_write(MO_VACTIVE_ODD,  sheight);
+       dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
+
+       // setup filters
+       value = 0;
+       value |= (1 << 19);        // CFILT (default)
+       if (core->tvnorm & V4L2_STD_SECAM) {
+               value |= (1 << 15);
+               value |= (1 << 16);
+       }
+       if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
+               value |= (1 << 13) | (1 << 5);
+       if (V4L2_FIELD_INTERLACED == field)
+               value |= (1 << 3); // VINT (interlaced vertical scaling)
+       if (width < 385)
+               value |= (1 << 0); // 3-tap interpolation
+       if (width < 193)
+               value |= (1 << 1); // 5-tap interpolation
+       if (nocomb)
+               value |= (3 << 5); // disable comb filter
+
+       cx_andor(MO_FILTER_EVEN,  0x7ffc7f, value); /* preserve PEAKEN, PSEL */
+       cx_andor(MO_FILTER_ODD,   0x7ffc7f, value);
+       dprintk(1,"set_scale: filter  0x%04x\n", value);
+
+       return 0;
+}
+
+static const u32 xtal = 28636363;
+
+static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
+{
+       static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
+       u64 pll;
+       u32 reg;
+       int i;
+
+       if (prescale < 2)
+               prescale = 2;
+       if (prescale > 5)
+               prescale = 5;
+
+       pll = ofreq * 8 * prescale * (u64)(1 << 20);
+       do_div(pll,xtal);
+       reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
+       if (((reg >> 20) & 0x3f) < 14) {
+               printk("%s/0: pll out of range\n",core->name);
+               return -1;
+       }
+
+       dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
+               reg, cx_read(MO_PLL_REG), ofreq);
+       cx_write(MO_PLL_REG, reg);
+       for (i = 0; i < 100; i++) {
+               reg = cx_read(MO_DEVICE_STATUS);
+               if (reg & (1<<2)) {
+                       dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
+                               prescale,ofreq);
+                       return 0;
+               }
+               dprintk(1,"pll not locked yet, waiting ...\n");
+               msleep(10);
+       }
+       dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
+       return -1;
+}
+
+int cx88_start_audio_dma(struct cx88_core *core)
+{
+       /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
+       int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
+
+       int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
+
+       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+               return 0;
+
+       /* setup fifo + format */
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
+                               rds_bpl, 0);
+
+       cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
+       cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
+
+       /* enable Up, Down and Audio RDS fifo */
+       cx_write(MO_AUD_DMACNTRL, 0x0007);
+
+       return 0;
+}
+
+int cx88_stop_audio_dma(struct cx88_core *core)
+{
+       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+               return 0;
+
+       /* stop dma */
+       cx_write(MO_AUD_DMACNTRL, 0x0000);
+
+       return 0;
+}
+
+static int set_tvaudio(struct cx88_core *core)
+{
+       v4l2_std_id norm = core->tvnorm;
+
+       if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
+           CX88_VMUX_CABLE != INPUT(core->input).type)
+               return 0;
+
+       if (V4L2_STD_PAL_BG & norm) {
+               core->tvaudio = WW_BG;
+
+       } else if (V4L2_STD_PAL_DK & norm) {
+               core->tvaudio = WW_DK;
+
+       } else if (V4L2_STD_PAL_I & norm) {
+               core->tvaudio = WW_I;
+
+       } else if (V4L2_STD_SECAM_L & norm) {
+               core->tvaudio = WW_L;
+
+       } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
+               core->tvaudio = WW_BG;
+
+       } else if (V4L2_STD_SECAM_DK & norm) {
+               core->tvaudio = WW_DK;
+
+       } else if ((V4L2_STD_NTSC_M & norm) ||
+                  (V4L2_STD_PAL_M  & norm)) {
+               core->tvaudio = WW_BTSC;
+
+       } else if (V4L2_STD_NTSC_M_JP & norm) {
+               core->tvaudio = WW_EIAJ;
+
+       } else {
+               printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
+                      core->name, v4l2_norm_to_name(core->tvnorm));
+               core->tvaudio = WW_NONE;
+               return 0;
+       }
+
+       cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
+       cx88_set_tvaudio(core);
+       /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
+
+/*
+   This should be needed only on cx88-alsa. It seems that some cx88 chips have
+   bugs and does require DMA enabled for it to work.
+ */
+       cx88_start_audio_dma(core);
+       return 0;
+}
+
+
+
+int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
+{
+       u32 fsc8;
+       u32 adc_clock;
+       u32 vdec_clock;
+       u32 step_db,step_dr;
+       u64 tmp64;
+       u32 bdelay,agcdelay,htotal;
+       u32 cxiformat, cxoformat;
+
+       core->tvnorm = norm;
+       fsc8       = norm_fsc8(norm);
+       adc_clock  = xtal;
+       vdec_clock = fsc8;
+       step_db    = fsc8;
+       step_dr    = fsc8;
+
+       if (norm & V4L2_STD_NTSC_M_JP) {
+               cxiformat = VideoFormatNTSCJapan;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_NTSC_443) {
+               cxiformat = VideoFormatNTSC443;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_PAL_M) {
+               cxiformat = VideoFormatPALM;
+               cxoformat = 0x1c1f0008;
+       } else if (norm & V4L2_STD_PAL_N) {
+               cxiformat = VideoFormatPALN;
+               cxoformat = 0x1c1f0008;
+       } else if (norm & V4L2_STD_PAL_Nc) {
+               cxiformat = VideoFormatPALNC;
+               cxoformat = 0x1c1f0008;
+       } else if (norm & V4L2_STD_PAL_60) {
+               cxiformat = VideoFormatPAL60;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_NTSC) {
+               cxiformat = VideoFormatNTSC;
+               cxoformat = 0x181f0008;
+       } else if (norm & V4L2_STD_SECAM) {
+               step_db = 4250000 * 8;
+               step_dr = 4406250 * 8;
+
+               cxiformat = VideoFormatSECAM;
+               cxoformat = 0x181f0008;
+       } else { /* PAL */
+               cxiformat = VideoFormatPAL;
+               cxoformat = 0x181f0008;
+       }
+
+       dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
+               v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
+               step_db, step_dr);
+       set_pll(core,2,vdec_clock);
+
+       dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
+               cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
+       /* 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",
+               cxoformat, cx_read(MO_OUTPUT_FORMAT));
+       cx_write(MO_OUTPUT_FORMAT, cxoformat);
+
+       // MO_SCONV_REG = adc clock / video dec clock * 2^17
+       tmp64  = adc_clock * (u64)(1 << 17);
+       do_div(tmp64, vdec_clock);
+       dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
+               (u32)tmp64, cx_read(MO_SCONV_REG));
+       cx_write(MO_SCONV_REG, (u32)tmp64);
+
+       // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
+       tmp64  = step_db * (u64)(1 << 22);
+       do_div(tmp64, vdec_clock);
+       dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
+               (u32)tmp64, cx_read(MO_SUB_STEP));
+       cx_write(MO_SUB_STEP, (u32)tmp64);
+
+       // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
+       tmp64  = step_dr * (u64)(1 << 22);
+       do_div(tmp64, vdec_clock);
+       dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
+               (u32)tmp64, cx_read(MO_SUB_STEP_DR));
+       cx_write(MO_SUB_STEP_DR, (u32)tmp64);
+
+       // bdelay + agcdelay
+       bdelay   = vdec_clock * 65 / 20000000 + 21;
+       agcdelay = vdec_clock * 68 / 20000000 + 15;
+       dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
+               (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
+       cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
+
+       // htotal
+       tmp64 = norm_htotal(norm) * (u64)vdec_clock;
+       do_div(tmp64, fsc8);
+       htotal = (u32)tmp64;
+       dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
+               htotal, cx_read(MO_HTOTAL), (u32)tmp64);
+       cx_andor(MO_HTOTAL, 0x07ff, htotal);
+
+       // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
+       // the effective vbi offset ~244 samples, the same as the Bt8x8
+       cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
+
+       // this is needed as well to set all tvnorm parameter
+       cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
+
+       // audio
+       set_tvaudio(core);
+
+       // tell i2c chips
+       call_all(core, core, s_std, norm);
+
+       /* The chroma_agc control should be inaccessible if the video format is SECAM */
+       v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
+
+       // done
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+struct video_device *cx88_vdev_init(struct cx88_core *core,
+                                   struct pci_dev *pci,
+                                   const struct video_device *template_,
+                                   const char *type)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template_;
+       vfd->v4l2_dev = &core->v4l2_dev;
+       vfd->release = video_device_release;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
+                core->name, type, core->board.name);
+       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+       return vfd;
+}
+
+struct cx88_core* cx88_core_get(struct pci_dev *pci)
+{
+       struct cx88_core *core;
+
+       mutex_lock(&devlist);
+       list_for_each_entry(core, &cx88_devlist, devlist) {
+               if (pci->bus->number != core->pci_bus)
+                       continue;
+               if (PCI_SLOT(pci->devfn) != core->pci_slot)
+                       continue;
+
+               if (0 != cx88_get_resources(core, pci)) {
+                       mutex_unlock(&devlist);
+                       return NULL;
+               }
+               atomic_inc(&core->refcount);
+               mutex_unlock(&devlist);
+               return core;
+       }
+
+       core = cx88_core_create(pci, cx88_devcount);
+       if (NULL != core) {
+               cx88_devcount++;
+               list_add_tail(&core->devlist, &cx88_devlist);
+       }
+
+       mutex_unlock(&devlist);
+       return core;
+}
+
+void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
+{
+       release_mem_region(pci_resource_start(pci,0),
+                          pci_resource_len(pci,0));
+
+       if (!atomic_dec_and_test(&core->refcount))
+               return;
+
+       mutex_lock(&devlist);
+       cx88_ir_fini(core);
+       if (0 == core->i2c_rc) {
+               if (core->i2c_rtc)
+                       i2c_unregister_device(core->i2c_rtc);
+               i2c_del_adapter(&core->i2c_adap);
+       }
+       list_del(&core->devlist);
+       iounmap(core->lmmio);
+       cx88_devcount--;
+       mutex_unlock(&devlist);
+       v4l2_ctrl_handler_free(&core->video_hdl);
+       v4l2_ctrl_handler_free(&core->audio_hdl);
+       v4l2_device_unregister(&core->v4l2_dev);
+       kfree(core);
+}
+
+/* ------------------------------------------------------------------ */
+
+EXPORT_SYMBOL(cx88_print_irqbits);
+
+EXPORT_SYMBOL(cx88_core_irq);
+EXPORT_SYMBOL(cx88_wakeup);
+EXPORT_SYMBOL(cx88_reset);
+EXPORT_SYMBOL(cx88_shutdown);
+
+EXPORT_SYMBOL(cx88_risc_buffer);
+EXPORT_SYMBOL(cx88_risc_databuffer);
+EXPORT_SYMBOL(cx88_risc_stopper);
+EXPORT_SYMBOL(cx88_free_buffer);
+
+EXPORT_SYMBOL(cx88_sram_channels);
+EXPORT_SYMBOL(cx88_sram_channel_setup);
+EXPORT_SYMBOL(cx88_sram_channel_dump);
+
+EXPORT_SYMBOL(cx88_set_tvnorm);
+EXPORT_SYMBOL(cx88_set_scale);
+
+EXPORT_SYMBOL(cx88_vdev_init);
+EXPORT_SYMBOL(cx88_core_get);
+EXPORT_SYMBOL(cx88_core_put);
+
+EXPORT_SYMBOL(cx88_ir_start);
+EXPORT_SYMBOL(cx88_ir_stop);
+
+/*
+ * 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
+ */
diff --git a/drivers/media/pci/cx88/cx88-dsp.c b/drivers/media/pci/cx88/cx88-dsp.c
new file mode 100644 (file)
index 0000000..a990726
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *
+ *  Stereo and SAP detection for cx88
+ *
+ *  Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
+ *
+ *  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>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define INT_PI                 ((s32)(3.141592653589 * 32768.0))
+
+#define compat_remainder(a, b) \
+        ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
+
+#define baseband_freq(carrier, srate, tone) ((s32)( \
+        (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
+
+/* We calculate the baseband frequencies of the carrier and the pilot tones
+ * based on the the sampling rate of the audio rds fifo. */
+
+#define FREQ_A2_CARRIER         baseband_freq(54687.5, 2689.36, 0.0)
+#define FREQ_A2_DUAL            baseband_freq(54687.5, 2689.36, 274.1)
+#define FREQ_A2_STEREO          baseband_freq(54687.5, 2689.36, 117.5)
+
+/* The frequencies below are from the reference driver. They probably need
+ * further adjustments, because they are not tested at all. You may even need
+ * to play a bit with the registers of the chip to select the proper signal
+ * for the input of the audio rds fifo, and measure it's sampling rate to
+ * calculate the proper baseband frequencies... */
+
+#define FREQ_A2M_CARRIER       ((s32)(2.114516 * 32768.0))
+#define FREQ_A2M_DUAL          ((s32)(2.754916 * 32768.0))
+#define FREQ_A2M_STEREO                ((s32)(2.462326 * 32768.0))
+
+#define FREQ_EIAJ_CARRIER      ((s32)(1.963495 * 32768.0)) /* 5pi/8  */
+#define FREQ_EIAJ_DUAL         ((s32)(2.562118 * 32768.0))
+#define FREQ_EIAJ_STEREO       ((s32)(2.601053 * 32768.0))
+
+#define FREQ_BTSC_DUAL         ((s32)(1.963495 * 32768.0)) /* 5pi/8  */
+#define FREQ_BTSC_DUAL_REF     ((s32)(1.374446 * 32768.0)) /* 7pi/16 */
+
+#define FREQ_BTSC_SAP          ((s32)(2.471532 * 32768.0))
+#define FREQ_BTSC_SAP_REF      ((s32)(1.730072 * 32768.0))
+
+/* The spectrum of the signal should be empty between these frequencies. */
+#define FREQ_NOISE_START       ((s32)(0.100000 * 32768.0))
+#define FREQ_NOISE_END         ((s32)(1.200000 * 32768.0))
+
+static unsigned int dsp_debug;
+module_param(dsp_debug, int, 0644);
+MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
+
+#define dprintk(level, fmt, arg...)    if (dsp_debug >= level) \
+       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+static s32 int_cos(u32 x)
+{
+       u32 t2, t4, t6, t8;
+       s32 ret;
+       u16 period = x / INT_PI;
+       if (period % 2)
+               return -int_cos(x - INT_PI);
+       x = x % INT_PI;
+       if (x > INT_PI/2)
+               return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
+       /* Now x is between 0 and INT_PI/2.
+        * To calculate cos(x) we use it's Taylor polinom. */
+       t2 = x*x/32768/2;
+       t4 = t2*x/32768*x/32768/3/4;
+       t6 = t4*x/32768*x/32768/5/6;
+       t8 = t6*x/32768*x/32768/7/8;
+       ret = 32768-t2+t4-t6+t8;
+       return ret;
+}
+
+static u32 int_goertzel(s16 x[], u32 N, u32 freq)
+{
+       /* We use the Goertzel algorithm to determine the power of the
+        * given frequency in the signal */
+       s32 s_prev = 0;
+       s32 s_prev2 = 0;
+       s32 coeff = 2*int_cos(freq);
+       u32 i;
+
+       u64 tmp;
+       u32 divisor;
+
+       for (i = 0; i < N; i++) {
+               s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
+               s_prev2 = s_prev;
+               s_prev = s;
+       }
+
+       tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
+                     (s64)coeff * s_prev2 * s_prev / 32768;
+
+       /* XXX: N must be low enough so that N*N fits in s32.
+        * Else we need two divisions. */
+       divisor = N * N;
+       do_div(tmp, divisor);
+
+       return (u32) tmp;
+}
+
+static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
+{
+       u32 sum = int_goertzel(x, N, freq);
+       return (u32)int_sqrt(sum);
+}
+
+static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end)
+{
+       int i;
+       u32 sum = 0;
+       u32 freq_step;
+       int samples = 5;
+
+       if (N > 192) {
+               /* The last 192 samples are enough for noise detection */
+               x += (N-192);
+               N = 192;
+       }
+
+       freq_step = (freq_end - freq_start) / (samples - 1);
+
+       for (i = 0; i < samples; i++) {
+               sum += int_goertzel(x, N, freq_start);
+               freq_start += freq_step;
+       }
+
+       return (u32)int_sqrt(sum / samples);
+}
+
+static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
+{
+       s32 carrier, stereo, dual, noise;
+       s32 carrier_freq, stereo_freq, dual_freq;
+       s32 ret;
+
+       switch (core->tvaudio) {
+       case WW_BG:
+       case WW_DK:
+               carrier_freq = FREQ_A2_CARRIER;
+               stereo_freq = FREQ_A2_STEREO;
+               dual_freq = FREQ_A2_DUAL;
+               break;
+       case WW_M:
+               carrier_freq = FREQ_A2M_CARRIER;
+               stereo_freq = FREQ_A2M_STEREO;
+               dual_freq = FREQ_A2M_DUAL;
+               break;
+       case WW_EIAJ:
+               carrier_freq = FREQ_EIAJ_CARRIER;
+               stereo_freq = FREQ_EIAJ_STEREO;
+               dual_freq = FREQ_EIAJ_DUAL;
+               break;
+       default:
+               printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
+                      core->name, core->tvaudio, __func__);
+               return UNSET;
+       }
+
+       carrier = freq_magnitude(x, N, carrier_freq);
+       stereo  = freq_magnitude(x, N, stereo_freq);
+       dual    = freq_magnitude(x, N, dual_freq);
+       noise   = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
+
+       dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
+                  "noise=%d\n", carrier, stereo, dual, noise);
+
+       if (stereo > dual)
+               ret = V4L2_TUNER_SUB_STEREO;
+       else
+               ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+       if (core->tvaudio == WW_EIAJ) {
+               /* EIAJ checks may need adjustments */
+               if ((carrier > max(stereo, dual)*2) &&
+                   (carrier < max(stereo, dual)*6) &&
+                   (carrier > 20 && carrier < 200) &&
+                   (max(stereo, dual) > min(stereo, dual))) {
+                       /* For EIAJ the carrier is always present,
+                          so we probably don't need noise detection */
+                       return ret;
+               }
+       } else {
+               if ((carrier > max(stereo, dual)*2) &&
+                   (carrier < max(stereo, dual)*8) &&
+                   (carrier > 20 && carrier < 200) &&
+                   (noise < 10) &&
+                   (max(stereo, dual) > min(stereo, dual)*2)) {
+                       return ret;
+               }
+       }
+       return V4L2_TUNER_SUB_MONO;
+}
+
+static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N)
+{
+       s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF);
+       s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
+       s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
+       s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
+       dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
+                  "\n", dual_ref, dual, sap_ref, sap);
+       /* FIXME: Currently not supported */
+       return UNSET;
+}
+
+static s16 *read_rds_samples(struct cx88_core *core, u32 *N)
+{
+       const struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27];
+       s16 *samples;
+
+       unsigned int i;
+       unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
+       unsigned int spl = bpl/4;
+       unsigned int sample_count = spl*(AUD_RDS_LINES-1);
+
+       u32 current_address = cx_read(srch->ptr1_reg);
+       u32 offset = (current_address - srch->fifo_start + bpl);
+
+       dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
+               "sample_count=%d, aud_intstat=%08x\n", current_address,
+               current_address - srch->fifo_start, sample_count,
+               cx_read(MO_AUD_INTSTAT));
+
+       samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
+       if (!samples)
+               return NULL;
+
+       *N = sample_count;
+
+       for (i = 0; i < sample_count; i++)  {
+               offset = offset % (AUD_RDS_LINES*bpl);
+               samples[i] = cx_read(srch->fifo_start + offset);
+               offset += 4;
+       }
+
+       if (dsp_debug >= 2) {
+               dprintk(2, "RDS samples dump: ");
+               for (i = 0; i < sample_count; i++)
+                       printk("%hd ", samples[i]);
+               printk(".\n");
+       }
+
+       return samples;
+}
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core)
+{
+       s16 *samples;
+       u32 N = 0;
+       s32 ret = UNSET;
+
+       /* If audio RDS fifo is disabled, we can't read the samples */
+       if (!(cx_read(MO_AUD_DMACNTRL) & 0x04))
+               return ret;
+       if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS))
+               return ret;
+
+       /* Wait at least 500 ms after an audio standard change */
+       if (time_before(jiffies, core->last_change + msecs_to_jiffies(500)))
+               return ret;
+
+       samples = read_rds_samples(core, &N);
+
+       if (!samples)
+               return ret;
+
+       switch (core->tvaudio) {
+       case WW_BG:
+       case WW_DK:
+       case WW_EIAJ:
+       case WW_M:
+               ret = detect_a2_a2m_eiaj(core, samples, N);
+               break;
+       case WW_BTSC:
+               ret = detect_btsc(core, samples, N);
+               break;
+       case WW_NONE:
+       case WW_I:
+       case WW_L:
+       case WW_I2SPT:
+       case WW_FM:
+       case WW_I2SADC:
+               break;
+       }
+
+       kfree(samples);
+
+       if (UNSET != ret)
+               dprintk(1, "stereo/sap detection result:%s%s%s\n",
+                          (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
+                          (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
+                          (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
+
+       return ret;
+}
+EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap);
+
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
new file mode 100644 (file)
index 0000000..d803bba
--- /dev/null
@@ -0,0 +1,1778 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * MPEG Transport Stream (DVB) routines
+ *
+ * (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, 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/fs.h>
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/suspend.h>
+
+#include "cx88.h"
+#include "dvb-pll.h"
+#include <media/v4l2-common.h>
+
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "cx88-vp3054-i2c.h"
+#include "zl10353.h"
+#include "cx22702.h"
+#include "or51132.h"
+#include "lgdt330x.h"
+#include "s5h1409.h"
+#include "xc4000.h"
+#include "xc5000.h"
+#include "nxt200x.h"
+#include "cx24123.h"
+#include "isl6421.h"
+#include "tuner-simple.h"
+#include "tda9887.h"
+#include "s5h1411.h"
+#include "stv0299.h"
+#include "z0194a.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "cx24116.h"
+#include "stv0900.h"
+#include "stb6100.h"
+#include "stb6100_proc.h"
+#include "mb86a16.h"
+#include "ds3000.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");
+MODULE_VERSION(CX88_VERSION);
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
+
+static unsigned int dvb_buf_tscnt = 32;
+module_param(dvb_buf_tscnt, int, 0644);
+MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [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)
+
+/* ------------------------------------------------------------------ */
+
+static int dvb_buf_setup(struct videobuf_queue *q,
+                        unsigned int *count, unsigned int *size)
+{
+       struct cx8802_dev *dev = q->priv_data;
+
+       dev->ts_packet_size  = 188 * 4;
+       dev->ts_packet_count = dvb_buf_tscnt;
+
+       *size  = dev->ts_packet_size * dev->ts_packet_count;
+       *count = dvb_buf_tscnt;
+       return 0;
+}
+
+static int dvb_buf_prepare(struct videobuf_queue *q,
+                          struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct cx8802_dev *dev = q->priv_data;
+       return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
+}
+
+static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx8802_dev *dev = q->priv_data;
+       cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
+}
+
+static void dvb_buf_release(struct videobuf_queue *q,
+                           struct videobuf_buffer *vb)
+{
+       cx88_free_buffer(q, (struct cx88_buffer*)vb);
+}
+
+static const struct videobuf_queue_ops dvb_qops = {
+       .buf_setup    = dvb_buf_setup,
+       .buf_prepare  = dvb_buf_prepare,
+       .buf_queue    = dvb_buf_queue,
+       .buf_release  = dvb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx8802_driver *drv = NULL;
+       int ret = 0;
+       int fe_id;
+
+       fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
+       if (!fe_id) {
+               printk(KERN_ERR "%s() No frontend found\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&dev->core->lock);
+       drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
+       if (drv) {
+               if (acquire){
+                       dev->frontends.active_fe_id = fe_id;
+                       ret = drv->request_acquire(drv);
+               } else {
+                       ret = drv->request_release(drv);
+                       dev->frontends.active_fe_id = 0;
+               }
+       }
+       mutex_unlock(&dev->core->lock);
+
+       return ret;
+}
+
+static void cx88_dvb_gate_ctrl(struct cx88_core  *core, int open)
+{
+       struct videobuf_dvb_frontends *f;
+       struct videobuf_dvb_frontend *fe;
+
+       if (!core->dvbdev)
+               return;
+
+       f = &core->dvbdev->frontends;
+
+       if (!f)
+               return;
+
+       if (f->gate <= 1) /* undefined or fe0 */
+               fe = videobuf_dvb_get_frontend(f, 1);
+       else
+               fe = videobuf_dvb_get_frontend(f, f->gate);
+
+       if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+               fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
+{
+       static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
+       static const u8 reset []         = { RESET,      0x80 };
+       static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+       static const u8 agc_cfg []       = { AGC_TARGET, 0x24, 0x20 };
+       static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+       static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+       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, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+       return 0;
+}
+
+static int dvico_dual_demod_init(struct dvb_frontend *fe)
+{
+       static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
+       static const u8 reset []         = { RESET,      0x80 };
+       static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+       static const u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
+       static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+       static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+       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, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
+static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
+{
+       static const u8 clock_config []  = { 0x89, 0x38, 0x39 };
+       static const u8 reset []         = { 0x50, 0x80 };
+       static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+       static const u8 agc_cfg []       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
+                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
+       static const u8 dntv_extra[]     = { 0xB5, 0x7A };
+       static const u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(2000);
+       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));
+       udelay(2000);
+       mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
+static const struct mt352_config dvico_fusionhdtv = {
+       .demod_address = 0x0f,
+       .demod_init    = dvico_fusionhdtv_demod_init,
+};
+
+static const struct mt352_config dntv_live_dvbt_config = {
+       .demod_address = 0x0f,
+       .demod_init    = dntv_live_dvbt_demod_init,
+};
+
+static const struct mt352_config dvico_fusionhdtv_dual = {
+       .demod_address = 0x0f,
+       .demod_init    = dvico_dual_demod_init,
+};
+
+static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner      = 1,
+       .if2           = 45600,
+};
+
+static struct mb86a16_config twinhan_vp1027 = {
+       .demod_address  = 0x08,
+};
+
+#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
+static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
+{
+       static const u8 clock_config []  = { 0x89, 0x38, 0x38 };
+       static const u8 reset []         = { 0x50, 0x80 };
+       static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+       static const u8 agc_cfg []       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
+                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
+       static const u8 dntv_extra[]     = { 0xB5, 0x7A };
+       static const u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(2000);
+       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));
+       udelay(2000);
+       mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
+static const struct mt352_config dntv_live_dvbt_pro_config = {
+       .demod_address = 0x0f,
+       .no_tuner      = 1,
+       .demod_init    = dntv_live_dvbt_pro_demod_init,
+};
+#endif
+
+static const struct zl10353_config dvico_fusionhdtv_hybrid = {
+       .demod_address = 0x0f,
+       .no_tuner      = 1,
+};
+
+static const struct zl10353_config dvico_fusionhdtv_xc3028 = {
+       .demod_address = 0x0f,
+       .if2           = 45600,
+       .no_tuner      = 1,
+};
+
+static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
+       .demod_address = 0x0f,
+       .if2 = 4560,
+       .no_tuner = 1,
+       .demod_init = dvico_fusionhdtv_demod_init,
+};
+
+static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
+       .demod_address = 0x0f,
+};
+
+static const struct cx22702_config connexant_refboard_config = {
+       .demod_address = 0x43,
+       .output_mode   = CX22702_SERIAL_OUTPUT,
+};
+
+static const struct cx22702_config hauppauge_hvr_config = {
+       .demod_address = 0x63,
+       .output_mode   = CX22702_SERIAL_OUTPUT,
+};
+
+static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
+       return 0;
+}
+
+static const struct or51132_config pchdtv_hd3000 = {
+       .demod_address = 0x15,
+       .set_ts_params = or51132_set_ts_param,
+};
+
+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", __func__, index);
+       if (index == 0)
+               cx_clear(MO_GP0_IO, 8);
+       else
+               cx_set(MO_GP0_IO, 8);
+       return 0;
+}
+
+static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       if (is_punctured)
+               dev->ts_gen_cntrl |= 0x04;
+       else
+               dev->ts_gen_cntrl &= ~0x04;
+       return 0;
+}
+
+static struct lgdt330x_config fusionhdtv_3_gold = {
+       .demod_address = 0x0e,
+       .demod_chip    = LGDT3302,
+       .serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
+       .set_ts_params = lgdt330x_set_ts_param,
+};
+
+static const struct lgdt330x_config fusionhdtv_5_gold = {
+       .demod_address = 0x0e,
+       .demod_chip    = LGDT3303,
+       .serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+       .set_ts_params = lgdt330x_set_ts_param,
+};
+
+static const struct lgdt330x_config pchdtv_hd5500 = {
+       .demod_address = 0x59,
+       .demod_chip    = LGDT3303,
+       .serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+       .set_ts_params = lgdt330x_set_ts_param,
+};
+
+static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
+       return 0;
+}
+
+static const struct nxt200x_config ati_hdtvwonder = {
+       .demod_address = 0x0a,
+       .set_ts_params = nxt200x_set_ts_param,
+};
+
+static int cx24123_set_ts_param(struct dvb_frontend* fe,
+       int is_punctured)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       dev->ts_gen_cntrl = 0x02;
+       return 0;
+}
+
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
+                                      fe_sec_voltage_t voltage)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       if (voltage == SEC_VOLTAGE_OFF)
+               cx_write(MO_GP0_IO, 0x000006fb);
+       else
+               cx_write(MO_GP0_IO, 0x000006f9);
+
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
+       return 0;
+}
+
+static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
+                                     fe_sec_voltage_t voltage)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       if (voltage == SEC_VOLTAGE_OFF) {
+               dprintk(1,"LNB Voltage OFF\n");
+               cx_write(MO_GP0_IO, 0x0000efff);
+       }
+
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
+       return 0;
+}
+
+static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
+                                     fe_sec_voltage_t voltage)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       cx_set(MO_GP0_IO, 0x6040);
+       switch (voltage) {
+       case SEC_VOLTAGE_13:
+               cx_clear(MO_GP0_IO, 0x20);
+               break;
+       case SEC_VOLTAGE_18:
+               cx_set(MO_GP0_IO, 0x20);
+               break;
+       case SEC_VOLTAGE_OFF:
+               cx_clear(MO_GP0_IO, 0x20);
+               break;
+       }
+
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
+       return 0;
+}
+
+static int vp1027_set_voltage(struct dvb_frontend *fe,
+                                   fe_sec_voltage_t voltage)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       switch (voltage) {
+       case SEC_VOLTAGE_13:
+               dprintk(1, "LNB SEC Voltage=13\n");
+               cx_write(MO_GP0_IO, 0x00001220);
+               break;
+       case SEC_VOLTAGE_18:
+               dprintk(1, "LNB SEC Voltage=18\n");
+               cx_write(MO_GP0_IO, 0x00001222);
+               break;
+       case SEC_VOLTAGE_OFF:
+               dprintk(1, "LNB Voltage OFF\n");
+               cx_write(MO_GP0_IO, 0x00001230);
+               break;
+       }
+
+       if (core->prev_set_voltage)
+               return core->prev_set_voltage(fe, voltage);
+       return 0;
+}
+
+static const struct cx24123_config geniatech_dvbs_config = {
+       .demod_address = 0x55,
+       .set_ts_params = cx24123_set_ts_param,
+};
+
+static const struct cx24123_config hauppauge_novas_config = {
+       .demod_address = 0x55,
+       .set_ts_params = cx24123_set_ts_param,
+};
+
+static const struct cx24123_config kworld_dvbs_100_config = {
+       .demod_address = 0x15,
+       .set_ts_params = cx24123_set_ts_param,
+       .lnb_polarity  = 1,
+};
+
+static const struct s5h1409_config pinnacle_pctv_hd_800i_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_PARALLEL_OUTPUT,
+       .gpio          = S5H1409_GPIO_ON,
+       .qam_if        = 44000,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+};
+
+static const 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 const 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 const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
+       .i2c_address    = 0x64,
+       .if_khz         = 5380,
+};
+
+static const struct zl10353_config cx88_pinnacle_hybrid_pctv = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner      = 1,
+       .if2           = 45600,
+};
+
+static const struct zl10353_config cx88_geniatech_x8000_mt = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static const struct s5h1411_config dvico_fusionhdtv7_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_ON,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+       .qam_if        = S5H1411_IF_44000,
+       .vsb_if        = S5H1411_IF_44000,
+       .inversion     = S5H1411_INVERSION_OFF,
+       .status_mode   = S5H1411_DEMODLOCKING
+};
+
+static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
+       .i2c_address    = 0xc2 >> 1,
+       .if_khz         = 5380,
+};
+
+static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
+{
+       struct dvb_frontend *fe;
+       struct videobuf_dvb_frontend *fe0 = NULL;
+       struct xc2028_ctrl ctl;
+       struct xc2028_config cfg = {
+               .i2c_adap  = &dev->core->i2c_adap,
+               .i2c_addr  = addr,
+               .ctrl      = &ctl,
+       };
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+       if (!fe0)
+               return -EINVAL;
+
+       if (!fe0->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, fe0->dvb.frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                      dev->core->name);
+               dvb_frontend_detach(fe0->dvb.frontend);
+               dvb_unregister_frontend(fe0->dvb.frontend);
+               fe0->dvb.frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc3028 attached\n",
+              dev->core->name);
+
+       return 0;
+}
+
+static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
+{
+       struct dvb_frontend *fe;
+       struct videobuf_dvb_frontend *fe0 = NULL;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+       if (!fe0)
+               return -EINVAL;
+
+       if (!fe0->dvb.frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                               "Can't attach xc4000\n",
+                      dev->core->name);
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
+                       cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+                      dev->core->name);
+               dvb_frontend_detach(fe0->dvb.frontend);
+               dvb_unregister_frontend(fe0->dvb.frontend);
+               fe0->dvb.frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
+
+       return 0;
+}
+
+static int cx24116_set_ts_param(struct dvb_frontend *fe,
+       int is_punctured)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       dev->ts_gen_cntrl = 0x2;
+
+       return 0;
+}
+
+static int stv0900_set_ts_param(struct dvb_frontend *fe,
+       int is_punctured)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       dev->ts_gen_cntrl = 0;
+
+       return 0;
+}
+
+static int cx24116_reset_device(struct dvb_frontend *fe)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       /* Reset the part */
+       /* Put the cx24116 into reset */
+       cx_write(MO_SRST_IO, 0);
+       msleep(10);
+       /* Take the cx24116 out of reset */
+       cx_write(MO_SRST_IO, 1);
+       msleep(10);
+
+       return 0;
+}
+
+static const struct cx24116_config hauppauge_hvr4000_config = {
+       .demod_address          = 0x05,
+       .set_ts_params          = cx24116_set_ts_param,
+       .reset_device           = cx24116_reset_device,
+};
+
+static const struct cx24116_config tevii_s460_config = {
+       .demod_address = 0x55,
+       .set_ts_params = cx24116_set_ts_param,
+       .reset_device  = cx24116_reset_device,
+};
+
+static int ds3000_set_ts_param(struct dvb_frontend *fe,
+       int is_punctured)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       dev->ts_gen_cntrl = 4;
+
+       return 0;
+}
+
+static struct ds3000_config tevii_ds3000_config = {
+       .demod_address = 0x68,
+       .set_ts_params = ds3000_set_ts_param,
+};
+
+static const struct stv0900_config prof_7301_stv0900_config = {
+       .demod_address = 0x6a,
+/*     demod_mode = 0,*/
+       .xtal = 27000000,
+       .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+       .diseqc_mode = 2,/* 2/3 PWM */
+       .tun1_maddress = 0,/* 0x60 */
+       .tun1_adc = 0,/* 2 Vpp */
+       .path1_mode = 3,
+       .set_ts_params = stv0900_set_ts_param,
+};
+
+static const struct stb6100_config prof_7301_stb6100_config = {
+       .tuner_address = 0x60,
+       .refclock = 27000000,
+};
+
+static const struct stv0299_config tevii_tuner_sharp_config = {
+       .demod_address = 0x68,
+       .inittab = sharp_z0194a_inittab,
+       .mclk = 88000000UL,
+       .invert = 1,
+       .skip_reinit = 0,
+       .lock_output = 1,
+       .volt13_op0_op1 = STV0299_VOLT13_OP1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = sharp_z0194a_set_symbol_rate,
+       .set_ts_params = cx24116_set_ts_param,
+};
+
+static const struct stv0288_config tevii_tuner_earda_config = {
+       .demod_address = 0x68,
+       .min_delay_ms = 100,
+       .set_ts_params = cx24116_set_ts_param,
+};
+
+static int cx8802_alloc_frontends(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       struct videobuf_dvb_frontend *fe = NULL;
+       int i;
+
+       mutex_init(&dev->frontends.lock);
+       INIT_LIST_HEAD(&dev->frontends.felist);
+
+       if (!core->board.num_frontends)
+               return -ENODEV;
+
+       printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+                        core->board.num_frontends);
+       for (i = 1; i <= core->board.num_frontends; i++) {
+               fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+               if (!fe) {
+                       printk(KERN_ERR "%s() failed to alloc\n", __func__);
+                       videobuf_dvb_dealloc_frontends(&dev->frontends);
+                       return -ENOMEM;
+               }
+       }
+       return 0;
+}
+
+
+
+static const u8 samsung_smt_7020_inittab[] = {
+            0x01, 0x15,
+            0x02, 0x00,
+            0x03, 0x00,
+            0x04, 0x7D,
+            0x05, 0x0F,
+            0x06, 0x02,
+            0x07, 0x00,
+            0x08, 0x60,
+
+            0x0A, 0xC2,
+            0x0B, 0x00,
+            0x0C, 0x01,
+            0x0D, 0x81,
+            0x0E, 0x44,
+            0x0F, 0x09,
+            0x10, 0x3C,
+            0x11, 0x84,
+            0x12, 0xDA,
+            0x13, 0x99,
+            0x14, 0x8D,
+            0x15, 0xCE,
+            0x16, 0xE8,
+            0x17, 0x43,
+            0x18, 0x1C,
+            0x19, 0x1B,
+            0x1A, 0x1D,
+
+            0x1C, 0x12,
+            0x1D, 0x00,
+            0x1E, 0x00,
+            0x1F, 0x00,
+            0x20, 0x00,
+            0x21, 0x00,
+            0x22, 0x00,
+            0x23, 0x00,
+
+            0x28, 0x02,
+            0x29, 0x28,
+            0x2A, 0x14,
+            0x2B, 0x0F,
+            0x2C, 0x09,
+            0x2D, 0x05,
+
+            0x31, 0x1F,
+            0x32, 0x19,
+            0x33, 0xFC,
+            0x34, 0x13,
+            0xff, 0xff,
+};
+
+
+static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct cx8802_dev *dev = fe->dvb->priv;
+       u8 buf[4];
+       u32 div;
+       struct i2c_msg msg = {
+               .addr = 0x61,
+               .flags = 0,
+               .buf = buf,
+               .len = sizeof(buf) };
+
+       div = c->frequency / 125;
+
+       buf[0] = (div >> 8) & 0x7f;
+       buf[1] = div & 0xff;
+       buf[2] = 0x84;  /* 0xC4 */
+       buf[3] = 0x00;
+
+       if (c->frequency < 1500000)
+               buf[3] |= 0x10;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1)
+               return -EIO;
+
+       return 0;
+}
+
+static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
+       fe_sec_tone_mode_t tone)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       cx_set(MO_GP0_IO, 0x0800);
+
+       switch (tone) {
+       case SEC_TONE_ON:
+               cx_set(MO_GP0_IO, 0x08);
+               break;
+       case SEC_TONE_OFF:
+               cx_clear(MO_GP0_IO, 0x08);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
+       fe_sec_voltage_t voltage)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+       struct cx88_core *core = dev->core;
+
+       u8 data;
+       struct i2c_msg msg = {
+               .addr = 8,
+               .flags = 0,
+               .buf = &data,
+               .len = sizeof(data) };
+
+       cx_set(MO_GP0_IO, 0x8000);
+
+       switch (voltage) {
+       case SEC_VOLTAGE_OFF:
+               break;
+       case SEC_VOLTAGE_13:
+               data = ISL6421_EN1 | ISL6421_LLC1;
+               cx_clear(MO_GP0_IO, 0x80);
+               break;
+       case SEC_VOLTAGE_18:
+               data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1;
+               cx_clear(MO_GP0_IO, 0x80);
+               break;
+       default:
+               return -EINVAL;
+       };
+
+       return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
+       u32 srate, u32 ratio)
+{
+       u8 aclk = 0;
+       u8 bclk = 0;
+
+       if (srate < 1500000) {
+               aclk = 0xb7;
+               bclk = 0x47;
+       } else if (srate < 3000000) {
+               aclk = 0xb7;
+               bclk = 0x4b;
+       } else if (srate < 7000000) {
+               aclk = 0xb7;
+               bclk = 0x4f;
+       } else if (srate < 14000000) {
+               aclk = 0xb7;
+               bclk = 0x53;
+       } else if (srate < 30000000) {
+               aclk = 0xb6;
+               bclk = 0x53;
+       } else if (srate < 45000000) {
+               aclk = 0xb4;
+               bclk = 0x51;
+       }
+
+       stv0299_writereg(fe, 0x13, aclk);
+       stv0299_writereg(fe, 0x14, bclk);
+       stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+       stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+       stv0299_writereg(fe, 0x21, ratio & 0xf0);
+
+       return 0;
+}
+
+
+static const struct stv0299_config samsung_stv0299_config = {
+       .demod_address = 0x68,
+       .inittab = samsung_smt_7020_inittab,
+       .mclk = 88000000UL,
+       .invert = 0,
+       .skip_reinit = 0,
+       .lock_output = STV0299_LOCKOUTPUT_LK,
+       .volt13_op0_op1 = STV0299_VOLT13_OP1,
+       .min_delay_ms = 100,
+       .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate,
+};
+
+static int dvb_register(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+       int mfe_shared = 0; /* bus not shared by default */
+       int res = -EINVAL;
+
+       if (0 != core->i2c_rc) {
+               printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
+               goto frontend_detach;
+       }
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+       if (!fe0)
+               goto frontend_detach;
+
+       /* multi-frontend gate control is undefined or defaults to fe0 */
+       dev->frontends.gate = 0;
+
+       /* Sets the gate control callback to be used by i2c command calls */
+       core->gate_ctrl = cx88_dvb_gate_ctrl;
+
+       /* init frontend(s) */
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE_DVB_T1:
+               fe0->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &connexant_refboard_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x61, &core->i2c_adap,
+                                       DVB_PLL_THOMSON_DTT759X))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+       case CX88_BOARD_CONEXANT_DVB_T1:
+       case CX88_BOARD_KWORLD_DVB_T_CX22702:
+       case CX88_BOARD_WINFAST_DTV1000:
+               fe0->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &connexant_refboard_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x60, &core->i2c_adap,
+                                       DVB_PLL_THOMSON_DTT7579))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_WINFAST_DTV2000H:
+       case CX88_BOARD_HAUPPAUGE_HVR1100:
+       case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               fe0->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216ME_MK3))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_WINFAST_DTV2000H_J:
+               fe0->dvb.frontend = dvb_attach(cx22702_attach,
+                                              &hauppauge_hvr_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &core->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216MEX_MK3))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+               /* MFE frontend 1 */
+               mfe_shared = 1;
+               dev->frontends.gate = 2;
+               /* DVB-S init */
+               fe0->dvb.frontend = dvb_attach(cx24123_attach,
+                                       &hauppauge_novas_config,
+                                       &dev->core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (!dvb_attach(isl6421_attach,
+                                       fe0->dvb.frontend,
+                                       &dev->core->i2c_adap,
+                                       0x08, ISL6421_DCL, 0x00))
+                               goto frontend_detach;
+               }
+               /* MFE frontend 2 */
+               fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+               if (!fe1)
+                       goto frontend_detach;
+               /* DVB-T init */
+               fe1->dvb.frontend = dvb_attach(cx22702_attach,
+                                       &hauppauge_hvr_config,
+                                       &dev->core->i2c_adap);
+               if (fe1->dvb.frontend) {
+                       fe1->dvb.frontend->id = 1;
+                       if (!dvb_attach(simple_tuner_attach,
+                                       fe1->dvb.frontend,
+                                       &dev->core->i2c_adap,
+                                       0x61, TUNER_PHILIPS_FMD1216ME_MK3))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dvico_fusionhdtv,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x60, NULL, DVB_PLL_THOMSON_DTT7579))
+                               goto frontend_detach;
+                       break;
+               }
+               /* ZL10353 replaces MT352 on later cards */
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_plus_v1_1,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x60, NULL, DVB_PLL_THOMSON_DTT7579))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+               /* The tin box says DEE1601, but it seems to be DTT7579
+                * compatible, with a slightly different MT352 AGC gain. */
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dvico_fusionhdtv_dual,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x61, NULL, DVB_PLL_THOMSON_DTT7579))
+                               goto frontend_detach;
+                       break;
+               }
+               /* ZL10353 replaces MT352 on later cards */
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_plus_v1_1,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x61, NULL, DVB_PLL_THOMSON_DTT7579))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dvico_fusionhdtv,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x61, NULL, DVB_PLL_LG_Z201))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_KWORLD_DVB_T:
+       case CX88_BOARD_DNTV_LIVE_DVB_T:
+       case CX88_BOARD_ADSTECH_DVB_T_PCI:
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                              &dntv_live_dvbt_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+                                       0x61, NULL, DVB_PLL_UNKNOWN_1))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
+               /* MT352 is on a secondary I2C bus made from some GPIO lines */
+               fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+                                              &dev->vp3054->adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_PHILIPS_FMD1216ME_MK3))
+                               goto frontend_detach;
+               }
+#else
+               printk(KERN_ERR "%s/2: built without vp3054 support\n",
+                               core->name);
+#endif
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_hybrid,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &core->i2c_adap, 0x61,
+                                  TUNER_THOMSON_FE6600))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &dvico_fusionhdtv_xc3028,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend == NULL)
+                       fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &dvico_fusionhdtv_mt352_xc3028,
+                                               &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 (fe0->dvb.frontend)
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+               if (attach_xc3028(0x61, dev) < 0)
+                       goto frontend_detach;
+               break;
+       case CX88_BOARD_PCHDTV_HD3000:
+               fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_THOMSON_DTT761X))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+               dev->ts_gen_cntrl = 0x08;
+
+               /* Do a hardware reset of chip before using it. */
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 1);
+               mdelay(200);
+
+               /* Select RF connector callback */
+               fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
+               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &fusionhdtv_3_gold,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_MICROTUNE_4042FI5))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+               dev->ts_gen_cntrl = 0x08;
+
+               /* Do a hardware reset of chip before using it. */
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 9);
+               mdelay(200);
+               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &fusionhdtv_3_gold,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_THOMSON_DTT761X))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+               dev->ts_gen_cntrl = 0x08;
+
+               /* Do a hardware reset of chip before using it. */
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 1);
+               mdelay(200);
+               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &fusionhdtv_5_gold,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_LG_TDVS_H06XF))
+                               goto frontend_detach;
+                       if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
+                                  &core->i2c_adap, 0x43))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_PCHDTV_HD5500:
+               dev->ts_gen_cntrl = 0x08;
+
+               /* Do a hardware reset of chip before using it. */
+               cx_clear(MO_GP0_IO, 1);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 1);
+               mdelay(200);
+               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+                                              &pchdtv_hd5500,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_LG_TDVS_H06XF))
+                               goto frontend_detach;
+                       if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
+                                  &core->i2c_adap, 0x43))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_ATI_HDTVWONDER:
+               fe0->dvb.frontend = dvb_attach(nxt200x_attach,
+                                              &ati_hdtvwonder,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x61,
+                                       TUNER_PHILIPS_TUV1236D))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+       case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+               fe0->dvb.frontend = dvb_attach(cx24123_attach,
+                                              &hauppauge_novas_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_KWORLD_DVBS_100:
+               fe0->dvb.frontend = dvb_attach(cx24123_attach,
+                                              &kworld_dvbs_100_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+                       fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+               }
+               break;
+       case CX88_BOARD_GENIATECH_DVBS:
+               fe0->dvb.frontend = dvb_attach(cx24123_attach,
+                                              &geniatech_dvbs_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+                       fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
+               }
+               break;
+       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                              &pinnacle_pctv_hd_800i_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap,
+                                       &pinnacle_pctv_hd_800i_tuner_config))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                               &dvico_hdtv5_pci_nano_config,
+                                               &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap  = &core->i2c_adap,
+                               .i2c_addr  = 0x61,
+                       };
+                       static struct xc2028_ctrl ctl = {
+                               .fname       = XC2028_DEFAULT_FIRMWARE,
+                               .max_len     = 64,
+                               .scode_table = XC3028_FE_OREN538,
+                       };
+
+                       fe = dvb_attach(xc2028_attach,
+                                       fe0->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:
+       case CX88_BOARD_WINFAST_DTV1800H:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_pinnacle_hybrid_pctv,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+                       if (attach_xc3028(0x61, dev) < 0)
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_pinnacle_hybrid_pctv,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       struct xc4000_config cfg = {
+                               .i2c_address      = 0x61,
+                               .default_pm       = 0,
+                               .dvb_amplitude    = 134,
+                               .set_smoothedcvbs = 1,
+                               .if_khz           = 4560
+                       };
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+                       if (attach_xc4000(dev, &cfg) < 0)
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_GENIATECH_X8000_MT:
+               dev->ts_gen_cntrl = 0x00;
+
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_geniatech_x8000_mt,
+                                              &core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       goto frontend_detach;
+               break;
+        case CX88_BOARD_KWORLD_ATSC_120:
+               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+                                              &kworld_atsc_120_config,
+                                              &core->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0)
+                       goto frontend_detach;
+               break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                                              &dvico_fusionhdtv7_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                       &core->i2c_adap,
+                                       &dvico_fusionhdtv7_tuner_config))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+               /* MFE frontend 1 */
+               mfe_shared = 1;
+               dev->frontends.gate = 2;
+               /* DVB-S/S2 Init */
+               fe0->dvb.frontend = dvb_attach(cx24116_attach,
+                                       &hauppauge_hvr4000_config,
+                                       &dev->core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (!dvb_attach(isl6421_attach,
+                                       fe0->dvb.frontend,
+                                       &dev->core->i2c_adap,
+                                       0x08, ISL6421_DCL, 0x00))
+                               goto frontend_detach;
+               }
+               /* MFE frontend 2 */
+               fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+               if (!fe1)
+                       goto frontend_detach;
+               /* DVB-T Init */
+               fe1->dvb.frontend = dvb_attach(cx22702_attach,
+                                       &hauppauge_hvr_config,
+                                       &dev->core->i2c_adap);
+               if (fe1->dvb.frontend) {
+                       fe1->dvb.frontend->id = 1;
+                       if (!dvb_attach(simple_tuner_attach,
+                                       fe1->dvb.frontend,
+                                       &dev->core->i2c_adap,
+                                       0x61, TUNER_PHILIPS_FMD1216ME_MK3))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+               fe0->dvb.frontend = dvb_attach(cx24116_attach,
+                                       &hauppauge_hvr4000_config,
+                                       &dev->core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (!dvb_attach(isl6421_attach,
+                                       fe0->dvb.frontend,
+                                       &dev->core->i2c_adap,
+                                       0x08, ISL6421_DCL, 0x00))
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_PROF_6200:
+       case CX88_BOARD_TBS_8910:
+       case CX88_BOARD_TEVII_S420:
+               fe0->dvb.frontend = dvb_attach(stv0299_attach,
+                                               &tevii_tuner_sharp_config,
+                                               &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
+                                       &core->i2c_adap, DVB_PLL_OPERA1))
+                               goto frontend_detach;
+                       core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+                       fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+
+               } else {
+                       fe0->dvb.frontend = dvb_attach(stv0288_attach,
+                                                           &tevii_tuner_earda_config,
+                                                           &core->i2c_adap);
+                               if (fe0->dvb.frontend != NULL) {
+                                       if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
+                                               &core->i2c_adap))
+                                       goto frontend_detach;
+                               core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+                               fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+                       }
+               }
+               break;
+       case CX88_BOARD_TEVII_S460:
+               fe0->dvb.frontend = dvb_attach(cx24116_attach,
+                                              &tevii_s460_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+               break;
+       case CX88_BOARD_TEVII_S464:
+               fe0->dvb.frontend = dvb_attach(ds3000_attach,
+                                               &tevii_ds3000_config,
+                                               &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       fe0->dvb.frontend->ops.set_voltage =
+                                                       tevii_dvbs_set_voltage;
+               break;
+       case CX88_BOARD_OMICOM_SS4_PCI:
+       case CX88_BOARD_TBS_8920:
+       case CX88_BOARD_PROF_7300:
+       case CX88_BOARD_SATTRADE_ST4200:
+               fe0->dvb.frontend = dvb_attach(cx24116_attach,
+                                              &hauppauge_hvr4000_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend != NULL)
+                       fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+               break;
+       case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                              &cx88_terratec_cinergy_ht_pci_mkii_config,
+                                              &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+                       if (attach_xc3028(0x61, dev) < 0)
+                               goto frontend_detach;
+               }
+               break;
+       case CX88_BOARD_PROF_7301:{
+               struct dvb_tuner_ops *tuner_ops = NULL;
+
+               fe0->dvb.frontend = dvb_attach(stv0900_attach,
+                                               &prof_7301_stv0900_config,
+                                               &core->i2c_adap, 0);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
+                                       &prof_7301_stb6100_config,
+                                       &core->i2c_adap))
+                               goto frontend_detach;
+
+                       tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
+                       tuner_ops->set_frequency = stb6100_set_freq;
+                       tuner_ops->get_frequency = stb6100_get_freq;
+                       tuner_ops->set_bandwidth = stb6100_set_bandw;
+                       tuner_ops->get_bandwidth = stb6100_get_bandw;
+
+                       core->prev_set_voltage =
+                                       fe0->dvb.frontend->ops.set_voltage;
+                       fe0->dvb.frontend->ops.set_voltage =
+                                       tevii_dvbs_set_voltage;
+               }
+               break;
+               }
+       case CX88_BOARD_SAMSUNG_SMT_7020:
+               dev->ts_gen_cntrl = 0x08;
+
+               cx_set(MO_GP0_IO, 0x0101);
+
+               cx_clear(MO_GP0_IO, 0x01);
+               mdelay(100);
+               cx_set(MO_GP0_IO, 0x01);
+               mdelay(200);
+
+               fe0->dvb.frontend = dvb_attach(stv0299_attach,
+                                       &samsung_stv0299_config,
+                                       &dev->core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.set_params =
+                               samsung_smt_7020_tuner_set_params;
+                       fe0->dvb.frontend->tuner_priv =
+                               &dev->core->i2c_adap;
+                       fe0->dvb.frontend->ops.set_voltage =
+                               samsung_smt_7020_set_voltage;
+                       fe0->dvb.frontend->ops.set_tone =
+                               samsung_smt_7020_set_tone;
+               }
+
+               break;
+       case CX88_BOARD_TWINHAN_VP1027_DVBS:
+               dev->ts_gen_cntrl = 0x00;
+               fe0->dvb.frontend = dvb_attach(mb86a16_attach,
+                                               &twinhan_vp1027,
+                                               &core->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       core->prev_set_voltage =
+                                       fe0->dvb.frontend->ops.set_voltage;
+                       fe0->dvb.frontend->ops.set_voltage =
+                                       vp1027_set_voltage;
+               }
+               break;
+
+       default:
+               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
+                      core->name);
+               break;
+       }
+
+       if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n",
+                      core->name);
+               goto frontend_detach;
+       }
+       /* define general-purpose callback pointer */
+       fe0->dvb.frontend->callback = cx88_tuner_callback;
+
+       /* Ensure all frontends negotiate bus access */
+       fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+       if (fe1)
+               fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+
+       /* Put the analog decoder in standby to keep it quiet */
+       call_all(core, core, s_power, 0);
+
+       /* register everything */
+       res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+               &dev->pci->dev, adapter_nr, mfe_shared);
+       if (res)
+               goto frontend_detach;
+       return res;
+
+frontend_detach:
+       core->gate_ctrl = NULL;
+       videobuf_dvb_dealloc_frontends(&dev->frontends);
+       return res;
+}
+
+/* ----------------------------------------------------------- */
+
+/* CX8802 MPEG -> mini driver - We have been given the hardware */
+static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+       dprintk( 1, "%s\n", __func__);
+
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* We arrive here with either the cx23416 or the cx22702
+                * on the bus. Take the bus from the cx23416 and enable the
+                * cx22702 demod
+                */
+               /* Toggle reset on cx22702 leaving i2c active */
+               cx_set(MO_GP0_IO, 0x00000080);
+               udelay(1000);
+               cx_clear(MO_GP0_IO, 0x00000080);
+               udelay(50);
+               cx_set(MO_GP0_IO, 0x00000080);
+               udelay(1000);
+               /* enable the cx22702 pins */
+               cx_clear(MO_GP0_IO, 0x00000004);
+               udelay(1000);
+               break;
+
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+               /* Toggle reset on cx22702 leaving i2c active */
+               cx_set(MO_GP0_IO, 0x00000080);
+               udelay(1000);
+               cx_clear(MO_GP0_IO, 0x00000080);
+               udelay(50);
+               cx_set(MO_GP0_IO, 0x00000080);
+               udelay(1000);
+               switch (core->dvbdev->frontends.active_fe_id) {
+               case 1: /* DVB-S/S2 Enabled */
+                       /* tri-state the cx22702 pins */
+                       cx_set(MO_GP0_IO, 0x00000004);
+                       /* Take the cx24116/cx24123 out of reset */
+                       cx_write(MO_SRST_IO, 1);
+                       core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
+                       break;
+               case 2: /* DVB-T Enabled */
+                       /* Put the cx24116/cx24123 into reset */
+                       cx_write(MO_SRST_IO, 0);
+                       /* enable the cx22702 pins */
+                       cx_clear(MO_GP0_IO, 0x00000004);
+                       core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
+                       break;
+               }
+               udelay(1000);
+               break;
+
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               /* set RF input to AIR for DVB-T (GPIO 16) */
+               cx_write(MO_GP2_IO, 0x0101);
+               break;
+
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+/* CX8802 MPEG -> mini driver - We no longer have the hardware */
+static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       int err = 0;
+       dprintk( 1, "%s\n", __func__);
+
+       switch (core->boardnr) {
+       case CX88_BOARD_HAUPPAUGE_HVR1300:
+               /* Do Nothing, leave the cx22702 on the bus. */
+               break;
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+               break;
+       default:
+               err = -ENODEV;
+       }
+       return err;
+}
+
+static int cx8802_dvb_probe(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       struct cx8802_dev *dev = drv->core->dvbdev;
+       int err;
+       struct videobuf_dvb_frontend *fe;
+       int i;
+
+       dprintk( 1, "%s\n", __func__);
+       dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+               core->boardnr,
+               core->name,
+               core->pci_bus,
+               core->pci_slot);
+
+       err = -ENODEV;
+       if (!(core->board.mpeg & CX88_MPEG_DVB))
+               goto fail_core;
+
+       /* If vp3054 isn't enabled, a stub will just return 0 */
+       err = vp3054_i2c_probe(dev);
+       if (0 != err)
+               goto fail_core;
+
+       /* dvb stuff */
+       printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
+       dev->ts_gen_cntrl = 0x0c;
+
+       err = cx8802_alloc_frontends(dev);
+       if (err)
+               goto fail_core;
+
+       err = -ENODEV;
+       for (i = 1; i <= core->board.num_frontends; i++) {
+               fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+               if (fe == NULL) {
+                       printk(KERN_ERR "%s() failed to get frontend(%d)\n",
+                                       __func__, i);
+                       goto fail_probe;
+               }
+               videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
+                                   &dev->pci->dev, &dev->slock,
+                                   V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                                   V4L2_FIELD_TOP,
+                                   sizeof(struct cx88_buffer),
+                                   dev, NULL);
+               /* init struct videobuf_dvb */
+               fe->dvb.name = dev->core->name;
+       }
+
+       err = dvb_register(dev);
+       if (err)
+               /* frontends/adapter de-allocated in dvb_register */
+               printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
+                      core->name, err);
+       return err;
+fail_probe:
+       videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
+fail_core:
+       return err;
+}
+
+static int cx8802_dvb_remove(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       struct cx8802_dev *dev = drv->core->dvbdev;
+
+       dprintk( 1, "%s\n", __func__);
+
+       videobuf_dvb_unregister_bus(&dev->frontends);
+
+       vp3054_i2c_remove(dev);
+
+       core->gate_ctrl = NULL;
+
+       return 0;
+}
+
+static struct cx8802_driver cx8802_dvb_driver = {
+       .type_id        = CX88_MPEG_DVB,
+       .hw_access      = CX8802_DRVCTL_SHARED,
+       .probe          = cx8802_dvb_probe,
+       .remove         = cx8802_dvb_remove,
+       .advise_acquire = cx8802_dvb_advise_acquire,
+       .advise_release = cx8802_dvb_advise_release,
+};
+
+static int __init dvb_init(void)
+{
+       printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
+              CX88_VERSION);
+       return cx8802_register_driver(&cx8802_dvb_driver);
+}
+
+static void __exit dvb_fini(void)
+{
+       cx8802_unregister_driver(&cx8802_dvb_driver);
+}
+
+module_init(dvb_init);
+module_exit(dvb_fini);
diff --git a/drivers/media/pci/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c
new file mode 100644 (file)
index 0000000..de0f1af
--- /dev/null
@@ -0,0 +1,184 @@
+
+/*
+
+    cx88-i2c.c  --  all the i2c code is here
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+                          & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+       - Multituner support and i2c address binding
+
+    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 <asm/io.h>
+
+#include "cx88.h"
+#include <media/v4l2-common.h>
+
+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;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static unsigned int i2c_udelay = 5;
+module_param(i2c_udelay, int, 0644);
+MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "
+               "(should be 5 or higher). Lower value means higher bus speed.");
+
+#define dprintk(level,fmt, arg...)     if (i2c_debug >= level) \
+       printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
+
+/* ----------------------------------------------------------------------- */
+
+static void cx8800_bit_setscl(void *data, int state)
+{
+       struct cx88_core *core = data;
+
+       if (state)
+               core->i2c_state |= 0x02;
+       else
+               core->i2c_state &= ~0x02;
+       cx_write(MO_I2C, core->i2c_state);
+       cx_read(MO_I2C);
+}
+
+static void cx8800_bit_setsda(void *data, int state)
+{
+       struct cx88_core *core = data;
+
+       if (state)
+               core->i2c_state |= 0x01;
+       else
+               core->i2c_state &= ~0x01;
+       cx_write(MO_I2C, core->i2c_state);
+       cx_read(MO_I2C);
+}
+
+static int cx8800_bit_getscl(void *data)
+{
+       struct cx88_core *core = data;
+       u32 state;
+
+       state = cx_read(MO_I2C);
+       return state & 0x02 ? 1 : 0;
+}
+
+static int cx8800_bit_getsda(void *data)
+{
+       struct cx88_core *core = data;
+       u32 state;
+
+       state = cx_read(MO_I2C);
+       return state & 0x01;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
+       .setsda  = cx8800_bit_setsda,
+       .setscl  = cx8800_bit_setscl,
+       .getsda  = cx8800_bit_getsda,
+       .getscl  = cx8800_bit_getscl,
+       .udelay  = 16,
+       .timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static const char * const i2c_devs[128] = {
+       [ 0x1c >> 1 ] = "lgdt330x",
+       [ 0x86 >> 1 ] = "tda9887/cx22702",
+       [ 0xa0 >> 1 ] = "eeprom",
+       [ 0xc0 >> 1 ] = "tuner (analog)",
+       [ 0xc2 >> 1 ] = "tuner (analog/dvb)",
+       [ 0xc8 >> 1 ] = "xc5000",
+};
+
+static void do_i2c_scan(const char *name, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i,rc;
+
+       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c,&buf,0);
+               if (rc < 0)
+                       continue;
+               printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
+                      name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+}
+
+/* init + register i2c adapter */
+int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
+{
+       /* Prevents usage of invalid delay values */
+       if (i2c_udelay<5)
+               i2c_udelay=5;
+
+       memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
+              sizeof(core->i2c_algo));
+
+
+       core->i2c_adap.dev.parent = &pci->dev;
+       strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
+       core->i2c_adap.owner = THIS_MODULE;
+       core->i2c_algo.udelay = i2c_udelay;
+       core->i2c_algo.data = core;
+       i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
+       core->i2c_adap.algo_data = &core->i2c_algo;
+       core->i2c_client.adapter = &core->i2c_adap;
+       strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
+
+       cx8800_bit_setscl(core,1);
+       cx8800_bit_setsda(core,1);
+
+       core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
+       if (0 == core->i2c_rc) {
+               static u8 tuner_data[] =
+                       { 0x0b, 0xdc, 0x86, 0x52 };
+               static struct i2c_msg tuner_msg =
+                       { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
+
+               dprintk(1, "i2c register ok\n");
+               switch( core->boardnr ) {
+                       case CX88_BOARD_HAUPPAUGE_HVR1300:
+                       case CX88_BOARD_HAUPPAUGE_HVR3000:
+                       case CX88_BOARD_HAUPPAUGE_HVR4000:
+                               printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
+                                       core->name);
+                               i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
+                               break;
+                       default:
+                               break;
+               }
+               if (i2c_scan)
+                       do_i2c_scan(core->name,&core->i2c_client);
+       } else
+               printk("%s: i2c register FAILED\n", core->name);
+
+       return core->i2c_rc;
+}
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
new file mode 100644 (file)
index 0000000..ebf448c
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ *
+ * Device driver for GPIO attached remote control interfaces
+ * on Conexant 2388x based TV/DVB cards.
+ *
+ * Copyright (c) 2003 Pavel Machek
+ * Copyright (c) 2004 Gerd Knorr
+ * Copyright (c) 2004, 2005 Chris Pascoe
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include "cx88.h"
+#include <media/rc-core.h>
+
+#define MODULE_NAME "cx88xx"
+
+/* ---------------------------------------------------------------------- */
+
+struct cx88_IR {
+       struct cx88_core *core;
+       struct rc_dev *dev;
+
+       int users;
+
+       char name[32];
+       char phys[32];
+
+       /* sample from gpio pin 16 */
+       u32 sampling;
+
+       /* poll external decoder */
+       int polling;
+       struct hrtimer timer;
+       u32 gpio_addr;
+       u32 last_gpio;
+       u32 mask_keycode;
+       u32 mask_keydown;
+       u32 mask_keyup;
+};
+
+static unsigned ir_samplerate = 4;
+module_param(ir_samplerate, uint, 0444);
+MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);     /* debug level [IR] */
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+#define ir_dprintk(fmt, arg...)        if (ir_debug) \
+       printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
+
+#define dprintk(fmt, arg...)   if (ir_debug) \
+       printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)
+
+/* ---------------------------------------------------------------------- */
+
+static void cx88_ir_handle_key(struct cx88_IR *ir)
+{
+       struct cx88_core *core = ir->core;
+       u32 gpio, data, auxgpio;
+
+       /* read gpio value */
+       gpio = cx_read(ir->gpio_addr);
+       switch (core->boardnr) {
+       case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
+               /* This board apparently uses a combination of 2 GPIO
+                  to represent the keys. Additionally, the second GPIO
+                  can be used for parity.
+
+                  Example:
+
+                  for key "5"
+                       gpio = 0x758, auxgpio = 0xe5 or 0xf5
+                  for key "Power"
+                       gpio = 0x758, auxgpio = 0xed or 0xfd
+                */
+
+               auxgpio = cx_read(MO_GP1_IO);
+               /* Take out the parity part */
+               gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
+               break;
+       case CX88_BOARD_WINFAST_DTV1000:
+       case CX88_BOARD_WINFAST_DTV1800H:
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+               gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
+               auxgpio = gpio;
+               break;
+       default:
+               auxgpio = gpio;
+       }
+       if (ir->polling) {
+               if (ir->last_gpio == auxgpio)
+                       return;
+               ir->last_gpio = auxgpio;
+       }
+
+       /* extract data */
+       data = ir_extract_bits(gpio, ir->mask_keycode);
+       ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
+                  gpio, data,
+                  ir->polling ? "poll" : "irq",
+                  (gpio & ir->mask_keydown) ? " down" : "",
+                  (gpio & ir->mask_keyup) ? " up" : "");
+
+       if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
+               u32 gpio_key = cx_read(MO_GP0_IO);
+
+               data = (data << 4) | ((gpio_key & 0xf0) >> 4);
+
+               rc_keydown(ir->dev, data, 0);
+
+       } else if (ir->mask_keydown) {
+               /* bit set on keydown */
+               if (gpio & ir->mask_keydown)
+                       rc_keydown_notimeout(ir->dev, data, 0);
+               else
+                       rc_keyup(ir->dev);
+
+       } else if (ir->mask_keyup) {
+               /* bit cleared on keydown */
+               if (0 == (gpio & ir->mask_keyup))
+                       rc_keydown_notimeout(ir->dev, data, 0);
+               else
+                       rc_keyup(ir->dev);
+
+       } else {
+               /* can't distinguish keydown/up :-/ */
+               rc_keydown_notimeout(ir->dev, data, 0);
+               rc_keyup(ir->dev);
+       }
+}
+
+static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
+{
+       unsigned long missed;
+       struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
+
+       cx88_ir_handle_key(ir);
+       missed = hrtimer_forward_now(&ir->timer,
+                                    ktime_set(0, ir->polling * 1000000));
+       if (missed > 1)
+               ir_dprintk("Missed ticks %ld\n", missed - 1);
+
+       return HRTIMER_RESTART;
+}
+
+static int __cx88_ir_start(void *priv)
+{
+       struct cx88_core *core = priv;
+       struct cx88_IR *ir;
+
+       if (!core || !core->ir)
+               return -EINVAL;
+
+       ir = core->ir;
+
+       if (ir->polling) {
+               hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+               ir->timer.function = cx88_ir_work;
+               hrtimer_start(&ir->timer,
+                             ktime_set(0, ir->polling * 1000000),
+                             HRTIMER_MODE_REL);
+       }
+       if (ir->sampling) {
+               core->pci_irqmask |= PCI_INT_IR_SMPINT;
+               cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
+               cx_write(MO_DDSCFG_IO, 0x5); /* enable */
+       }
+       return 0;
+}
+
+static void __cx88_ir_stop(void *priv)
+{
+       struct cx88_core *core = priv;
+       struct cx88_IR *ir;
+
+       if (!core || !core->ir)
+               return;
+
+       ir = core->ir;
+       if (ir->sampling) {
+               cx_write(MO_DDSCFG_IO, 0x0);
+               core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
+       }
+
+       if (ir->polling)
+               hrtimer_cancel(&ir->timer);
+}
+
+int cx88_ir_start(struct cx88_core *core)
+{
+       if (core->ir->users)
+               return __cx88_ir_start(core);
+
+       return 0;
+}
+
+void cx88_ir_stop(struct cx88_core *core)
+{
+       if (core->ir->users)
+               __cx88_ir_stop(core);
+}
+
+static int cx88_ir_open(struct rc_dev *rc)
+{
+       struct cx88_core *core = rc->priv;
+
+       core->ir->users++;
+       return __cx88_ir_start(core);
+}
+
+static void cx88_ir_close(struct rc_dev *rc)
+{
+       struct cx88_core *core = rc->priv;
+
+       core->ir->users--;
+       if (!core->ir->users)
+               __cx88_ir_stop(core);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+{
+       struct cx88_IR *ir;
+       struct rc_dev *dev;
+       char *ir_codes = NULL;
+       u64 rc_type = RC_TYPE_OTHER;
+       int err = -ENOMEM;
+       u32 hardware_mask = 0;  /* For devices with a hardware mask, when
+                                * used with a full-code IR table
+                                */
+
+       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       dev = rc_allocate_device();
+       if (!ir || !dev)
+               goto err_out_free;
+
+       ir->dev = dev;
+
+       /* detect & configure */
+       switch (core->boardnr) {
+       case CX88_BOARD_DNTV_LIVE_DVB_T:
+       case CX88_BOARD_KWORLD_DVB_T:
+       case CX88_BOARD_KWORLD_DVB_T_CX22702:
+               ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keycode = 0x1f;
+               ir->mask_keyup = 0x60;
+               ir->polling = 50; /* ms */
+               break;
+       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+               ir_codes = RC_MAP_CINERGY_1400;
+               ir->sampling = 0xeb04; /* address */
+               break;
+       case CX88_BOARD_HAUPPAUGE:
+       case CX88_BOARD_HAUPPAUGE_DVB_T1:
+       case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+       case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+       case CX88_BOARD_HAUPPAUGE_HVR1100:
+       case CX88_BOARD_HAUPPAUGE_HVR3000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000:
+       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+       case CX88_BOARD_PCHDTV_HD3000:
+       case CX88_BOARD_PCHDTV_HD5500:
+       case CX88_BOARD_HAUPPAUGE_IRONLY:
+               ir_codes = RC_MAP_HAUPPAUGE;
+               ir->sampling = 1;
+               break;
+       case CX88_BOARD_WINFAST_DTV2000H:
+       case CX88_BOARD_WINFAST_DTV2000H_J:
+       case CX88_BOARD_WINFAST_DTV1800H:
+       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+               ir_codes = RC_MAP_WINFAST;
+               ir->gpio_addr = MO_GP0_IO;
+               ir->mask_keycode = 0x8f8;
+               ir->mask_keyup = 0x100;
+               ir->polling = 50; /* ms */
+               break;
+       case CX88_BOARD_WINFAST2000XP_EXPERT:
+       case CX88_BOARD_WINFAST_DTV1000:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+               ir_codes = RC_MAP_WINFAST;
+               ir->gpio_addr = MO_GP0_IO;
+               ir->mask_keycode = 0x8f8;
+               ir->mask_keyup = 0x100;
+               ir->polling = 1; /* ms */
+               break;
+       case CX88_BOARD_IODATA_GVBCTV7E:
+               ir_codes = RC_MAP_IODATA_BCTV7E;
+               ir->gpio_addr = MO_GP0_IO;
+               ir->mask_keycode = 0xfd;
+               ir->mask_keydown = 0x02;
+               ir->polling = 5; /* ms */
+               break;
+       case CX88_BOARD_PROLINK_PLAYTVPVR:
+       case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
+               /*
+                * It seems that this hardware is paired with NEC extended
+                * address 0x866b. So, unfortunately, its usage with other
+                * IR's with different address won't work. Still, there are
+                * other IR's from the same manufacturer that works, like the
+                * 002-T mini RC, provided with newer PV hardware
+                */
+               ir_codes = RC_MAP_PIXELVIEW_MK12;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keyup = 0x80;
+               ir->polling = 10; /* ms */
+               hardware_mask = 0x3f;   /* Hardware returns only 6 bits from command part */
+               break;
+       case CX88_BOARD_PROLINK_PV_8000GT:
+       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+               ir_codes = RC_MAP_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 = RC_MAP_PIXELVIEW;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keycode = 0x1f;
+               ir->mask_keyup = 0x60;
+               ir->polling = 1; /* ms */
+               break;
+       case CX88_BOARD_ADSTECH_DVB_T_PCI:
+               ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keycode = 0xbf;
+               ir->mask_keyup = 0x40;
+               ir->polling = 50; /* ms */
+               break;
+       case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+               ir_codes = RC_MAP_MSI_TVANYWHERE;
+               ir->gpio_addr = MO_GP1_IO;
+               ir->mask_keycode = 0x1f;
+               ir->mask_keyup = 0x40;
+               ir->polling = 1; /* ms */
+               break;
+       case CX88_BOARD_AVERTV_303:
+       case CX88_BOARD_AVERTV_STUDIO_303:
+               ir_codes         = RC_MAP_AVERTV_303;
+               ir->gpio_addr    = MO_GP2_IO;
+               ir->mask_keycode = 0xfb;
+               ir->mask_keydown = 0x02;
+               ir->polling      = 50; /* ms */
+               break;
+       case CX88_BOARD_OMICOM_SS4_PCI:
+       case CX88_BOARD_SATTRADE_ST4200:
+       case CX88_BOARD_TBS_8920:
+       case CX88_BOARD_TBS_8910:
+       case CX88_BOARD_PROF_7300:
+       case CX88_BOARD_PROF_7301:
+       case CX88_BOARD_PROF_6200:
+               ir_codes = RC_MAP_TBS_NEC;
+               ir->sampling = 0xff00; /* address */
+               break;
+       case CX88_BOARD_TEVII_S464:
+       case CX88_BOARD_TEVII_S460:
+       case CX88_BOARD_TEVII_S420:
+               ir_codes = RC_MAP_TEVII_NEC;
+               ir->sampling = 0xff00; /* address */
+               break;
+       case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+               ir_codes         = RC_MAP_DNTV_LIVE_DVBT_PRO;
+               ir->sampling     = 0xff00; /* address */
+               break;
+       case CX88_BOARD_NORWOOD_MICRO:
+               ir_codes         = RC_MAP_NORWOOD;
+               ir->gpio_addr    = MO_GP1_IO;
+               ir->mask_keycode = 0x0e;
+               ir->mask_keyup   = 0x80;
+               ir->polling      = 50; /* ms */
+               break;
+       case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
+               ir_codes         = RC_MAP_NPGTECH;
+               ir->gpio_addr    = MO_GP0_IO;
+               ir->mask_keycode = 0xfa;
+               ir->polling      = 50; /* ms */
+               break;
+       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+               ir_codes         = RC_MAP_PINNACLE_PCTV_HD;
+               ir->sampling     = 1;
+               break;
+       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+               ir_codes         = RC_MAP_POWERCOLOR_REAL_ANGEL;
+               ir->gpio_addr    = MO_GP2_IO;
+               ir->mask_keycode = 0x7e;
+               ir->polling      = 100; /* ms */
+               break;
+       case CX88_BOARD_TWINHAN_VP1027_DVBS:
+               ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
+               rc_type          = RC_TYPE_NEC;
+               ir->sampling     = 0xff00; /* address */
+               break;
+       }
+
+       if (!ir_codes) {
+               err = -ENODEV;
+               goto err_out_free;
+       }
+
+       /*
+        * The usage of mask_keycode were very convenient, due to several
+        * reasons. Among others, the scancode tables were using the scancode
+        * as the index elements. So, the less bits it was used, the smaller
+        * the table were stored. After the input changes, the better is to use
+        * the full scancodes, since it allows replacing the IR remote by
+        * another one. Unfortunately, there are still some hardware, like
+        * Pixelview Ultra Pro, where only part of the scancode is sent via
+        * GPIO. So, there's no way to get the full scancode. Due to that,
+        * hardware_mask were introduced here: it represents those hardware
+        * that has such limits.
+        */
+       if (hardware_mask && !ir->mask_keycode)
+               ir->mask_keycode = hardware_mask;
+
+       /* init input device */
+       snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
+       snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
+
+       dev->input_name = ir->name;
+       dev->input_phys = ir->phys;
+       dev->input_id.bustype = BUS_PCI;
+       dev->input_id.version = 1;
+       if (pci->subsystem_vendor) {
+               dev->input_id.vendor = pci->subsystem_vendor;
+               dev->input_id.product = pci->subsystem_device;
+       } else {
+               dev->input_id.vendor = pci->vendor;
+               dev->input_id.product = pci->device;
+       }
+       dev->dev.parent = &pci->dev;
+       dev->map_name = ir_codes;
+       dev->driver_name = MODULE_NAME;
+       dev->priv = core;
+       dev->open = cx88_ir_open;
+       dev->close = cx88_ir_close;
+       dev->scanmask = hardware_mask;
+
+       if (ir->sampling) {
+               dev->driver_type = RC_DRIVER_IR_RAW;
+               dev->timeout = 10 * 1000 * 1000; /* 10 ms */
+       } else {
+               dev->driver_type = RC_DRIVER_SCANCODE;
+               dev->allowed_protos = rc_type;
+       }
+
+       ir->core = core;
+       core->ir = ir;
+
+       /* all done */
+       err = rc_register_device(dev);
+       if (err)
+               goto err_out_free;
+
+       return 0;
+
+err_out_free:
+       rc_free_device(dev);
+       core->ir = NULL;
+       kfree(ir);
+       return err;
+}
+
+int cx88_ir_fini(struct cx88_core *core)
+{
+       struct cx88_IR *ir = core->ir;
+
+       /* skip detach on non attached boards */
+       if (NULL == ir)
+               return 0;
+
+       cx88_ir_stop(core);
+       rc_unregister_device(ir->dev);
+       kfree(ir);
+
+       /* done */
+       core->ir = NULL;
+       return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void cx88_ir_irq(struct cx88_core *core)
+{
+       struct cx88_IR *ir = core->ir;
+       u32 samples;
+       unsigned todo, bits;
+       struct ir_raw_event ev;
+
+       if (!ir || !ir->sampling)
+               return;
+
+       /*
+        * Samples are stored in a 32 bit register, oldest sample in
+        * the msb. A set bit represents space and an unset bit
+        * represents a pulse.
+        */
+       samples = cx_read(MO_SAMPLE_IO);
+
+       if (samples == 0xff && ir->dev->idle)
+               return;
+
+       init_ir_raw_event(&ev);
+       for (todo = 32; todo > 0; todo -= bits) {
+               ev.pulse = samples & 0x80000000 ? false : true;
+               bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
+               ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
+               ir_raw_event_store_with_filter(ir->dev, &ev);
+               samples <<= bits;
+       }
+       ir_raw_event_handle(ir->dev);
+}
+
+static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       int flags, code;
+
+       /* poll IR chip */
+       flags = i2c_smbus_read_byte_data(ir->c, 0x10);
+       if (flags < 0) {
+               dprintk("read error\n");
+               return 0;
+       }
+       /* key pressed ? */
+       if (0 == (flags & 0x80))
+               return 0;
+
+       /* read actual key code */
+       code = i2c_smbus_read_byte_data(ir->c, 0x00);
+       if (code < 0) {
+               dprintk("read error\n");
+               return 0;
+       }
+
+       dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
+                  code & 0xff, flags & 0xff);
+
+       *ir_key = code & 0xff;
+       *ir_raw = code;
+       return 1;
+}
+
+void cx88_i2c_init_ir(struct cx88_core *core)
+{
+       struct i2c_board_info info;
+       const unsigned short default_addr_list[] = {
+               0x18, 0x6b, 0x71,
+               I2C_CLIENT_END
+       };
+       const unsigned short pvr2000_addr_list[] = {
+               0x18, 0x1a,
+               I2C_CLIENT_END
+       };
+       const unsigned short *addr_list = default_addr_list;
+       const unsigned short *addrp;
+       /* Instantiate the IR receiver device, if present */
+       if (0 != core->i2c_rc)
+               return;
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
+       switch (core->boardnr) {
+       case CX88_BOARD_LEADTEK_PVR2000:
+               addr_list = pvr2000_addr_list;
+               core->init_data.name = "cx88 Leadtek PVR 2000 remote";
+               core->init_data.type = RC_TYPE_UNKNOWN;
+               core->init_data.get_key = get_key_pvr2000;
+               core->init_data.ir_codes = RC_MAP_EMPTY;
+               break;
+       }
+
+       /*
+        * We can't call i2c_new_probed_device() because it uses
+        * quick writes for probing and at least some RC receiver
+        * devices only reply to reads.
+        * Also, Hauppauge XVR needs to be specified, as address 0x71
+        * conflicts with another remote type used with saa7134
+        */
+       for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
+               info.platform_data = NULL;
+               memset(&core->init_data, 0, sizeof(core->init_data));
+
+               if (*addrp == 0x71) {
+                       /* Hauppauge XVR */
+                       core->init_data.name = "cx88 Hauppauge XVR remote";
+                       core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
+                       core->init_data.type = RC_TYPE_RC5;
+                       core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+
+                       info.platform_data = &core->init_data;
+               }
+               if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
+                                       I2C_SMBUS_READ, 0,
+                                       I2C_SMBUS_QUICK, NULL) >= 0) {
+                       info.addr = *addrp;
+                       i2c_new_device(&core->i2c_adap, &info);
+                       break;
+               }
+       }
+}
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
+MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
new file mode 100644 (file)
index 0000000..cd5386e
--- /dev/null
@@ -0,0 +1,929 @@
+/*
+ *
+ *  Support for the mpeg transport stream transfers
+ *  PCI function #2 of the cx2388x.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.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/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <asm/delay.h>
+
+#include "cx88.h"
+
+/* ------------------------------------------------------------------ */
+
+MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
+MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
+
+#define dprintk(level,fmt, arg...)     if (debug >= level) \
+       printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
+
+#define mpeg_dbg(level,fmt, arg...)    if (debug >= level) \
+       printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
+
+       if (dev->core->board.mpeg & CX88_MPEG_DVB)
+               request_module("cx88-dvb");
+       if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
+               request_module("cx88-blackbird");
+}
+
+static void request_modules(struct cx8802_dev *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct cx8802_dev *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+
+static LIST_HEAD(cx8802_devlist);
+static DEFINE_MUTEX(cx8802_mutex);
+/* ------------------------------------------------------------------ */
+
+static int cx8802_start_dma(struct cx8802_dev    *dev,
+                           struct cx88_dmaqueue *q,
+                           struct cx88_buffer   *buf)
+{
+       struct cx88_core *core = dev->core;
+
+       dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
+               buf->vb.width, buf->vb.height, buf->vb.field);
+
+       /* setup fifo + format */
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
+                               dev->ts_packet_size, buf->risc.dma);
+
+       /* write TS length to chip */
+       cx_write(MO_TS_LNGTH, buf->vb.width);
+
+       /* FIXME: this needs a review.
+        * also: move to cx88-blackbird + cx88-dvb source files? */
+
+       dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
+
+       if ( (core->active_type_id == CX88_MPEG_DVB) &&
+               (core->board.mpeg & CX88_MPEG_DVB) ) {
+
+               dprintk( 1, "cx8802_start_dma doing .dvb\n");
+               /* negedge driven & software reset */
+               cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
+               udelay(100);
+               cx_write(MO_PINMUX_IO, 0x00);
+               cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
+               switch (core->boardnr) {
+               case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+               case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+               case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+               case CX88_BOARD_PCHDTV_HD5500:
+                       cx_write(TS_SOP_STAT, 1<<13);
+                       break;
+               case CX88_BOARD_SAMSUNG_SMT_7020:
+                       cx_write(TS_SOP_STAT, 0x00);
+                       break;
+               case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+               case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+                       cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
+                       udelay(100);
+                       break;
+               case CX88_BOARD_HAUPPAUGE_HVR1300:
+                       /* Enable MPEG parallel IO and video signal pins */
+                       cx_write(MO_PINMUX_IO, 0x88);
+                       cx_write(TS_SOP_STAT, 0);
+                       cx_write(TS_VALERR_CNTRL, 0);
+                       break;
+               case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+                       /* Enable MPEG parallel IO and video signal pins */
+                       cx_write(MO_PINMUX_IO, 0x88);
+                       cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4));
+                       dev->ts_gen_cntrl = 5;
+                       cx_write(TS_SOP_STAT, 0);
+                       cx_write(TS_VALERR_CNTRL, 0);
+                       udelay(100);
+                       break;
+               default:
+                       cx_write(TS_SOP_STAT, 0x00);
+                       break;
+               }
+               cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
+               udelay(100);
+       } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
+               (core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
+               dprintk( 1, "cx8802_start_dma doing .blackbird\n");
+               cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
+
+               cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
+               udelay(100);
+
+               cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
+               cx_write(TS_VALERR_CNTRL, 0x2000);
+
+               cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
+               udelay(100);
+       } else {
+               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
+                       core->board.mpeg );
+               return -EINVAL;
+       }
+
+       /* reset counter */
+       cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
+       q->count = 1;
+
+       /* enable irqs */
+       dprintk( 1, "setting the interrupt mask\n" );
+       cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
+       cx_set(MO_TS_INTMSK,  0x1f0011);
+
+       /* start dma */
+       cx_set(MO_DEV_CNTRL2, (1<<5));
+       cx_set(MO_TS_DMACNTRL, 0x11);
+       return 0;
+}
+
+static int cx8802_stop_dma(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       dprintk( 1, "cx8802_stop_dma\n" );
+
+       /* stop dma */
+       cx_clear(MO_TS_DMACNTRL, 0x11);
+
+       /* disable irqs */
+       cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT);
+       cx_clear(MO_TS_INTMSK, 0x1f0011);
+
+       /* Reset the controller */
+       cx_write(TS_GEN_CNTRL, 0xcd);
+       return 0;
+}
+
+static int cx8802_restart_queue(struct cx8802_dev    *dev,
+                               struct cx88_dmaqueue *q)
+{
+       struct cx88_buffer *buf;
+
+       dprintk( 1, "cx8802_restart_queue\n" );
+       if (list_empty(&q->active))
+       {
+               struct cx88_buffer *prev;
+               prev = NULL;
+
+               dprintk(1, "cx8802_restart_queue: queue is empty\n" );
+
+               for (;;) {
+                       if (list_empty(&q->queued))
+                               return 0;
+                       buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+                       if (NULL == prev) {
+                               list_del(&buf->vb.queue);
+                               list_add_tail(&buf->vb.queue,&q->active);
+                               cx8802_start_dma(dev, q, buf);
+                               buf->vb.state = VIDEOBUF_ACTIVE;
+                               buf->count    = q->count++;
+                               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+                               dprintk(1,"[%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,&q->active);
+                               buf->vb.state = VIDEOBUF_ACTIVE;
+                               buf->count    = q->count++;
+                               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                               dprintk(1,"[%p/%d] restart_queue - move to active\n",
+                                       buf,buf->vb.i);
+                       } else {
+                               return 0;
+                       }
+                       prev = buf;
+               }
+               return 0;
+       }
+
+       buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+       dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+               buf, buf->vb.i);
+       cx8802_start_dma(dev, q, buf);
+       list_for_each_entry(buf, &q->active, vb.queue)
+               buf->count = q->count++;
+       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+                       struct cx88_buffer *buf, enum v4l2_field field)
+{
+       int size = dev->ts_packet_size * dev->ts_packet_count;
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+       int rc;
+
+       dprintk(1, "%s: %p\n", __func__, buf);
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               buf->vb.width  = dev->ts_packet_size;
+               buf->vb.height = dev->ts_packet_count;
+               buf->vb.size   = size;
+               buf->vb.field  = field /*V4L2_FIELD_TOP*/;
+
+               if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+                       goto fail;
+               cx88_risc_databuffer(dev->pci, &buf->risc,
+                                    dma->sglist,
+                                    buf->vb.width, buf->vb.height, 0);
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       cx88_free_buffer(q,buf);
+       return rc;
+}
+
+void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
+{
+       struct cx88_buffer    *prev;
+       struct cx88_dmaqueue  *cx88q = &dev->mpegq;
+
+       dprintk( 1, "cx8802_buf_queue\n" );
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
+
+       if (list_empty(&cx88q->active)) {
+               dprintk( 1, "queue is empty - first active\n" );
+               list_add_tail(&buf->vb.queue,&cx88q->active);
+               cx8802_start_dma(dev, cx88q, buf);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = cx88q->count++;
+               mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
+               dprintk(1,"[%p/%d] %s - first active\n",
+                       buf, buf->vb.i, __func__);
+
+       } else {
+               dprintk( 1, "queue is not empty - append to active\n" );
+               prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
+               list_add_tail(&buf->vb.queue,&cx88q->active);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               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, __func__);
+       }
+}
+
+/* ----------------------------------------------------------- */
+
+static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
+{
+       struct cx88_dmaqueue *q = &dev->mpegq;
+       struct cx88_buffer *buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->slock,flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
+                       buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
+       }
+       if (restart)
+       {
+               dprintk(1, "restarting queue\n" );
+               cx8802_restart_queue(dev,q);
+       }
+       spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+void cx8802_cancel_buffers(struct cx8802_dev *dev)
+{
+       struct cx88_dmaqueue *q = &dev->mpegq;
+
+       dprintk( 1, "cx8802_cancel_buffers" );
+       del_timer_sync(&q->timeout);
+       cx8802_stop_dma(dev);
+       do_cancel_buffers(dev,"cancel",0);
+}
+
+static void cx8802_timeout(unsigned long data)
+{
+       struct cx8802_dev *dev = (struct cx8802_dev*)data;
+
+       dprintk(1, "%s\n",__func__);
+
+       if (debug)
+               cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+       cx8802_stop_dma(dev);
+       do_cancel_buffers(dev,"timeout",1);
+}
+
+static const char * cx88_mpeg_irqs[32] = {
+       "ts_risci1", NULL, NULL, NULL,
+       "ts_risci2", NULL, NULL, NULL,
+       "ts_oflow",  NULL, NULL, NULL,
+       "ts_sync",   NULL, NULL, NULL,
+       "opc_err", "par_err", "rip_err", "pci_abort",
+       "ts_err?",
+};
+
+static void cx8802_mpeg_irq(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       u32 status, mask, count;
+
+       dprintk( 1, "cx8802_mpeg_irq\n" );
+       status = cx_read(MO_TS_INTSTAT);
+       mask   = cx_read(MO_TS_INTMSK);
+       if (0 == (status & mask))
+               return;
+
+       cx_write(MO_TS_INTSTAT, status);
+
+       if (debug || (status & mask & ~0xff))
+               cx88_print_irqbits(core->name, "irq mpeg ",
+                                  cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
+                                  status, mask);
+
+       /* risc op code error */
+       if (status & (1 << 16)) {
+               printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
+               cx_clear(MO_TS_DMACNTRL, 0x11);
+               cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+       }
+
+       /* risc1 y */
+       if (status & 0x01) {
+               dprintk( 1, "wake up\n" );
+               spin_lock(&dev->slock);
+               count = cx_read(MO_TS_GPCNT);
+               cx88_wakeup(dev->core, &dev->mpegq, count);
+               spin_unlock(&dev->slock);
+       }
+
+       /* risc2 y */
+       if (status & 0x10) {
+               spin_lock(&dev->slock);
+               cx8802_restart_queue(dev,&dev->mpegq);
+               spin_unlock(&dev->slock);
+       }
+
+       /* other general errors */
+       if (status & 0x1f0100) {
+               dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
+               spin_lock(&dev->slock);
+               cx8802_stop_dma(dev);
+               cx8802_restart_queue(dev,&dev->mpegq);
+               spin_unlock(&dev->slock);
+       }
+}
+
+#define MAX_IRQ_LOOP 10
+
+static irqreturn_t cx8802_irq(int irq, void *dev_id)
+{
+       struct cx8802_dev *dev = dev_id;
+       struct cx88_core *core = dev->core;
+       u32 status;
+       int loop, handled = 0;
+
+       for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
+               status = cx_read(MO_PCI_INTSTAT) &
+                       (core->pci_irqmask | PCI_INT_TSINT);
+               if (0 == status)
+                       goto out;
+               dprintk( 1, "cx8802_irq\n" );
+               dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
+               dprintk( 1, "    status: %d\n", status );
+               handled = 1;
+               cx_write(MO_PCI_INTSTAT, status);
+
+               if (status & core->pci_irqmask)
+                       cx88_core_irq(core,status);
+               if (status & PCI_INT_TSINT)
+                       cx8802_mpeg_irq(dev);
+       };
+       if (MAX_IRQ_LOOP == loop) {
+               dprintk( 0, "clearing mask\n" );
+               printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
+                      core->name);
+               cx_write(MO_PCI_INTMSK,0);
+       }
+
+ out:
+       return IRQ_RETVAL(handled);
+}
+
+static int cx8802_init_common(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       int err;
+
+       /* pci init */
+       if (pci_enable_device(dev->pci))
+               return -EIO;
+       pci_set_master(dev->pci);
+       if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
+               printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
+               return -EIO;
+       }
+
+       dev->pci_rev = dev->pci->revision;
+       pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);
+       printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
+              "latency: %d, mmio: 0x%llx\n", dev->core->name,
+              pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
+              dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
+
+       /* initialize driver struct */
+       spin_lock_init(&dev->slock);
+
+       /* init dma queue */
+       INIT_LIST_HEAD(&dev->mpegq.active);
+       INIT_LIST_HEAD(&dev->mpegq.queued);
+       dev->mpegq.timeout.function = cx8802_timeout;
+       dev->mpegq.timeout.data     = (unsigned long)dev;
+       init_timer(&dev->mpegq.timeout);
+       cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
+                         MO_TS_DMACNTRL,0x11,0x00);
+
+       /* get irq */
+       err = request_irq(dev->pci->irq, cx8802_irq,
+                         IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
+       if (err < 0) {
+               printk(KERN_ERR "%s: can't get IRQ %d\n",
+                      dev->core->name, dev->pci->irq);
+               return err;
+       }
+       cx_set(MO_PCI_INTMSK, core->pci_irqmask);
+
+       /* everything worked */
+       pci_set_drvdata(dev->pci,dev);
+       return 0;
+}
+
+static void cx8802_fini_common(struct cx8802_dev *dev)
+{
+       dprintk( 2, "cx8802_fini_common\n" );
+       cx8802_stop_dma(dev);
+       pci_disable_device(dev->pci);
+
+       /* unregister stuff */
+       free_irq(dev->pci->irq, dev);
+       pci_set_drvdata(dev->pci, NULL);
+
+       /* free memory */
+       btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
+}
+
+/* ----------------------------------------------------------- */
+
+static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
+{
+       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx88_core *core = dev->core;
+
+       /* stop mpeg dma */
+       spin_lock(&dev->slock);
+       if (!list_empty(&dev->mpegq.active)) {
+               dprintk( 2, "suspend\n" );
+               printk("%s: suspend mpeg\n", core->name);
+               cx8802_stop_dma(dev);
+               del_timer(&dev->mpegq.timeout);
+       }
+       spin_unlock(&dev->slock);
+
+       /* FIXME -- shutdown device */
+       cx88_shutdown(dev->core);
+
+       pci_save_state(pci_dev);
+       if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+               pci_disable_device(pci_dev);
+               dev->state.disabled = 1;
+       }
+       return 0;
+}
+
+static int cx8802_resume_common(struct pci_dev *pci_dev)
+{
+       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx88_core *core = dev->core;
+       int err;
+
+       if (dev->state.disabled) {
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       printk(KERN_ERR "%s: can't enable device\n",
+                                              dev->core->name);
+                       return err;
+               }
+               dev->state.disabled = 0;
+       }
+       err=pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               printk(KERN_ERR "%s: can't enable device\n",
+                                              dev->core->name);
+               pci_disable_device(pci_dev);
+               dev->state.disabled = 1;
+
+               return err;
+       }
+       pci_restore_state(pci_dev);
+
+       /* FIXME: re-initialize hardware */
+       cx88_reset(dev->core);
+
+       /* restart video+vbi capture */
+       spin_lock(&dev->slock);
+       if (!list_empty(&dev->mpegq.active)) {
+               printk("%s: resume mpeg\n", core->name);
+               cx8802_restart_queue(dev,&dev->mpegq);
+       }
+       spin_unlock(&dev->slock);
+
+       return 0;
+}
+
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
+{
+       struct cx8802_driver *d;
+
+       list_for_each_entry(d, &dev->drvlist, drvlist)
+               if (d->type_id == btype)
+                       return d;
+
+       return NULL;
+}
+
+/* Driver asked for hardware access. */
+static int cx8802_request_acquire(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+       unsigned int    i;
+
+       /* Fail a request for hardware if the device is busy. */
+       if (core->active_type_id != CX88_BOARD_NONE &&
+           core->active_type_id != drv->type_id)
+               return -EBUSY;
+
+       if (drv->type_id == CX88_MPEG_DVB) {
+               /* When switching to DVB, always set the input to the tuner */
+               core->last_analog_input = core->input;
+               core->input = 0;
+               for (i = 0;
+                    i < (sizeof(core->board.input) / sizeof(struct cx88_input));
+                    i++) {
+                       if (core->board.input[i].type == CX88_VMUX_DVB) {
+                               core->input = i;
+                               break;
+                       }
+               }
+       }
+
+       if (drv->advise_acquire)
+       {
+               core->active_ref++;
+               if (core->active_type_id == CX88_BOARD_NONE) {
+                       core->active_type_id = drv->type_id;
+                       drv->advise_acquire(drv);
+               }
+
+               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+       }
+
+       return 0;
+}
+
+/* Driver asked to release hardware. */
+static int cx8802_request_release(struct cx8802_driver *drv)
+{
+       struct cx88_core *core = drv->core;
+
+       if (drv->advise_release && --core->active_ref == 0)
+       {
+               if (drv->type_id == CX88_MPEG_DVB) {
+                       /* If the DVB driver is releasing, reset the input
+                          state to the last configured analog input */
+                       core->input = core->last_analog_input;
+               }
+
+               drv->advise_release(drv);
+               core->active_type_id = CX88_BOARD_NONE;
+               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+       }
+
+       return 0;
+}
+
+static int cx8802_check_driver(struct cx8802_driver *drv)
+{
+       if (drv == NULL)
+               return -ENODEV;
+
+       if ((drv->type_id != CX88_MPEG_DVB) &&
+               (drv->type_id != CX88_MPEG_BLACKBIRD))
+               return -EINVAL;
+
+       if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
+               (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
+               return -EINVAL;
+
+       if ((drv->probe == NULL) ||
+               (drv->remove == NULL) ||
+               (drv->advise_acquire == NULL) ||
+               (drv->advise_release == NULL))
+               return -EINVAL;
+
+       return 0;
+}
+
+int cx8802_register_driver(struct cx8802_driver *drv)
+{
+       struct cx8802_dev *dev;
+       struct cx8802_driver *driver;
+       int err, i = 0;
+
+       printk(KERN_INFO
+              "cx88/2: registering cx8802 driver, type: %s access: %s\n",
+              drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+              drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+
+       if ((err = cx8802_check_driver(drv)) != 0) {
+               printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
+               return err;
+       }
+
+       mutex_lock(&cx8802_mutex);
+
+       list_for_each_entry(dev, &cx8802_devlist, devlist) {
+               printk(KERN_INFO
+                      "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
+                      dev->core->name, dev->pci->subsystem_vendor,
+                      dev->pci->subsystem_device, dev->core->board.name,
+                      dev->core->boardnr);
+
+               /* Bring up a new struct for each driver instance */
+               driver = kzalloc(sizeof(*drv),GFP_KERNEL);
+               if (driver == NULL) {
+                       err = -ENOMEM;
+                       goto out;
+               }
+
+               /* Snapshot of the driver registration data */
+               drv->core = dev->core;
+               drv->suspend = cx8802_suspend_common;
+               drv->resume = cx8802_resume_common;
+               drv->request_acquire = cx8802_request_acquire;
+               drv->request_release = cx8802_request_release;
+               memcpy(driver, drv, sizeof(*driver));
+
+               mutex_lock(&drv->core->lock);
+               err = drv->probe(driver);
+               if (err == 0) {
+                       i++;
+                       list_add_tail(&driver->drvlist, &dev->drvlist);
+               } else {
+                       printk(KERN_ERR
+                              "%s/2: cx8802 probe failed, err = %d\n",
+                              dev->core->name, err);
+               }
+               mutex_unlock(&drv->core->lock);
+       }
+
+       err = i ? 0 : -ENODEV;
+out:
+       mutex_unlock(&cx8802_mutex);
+       return err;
+}
+
+int cx8802_unregister_driver(struct cx8802_driver *drv)
+{
+       struct cx8802_dev *dev;
+       struct cx8802_driver *d, *dtmp;
+       int err = 0;
+
+       printk(KERN_INFO
+              "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
+              drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+              drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+
+       mutex_lock(&cx8802_mutex);
+
+       list_for_each_entry(dev, &cx8802_devlist, devlist) {
+               printk(KERN_INFO
+                      "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
+                      dev->core->name, dev->pci->subsystem_vendor,
+                      dev->pci->subsystem_device, dev->core->board.name,
+                      dev->core->boardnr);
+
+               mutex_lock(&dev->core->lock);
+
+               list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
+                       /* only unregister the correct driver type */
+                       if (d->type_id != drv->type_id)
+                               continue;
+
+                       err = d->remove(d);
+                       if (err == 0) {
+                               list_del(&d->drvlist);
+                               kfree(d);
+                       } else
+                               printk(KERN_ERR "%s/2: cx8802 driver remove "
+                                      "failed (%d)\n", dev->core->name, err);
+               }
+
+               mutex_unlock(&dev->core->lock);
+       }
+
+       mutex_unlock(&cx8802_mutex);
+
+       return err;
+}
+
+/* ----------------------------------------------------------- */
+static int __devinit cx8802_probe(struct pci_dev *pci_dev,
+                              const struct pci_device_id *pci_id)
+{
+       struct cx8802_dev *dev;
+       struct cx88_core  *core;
+       int err;
+
+       /* general setup */
+       core = cx88_core_get(pci_dev);
+       if (NULL == core)
+               return -EINVAL;
+
+       printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
+
+       err = -ENODEV;
+       if (!core->board.mpeg)
+               goto fail_core;
+
+       err = -ENOMEM;
+       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+       if (NULL == dev)
+               goto fail_core;
+       dev->pci = pci_dev;
+       dev->core = core;
+
+       /* Maintain a reference so cx88-video can query the 8802 device. */
+       core->dvbdev = dev;
+
+       err = cx8802_init_common(dev);
+       if (err != 0)
+               goto fail_free;
+
+       INIT_LIST_HEAD(&dev->drvlist);
+       mutex_lock(&cx8802_mutex);
+       list_add_tail(&dev->devlist,&cx8802_devlist);
+       mutex_unlock(&cx8802_mutex);
+
+       /* now autoload cx88-dvb or cx88-blackbird */
+       request_modules(dev);
+       return 0;
+
+ fail_free:
+       kfree(dev);
+ fail_core:
+       core->dvbdev = NULL;
+       cx88_core_put(core,pci_dev);
+       return err;
+}
+
+static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+{
+       struct cx8802_dev *dev;
+
+       dev = pci_get_drvdata(pci_dev);
+
+       dprintk( 1, "%s\n", __func__);
+
+       flush_request_modules(dev);
+
+       mutex_lock(&dev->core->lock);
+
+       if (!list_empty(&dev->drvlist)) {
+               struct cx8802_driver *drv, *tmp;
+               int err;
+
+               printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
+                      "while cx8802 sub-drivers still loaded?!\n",
+                      dev->core->name);
+
+               list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
+                       err = drv->remove(drv);
+                       if (err == 0) {
+                               list_del(&drv->drvlist);
+                       } else
+                               printk(KERN_ERR "%s/2: cx8802 driver remove "
+                                      "failed (%d)\n", dev->core->name, err);
+                       kfree(drv);
+               }
+       }
+
+       mutex_unlock(&dev->core->lock);
+
+       /* Destroy any 8802 reference. */
+       dev->core->dvbdev = NULL;
+
+       /* common */
+       cx8802_fini_common(dev);
+       cx88_core_put(dev->core,dev->pci);
+       kfree(dev);
+}
+
+static const struct pci_device_id cx8802_pci_tbl[] = {
+       {
+               .vendor       = 0x14f1,
+               .device       = 0x8802,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       },{
+               /* --- end of list --- */
+       }
+};
+MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
+
+static struct pci_driver cx8802_pci_driver = {
+       .name     = "cx88-mpeg driver manager",
+       .id_table = cx8802_pci_tbl,
+       .probe    = cx8802_probe,
+       .remove   = __devexit_p(cx8802_remove),
+};
+
+static int __init cx8802_init(void)
+{
+       printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
+              CX88_VERSION);
+       return pci_register_driver(&cx8802_pci_driver);
+}
+
+static void __exit cx8802_fini(void)
+{
+       pci_unregister_driver(&cx8802_pci_driver);
+}
+
+module_init(cx8802_init);
+module_exit(cx8802_fini);
+EXPORT_SYMBOL(cx8802_buf_prepare);
+EXPORT_SYMBOL(cx8802_buf_queue);
+EXPORT_SYMBOL(cx8802_cancel_buffers);
+
+EXPORT_SYMBOL(cx8802_register_driver);
+EXPORT_SYMBOL(cx8802_unregister_driver);
+EXPORT_SYMBOL(cx8802_get_driver);
+/* ----------------------------------------------------------- */
+/*
+ * 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
+ */
diff --git a/drivers/media/pci/cx88/cx88-reg.h b/drivers/media/pci/cx88/cx88-reg.h
new file mode 100644 (file)
index 0000000..2ec52d1
--- /dev/null
@@ -0,0 +1,836 @@
+/*
+
+    cx88x-hw.h - CX2388x register offsets
+
+    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
+                 2001 Michael Eskin
+                 2002 Yurij Sysoev <yurij@naturesoft.net>
+                 2003 Gerd Knorr <kraxel@bytesex.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 _CX88_REG_H_
+#define _CX88_REG_H_
+
+/* ---------------------------------------------------------------------- */
+/* PCI IDs and config space                                               */
+
+#ifndef PCI_VENDOR_ID_CONEXANT
+# define PCI_VENDOR_ID_CONEXANT                0x14F1
+#endif
+#ifndef PCI_DEVICE_ID_CX2300_VID
+# define PCI_DEVICE_ID_CX2300_VID      0x8800
+#endif
+
+#define CX88X_DEVCTRL 0x40
+#define CX88X_EN_TBFX 0x02
+#define CX88X_EN_VSFX 0x04
+
+/* ---------------------------------------------------------------------- */
+/* PCI controller registers                                               */
+
+/* Command and Status Register */
+#define F0_CMD_STAT_MM      0x2f0004
+#define F1_CMD_STAT_MM      0x2f0104
+#define F2_CMD_STAT_MM      0x2f0204
+#define F3_CMD_STAT_MM      0x2f0304
+#define F4_CMD_STAT_MM      0x2f0404
+
+/* Device Control #1 */
+#define F0_DEV_CNTRL1_MM    0x2f0040
+#define F1_DEV_CNTRL1_MM    0x2f0140
+#define F2_DEV_CNTRL1_MM    0x2f0240
+#define F3_DEV_CNTRL1_MM    0x2f0340
+#define F4_DEV_CNTRL1_MM    0x2f0440
+
+/* Device Control #1 */
+#define F0_BAR0_MM          0x2f0010
+#define F1_BAR0_MM          0x2f0110
+#define F2_BAR0_MM          0x2f0210
+#define F3_BAR0_MM          0x2f0310
+#define F4_BAR0_MM          0x2f0410
+
+/* ---------------------------------------------------------------------- */
+/* DMA Controller registers                                               */
+
+#define MO_PDMA_STHRSH      0x200000 // Source threshold
+#define MO_PDMA_STADRS      0x200004 // Source target address
+#define MO_PDMA_SIADRS      0x200008 // Source internal address
+#define MO_PDMA_SCNTRL      0x20000C // Source control
+#define MO_PDMA_DTHRSH      0x200010 // Destination threshold
+#define MO_PDMA_DTADRS      0x200014 // Destination target address
+#define MO_PDMA_DIADRS      0x200018 // Destination internal address
+#define MO_PDMA_DCNTRL      0x20001C // Destination control
+#define MO_LD_SSID          0x200030 // Load subsystem ID
+#define MO_DEV_CNTRL2       0x200034 // Device control
+#define MO_PCI_INTMSK       0x200040 // PCI interrupt mask
+#define MO_PCI_INTSTAT      0x200044 // PCI interrupt status
+#define MO_PCI_INTMSTAT     0x200048 // PCI interrupt masked status
+#define MO_VID_INTMSK       0x200050 // Video interrupt mask
+#define MO_VID_INTSTAT      0x200054 // Video interrupt status
+#define MO_VID_INTMSTAT     0x200058 // Video interrupt masked status
+#define MO_VID_INTSSTAT     0x20005C // Video interrupt set status
+#define MO_AUD_INTMSK       0x200060 // Audio interrupt mask
+#define MO_AUD_INTSTAT      0x200064 // Audio interrupt status
+#define MO_AUD_INTMSTAT     0x200068 // Audio interrupt masked status
+#define MO_AUD_INTSSTAT     0x20006C // Audio interrupt set status
+#define MO_TS_INTMSK        0x200070 // Transport stream interrupt mask
+#define MO_TS_INTSTAT       0x200074 // Transport stream interrupt status
+#define MO_TS_INTMSTAT      0x200078 // Transport stream interrupt mask status
+#define MO_TS_INTSSTAT      0x20007C // Transport stream interrupt set status
+#define MO_VIP_INTMSK       0x200080 // VIP interrupt mask
+#define MO_VIP_INTSTAT      0x200084 // VIP interrupt status
+#define MO_VIP_INTMSTAT     0x200088 // VIP interrupt masked status
+#define MO_VIP_INTSSTAT     0x20008C // VIP interrupt set status
+#define MO_GPHST_INTMSK     0x200090 // Host interrupt mask
+#define MO_GPHST_INTSTAT    0x200094 // Host interrupt status
+#define MO_GPHST_INTMSTAT   0x200098 // Host interrupt masked status
+#define MO_GPHST_INTSSTAT   0x20009C // Host interrupt set status
+
+// DMA Channels 1-6 belong to SPIPE
+#define MO_DMA7_PTR1        0x300018 // {24}RW* DMA Current Ptr : Ch#7
+#define MO_DMA8_PTR1        0x30001C // {24}RW* DMA Current Ptr : Ch#8
+
+// DMA Channels 9-20 belong to SPIPE
+#define MO_DMA21_PTR1       0x300080 // {24}R0* DMA Current Ptr : Ch#21
+#define MO_DMA22_PTR1       0x300084 // {24}R0* DMA Current Ptr : Ch#22
+#define MO_DMA23_PTR1       0x300088 // {24}R0* DMA Current Ptr : Ch#23
+#define MO_DMA24_PTR1       0x30008C // {24}R0* DMA Current Ptr : Ch#24
+#define MO_DMA25_PTR1       0x300090 // {24}R0* DMA Current Ptr : Ch#25
+#define MO_DMA26_PTR1       0x300094 // {24}R0* DMA Current Ptr : Ch#26
+#define MO_DMA27_PTR1       0x300098 // {24}R0* DMA Current Ptr : Ch#27
+#define MO_DMA28_PTR1       0x30009C // {24}R0* DMA Current Ptr : Ch#28
+#define MO_DMA29_PTR1       0x3000A0 // {24}R0* DMA Current Ptr : Ch#29
+#define MO_DMA30_PTR1       0x3000A4 // {24}R0* DMA Current Ptr : Ch#30
+#define MO_DMA31_PTR1       0x3000A8 // {24}R0* DMA Current Ptr : Ch#31
+#define MO_DMA32_PTR1       0x3000AC // {24}R0* DMA Current Ptr : Ch#32
+
+#define MO_DMA21_PTR2       0x3000C0 // {24}RW* DMA Tab Ptr : Ch#21
+#define MO_DMA22_PTR2       0x3000C4 // {24}RW* DMA Tab Ptr : Ch#22
+#define MO_DMA23_PTR2       0x3000C8 // {24}RW* DMA Tab Ptr : Ch#23
+#define MO_DMA24_PTR2       0x3000CC // {24}RW* DMA Tab Ptr : Ch#24
+#define MO_DMA25_PTR2       0x3000D0 // {24}RW* DMA Tab Ptr : Ch#25
+#define MO_DMA26_PTR2       0x3000D4 // {24}RW* DMA Tab Ptr : Ch#26
+#define MO_DMA27_PTR2       0x3000D8 // {24}RW* DMA Tab Ptr : Ch#27
+#define MO_DMA28_PTR2       0x3000DC // {24}RW* DMA Tab Ptr : Ch#28
+#define MO_DMA29_PTR2       0x3000E0 // {24}RW* DMA Tab Ptr : Ch#29
+#define MO_DMA30_PTR2       0x3000E4 // {24}RW* DMA Tab Ptr : Ch#30
+#define MO_DMA31_PTR2       0x3000E8 // {24}RW* DMA Tab Ptr : Ch#31
+#define MO_DMA32_PTR2       0x3000EC // {24}RW* DMA Tab Ptr : Ch#32
+
+#define MO_DMA21_CNT1       0x300100 // {11}RW* DMA Buffer Size : Ch#21
+#define MO_DMA22_CNT1       0x300104 // {11}RW* DMA Buffer Size : Ch#22
+#define MO_DMA23_CNT1       0x300108 // {11}RW* DMA Buffer Size : Ch#23
+#define MO_DMA24_CNT1       0x30010C // {11}RW* DMA Buffer Size : Ch#24
+#define MO_DMA25_CNT1       0x300110 // {11}RW* DMA Buffer Size : Ch#25
+#define MO_DMA26_CNT1       0x300114 // {11}RW* DMA Buffer Size : Ch#26
+#define MO_DMA27_CNT1       0x300118 // {11}RW* DMA Buffer Size : Ch#27
+#define MO_DMA28_CNT1       0x30011C // {11}RW* DMA Buffer Size : Ch#28
+#define MO_DMA29_CNT1       0x300120 // {11}RW* DMA Buffer Size : Ch#29
+#define MO_DMA30_CNT1       0x300124 // {11}RW* DMA Buffer Size : Ch#30
+#define MO_DMA31_CNT1       0x300128 // {11}RW* DMA Buffer Size : Ch#31
+#define MO_DMA32_CNT1       0x30012C // {11}RW* DMA Buffer Size : Ch#32
+
+#define MO_DMA21_CNT2       0x300140 // {11}RW* DMA Table Size : Ch#21
+#define MO_DMA22_CNT2       0x300144 // {11}RW* DMA Table Size : Ch#22
+#define MO_DMA23_CNT2       0x300148 // {11}RW* DMA Table Size : Ch#23
+#define MO_DMA24_CNT2       0x30014C // {11}RW* DMA Table Size : Ch#24
+#define MO_DMA25_CNT2       0x300150 // {11}RW* DMA Table Size : Ch#25
+#define MO_DMA26_CNT2       0x300154 // {11}RW* DMA Table Size : Ch#26
+#define MO_DMA27_CNT2       0x300158 // {11}RW* DMA Table Size : Ch#27
+#define MO_DMA28_CNT2       0x30015C // {11}RW* DMA Table Size : Ch#28
+#define MO_DMA29_CNT2       0x300160 // {11}RW* DMA Table Size : Ch#29
+#define MO_DMA30_CNT2       0x300164 // {11}RW* DMA Table Size : Ch#30
+#define MO_DMA31_CNT2       0x300168 // {11}RW* DMA Table Size : Ch#31
+#define MO_DMA32_CNT2       0x30016C // {11}RW* DMA Table Size : Ch#32
+
+
+/* ---------------------------------------------------------------------- */
+/* Video registers                                                        */
+
+#define MO_VIDY_DMA         0x310000 // {64}RWp Video Y
+#define MO_VIDU_DMA         0x310008 // {64}RWp Video U
+#define MO_VIDV_DMA         0x310010 // {64}RWp Video V
+#define MO_VBI_DMA          0x310018 // {64}RWp VBI (Vertical blanking interval)
+
+#define MO_DEVICE_STATUS    0x310100
+#define MO_INPUT_FORMAT     0x310104
+#define MO_AGC_BURST        0x31010c
+#define MO_CONTR_BRIGHT     0x310110
+#define MO_UV_SATURATION    0x310114
+#define MO_HUE              0x310118
+#define MO_HTOTAL           0x310120
+#define MO_HDELAY_EVEN      0x310124
+#define MO_HDELAY_ODD       0x310128
+#define MO_VDELAY_ODD       0x31012c
+#define MO_VDELAY_EVEN      0x310130
+#define MO_HACTIVE_EVEN     0x31013c
+#define MO_HACTIVE_ODD      0x310140
+#define MO_VACTIVE_EVEN     0x310144
+#define MO_VACTIVE_ODD      0x310148
+#define MO_HSCALE_EVEN      0x31014c
+#define MO_HSCALE_ODD       0x310150
+#define MO_VSCALE_EVEN      0x310154
+#define MO_FILTER_EVEN      0x31015c
+#define MO_VSCALE_ODD       0x310158
+#define MO_FILTER_ODD       0x310160
+#define MO_OUTPUT_FORMAT    0x310164
+
+#define MO_PLL_REG          0x310168 // PLL register
+#define MO_PLL_ADJ_CTRL     0x31016c // PLL adjust control register
+#define MO_SCONV_REG        0x310170 // sample rate conversion register
+#define MO_SCONV_FIFO       0x310174 // sample rate conversion fifo
+#define MO_SUB_STEP         0x310178 // subcarrier step size
+#define MO_SUB_STEP_DR      0x31017c // subcarrier step size for DR line
+
+#define MO_CAPTURE_CTRL     0x310180 // capture control
+#define MO_COLOR_CTRL       0x310184
+#define MO_VBI_PACKET       0x310188 // vbi packet size / delay
+#define MO_FIELD_COUNT      0x310190 // field counter
+#define MO_VIP_CONFIG       0x310194
+#define MO_VBOS_CONTROL            0x3101a8
+
+#define MO_AGC_BACK_VBI     0x310200
+#define MO_AGC_SYNC_TIP1    0x310208
+
+#define MO_VIDY_GPCNT       0x31C020 // {16}RO Video Y general purpose counter
+#define MO_VIDU_GPCNT       0x31C024 // {16}RO Video U general purpose counter
+#define MO_VIDV_GPCNT       0x31C028 // {16}RO Video V general purpose counter
+#define MO_VBI_GPCNT        0x31C02C // {16}RO VBI general purpose counter
+#define MO_VIDY_GPCNTRL     0x31C030 // {2}WO Video Y general purpose control
+#define MO_VIDU_GPCNTRL     0x31C034 // {2}WO Video U general purpose control
+#define MO_VIDV_GPCNTRL     0x31C038 // {2}WO Video V general purpose control
+#define MO_VBI_GPCNTRL      0x31C03C // {2}WO VBI general purpose counter
+#define MO_VID_DMACNTRL     0x31C040 // {8}RW Video DMA control
+#define MO_VID_XFR_STAT     0x31C044 // {1}RO Video transfer status
+
+
+/* ---------------------------------------------------------------------- */
+/* audio registers                                                        */
+
+#define MO_AUDD_DMA         0x320000 // {64}RWp Audio downstream
+#define MO_AUDU_DMA         0x320008 // {64}RWp Audio upstream
+#define MO_AUDR_DMA         0x320010 // {64}RWp Audio RDS (downstream)
+#define MO_AUDD_GPCNT       0x32C020 // {16}RO Audio down general purpose counter
+#define MO_AUDU_GPCNT       0x32C024 // {16}RO Audio up general purpose counter
+#define MO_AUDR_GPCNT       0x32C028 // {16}RO Audio RDS general purpose counter
+#define MO_AUDD_GPCNTRL     0x32C030 // {2}WO Audio down general purpose control
+#define MO_AUDU_GPCNTRL     0x32C034 // {2}WO Audio up general purpose control
+#define MO_AUDR_GPCNTRL     0x32C038 // {2}WO Audio RDS general purpose control
+#define MO_AUD_DMACNTRL     0x32C040 // {6}RW Audio DMA control
+#define MO_AUD_XFR_STAT     0x32C044 // {1}RO Audio transfer status
+#define MO_AUDD_LNGTH       0x32C048 // {12}RW Audio down line length
+#define MO_AUDR_LNGTH       0x32C04C // {12}RW Audio RDS line length
+
+#define AUD_INIT                 0x320100
+#define AUD_INIT_LD              0x320104
+#define AUD_SOFT_RESET           0x320108
+#define AUD_I2SINPUTCNTL         0x320120
+#define AUD_BAUDRATE             0x320124
+#define AUD_I2SOUTPUTCNTL        0x320128
+#define AAGC_HYST                0x320134
+#define AAGC_GAIN                0x320138
+#define AAGC_DEF                 0x32013c
+#define AUD_IIR1_0_SEL           0x320150
+#define AUD_IIR1_0_SHIFT         0x320154
+#define AUD_IIR1_1_SEL           0x320158
+#define AUD_IIR1_1_SHIFT         0x32015c
+#define AUD_IIR1_2_SEL           0x320160
+#define AUD_IIR1_2_SHIFT         0x320164
+#define AUD_IIR1_3_SEL           0x320168
+#define AUD_IIR1_3_SHIFT         0x32016c
+#define AUD_IIR1_4_SEL           0x320170
+#define AUD_IIR1_4_SHIFT         0x32017c
+#define AUD_IIR1_5_SEL           0x320180
+#define AUD_IIR1_5_SHIFT         0x320184
+#define AUD_IIR2_0_SEL           0x320190
+#define AUD_IIR2_0_SHIFT         0x320194
+#define AUD_IIR2_1_SEL           0x320198
+#define AUD_IIR2_1_SHIFT         0x32019c
+#define AUD_IIR2_2_SEL           0x3201a0
+#define AUD_IIR2_2_SHIFT         0x3201a4
+#define AUD_IIR2_3_SEL           0x3201a8
+#define AUD_IIR2_3_SHIFT         0x3201ac
+#define AUD_IIR3_0_SEL           0x3201c0
+#define AUD_IIR3_0_SHIFT         0x3201c4
+#define AUD_IIR3_1_SEL           0x3201c8
+#define AUD_IIR3_1_SHIFT         0x3201cc
+#define AUD_IIR3_2_SEL           0x3201d0
+#define AUD_IIR3_2_SHIFT         0x3201d4
+#define AUD_IIR4_0_SEL           0x3201e0
+#define AUD_IIR4_0_SHIFT         0x3201e4
+#define AUD_IIR4_1_SEL           0x3201e8
+#define AUD_IIR4_1_SHIFT         0x3201ec
+#define AUD_IIR4_2_SEL           0x3201f0
+#define AUD_IIR4_2_SHIFT         0x3201f4
+#define AUD_IIR4_0_CA0           0x320200
+#define AUD_IIR4_0_CA1           0x320204
+#define AUD_IIR4_0_CA2           0x320208
+#define AUD_IIR4_0_CB0           0x32020c
+#define AUD_IIR4_0_CB1           0x320210
+#define AUD_IIR4_1_CA0           0x320214
+#define AUD_IIR4_1_CA1           0x320218
+#define AUD_IIR4_1_CA2           0x32021c
+#define AUD_IIR4_1_CB0           0x320220
+#define AUD_IIR4_1_CB1           0x320224
+#define AUD_IIR4_2_CA0           0x320228
+#define AUD_IIR4_2_CA1           0x32022c
+#define AUD_IIR4_2_CA2           0x320230
+#define AUD_IIR4_2_CB0           0x320234
+#define AUD_IIR4_2_CB1           0x320238
+#define AUD_HP_MD_IIR4_1         0x320250
+#define AUD_HP_PROG_IIR4_1       0x320254
+#define AUD_FM_MODE_ENABLE       0x320258
+#define AUD_POLY0_DDS_CONSTANT   0x320270
+#define AUD_DN0_FREQ             0x320274
+#define AUD_DN1_FREQ             0x320278
+#define AUD_DN1_FREQ_SHIFT       0x32027c
+#define AUD_DN1_AFC              0x320280
+#define AUD_DN1_SRC_SEL          0x320284
+#define AUD_DN1_SHFT             0x320288
+#define AUD_DN2_FREQ             0x32028c
+#define AUD_DN2_FREQ_SHIFT       0x320290
+#define AUD_DN2_AFC              0x320294
+#define AUD_DN2_SRC_SEL          0x320298
+#define AUD_DN2_SHFT             0x32029c
+#define AUD_CRDC0_SRC_SEL        0x320300
+#define AUD_CRDC0_SHIFT          0x320304
+#define AUD_CORDIC_SHIFT_0       0x320308
+#define AUD_CRDC1_SRC_SEL        0x32030c
+#define AUD_CRDC1_SHIFT          0x320310
+#define AUD_CORDIC_SHIFT_1       0x320314
+#define AUD_DCOC_0_SRC           0x320320
+#define AUD_DCOC0_SHIFT          0x320324
+#define AUD_DCOC_0_SHIFT_IN0     0x320328
+#define AUD_DCOC_0_SHIFT_IN1     0x32032c
+#define AUD_DCOC_1_SRC           0x320330
+#define AUD_DCOC1_SHIFT          0x320334
+#define AUD_DCOC_1_SHIFT_IN0     0x320338
+#define AUD_DCOC_1_SHIFT_IN1     0x32033c
+#define AUD_DCOC_2_SRC           0x320340
+#define AUD_DCOC2_SHIFT          0x320344
+#define AUD_DCOC_2_SHIFT_IN0     0x320348
+#define AUD_DCOC_2_SHIFT_IN1     0x32034c
+#define AUD_DCOC_PASS_IN         0x320350
+#define AUD_PDET_SRC             0x320370
+#define AUD_PDET_SHIFT           0x320374
+#define AUD_PILOT_BQD_1_K0       0x320380
+#define AUD_PILOT_BQD_1_K1       0x320384
+#define AUD_PILOT_BQD_1_K2       0x320388
+#define AUD_PILOT_BQD_1_K3       0x32038c
+#define AUD_PILOT_BQD_1_K4       0x320390
+#define AUD_PILOT_BQD_2_K0       0x320394
+#define AUD_PILOT_BQD_2_K1       0x320398
+#define AUD_PILOT_BQD_2_K2       0x32039c
+#define AUD_PILOT_BQD_2_K3       0x3203a0
+#define AUD_PILOT_BQD_2_K4       0x3203a4
+#define AUD_THR_FR               0x3203c0
+#define AUD_X_PROG               0x3203c4
+#define AUD_Y_PROG               0x3203c8
+#define AUD_HARMONIC_MULT        0x3203cc
+#define AUD_C1_UP_THR            0x3203d0
+#define AUD_C1_LO_THR            0x3203d4
+#define AUD_C2_UP_THR            0x3203d8
+#define AUD_C2_LO_THR            0x3203dc
+#define AUD_PLL_EN               0x320400
+#define AUD_PLL_SRC              0x320404
+#define AUD_PLL_SHIFT            0x320408
+#define AUD_PLL_IF_SEL           0x32040c
+#define AUD_PLL_IF_SHIFT         0x320410
+#define AUD_BIQUAD_PLL_K0        0x320414
+#define AUD_BIQUAD_PLL_K1        0x320418
+#define AUD_BIQUAD_PLL_K2        0x32041c
+#define AUD_BIQUAD_PLL_K3        0x320420
+#define AUD_BIQUAD_PLL_K4        0x320424
+#define AUD_DEEMPH0_SRC_SEL      0x320440
+#define AUD_DEEMPH0_SHIFT        0x320444
+#define AUD_DEEMPH0_G0           0x320448
+#define AUD_DEEMPH0_A0           0x32044c
+#define AUD_DEEMPH0_B0           0x320450
+#define AUD_DEEMPH0_A1           0x320454
+#define AUD_DEEMPH0_B1           0x320458
+#define AUD_DEEMPH1_SRC_SEL      0x32045c
+#define AUD_DEEMPH1_SHIFT        0x320460
+#define AUD_DEEMPH1_G0           0x320464
+#define AUD_DEEMPH1_A0           0x320468
+#define AUD_DEEMPH1_B0           0x32046c
+#define AUD_DEEMPH1_A1           0x320470
+#define AUD_DEEMPH1_B1           0x320474
+#define AUD_OUT0_SEL             0x320490
+#define AUD_OUT0_SHIFT           0x320494
+#define AUD_OUT1_SEL             0x320498
+#define AUD_OUT1_SHIFT           0x32049c
+#define AUD_RDSI_SEL             0x3204a0
+#define AUD_RDSI_SHIFT           0x3204a4
+#define AUD_RDSQ_SEL             0x3204a8
+#define AUD_RDSQ_SHIFT           0x3204ac
+#define AUD_DBX_IN_GAIN          0x320500
+#define AUD_DBX_WBE_GAIN         0x320504
+#define AUD_DBX_SE_GAIN          0x320508
+#define AUD_DBX_RMS_WBE          0x32050c
+#define AUD_DBX_RMS_SE           0x320510
+#define AUD_DBX_SE_BYPASS        0x320514
+#define AUD_FAWDETCTL            0x320530
+#define AUD_FAWDETWINCTL         0x320534
+#define AUD_DEEMPHGAIN_R         0x320538
+#define AUD_DEEMPHNUMER1_R       0x32053c
+#define AUD_DEEMPHNUMER2_R       0x320540
+#define AUD_DEEMPHDENOM1_R       0x320544
+#define AUD_DEEMPHDENOM2_R       0x320548
+#define AUD_ERRLOGPERIOD_R       0x32054c
+#define AUD_ERRINTRPTTHSHLD1_R   0x320550
+#define AUD_ERRINTRPTTHSHLD2_R   0x320554
+#define AUD_ERRINTRPTTHSHLD3_R   0x320558
+#define AUD_NICAM_STATUS1        0x32055c
+#define AUD_NICAM_STATUS2        0x320560
+#define AUD_ERRLOG1              0x320564
+#define AUD_ERRLOG2              0x320568
+#define AUD_ERRLOG3              0x32056c
+#define AUD_DAC_BYPASS_L         0x320580
+#define AUD_DAC_BYPASS_R         0x320584
+#define AUD_DAC_BYPASS_CTL       0x320588
+#define AUD_CTL                  0x32058c
+#define AUD_STATUS               0x320590
+#define AUD_VOL_CTL              0x320594
+#define AUD_BAL_CTL              0x320598
+#define AUD_START_TIMER          0x3205b0
+#define AUD_MODE_CHG_TIMER       0x3205b4
+#define AUD_POLYPH80SCALEFAC     0x3205b8
+#define AUD_DMD_RA_DDS           0x3205bc
+#define AUD_I2S_RA_DDS           0x3205c0
+#define AUD_RATE_THRES_DMD       0x3205d0
+#define AUD_RATE_THRES_I2S       0x3205d4
+#define AUD_RATE_ADJ1            0x3205d8
+#define AUD_RATE_ADJ2            0x3205dc
+#define AUD_RATE_ADJ3            0x3205e0
+#define AUD_RATE_ADJ4            0x3205e4
+#define AUD_RATE_ADJ5            0x3205e8
+#define AUD_APB_IN_RATE_ADJ      0x3205ec
+#define AUD_I2SCNTL              0x3205ec
+#define AUD_PHASE_FIX_CTL        0x3205f0
+#define AUD_PLL_PRESCALE         0x320600
+#define AUD_PLL_DDS              0x320604
+#define AUD_PLL_INT              0x320608
+#define AUD_PLL_FRAC             0x32060c
+#define AUD_PLL_JTAG             0x320620
+#define AUD_PLL_SPMP             0x320624
+#define AUD_AFE_12DB_EN          0x320628
+
+// Audio QAM Register Addresses
+#define AUD_PDF_DDS_CNST_BYTE2   0x320d01
+#define AUD_PDF_DDS_CNST_BYTE1   0x320d02
+#define AUD_PDF_DDS_CNST_BYTE0   0x320d03
+#define AUD_PHACC_FREQ_8MSB      0x320d2a
+#define AUD_PHACC_FREQ_8LSB      0x320d2b
+#define AUD_QAM_MODE             0x320d04
+
+
+/* ---------------------------------------------------------------------- */
+/* transport stream registers                                             */
+
+#define MO_TS_DMA           0x330000 // {64}RWp Transport stream downstream
+#define MO_TS_GPCNT         0x33C020 // {16}RO TS general purpose counter
+#define MO_TS_GPCNTRL       0x33C030 // {2}WO TS general purpose control
+#define MO_TS_DMACNTRL      0x33C040 // {6}RW TS DMA control
+#define MO_TS_XFR_STAT      0x33C044 // {1}RO TS transfer status
+#define MO_TS_LNGTH         0x33C048 // {12}RW TS line length
+
+#define TS_HW_SOP_CNTRL     0x33C04C
+#define TS_GEN_CNTRL        0x33C050
+#define TS_BD_PKT_STAT      0x33C054
+#define TS_SOP_STAT         0x33C058
+#define TS_FIFO_OVFL_STAT   0x33C05C
+#define TS_VALERR_CNTRL     0x33C060
+
+
+/* ---------------------------------------------------------------------- */
+/* VIP registers                                                          */
+
+#define MO_VIPD_DMA         0x340000 // {64}RWp VIP downstream
+#define MO_VIPU_DMA         0x340008 // {64}RWp VIP upstream
+#define MO_VIPD_GPCNT       0x34C020 // {16}RO VIP down general purpose counter
+#define MO_VIPU_GPCNT       0x34C024 // {16}RO VIP up general purpose counter
+#define MO_VIPD_GPCNTRL     0x34C030 // {2}WO VIP down general purpose control
+#define MO_VIPU_GPCNTRL     0x34C034 // {2}WO VIP up general purpose control
+#define MO_VIP_DMACNTRL     0x34C040 // {6}RW VIP DMA control
+#define MO_VIP_XFR_STAT     0x34C044 // {1}RO VIP transfer status
+#define MO_VIP_CFG          0x340048 // VIP configuration
+#define MO_VIPU_CNTRL       0x34004C // VIP upstream control #1
+#define MO_VIPD_CNTRL       0x340050 // VIP downstream control #2
+#define MO_VIPD_LNGTH       0x340054 // VIP downstream line length
+#define MO_VIP_BRSTLN       0x340058 // VIP burst length
+#define MO_VIP_INTCNTRL     0x34C05C // VIP Interrupt Control
+#define MO_VIP_XFTERM       0x340060 // VIP transfer terminate
+
+
+/* ---------------------------------------------------------------------- */
+/* misc registers                                                         */
+
+#define MO_M2M_DMA          0x350000 // {64}RWp Mem2Mem DMA Bfr
+#define MO_GP0_IO           0x350010 // {32}RW* GPIOoutput enablesdata I/O
+#define MO_GP1_IO           0x350014 // {32}RW* GPIOoutput enablesdata I/O
+#define MO_GP2_IO           0x350018 // {32}RW* GPIOoutput enablesdata I/O
+#define MO_GP3_IO           0x35001C // {32}RW* GPIO Mode/Ctrloutput enables
+#define MO_GPIO             0x350020 // {32}RW* GPIO I2C Ctrldata I/O
+#define MO_GPOE             0x350024 // {32}RW  GPIO I2C Ctrloutput enables
+#define MO_GP_ISM           0x350028 // {16}WO  GPIO Intr Sens/Pol
+
+#define MO_PLL_B            0x35C008 // {32}RW* PLL Control for ASB bus clks
+#define MO_M2M_CNT          0x35C024 // {32}RW  Mem2Mem DMA Cnt
+#define MO_M2M_XSUM         0x35C028 // {32}RO  M2M XOR-Checksum
+#define MO_CRC              0x35C02C // {16}RW  CRC16 init/result
+#define MO_CRC_D            0x35C030 // {32}WO  CRC16 new data in
+#define MO_TM_CNT_LDW       0x35C034 // {32}RO  Timer : Counter low dword
+#define MO_TM_CNT_UW        0x35C038 // {16}RO  Timer : Counter high word
+#define MO_TM_LMT_LDW       0x35C03C // {32}RW  Timer : Limit low dword
+#define MO_TM_LMT_UW        0x35C040 // {32}RW  Timer : Limit high word
+#define MO_PINMUX_IO        0x35C044 // {8}RW  Pin Mux Control
+#define MO_TSTSEL_IO        0x35C048 // {2}RW  Pin Mux Control
+#define MO_AFECFG_IO        0x35C04C // AFE configuration reg
+#define MO_DDS_IO           0x35C050 // DDS Increment reg
+#define MO_DDSCFG_IO        0x35C054 // DDS Configuration reg
+#define MO_SAMPLE_IO        0x35C058 // IRIn sample reg
+#define MO_SRST_IO          0x35C05C // Output system reset reg
+
+#define MO_INT1_MSK         0x35C060 // DMA RISC interrupt mask
+#define MO_INT1_STAT        0x35C064 // DMA RISC interrupt status
+#define MO_INT1_MSTAT       0x35C068 // DMA RISC interrupt masked status
+
+
+/* ---------------------------------------------------------------------- */
+/* i2c bus registers                                                      */
+
+#define MO_I2C              0x368000 // I2C data/control
+#define MO_I2C_DIV          (0xf<<4)
+#define MO_I2C_SYNC         (1<<3)
+#define MO_I2C_W3B          (1<<2)
+#define MO_I2C_SCL          (1<<1)
+#define MO_I2C_SDA          (1<<0)
+
+
+/* ---------------------------------------------------------------------- */
+/* general purpose host registers                                         */
+/* FIXME: tyops?  s/0x35/0x38/ ??                                         */
+
+#define MO_GPHSTD_DMA       0x350000 // {64}RWp Host downstream
+#define MO_GPHSTU_DMA       0x350008 // {64}RWp Host upstream
+#define MO_GPHSTU_CNTRL     0x380048 // Host upstream control #1
+#define MO_GPHSTD_CNTRL     0x38004C // Host downstream control #2
+#define MO_GPHSTD_LNGTH     0x380050 // Host downstream line length
+#define MO_GPHST_WSC        0x380054 // Host wait state control
+#define MO_GPHST_XFR        0x380058 // Host transfer control
+#define MO_GPHST_WDTH       0x38005C // Host interface width
+#define MO_GPHST_HDSHK      0x380060 // Host peripheral handshake
+#define MO_GPHST_MUX16      0x380064 // Host muxed 16-bit transfer parameters
+#define MO_GPHST_MODE       0x380068 // Host mode select
+
+#define MO_GPHSTD_GPCNT     0x35C020 // Host down general purpose counter
+#define MO_GPHSTU_GPCNT     0x35C024 // Host up general purpose counter
+#define MO_GPHSTD_GPCNTRL   0x38C030 // Host down general purpose control
+#define MO_GPHSTU_GPCNTRL   0x38C034 // Host up general purpose control
+#define MO_GPHST_DMACNTRL   0x38C040 // Host DMA control
+#define MO_GPHST_XFR_STAT   0x38C044 // Host transfer status
+#define MO_GPHST_SOFT_RST   0x38C06C // Host software reset
+
+
+/* ---------------------------------------------------------------------- */
+/* RISC instructions                                                      */
+
+#define RISC_SYNC               0x80000000
+#define RISC_SYNC_ODD           0x80000000
+#define RISC_SYNC_EVEN          0x80000200
+#define RISC_RESYNC             0x80008000
+#define RISC_RESYNC_ODD                 0x80008000
+#define RISC_RESYNC_EVEN        0x80008200
+#define RISC_WRITE              0x10000000
+#define RISC_WRITEC             0x50000000
+#define RISC_READ               0x90000000
+#define RISC_READC              0xA0000000
+#define RISC_JUMP               0x70000000
+#define RISC_SKIP               0x20000000
+#define RISC_WRITERM            0xB0000000
+#define RISC_WRITECM            0xC0000000
+#define RISC_WRITECR            0xD0000000
+#define RISC_IMM                0x00000001
+
+#define RISC_SOL                0x08000000
+#define RISC_EOL                0x04000000
+
+#define RISC_IRQ2               0x02000000
+#define RISC_IRQ1               0x01000000
+
+#define RISC_CNT_NONE           0x00000000
+#define RISC_CNT_INC            0x00010000
+#define RISC_CNT_RSVR           0x00020000
+#define RISC_CNT_RESET          0x00030000
+#define RISC_JMP_SRP            0x01
+
+
+/* ---------------------------------------------------------------------- */
+/* various constants                                                      */
+
+// DMA
+/* Interrupt mask/status */
+#define PCI_INT_VIDINT         (1 <<  0)
+#define PCI_INT_AUDINT         (1 <<  1)
+#define PCI_INT_TSINT          (1 <<  2)
+#define PCI_INT_VIPINT         (1 <<  3)
+#define PCI_INT_HSTINT         (1 <<  4)
+#define PCI_INT_TM1INT         (1 <<  5)
+#define PCI_INT_SRCDMAINT      (1 <<  6)
+#define PCI_INT_DSTDMAINT      (1 <<  7)
+#define PCI_INT_RISC_RD_BERRINT        (1 << 10)
+#define PCI_INT_RISC_WR_BERRINT        (1 << 11)
+#define PCI_INT_BRDG_BERRINT   (1 << 12)
+#define PCI_INT_SRC_DMA_BERRINT        (1 << 13)
+#define PCI_INT_DST_DMA_BERRINT        (1 << 14)
+#define PCI_INT_IPB_DMA_BERRINT        (1 << 15)
+#define PCI_INT_I2CDONE                (1 << 16)
+#define PCI_INT_I2CRACK                (1 << 17)
+#define PCI_INT_IR_SMPINT      (1 << 18)
+#define PCI_INT_GPIO_INT0      (1 << 19)
+#define PCI_INT_GPIO_INT1      (1 << 20)
+
+#define SEL_BTSC     0x01
+#define SEL_EIAJ     0x02
+#define SEL_A2       0x04
+#define SEL_SAP      0x08
+#define SEL_NICAM    0x10
+#define SEL_FMRADIO  0x20
+
+// AUD_CTL
+#define AUD_INT_DN_RISCI1      (1 <<  0)
+#define AUD_INT_UP_RISCI1      (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1  (1 <<  2)
+#define AUD_INT_DN_RISCI2      (1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2      (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2  (1 <<  6)
+#define AUD_INT_DN_SYNC                (1 << 12)
+#define AUD_INT_UP_SYNC                (1 << 13)
+#define AUD_INT_RDS_DN_SYNC    (1 << 14)
+#define AUD_INT_OPC_ERR                (1 << 16)
+#define AUD_INT_BER_IRQ                (1 << 20)
+#define AUD_INT_MCHG_IRQ       (1 << 21)
+
+#define EN_BTSC_FORCE_MONO      0
+#define EN_BTSC_FORCE_STEREO    1
+#define EN_BTSC_FORCE_SAP       2
+#define EN_BTSC_AUTO_STEREO     3
+#define EN_BTSC_AUTO_SAP        4
+
+#define EN_A2_FORCE_MONO1       8
+#define EN_A2_FORCE_MONO2       9
+#define EN_A2_FORCE_STEREO      10
+#define EN_A2_AUTO_MONO2        11
+#define EN_A2_AUTO_STEREO       12
+
+#define EN_EIAJ_FORCE_MONO1     16
+#define EN_EIAJ_FORCE_MONO2     17
+#define EN_EIAJ_FORCE_STEREO    18
+#define EN_EIAJ_AUTO_MONO2      19
+#define EN_EIAJ_AUTO_STEREO     20
+
+#define EN_NICAM_FORCE_MONO1    32
+#define EN_NICAM_FORCE_MONO2    33
+#define EN_NICAM_FORCE_STEREO   34
+#define EN_NICAM_AUTO_MONO2     35
+#define EN_NICAM_AUTO_STEREO    36
+
+#define EN_FMRADIO_FORCE_MONO   24
+#define EN_FMRADIO_FORCE_STEREO 25
+#define EN_FMRADIO_AUTO_STEREO  26
+
+#define EN_NICAM_AUTO_FALLBACK  0x00000040
+#define EN_FMRADIO_EN_RDS       0x00000200
+#define EN_NICAM_TRY_AGAIN_BIT  0x00000400
+#define EN_DAC_ENABLE           0x00001000
+#define EN_I2SOUT_ENABLE        0x00002000
+#define EN_I2SIN_STR2DAC        0x00004000
+#define EN_I2SIN_ENABLE         0x00008000
+
+#define EN_DMTRX_SUMDIFF        (0 << 7)
+#define EN_DMTRX_SUMR           (1 << 7)
+#define EN_DMTRX_LR             (2 << 7)
+#define EN_DMTRX_MONO           (3 << 7)
+#define EN_DMTRX_BYPASS         (1 << 11)
+
+// Video
+#define VID_CAPTURE_CONTROL            0x310180
+
+#define CX23880_CAP_CTL_CAPTURE_VBI_ODD  (1<<3)
+#define CX23880_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
+#define CX23880_CAP_CTL_CAPTURE_ODD      (1<<1)
+#define CX23880_CAP_CTL_CAPTURE_EVEN     (1<<0)
+
+#define VideoInputMux0          0x0
+#define VideoInputMux1          0x1
+#define VideoInputMux2          0x2
+#define VideoInputMux3          0x3
+#define VideoInputTuner                 0x0
+#define VideoInputComposite     0x1
+#define VideoInputSVideo        0x2
+#define VideoInputOther                 0x3
+
+#define Xtal0           0x1
+#define Xtal1           0x2
+#define XtalAuto        0x3
+
+#define VideoFormatAuto                 0x0
+#define VideoFormatNTSC                 0x1
+#define VideoFormatNTSCJapan    0x2
+#define VideoFormatNTSC443      0x3
+#define VideoFormatPAL          0x4
+#define VideoFormatPALB                 0x4
+#define VideoFormatPALD                 0x4
+#define VideoFormatPALG                 0x4
+#define VideoFormatPALH                 0x4
+#define VideoFormatPALI                 0x4
+#define VideoFormatPALBDGHI     0x4
+#define VideoFormatPALM                 0x5
+#define VideoFormatPALN                 0x6
+#define VideoFormatPALNC        0x7
+#define VideoFormatPAL60        0x8
+#define VideoFormatSECAM        0x9
+
+#define VideoFormatAuto27MHz            0x10
+#define VideoFormatNTSC27MHz            0x11
+#define VideoFormatNTSCJapan27MHz       0x12
+#define VideoFormatNTSC44327MHz                 0x13
+#define VideoFormatPAL27MHz             0x14
+#define VideoFormatPALB27MHz            0x14
+#define VideoFormatPALD27MHz            0x14
+#define VideoFormatPALG27MHz            0x14
+#define VideoFormatPALH27MHz            0x14
+#define VideoFormatPALI27MHz            0x14
+#define VideoFormatPALBDGHI27MHz        0x14
+#define VideoFormatPALM27MHz            0x15
+#define VideoFormatPALN27MHz            0x16
+#define VideoFormatPALNC27MHz           0x17
+#define VideoFormatPAL6027MHz           0x18
+#define VideoFormatSECAM27MHz           0x19
+
+#define NominalUSECAM   0x87
+#define NominalVSECAM   0x85
+#define NominalUNTSC    0xFE
+#define NominalVNTSC    0xB4
+
+#define NominalContrast  0xD8
+
+#define HFilterAutoFormat       0x0
+#define HFilterCIF              0x1
+#define HFilterQCIF             0x2
+#define HFilterICON             0x3
+
+#define VFilter2TapInterpolate  0
+#define VFilter3TapInterpolate  1
+#define VFilter4TapInterpolate  2
+#define VFilter5TapInterpolate  3
+#define VFilter2TapNoInterpolate  4
+#define VFilter3TapNoInterpolate  5
+#define VFilter4TapNoInterpolate  6
+#define VFilter5TapNoInterpolate  7
+
+#define ColorFormatRGB32        0x0000
+#define ColorFormatRGB24        0x0011
+#define ColorFormatRGB16        0x0022
+#define ColorFormatRGB15        0x0033
+#define ColorFormatYUY2                 0x0044
+#define ColorFormatBTYUV        0x0055
+#define ColorFormatY8           0x0066
+#define ColorFormatRGB8                 0x0077
+#define ColorFormatPL422        0x0088
+#define ColorFormatPL411        0x0099
+#define ColorFormatYUV12        0x00AA
+#define ColorFormatYUV9                 0x00BB
+#define ColorFormatRAW          0x00EE
+#define ColorFormatBSWAP         0x0300
+#define ColorFormatWSWAP         0x0c00
+#define ColorFormatEvenMask      0x050f
+#define ColorFormatOddMask       0x0af0
+#define ColorFormatGamma         0x1000
+
+#define Interlaced              0x1
+#define NonInterlaced           0x0
+
+#define FieldEven               0x1
+#define FieldOdd                0x0
+
+#define TGReadWriteMode                 0x0
+#define TGEnableMode            0x1
+
+#define DV_CbAlign              0x0
+#define DV_Y0Align              0x1
+#define DV_CrAlign              0x2
+#define DV_Y1Align              0x3
+
+#define DVF_Analog              0x0
+#define DVF_CCIR656             0x1
+#define DVF_ByteStream          0x2
+#define DVF_ExtVSYNC            0x4
+#define DVF_ExtField            0x5
+
+#define CHANNEL_VID_Y           0x1
+#define CHANNEL_VID_U           0x2
+#define CHANNEL_VID_V           0x3
+#define CHANNEL_VID_VBI                 0x4
+#define CHANNEL_AUD_DN          0x5
+#define CHANNEL_AUD_UP          0x6
+#define CHANNEL_AUD_RDS_DN      0x7
+#define CHANNEL_MPEG_DN                 0x8
+#define CHANNEL_VIP_DN          0x9
+#define CHANNEL_VIP_UP          0xA
+#define CHANNEL_HOST_DN                 0xB
+#define CHANNEL_HOST_UP                 0xC
+#define CHANNEL_FIRST           0x1
+#define CHANNEL_LAST            0xC
+
+#define GP_COUNT_CONTROL_NONE           0x0
+#define GP_COUNT_CONTROL_INC            0x1
+#define GP_COUNT_CONTROL_RESERVED       0x2
+#define GP_COUNT_CONTROL_RESET          0x3
+
+#define PLL_PRESCALE_BY_2  2
+#define PLL_PRESCALE_BY_3  3
+#define PLL_PRESCALE_BY_4  4
+#define PLL_PRESCALE_BY_5  5
+
+#define HLNotchFilter4xFsc      0
+#define HLNotchFilterSquare     1
+#define HLNotchFilter135NTSC    2
+#define HLNotchFilter135PAL     3
+
+#define NTSC_8x_SUB_CARRIER  28.63636E6
+#define PAL_8x_SUB_CARRIER  35.46895E6
+
+// Default analog settings
+#define DEFAULT_HUE_NTSC                       0x00
+#define DEFAULT_BRIGHTNESS_NTSC                        0x00
+#define DEFAULT_CONTRAST_NTSC                  0x39
+#define DEFAULT_SAT_U_NTSC                     0x7F
+#define DEFAULT_SAT_V_NTSC                     0x5A
+
+typedef enum
+{
+       SOURCE_TUNER = 0,
+       SOURCE_COMPOSITE,
+       SOURCE_SVIDEO,
+       SOURCE_OTHER1,
+       SOURCE_OTHER2,
+       SOURCE_COMPVIASVIDEO,
+       SOURCE_CCIR656
+} VIDEOSOURCETYPE;
+
+#endif /* _CX88_REG_H_ */
diff --git a/drivers/media/pci/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c
new file mode 100644 (file)
index 0000000..770ec05
--- /dev/null
@@ -0,0 +1,1059 @@
+/*
+
+    cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
+
+     (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
+     (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
+     (c) 2003 Gerd Knorr <kraxel@bytesex.org>
+
+    -----------------------------------------------------------------------
+
+    Lot of voodoo here.  Even the data sheet doesn't help to
+    understand what is going on here, the documentation for the audio
+    part of the cx2388x chip is *very* bad.
+
+    Some of this comes from party done linux driver sources I got from
+    [undocumented].
+
+    Some comes from the dscaler sources, one of the dscaler driver guy works
+    for Conexant ...
+
+    -----------------------------------------------------------------------
+
+    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/errno.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+
+#include "cx88.h"
+
+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;
+module_param(always_analog,int,0644);
+MODULE_PARM_DESC(always_analog,"force analog audio out");
+
+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)");
+
+#define dprintk(fmt, arg...)   if (audio_debug) \
+       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+/* ----------------------------------------------------------- */
+
+static const char * const aud_ctl_names[64] = {
+       [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
+       [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
+       [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
+       [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
+       [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
+       [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
+       [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
+       [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
+       [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
+       [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
+       [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
+       [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
+       [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
+       [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
+       [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
+       [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
+       [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
+       [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
+       [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
+       [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
+       [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
+       [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
+       [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
+};
+
+struct rlist {
+       u32 reg;
+       u32 val;
+};
+
+static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
+{
+       int i;
+
+       for (i = 0; l[i].reg; i++) {
+               switch (l[i].reg) {
+               case AUD_PDF_DDS_CNST_BYTE2:
+               case AUD_PDF_DDS_CNST_BYTE1:
+               case AUD_PDF_DDS_CNST_BYTE0:
+               case AUD_QAM_MODE:
+               case AUD_PHACC_FREQ_8MSB:
+               case AUD_PHACC_FREQ_8LSB:
+                       cx_writeb(l[i].reg, l[i].val);
+                       break;
+               default:
+                       cx_write(l[i].reg, l[i].val);
+                       break;
+               }
+       }
+}
+
+static void set_audio_start(struct cx88_core *core, u32 mode)
+{
+       /* mute */
+       cx_write(AUD_VOL_CTL, (1 << 6));
+
+       /* start programming */
+       cx_write(AUD_INIT, mode);
+       cx_write(AUD_INIT_LD, 0x0001);
+       cx_write(AUD_SOFT_RESET, 0x0001);
+}
+
+static void set_audio_finish(struct cx88_core *core, u32 ctl)
+{
+       u32 volume;
+
+       /* restart dma; This avoids buzz in NICAM and is good in others  */
+       cx88_stop_audio_dma(core);
+       cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
+       cx88_start_audio_dma(core);
+
+       if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
+               cx_write(AUD_I2SINPUTCNTL, 4);
+               cx_write(AUD_BAUDRATE, 1);
+               /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
+               cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
+               cx_write(AUD_I2SOUTPUTCNTL, 1);
+               cx_write(AUD_I2SCNTL, 0);
+               /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
+       }
+       if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
+               ctl |= EN_DAC_ENABLE;
+               cx_write(AUD_CTL, ctl);
+       }
+
+       /* finish programming */
+       cx_write(AUD_SOFT_RESET, 0x0000);
+
+       /* unmute */
+       volume = cx_sread(SHADOW_AUD_VOL_CTL);
+       cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
+
+       core->last_change = jiffies;
+}
+
+/* ----------------------------------------------------------- */
+
+static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
+                                   u32 mode)
+{
+       static const struct rlist btsc[] = {
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AUD_OUT1_SEL, 0x00000013},
+               {AUD_OUT1_SHIFT, 0x00000000},
+               {AUD_POLY0_DDS_CONSTANT, 0x0012010c},
+               {AUD_DMD_RA_DDS, 0x00c3e7aa},
+               {AUD_DBX_IN_GAIN, 0x00004734},
+               {AUD_DBX_WBE_GAIN, 0x00004640},
+               {AUD_DBX_SE_GAIN, 0x00008d31},
+               {AUD_DCOC_0_SRC, 0x0000001a},
+               {AUD_IIR1_4_SEL, 0x00000021},
+               {AUD_DCOC_PASS_IN, 0x00000003},
+               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+               {AUD_DN0_FREQ, 0x0000283b},
+               {AUD_DN2_SRC_SEL, 0x00000008},
+               {AUD_DN2_FREQ, 0x00003000},
+               {AUD_DN2_AFC, 0x00000002},
+               {AUD_DN2_SHFT, 0x00000000},
+               {AUD_IIR2_2_SEL, 0x00000020},
+               {AUD_IIR2_2_SHIFT, 0x00000000},
+               {AUD_IIR2_3_SEL, 0x0000001f},
+               {AUD_IIR2_3_SHIFT, 0x00000000},
+               {AUD_CRDC1_SRC_SEL, 0x000003ce},
+               {AUD_CRDC1_SHIFT, 0x00000000},
+               {AUD_CORDIC_SHIFT_1, 0x00000007},
+               {AUD_DCOC_1_SRC, 0x0000001b},
+               {AUD_DCOC1_SHIFT, 0x00000000},
+               {AUD_RDSI_SEL, 0x00000008},
+               {AUD_RDSQ_SEL, 0x00000008},
+               {AUD_RDSI_SHIFT, 0x00000000},
+               {AUD_RDSQ_SHIFT, 0x00000000},
+               {AUD_POLYPH80SCALEFAC, 0x00000003},
+               { /* end of list */ },
+       };
+       static const struct rlist btsc_sap[] = {
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AUD_DBX_IN_GAIN, 0x00007200},
+               {AUD_DBX_WBE_GAIN, 0x00006200},
+               {AUD_DBX_SE_GAIN, 0x00006200},
+               {AUD_IIR1_1_SEL, 0x00000000},
+               {AUD_IIR1_3_SEL, 0x00000001},
+               {AUD_DN1_SRC_SEL, 0x00000007},
+               {AUD_IIR1_4_SHIFT, 0x00000006},
+               {AUD_IIR2_1_SHIFT, 0x00000000},
+               {AUD_IIR2_2_SHIFT, 0x00000000},
+               {AUD_IIR3_0_SHIFT, 0x00000000},
+               {AUD_IIR3_1_SHIFT, 0x00000000},
+               {AUD_IIR3_0_SEL, 0x0000000d},
+               {AUD_IIR3_1_SEL, 0x0000000e},
+               {AUD_DEEMPH1_SRC_SEL, 0x00000014},
+               {AUD_DEEMPH1_SHIFT, 0x00000000},
+               {AUD_DEEMPH1_G0, 0x00004000},
+               {AUD_DEEMPH1_A0, 0x00000000},
+               {AUD_DEEMPH1_B0, 0x00000000},
+               {AUD_DEEMPH1_A1, 0x00000000},
+               {AUD_DEEMPH1_B1, 0x00000000},
+               {AUD_OUT0_SEL, 0x0000003f},
+               {AUD_OUT1_SEL, 0x0000003f},
+               {AUD_DN1_AFC, 0x00000002},
+               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+               {AUD_IIR1_0_SEL, 0x0000001d},
+               {AUD_IIR1_2_SEL, 0x0000001e},
+               {AUD_IIR2_1_SEL, 0x00000002},
+               {AUD_IIR2_2_SEL, 0x00000004},
+               {AUD_IIR3_2_SEL, 0x0000000f},
+               {AUD_DCOC2_SHIFT, 0x00000001},
+               {AUD_IIR3_2_SHIFT, 0x00000001},
+               {AUD_DEEMPH0_SRC_SEL, 0x00000014},
+               {AUD_CORDIC_SHIFT_1, 0x00000006},
+               {AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
+               {AUD_DMD_RA_DDS, 0x00f696e6},
+               {AUD_IIR2_3_SEL, 0x00000025},
+               {AUD_IIR1_4_SEL, 0x00000021},
+               {AUD_DN1_FREQ, 0x0000c965},
+               {AUD_DCOC_PASS_IN, 0x00000003},
+               {AUD_DCOC_0_SRC, 0x0000001a},
+               {AUD_DCOC_1_SRC, 0x0000001b},
+               {AUD_DCOC1_SHIFT, 0x00000000},
+               {AUD_RDSI_SEL, 0x00000009},
+               {AUD_RDSQ_SEL, 0x00000009},
+               {AUD_RDSI_SHIFT, 0x00000000},
+               {AUD_RDSQ_SHIFT, 0x00000000},
+               {AUD_POLYPH80SCALEFAC, 0x00000003},
+               { /* end of list */ },
+       };
+
+       mode |= EN_FMRADIO_EN_RDS;
+
+       if (sap) {
+               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", __func__);
+               set_audio_start(core, SEL_BTSC);
+               set_audio_registers(core, btsc);
+               set_audio_finish(core, mode);
+       }
+}
+
+static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
+{
+       static const struct rlist nicam_l[] = {
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AUD_RATE_ADJ1, 0x00000060},
+               {AUD_RATE_ADJ2, 0x000000F9},
+               {AUD_RATE_ADJ3, 0x000001CC},
+               {AUD_RATE_ADJ4, 0x000002B3},
+               {AUD_RATE_ADJ5, 0x00000726},
+               {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
+               {AUD_DEEMPHDENOM2_R, 0x00000000},
+               {AUD_ERRLOGPERIOD_R, 0x00000064},
+               {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
+               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
+               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
+               {AUD_POLYPH80SCALEFAC, 0x00000003},
+               {AUD_DMD_RA_DDS, 0x00C00000},
+               {AUD_PLL_INT, 0x0000001E},
+               {AUD_PLL_DDS, 0x00000000},
+               {AUD_PLL_FRAC, 0x0000E542},
+               {AUD_START_TIMER, 0x00000000},
+               {AUD_DEEMPHNUMER1_R, 0x000353DE},
+               {AUD_DEEMPHNUMER2_R, 0x000001B1},
+               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+               {AUD_QAM_MODE, 0x05},
+               {AUD_PHACC_FREQ_8MSB, 0x34},
+               {AUD_PHACC_FREQ_8LSB, 0x4C},
+               {AUD_DEEMPHGAIN_R, 0x00006680},
+               {AUD_RATE_THRES_DMD, 0x000000C0},
+               { /* end of list */ },
+       };
+
+       static const struct rlist nicam_bgdki_common[] = {
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AUD_RATE_ADJ1, 0x00000010},
+               {AUD_RATE_ADJ2, 0x00000040},
+               {AUD_RATE_ADJ3, 0x00000100},
+               {AUD_RATE_ADJ4, 0x00000400},
+               {AUD_RATE_ADJ5, 0x00001000},
+               {AUD_ERRLOGPERIOD_R, 0x00000fff},
+               {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
+               {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
+               {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
+               {AUD_POLYPH80SCALEFAC, 0x00000003},
+               {AUD_DEEMPHGAIN_R, 0x000023c2},
+               {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
+               {AUD_DEEMPHNUMER2_R, 0x0003023e},
+               {AUD_DEEMPHDENOM1_R, 0x0000f3d0},
+               {AUD_DEEMPHDENOM2_R, 0x00000000},
+               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+               {AUD_QAM_MODE, 0x05},
+               { /* end of list */ },
+       };
+
+       static const struct rlist nicam_i[] = {
+               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+               {AUD_PHACC_FREQ_8MSB, 0x3a},
+               {AUD_PHACC_FREQ_8LSB, 0x93},
+               { /* end of list */ },
+       };
+
+       static const struct rlist nicam_default[] = {
+               {AUD_PDF_DDS_CNST_BYTE0, 0x16},
+               {AUD_PHACC_FREQ_8MSB, 0x34},
+               {AUD_PHACC_FREQ_8LSB, 0x4c},
+               { /* end of list */ },
+       };
+
+       set_audio_start(core,SEL_NICAM);
+       switch (core->tvaudio) {
+       case WW_L:
+               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", __func__);
+               set_audio_registers(core, nicam_bgdki_common);
+               set_audio_registers(core, nicam_i);
+               break;
+       case WW_NONE:
+       case WW_BTSC:
+       case WW_BG:
+       case WW_DK:
+       case WW_EIAJ:
+       case WW_I2SPT:
+       case WW_FM:
+       case WW_I2SADC:
+       case WW_M:
+               dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
+               set_audio_registers(core, nicam_bgdki_common);
+               set_audio_registers(core, nicam_default);
+               break;
+       };
+
+       mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
+       set_audio_finish(core, mode);
+}
+
+static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
+{
+       static const struct rlist a2_bgdk_common[] = {
+               {AUD_ERRLOGPERIOD_R, 0x00000064},
+               {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+               {AUD_QAM_MODE, 0x05},
+               {AUD_PHACC_FREQ_8MSB, 0x34},
+               {AUD_PHACC_FREQ_8LSB, 0x4c},
+               {AUD_RATE_ADJ1, 0x00000100},
+               {AUD_RATE_ADJ2, 0x00000200},
+               {AUD_RATE_ADJ3, 0x00000300},
+               {AUD_RATE_ADJ4, 0x00000400},
+               {AUD_RATE_ADJ5, 0x00000500},
+               {AUD_THR_FR, 0x00000000},
+               {AAGC_HYST, 0x0000001a},
+               {AUD_PILOT_BQD_1_K0, 0x0000755b},
+               {AUD_PILOT_BQD_1_K1, 0x00551340},
+               {AUD_PILOT_BQD_1_K2, 0x006d30be},
+               {AUD_PILOT_BQD_1_K3, 0xffd394af},
+               {AUD_PILOT_BQD_1_K4, 0x00400000},
+               {AUD_PILOT_BQD_2_K0, 0x00040000},
+               {AUD_PILOT_BQD_2_K1, 0x002a4841},
+               {AUD_PILOT_BQD_2_K2, 0x00400000},
+               {AUD_PILOT_BQD_2_K3, 0x00000000},
+               {AUD_PILOT_BQD_2_K4, 0x00000000},
+               {AUD_MODE_CHG_TIMER, 0x00000040},
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AUD_CORDIC_SHIFT_0, 0x00000007},
+               {AUD_CORDIC_SHIFT_1, 0x00000007},
+               {AUD_DEEMPH0_G0, 0x00000380},
+               {AUD_DEEMPH1_G0, 0x00000380},
+               {AUD_DCOC_0_SRC, 0x0000001a},
+               {AUD_DCOC0_SHIFT, 0x00000000},
+               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+               {AUD_DCOC_PASS_IN, 0x00000003},
+               {AUD_IIR3_0_SEL, 0x00000021},
+               {AUD_DN2_AFC, 0x00000002},
+               {AUD_DCOC_1_SRC, 0x0000001b},
+               {AUD_DCOC1_SHIFT, 0x00000000},
+               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+               {AUD_IIR3_1_SEL, 0x00000023},
+               {AUD_RDSI_SEL, 0x00000017},
+               {AUD_RDSI_SHIFT, 0x00000000},
+               {AUD_RDSQ_SEL, 0x00000017},
+               {AUD_RDSQ_SHIFT, 0x00000000},
+               {AUD_PLL_INT, 0x0000001e},
+               {AUD_PLL_DDS, 0x00000000},
+               {AUD_PLL_FRAC, 0x0000e542},
+               {AUD_POLYPH80SCALEFAC, 0x00000001},
+               {AUD_START_TIMER, 0x00000000},
+               { /* end of list */ },
+       };
+
+       static const struct rlist a2_bg[] = {
+               {AUD_DMD_RA_DDS, 0x002a4f2f},
+               {AUD_C1_UP_THR, 0x00007000},
+               {AUD_C1_LO_THR, 0x00005400},
+               {AUD_C2_UP_THR, 0x00005400},
+               {AUD_C2_LO_THR, 0x00003000},
+               { /* end of list */ },
+       };
+
+       static const struct rlist a2_dk[] = {
+               {AUD_DMD_RA_DDS, 0x002a4f2f},
+               {AUD_C1_UP_THR, 0x00007000},
+               {AUD_C1_LO_THR, 0x00005400},
+               {AUD_C2_UP_THR, 0x00005400},
+               {AUD_C2_LO_THR, 0x00003000},
+               {AUD_DN0_FREQ, 0x00003a1c},
+               {AUD_DN2_FREQ, 0x0000d2e0},
+               { /* end of list */ },
+       };
+
+       static const struct rlist a1_i[] = {
+               {AUD_ERRLOGPERIOD_R, 0x00000064},
+               {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
+               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
+               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
+               {AUD_QAM_MODE, 0x05},
+               {AUD_PHACC_FREQ_8MSB, 0x3a},
+               {AUD_PHACC_FREQ_8LSB, 0x93},
+               {AUD_DMD_RA_DDS, 0x002a4f2f},
+               {AUD_PLL_INT, 0x0000001e},
+               {AUD_PLL_DDS, 0x00000004},
+               {AUD_PLL_FRAC, 0x0000e542},
+               {AUD_RATE_ADJ1, 0x00000100},
+               {AUD_RATE_ADJ2, 0x00000200},
+               {AUD_RATE_ADJ3, 0x00000300},
+               {AUD_RATE_ADJ4, 0x00000400},
+               {AUD_RATE_ADJ5, 0x00000500},
+               {AUD_THR_FR, 0x00000000},
+               {AUD_PILOT_BQD_1_K0, 0x0000755b},
+               {AUD_PILOT_BQD_1_K1, 0x00551340},
+               {AUD_PILOT_BQD_1_K2, 0x006d30be},
+               {AUD_PILOT_BQD_1_K3, 0xffd394af},
+               {AUD_PILOT_BQD_1_K4, 0x00400000},
+               {AUD_PILOT_BQD_2_K0, 0x00040000},
+               {AUD_PILOT_BQD_2_K1, 0x002a4841},
+               {AUD_PILOT_BQD_2_K2, 0x00400000},
+               {AUD_PILOT_BQD_2_K3, 0x00000000},
+               {AUD_PILOT_BQD_2_K4, 0x00000000},
+               {AUD_MODE_CHG_TIMER, 0x00000060},
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AAGC_HYST, 0x0000000a},
+               {AUD_CORDIC_SHIFT_0, 0x00000007},
+               {AUD_CORDIC_SHIFT_1, 0x00000007},
+               {AUD_C1_UP_THR, 0x00007000},
+               {AUD_C1_LO_THR, 0x00005400},
+               {AUD_C2_UP_THR, 0x00005400},
+               {AUD_C2_LO_THR, 0x00003000},
+               {AUD_DCOC_0_SRC, 0x0000001a},
+               {AUD_DCOC0_SHIFT, 0x00000000},
+               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+               {AUD_DCOC_PASS_IN, 0x00000003},
+               {AUD_IIR3_0_SEL, 0x00000021},
+               {AUD_DN2_AFC, 0x00000002},
+               {AUD_DCOC_1_SRC, 0x0000001b},
+               {AUD_DCOC1_SHIFT, 0x00000000},
+               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+               {AUD_IIR3_1_SEL, 0x00000023},
+               {AUD_DN0_FREQ, 0x000035a3},
+               {AUD_DN2_FREQ, 0x000029c7},
+               {AUD_CRDC0_SRC_SEL, 0x00000511},
+               {AUD_IIR1_0_SEL, 0x00000001},
+               {AUD_IIR1_1_SEL, 0x00000000},
+               {AUD_IIR3_2_SEL, 0x00000003},
+               {AUD_IIR3_2_SHIFT, 0x00000000},
+               {AUD_IIR3_0_SEL, 0x00000002},
+               {AUD_IIR2_0_SEL, 0x00000021},
+               {AUD_IIR2_0_SHIFT, 0x00000002},
+               {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
+               {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
+               {AUD_POLYPH80SCALEFAC, 0x00000001},
+               {AUD_START_TIMER, 0x00000000},
+               { /* end of list */ },
+       };
+
+       static const struct rlist am_l[] = {
+               {AUD_ERRLOGPERIOD_R, 0x00000064},
+               {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
+               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
+               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
+               {AUD_PDF_DDS_CNST_BYTE2, 0x48},
+               {AUD_PDF_DDS_CNST_BYTE1, 0x3D},
+               {AUD_QAM_MODE, 0x00},
+               {AUD_PDF_DDS_CNST_BYTE0, 0xf5},
+               {AUD_PHACC_FREQ_8MSB, 0x3a},
+               {AUD_PHACC_FREQ_8LSB, 0x4a},
+               {AUD_DEEMPHGAIN_R, 0x00006680},
+               {AUD_DEEMPHNUMER1_R, 0x000353DE},
+               {AUD_DEEMPHNUMER2_R, 0x000001B1},
+               {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
+               {AUD_DEEMPHDENOM2_R, 0x00000000},
+               {AUD_FM_MODE_ENABLE, 0x00000007},
+               {AUD_POLYPH80SCALEFAC, 0x00000003},
+               {AUD_AFE_12DB_EN, 0x00000001},
+               {AAGC_GAIN, 0x00000000},
+               {AAGC_HYST, 0x00000018},
+               {AAGC_DEF, 0x00000020},
+               {AUD_DN0_FREQ, 0x00000000},
+               {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
+               {AUD_DCOC_0_SRC, 0x00000021},
+               {AUD_IIR1_0_SEL, 0x00000000},
+               {AUD_IIR1_0_SHIFT, 0x00000007},
+               {AUD_IIR1_1_SEL, 0x00000002},
+               {AUD_IIR1_1_SHIFT, 0x00000000},
+               {AUD_DCOC_1_SRC, 0x00000003},
+               {AUD_DCOC1_SHIFT, 0x00000000},
+               {AUD_DCOC_PASS_IN, 0x00000000},
+               {AUD_IIR1_2_SEL, 0x00000023},
+               {AUD_IIR1_2_SHIFT, 0x00000000},
+               {AUD_IIR1_3_SEL, 0x00000004},
+               {AUD_IIR1_3_SHIFT, 0x00000007},
+               {AUD_IIR1_4_SEL, 0x00000005},
+               {AUD_IIR1_4_SHIFT, 0x00000007},
+               {AUD_IIR3_0_SEL, 0x00000007},
+               {AUD_IIR3_0_SHIFT, 0x00000000},
+               {AUD_DEEMPH0_SRC_SEL, 0x00000011},
+               {AUD_DEEMPH0_SHIFT, 0x00000000},
+               {AUD_DEEMPH0_G0, 0x00007000},
+               {AUD_DEEMPH0_A0, 0x00000000},
+               {AUD_DEEMPH0_B0, 0x00000000},
+               {AUD_DEEMPH0_A1, 0x00000000},
+               {AUD_DEEMPH0_B1, 0x00000000},
+               {AUD_DEEMPH1_SRC_SEL, 0x00000011},
+               {AUD_DEEMPH1_SHIFT, 0x00000000},
+               {AUD_DEEMPH1_G0, 0x00007000},
+               {AUD_DEEMPH1_A0, 0x00000000},
+               {AUD_DEEMPH1_B0, 0x00000000},
+               {AUD_DEEMPH1_A1, 0x00000000},
+               {AUD_DEEMPH1_B1, 0x00000000},
+               {AUD_OUT0_SEL, 0x0000003F},
+               {AUD_OUT1_SEL, 0x0000003F},
+               {AUD_DMD_RA_DDS, 0x00F5C285},
+               {AUD_PLL_INT, 0x0000001E},
+               {AUD_PLL_DDS, 0x00000000},
+               {AUD_PLL_FRAC, 0x0000E542},
+               {AUD_RATE_ADJ1, 0x00000100},
+               {AUD_RATE_ADJ2, 0x00000200},
+               {AUD_RATE_ADJ3, 0x00000300},
+               {AUD_RATE_ADJ4, 0x00000400},
+               {AUD_RATE_ADJ5, 0x00000500},
+               {AUD_RATE_THRES_DMD, 0x000000C0},
+               { /* end of list */ },
+       };
+
+       static const struct rlist a2_deemph50[] = {
+               {AUD_DEEMPH0_G0, 0x00000380},
+               {AUD_DEEMPH1_G0, 0x00000380},
+               {AUD_DEEMPHGAIN_R, 0x000011e1},
+               {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
+               {AUD_DEEMPHNUMER2_R, 0x0003023c},
+               { /* end of list */ },
+       };
+
+       set_audio_start(core, SEL_A2);
+       switch (core->tvaudio) {
+       case WW_BG:
+               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", __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", __func__);
+               set_audio_registers(core, a1_i);
+               set_audio_registers(core, a2_deemph50);
+               break;
+       case WW_L:
+               dprintk("%s AM-L (status: devel)\n", __func__);
+               set_audio_registers(core, am_l);
+               break;
+       case WW_NONE:
+       case WW_BTSC:
+       case WW_EIAJ:
+       case WW_I2SPT:
+       case WW_FM:
+       case WW_I2SADC:
+       case WW_M:
+               dprintk("%s Warning: wrong value\n", __func__);
+               return;
+               break;
+       };
+
+       mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
+       set_audio_finish(core, mode);
+}
+
+static void set_audio_standard_EIAJ(struct cx88_core *core)
+{
+       static const struct rlist eiaj[] = {
+               /* TODO: eiaj register settings are not there yet ... */
+
+               { /* end of list */ },
+       };
+       dprintk("%s (status: unknown)\n", __func__);
+
+       set_audio_start(core, SEL_EIAJ);
+       set_audio_registers(core, eiaj);
+       set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
+}
+
+static void set_audio_standard_FM(struct cx88_core *core,
+                                 enum cx88_deemph_type deemph)
+{
+       static const struct rlist fm_deemph_50[] = {
+               {AUD_DEEMPH0_G0, 0x0C45},
+               {AUD_DEEMPH0_A0, 0x6262},
+               {AUD_DEEMPH0_B0, 0x1C29},
+               {AUD_DEEMPH0_A1, 0x3FC66},
+               {AUD_DEEMPH0_B1, 0x399A},
+
+               {AUD_DEEMPH1_G0, 0x0D80},
+               {AUD_DEEMPH1_A0, 0x6262},
+               {AUD_DEEMPH1_B0, 0x1C29},
+               {AUD_DEEMPH1_A1, 0x3FC66},
+               {AUD_DEEMPH1_B1, 0x399A},
+
+               {AUD_POLYPH80SCALEFAC, 0x0003},
+               { /* end of list */ },
+       };
+       static const struct rlist fm_deemph_75[] = {
+               {AUD_DEEMPH0_G0, 0x091B},
+               {AUD_DEEMPH0_A0, 0x6B68},
+               {AUD_DEEMPH0_B0, 0x11EC},
+               {AUD_DEEMPH0_A1, 0x3FC66},
+               {AUD_DEEMPH0_B1, 0x399A},
+
+               {AUD_DEEMPH1_G0, 0x0AA0},
+               {AUD_DEEMPH1_A0, 0x6B68},
+               {AUD_DEEMPH1_B0, 0x11EC},
+               {AUD_DEEMPH1_A1, 0x3FC66},
+               {AUD_DEEMPH1_B1, 0x399A},
+
+               {AUD_POLYPH80SCALEFAC, 0x0003},
+               { /* end of list */ },
+       };
+
+       /* It is enough to leave default values? */
+       /* No, it's not!  The deemphasis registers are reset to the 75us
+        * values by default.  Analyzing the spectrum of the decoded audio
+        * reveals that "no deemphasis" is the same as 75 us, while the 50 us
+        * setting results in less deemphasis.  */
+       static const struct rlist fm_no_deemph[] = {
+
+               {AUD_POLYPH80SCALEFAC, 0x0003},
+               { /* end of list */ },
+       };
+
+       dprintk("%s (status: unknown)\n", __func__);
+       set_audio_start(core, SEL_FMRADIO);
+
+       switch (deemph) {
+       default:
+       case FM_NO_DEEMPH:
+               set_audio_registers(core, fm_no_deemph);
+               break;
+
+       case FM_DEEMPH_50:
+               set_audio_registers(core, fm_deemph_50);
+               break;
+
+       case FM_DEEMPH_75:
+               set_audio_registers(core, fm_deemph_75);
+               break;
+       }
+
+       set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
+}
+
+/* ----------------------------------------------------------- */
+
+static int cx88_detect_nicam(struct cx88_core *core)
+{
+       int i, j = 0;
+
+       dprintk("start nicam autodetect.\n");
+
+       for (i = 0; i < 6; i++) {
+               /* if bit1=1 then nicam is detected */
+               j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
+
+               if (j == 1) {
+                       dprintk("nicam is detected.\n");
+                       return 1;
+               }
+
+               /* wait a little bit for next reading status */
+               msleep(10);
+       }
+
+       dprintk("nicam is not detected.\n");
+       return 0;
+}
+
+void cx88_set_tvaudio(struct cx88_core *core)
+{
+       switch (core->tvaudio) {
+       case WW_BTSC:
+               set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+               break;
+       case WW_BG:
+       case WW_DK:
+       case WW_M:
+       case WW_I:
+       case WW_L:
+               /* prepare all dsp registers */
+               set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+
+               /* set nicam mode - otherwise
+                  AUD_NICAM_STATUS2 contains wrong values */
+               set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
+               if (0 == cx88_detect_nicam(core)) {
+                       /* fall back to fm / am mono */
+                       set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+                       core->audiomode_current = V4L2_TUNER_MODE_MONO;
+                       core->use_nicam = 0;
+               } else {
+                       core->use_nicam = 1;
+               }
+               break;
+       case WW_EIAJ:
+               set_audio_standard_EIAJ(core);
+               break;
+       case WW_FM:
+               set_audio_standard_FM(core, radio_deemphasis);
+               break;
+       case WW_I2SADC:
+               set_audio_start(core, 0x01);
+               /*
+                * Slave/Philips/Autobaud
+                * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
+                *      0= Sony, 1=Philips
+                */
+               cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
+               /* Switch to "I2S ADC mode" */
+               cx_write(AUD_I2SCNTL, 0x1);
+               set_audio_finish(core, EN_I2SIN_ENABLE);
+               break;
+       case WW_NONE:
+       case WW_I2SPT:
+               printk("%s/0: unknown tv audio mode [%d]\n",
+                      core->name, core->tvaudio);
+               break;
+       }
+       return;
+}
+
+void cx88_newstation(struct cx88_core *core)
+{
+       core->audiomode_manual = UNSET;
+       core->last_change = jiffies;
+}
+
+void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
+{
+       static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
+       static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
+       u32 reg, mode, pilot;
+
+       reg = cx_read(AUD_STATUS);
+       mode = reg & 0x03;
+       pilot = (reg >> 2) & 0x03;
+
+       if (core->astat != reg)
+               dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
+                       reg, m[mode], p[pilot],
+                       aud_ctl_names[cx_read(AUD_CTL) & 63]);
+       core->astat = reg;
+
+       t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
+           V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+       t->rxsubchans = UNSET;
+       t->audmode = V4L2_TUNER_MODE_MONO;
+
+       switch (mode) {
+       case 0:
+               t->audmode = V4L2_TUNER_MODE_STEREO;
+               break;
+       case 1:
+               t->audmode = V4L2_TUNER_MODE_LANG2;
+               break;
+       case 2:
+               t->audmode = V4L2_TUNER_MODE_MONO;
+               break;
+       case 3:
+               t->audmode = V4L2_TUNER_MODE_SAP;
+               break;
+       }
+
+       switch (core->tvaudio) {
+       case WW_BTSC:
+       case WW_BG:
+       case WW_DK:
+       case WW_M:
+       case WW_EIAJ:
+               if (!core->use_nicam) {
+                       t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
+                       break;
+               }
+               break;
+       case WW_NONE:
+       case WW_I:
+       case WW_L:
+       case WW_I2SPT:
+       case WW_FM:
+       case WW_I2SADC:
+               /* nothing */
+               break;
+       }
+
+       /* If software stereo detection is not supported... */
+       if (UNSET == t->rxsubchans) {
+               t->rxsubchans = V4L2_TUNER_SUB_MONO;
+               /* If the hardware itself detected stereo, also return
+                  stereo as an available subchannel */
+               if (V4L2_TUNER_MODE_STEREO == t->audmode)
+                       t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+       }
+       return;
+}
+
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
+{
+       u32 ctl = UNSET;
+       u32 mask = UNSET;
+
+       if (manual) {
+               core->audiomode_manual = mode;
+       } else {
+               if (UNSET != core->audiomode_manual)
+                       return;
+       }
+       core->audiomode_current = mode;
+
+       switch (core->tvaudio) {
+       case WW_BTSC:
+               switch (mode) {
+               case V4L2_TUNER_MODE_MONO:
+                       set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
+                       break;
+               case V4L2_TUNER_MODE_LANG1:
+                       set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+                       break;
+               case V4L2_TUNER_MODE_LANG2:
+                       set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
+                       break;
+               case V4L2_TUNER_MODE_STEREO:
+               case V4L2_TUNER_MODE_LANG1_LANG2:
+                       set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
+                       break;
+               }
+               break;
+       case WW_BG:
+       case WW_DK:
+       case WW_M:
+       case WW_I:
+       case WW_L:
+               if (1 == core->use_nicam) {
+                       switch (mode) {
+                       case V4L2_TUNER_MODE_MONO:
+                       case V4L2_TUNER_MODE_LANG1:
+                               set_audio_standard_NICAM(core,
+                                                        EN_NICAM_FORCE_MONO1);
+                               break;
+                       case V4L2_TUNER_MODE_LANG2:
+                               set_audio_standard_NICAM(core,
+                                                        EN_NICAM_FORCE_MONO2);
+                               break;
+                       case V4L2_TUNER_MODE_STEREO:
+                       case V4L2_TUNER_MODE_LANG1_LANG2:
+                               set_audio_standard_NICAM(core,
+                                                        EN_NICAM_FORCE_STEREO);
+                               break;
+                       }
+               } else {
+                       if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
+                               /* fall back to fm / am mono */
+                               set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+                       } else {
+                               /* TODO: Add A2 autodection */
+                               mask = 0x3f;
+                               switch (mode) {
+                               case V4L2_TUNER_MODE_MONO:
+                               case V4L2_TUNER_MODE_LANG1:
+                                       ctl = EN_A2_FORCE_MONO1;
+                                       break;
+                               case V4L2_TUNER_MODE_LANG2:
+                                       ctl = EN_A2_FORCE_MONO2;
+                                       break;
+                               case V4L2_TUNER_MODE_STEREO:
+                               case V4L2_TUNER_MODE_LANG1_LANG2:
+                                       ctl = EN_A2_FORCE_STEREO;
+                                       break;
+                               }
+                       }
+               }
+               break;
+       case WW_FM:
+               switch (mode) {
+               case V4L2_TUNER_MODE_MONO:
+                       ctl = EN_FMRADIO_FORCE_MONO;
+                       mask = 0x3f;
+                       break;
+               case V4L2_TUNER_MODE_STEREO:
+                       ctl = EN_FMRADIO_AUTO_STEREO;
+                       mask = 0x3f;
+                       break;
+               }
+               break;
+       case WW_I2SADC:
+       case WW_NONE:
+       case WW_EIAJ:
+       case WW_I2SPT:
+               /* DO NOTHING */
+               break;
+       }
+
+       if (UNSET != ctl) {
+               dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
+                       "[status=0x%x,ctl=0x%x,vol=0x%x]\n",
+                       mask, ctl, cx_read(AUD_STATUS),
+                       cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
+               cx_andor(AUD_CTL, mask, ctl);
+       }
+       return;
+}
+
+int cx88_audio_thread(void *data)
+{
+       struct cx88_core *core = data;
+       struct v4l2_tuner t;
+       u32 mode = 0;
+
+       dprintk("cx88: tvaudio thread started\n");
+       set_freezable();
+       for (;;) {
+               msleep_interruptible(1000);
+               if (kthread_should_stop())
+                       break;
+               try_to_freeze();
+
+               switch (core->tvaudio) {
+               case WW_BG:
+               case WW_DK:
+               case WW_M:
+               case WW_I:
+               case WW_L:
+                       if (core->use_nicam)
+                               goto hw_autodetect;
+
+                       /* just monitor the audio status for now ... */
+                       memset(&t, 0, sizeof(t));
+                       cx88_get_stereo(core, &t);
+
+                       if (UNSET != core->audiomode_manual)
+                               /* manually set, don't do anything. */
+                               continue;
+
+                       /* monitor signal and set stereo if available */
+                       if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
+                               mode = V4L2_TUNER_MODE_STEREO;
+                       else
+                               mode = V4L2_TUNER_MODE_MONO;
+                       if (mode == core->audiomode_current)
+                               continue;
+                       /* automatically switch to best available mode */
+                       cx88_set_stereo(core, mode, 0);
+                       break;
+               case WW_NONE:
+               case WW_BTSC:
+               case WW_EIAJ:
+               case WW_I2SPT:
+               case WW_FM:
+               case WW_I2SADC:
+hw_autodetect:
+                       /* stereo autodetection is supported by hardware so
+                          we don't need to do it manually. Do nothing. */
+                       break;
+               }
+       }
+
+       dprintk("cx88: tvaudio thread exiting\n");
+       return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+EXPORT_SYMBOL(cx88_set_tvaudio);
+EXPORT_SYMBOL(cx88_newstation);
+EXPORT_SYMBOL(cx88_set_stereo);
+EXPORT_SYMBOL(cx88_get_stereo);
+EXPORT_SYMBOL(cx88_audio_thread);
+
+/*
+ * 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
+ */
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
new file mode 100644 (file)
index 0000000..f8f8389
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "cx88.h"
+
+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;
+module_param(vbi_debug,int,0644);
+MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+
+#define dprintk(level,fmt, arg...)     if (vbi_debug >= level) \
+       printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+
+int cx8800_vbi_fmt (struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev  = fh->dev;
+
+       f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       f->fmt.vbi.offset = 244;
+       f->fmt.vbi.count[0] = VBI_LINE_COUNT;
+       f->fmt.vbi.count[1] = VBI_LINE_COUNT;
+
+       if (dev->core->tvnorm & V4L2_STD_525_60) {
+               /* ntsc */
+               f->fmt.vbi.sampling_rate = 28636363;
+               f->fmt.vbi.start[0] = 10;
+               f->fmt.vbi.start[1] = 273;
+
+       } else if (dev->core->tvnorm & V4L2_STD_625_50) {
+               /* pal */
+               f->fmt.vbi.sampling_rate = 35468950;
+               f->fmt.vbi.start[0] = 7 -1;
+               f->fmt.vbi.start[1] = 319 -1;
+       }
+       return 0;
+}
+
+static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
+                        struct cx88_dmaqueue *q,
+                        struct cx88_buffer   *buf)
+{
+       struct cx88_core *core = dev->core;
+
+       /* setup fifo + format */
+       cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
+                               buf->vb.width, buf->risc.dma);
+
+       cx_write(MO_VBOS_CONTROL, ( (1 << 18) |  // comb filter delay fixup
+                                   (1 << 15) |  // enable vbi capture
+                                   (1 << 11) ));
+
+       /* reset counter */
+       cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
+       q->count = 1;
+
+       /* enable irqs */
+       cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
+       cx_set(MO_VID_INTMSK, 0x0f0088);
+
+       /* enable capture */
+       cx_set(VID_CAPTURE_CONTROL,0x18);
+
+       /* start dma */
+       cx_set(MO_DEV_CNTRL2, (1<<5));
+       cx_set(MO_VID_DMACNTRL, 0x88);
+
+       return 0;
+}
+
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+
+       /* stop dma */
+       cx_clear(MO_VID_DMACNTRL, 0x88);
+
+       /* disable capture */
+       cx_clear(VID_CAPTURE_CONTROL,0x18);
+
+       /* disable irqs */
+       cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
+       cx_clear(MO_VID_INTMSK, 0x0f0088);
+       return 0;
+}
+
+int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
+                            struct cx88_dmaqueue *q)
+{
+       struct cx88_buffer *buf;
+
+       if (list_empty(&q->active))
+               return 0;
+
+       buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+       dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+               buf, buf->vb.i);
+       cx8800_start_vbi_dma(dev, q, buf);
+       list_for_each_entry(buf, &q->active, vb.queue)
+               buf->count = q->count++;
+       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+       return 0;
+}
+
+void cx8800_vbi_timeout(unsigned long data)
+{
+       struct cx8800_dev *dev = (struct cx8800_dev*)data;
+       struct cx88_core *core = dev->core;
+       struct cx88_dmaqueue *q = &dev->vbiq;
+       struct cx88_buffer *buf;
+       unsigned long flags;
+
+       cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
+
+       cx_clear(MO_VID_DMACNTRL, 0x88);
+       cx_clear(VID_CAPTURE_CONTROL, 0x18);
+
+       spin_lock_irqsave(&dev->slock,flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
+                      buf, buf->vb.i, (unsigned long)buf->risc.dma);
+       }
+       cx8800_restart_vbi_queue(dev,q);
+       spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int
+vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+       if (0 == *count)
+               *count = vbibufs;
+       if (*count < 2)
+               *count = 2;
+       if (*count > 32)
+               *count = 32;
+       return 0;
+}
+
+static int
+vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+           enum v4l2_field field)
+{
+       struct cx8800_fh   *fh  = q->priv_data;
+       struct cx8800_dev  *dev = fh->dev;
+       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+       unsigned int size;
+       int rc;
+
+       size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+               buf->vb.width  = VBI_LINE_LENGTH;
+               buf->vb.height = VBI_LINE_COUNT;
+               buf->vb.size   = size;
+               buf->vb.field  = V4L2_FIELD_SEQ_TB;
+
+               if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+                       goto fail;
+               cx88_risc_buffer(dev->pci, &buf->risc,
+                                dma->sglist,
+                                0, buf->vb.width * buf->vb.height,
+                                buf->vb.width, 0,
+                                buf->vb.height);
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       cx88_free_buffer(q,buf);
+       return rc;
+}
+
+static void
+vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
+       struct cx88_buffer    *prev;
+       struct cx8800_fh      *fh   = vq->priv_data;
+       struct cx8800_dev     *dev  = fh->dev;
+       struct cx88_dmaqueue  *q    = &dev->vbiq;
+
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+
+       if (list_empty(&q->active)) {
+               list_add_tail(&buf->vb.queue,&q->active);
+               cx8800_start_vbi_dma(dev, q, buf);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = q->count++;
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+               dprintk(2,"[%p/%d] vbi_queue - first active\n",
+                       buf, buf->vb.i);
+
+       } else {
+               prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+               list_add_tail(&buf->vb.queue,&q->active);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = q->count++;
+               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+               dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+                       buf, buf->vb.i);
+       }
+}
+
+static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+
+       cx88_free_buffer(q,buf);
+}
+
+const struct videobuf_queue_ops cx8800_vbi_qops = {
+       .buf_setup    = vbi_setup,
+       .buf_prepare  = vbi_prepare,
+       .buf_queue    = vbi_queue,
+       .buf_release  = vbi_release,
+};
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
new file mode 100644 (file)
index 0000000..f6fcc7e
--- /dev/null
@@ -0,0 +1,2075 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * video4linux video interface
+ *
+ * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     - Multituner support
+ *     - video_ioctl2 conversion
+ *     - PAL/M fixes
+ *
+ *  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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx88.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/wm8775.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr,   int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+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;
+module_param(video_debug,int,0644);
+MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug,int,0644);
+MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
+#define dprintk(level,fmt, arg...)     if (video_debug >= level) \
+       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+/* ------------------------------------------------------------------- */
+/* static data                                                         */
+
+static const struct cx8800_fmt formats[] = {
+       {
+               .name     = "8 bpp, gray",
+               .fourcc   = V4L2_PIX_FMT_GREY,
+               .cxformat = ColorFormatY8,
+               .depth    = 8,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "15 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB555,
+               .cxformat = ColorFormatRGB15,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "15 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB555X,
+               .cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "16 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB565,
+               .cxformat = ColorFormatRGB16,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "16 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB565X,
+               .cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "24 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR24,
+               .cxformat = ColorFormatRGB24,
+               .depth    = 24,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "32 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR32,
+               .cxformat = ColorFormatRGB32,
+               .depth    = 32,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "32 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB32,
+               .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
+               .depth    = 32,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "4:2:2, packed, YUYV",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .cxformat = ColorFormatYUY2,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },{
+               .name     = "4:2:2, packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
+               .depth    = 16,
+               .flags    = FORMAT_FLAGS_PACKED,
+       },
+};
+
+static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(formats); i++)
+               if (formats[i].fourcc == fourcc)
+                       return formats+i;
+       return NULL;
+}
+
+/* ------------------------------------------------------------------- */
+
+struct cx88_ctrl {
+       /* control information */
+       u32 id;
+       s32 minimum;
+       s32 maximum;
+       u32 step;
+       s32 default_value;
+
+       /* control register information */
+       u32 off;
+       u32 reg;
+       u32 sreg;
+       u32 mask;
+       u32 shift;
+};
+
+static const struct cx88_ctrl cx8800_vid_ctls[] = {
+       /* --- video --- */
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .minimum       = 0x00,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0x7f,
+               .off           = 128,
+               .reg           = MO_CONTR_BRIGHT,
+               .mask          = 0x00ff,
+               .shift         = 0,
+       },{
+               .id            = V4L2_CID_CONTRAST,
+               .minimum       = 0,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0x3f,
+               .off           = 0,
+               .reg           = MO_CONTR_BRIGHT,
+               .mask          = 0xff00,
+               .shift         = 8,
+       },{
+               .id            = V4L2_CID_HUE,
+               .minimum       = 0,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0x7f,
+               .off           = 128,
+               .reg           = MO_HUE,
+               .mask          = 0x00ff,
+               .shift         = 0,
+       },{
+               /* strictly, this only describes only U saturation.
+                * V saturation is handled specially through code.
+                */
+               .id            = V4L2_CID_SATURATION,
+               .minimum       = 0,
+               .maximum       = 0xff,
+               .step          = 1,
+               .default_value = 0x7f,
+               .off           = 0,
+               .reg           = MO_UV_SATURATION,
+               .mask          = 0x00ff,
+               .shift         = 0,
+       }, {
+               .id            = V4L2_CID_SHARPNESS,
+               .minimum       = 0,
+               .maximum       = 4,
+               .step          = 1,
+               .default_value = 0x0,
+               .off           = 0,
+               /* NOTE: the value is converted and written to both even
+                  and odd registers in the code */
+               .reg           = MO_FILTER_ODD,
+               .mask          = 7 << 7,
+               .shift         = 7,
+       }, {
+               .id            = V4L2_CID_CHROMA_AGC,
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 0x1,
+               .reg           = MO_INPUT_FORMAT,
+               .mask          = 1 << 10,
+               .shift         = 10,
+       }, {
+               .id            = V4L2_CID_COLOR_KILLER,
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 0x1,
+               .reg           = MO_INPUT_FORMAT,
+               .mask          = 1 << 9,
+               .shift         = 9,
+       }, {
+               .id            = V4L2_CID_BAND_STOP_FILTER,
+               .minimum       = 0,
+               .maximum       = 1,
+               .step          = 1,
+               .default_value = 0x0,
+               .off           = 0,
+               .reg           = MO_HTOTAL,
+               .mask          = 3 << 11,
+               .shift         = 11,
+       }
+};
+
+static const struct cx88_ctrl cx8800_aud_ctls[] = {
+       {
+               /* --- audio --- */
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .reg           = AUD_VOL_CTL,
+               .sreg          = SHADOW_AUD_VOL_CTL,
+               .mask          = (1 << 6),
+               .shift         = 6,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .minimum       = 0,
+               .maximum       = 0x3f,
+               .step          = 1,
+               .default_value = 0x3f,
+               .reg           = AUD_VOL_CTL,
+               .sreg          = SHADOW_AUD_VOL_CTL,
+               .mask          = 0x3f,
+               .shift         = 0,
+       },{
+               .id            = V4L2_CID_AUDIO_BALANCE,
+               .minimum       = 0,
+               .maximum       = 0x7f,
+               .step          = 1,
+               .default_value = 0x40,
+               .reg           = AUD_BAL_CTL,
+               .sreg          = SHADOW_AUD_BAL_CTL,
+               .mask          = 0x7f,
+               .shift         = 0,
+       }
+};
+
+enum {
+       CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls),
+       CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
+};
+
+/* ------------------------------------------------------------------- */
+/* resource management                                                 */
+
+static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
+{
+       struct cx88_core *core = dev->core;
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       /* is it free? */
+       mutex_lock(&core->lock);
+       if (dev->resources & bit) {
+               /* no, someone else uses it */
+               mutex_unlock(&core->lock);
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       dev->resources |= bit;
+       dprintk(1,"res: get %d\n",bit);
+       mutex_unlock(&core->lock);
+       return 1;
+}
+
+static
+int res_check(struct cx8800_fh *fh, unsigned int bit)
+{
+       return (fh->resources & bit);
+}
+
+static
+int res_locked(struct cx8800_dev *dev, unsigned int bit)
+{
+       return (dev->resources & bit);
+}
+
+static
+void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
+{
+       struct cx88_core *core = dev->core;
+       BUG_ON((fh->resources & bits) != bits);
+
+       mutex_lock(&core->lock);
+       fh->resources  &= ~bits;
+       dev->resources &= ~bits;
+       dprintk(1,"res: put %d\n",bits);
+       mutex_unlock(&core->lock);
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx88_video_mux(struct cx88_core *core, unsigned int input)
+{
+       /* struct cx88_core *core = dev->core; */
+
+       dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
+               input, INPUT(input).vmux,
+               INPUT(input).gpio0,INPUT(input).gpio1,
+               INPUT(input).gpio2,INPUT(input).gpio3);
+       core->input = input;
+       cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
+       cx_write(MO_GP3_IO, INPUT(input).gpio3);
+       cx_write(MO_GP0_IO, INPUT(input).gpio0);
+       cx_write(MO_GP1_IO, INPUT(input).gpio1);
+       cx_write(MO_GP2_IO, INPUT(input).gpio2);
+
+       switch (INPUT(input).type) {
+       case CX88_VMUX_SVIDEO:
+               cx_set(MO_AFECFG_IO,    0x00000001);
+               cx_set(MO_INPUT_FORMAT, 0x00010010);
+               cx_set(MO_FILTER_EVEN,  0x00002020);
+               cx_set(MO_FILTER_ODD,   0x00002020);
+               break;
+       default:
+               cx_clear(MO_AFECFG_IO,    0x00000001);
+               cx_clear(MO_INPUT_FORMAT, 0x00010010);
+               cx_clear(MO_FILTER_EVEN,  0x00002020);
+               cx_clear(MO_FILTER_ODD,   0x00002020);
+               break;
+       }
+
+       /* if there are audioroutes defined, we have an external
+          ADC to deal with audio */
+       if (INPUT(input).audioroute) {
+               /* The wm8775 module has the "2" route hardwired into
+                  the initialization. Some boards may use different
+                  routes for different inputs. HVR-1300 surely does */
+               if (core->board.audio_chip &&
+                   core->board.audio_chip == V4L2_IDENT_WM8775) {
+                       call_all(core, audio, s_routing,
+                                INPUT(input).audioroute, 0, 0);
+               }
+               /* cx2388's C-ADC is connected to the tuner only.
+                  When used with S-Video, that ADC is busy dealing with
+                  chroma, so an external must be used for baseband audio */
+               if (INPUT(input).type != CX88_VMUX_TELEVISION &&
+                   INPUT(input).type != CX88_VMUX_CABLE) {
+                       /* "I2S ADC mode" */
+                       core->tvaudio = WW_I2SADC;
+                       cx88_set_tvaudio(core);
+               } else {
+                       /* Normal mode */
+                       cx_write(AUD_I2SCNTL, 0x0);
+                       cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(cx88_video_mux);
+
+/* ------------------------------------------------------------------ */
+
+static int start_video_dma(struct cx8800_dev    *dev,
+                          struct cx88_dmaqueue *q,
+                          struct cx88_buffer   *buf)
+{
+       struct cx88_core *core = dev->core;
+
+       /* setup fifo + format */
+       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
+                               buf->bpl, buf->risc.dma);
+       cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
+       cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
+
+       /* reset counter */
+       cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
+       q->count = 1;
+
+       /* enable irqs */
+       cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
+
+       /* Enables corresponding bits at PCI_INT_STAT:
+               bits 0 to 4: video, audio, transport stream, VIP, Host
+               bit 7: timer
+               bits 8 and 9: DMA complete for: SRC, DST
+               bits 10 and 11: BERR signal asserted for RISC: RD, WR
+               bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
+        */
+       cx_set(MO_VID_INTMSK, 0x0f0011);
+
+       /* enable capture */
+       cx_set(VID_CAPTURE_CONTROL,0x06);
+
+       /* start dma */
+       cx_set(MO_DEV_CNTRL2, (1<<5));
+       cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int stop_video_dma(struct cx8800_dev    *dev)
+{
+       struct cx88_core *core = dev->core;
+
+       /* stop dma */
+       cx_clear(MO_VID_DMACNTRL, 0x11);
+
+       /* disable capture */
+       cx_clear(VID_CAPTURE_CONTROL,0x06);
+
+       /* disable irqs */
+       cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
+       cx_clear(MO_VID_INTMSK, 0x0f0011);
+       return 0;
+}
+#endif
+
+static int restart_video_queue(struct cx8800_dev    *dev,
+                              struct cx88_dmaqueue *q)
+{
+       struct cx88_core *core = dev->core;
+       struct cx88_buffer *buf, *prev;
+
+       if (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+               dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+                       buf, buf->vb.i);
+               start_video_dma(dev, q, buf);
+               list_for_each_entry(buf, &q->active, vb.queue)
+                       buf->count = q->count++;
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+               return 0;
+       }
+
+       prev = NULL;
+       for (;;) {
+               if (list_empty(&q->queued))
+                       return 0;
+               buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+               if (NULL == prev) {
+                       list_move_tail(&buf->vb.queue, &q->active);
+                       start_video_dma(dev, q, buf);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count    = q->count++;
+                       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+                       dprintk(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_move_tail(&buf->vb.queue, &q->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count    = q->count++;
+                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                       dprintk(2,"[%p/%d] restart_queue - move to active\n",
+                               buf,buf->vb.i);
+               } else {
+                       return 0;
+               }
+               prev = buf;
+       }
+}
+
+/* ------------------------------------------------------------------ */
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       struct cx8800_fh *fh = q->priv_data;
+       struct cx8800_dev  *dev = fh->dev;
+
+       *size = dev->fmt->depth * dev->width * dev->height >> 3;
+       if (0 == *count)
+               *count = 32;
+       if (*size * *count > vid_limit * 1024 * 1024)
+               *count = (vid_limit * 1024 * 1024) / *size;
+       return 0;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+              enum v4l2_field field)
+{
+       struct cx8800_fh   *fh  = q->priv_data;
+       struct cx8800_dev  *dev = fh->dev;
+       struct cx88_core *core = dev->core;
+       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+       int rc, init_buffer = 0;
+
+       BUG_ON(NULL == dev->fmt);
+       if (dev->width  < 48 || dev->width  > norm_maxw(core->tvnorm) ||
+           dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
+               return -EINVAL;
+       buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       if (buf->fmt       != dev->fmt    ||
+           buf->vb.width  != dev->width  ||
+           buf->vb.height != dev->height ||
+           buf->vb.field  != field) {
+               buf->fmt       = dev->fmt;
+               buf->vb.width  = dev->width;
+               buf->vb.height = dev->height;
+               buf->vb.field  = field;
+               init_buffer = 1;
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               init_buffer = 1;
+               if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+                       goto fail;
+       }
+
+       if (init_buffer) {
+               buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
+               switch (buf->vb.field) {
+               case V4L2_FIELD_TOP:
+                       cx88_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist, 0, UNSET,
+                                        buf->bpl, 0, buf->vb.height);
+                       break;
+               case V4L2_FIELD_BOTTOM:
+                       cx88_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist, UNSET, 0,
+                                        buf->bpl, 0, buf->vb.height);
+                       break;
+               case V4L2_FIELD_INTERLACED:
+                       cx88_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist, 0, buf->bpl,
+                                        buf->bpl, buf->bpl,
+                                        buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_TB:
+                       cx88_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist,
+                                        0, buf->bpl * (buf->vb.height >> 1),
+                                        buf->bpl, 0,
+                                        buf->vb.height >> 1);
+                       break;
+               case V4L2_FIELD_SEQ_BT:
+                       cx88_risc_buffer(dev->pci, &buf->risc,
+                                        dma->sglist,
+                                        buf->bpl * (buf->vb.height >> 1), 0,
+                                        buf->bpl, 0,
+                                        buf->vb.height >> 1);
+                       break;
+               default:
+                       BUG();
+               }
+       }
+       dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+               buf, buf->vb.i,
+               dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
+               (unsigned long)buf->risc.dma);
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+ fail:
+       cx88_free_buffer(q,buf);
+       return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
+       struct cx88_buffer    *prev;
+       struct cx8800_fh      *fh   = vq->priv_data;
+       struct cx8800_dev     *dev  = fh->dev;
+       struct cx88_core      *core = dev->core;
+       struct cx88_dmaqueue  *q    = &dev->vidq;
+
+       /* add jump to stopper */
+       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+
+       if (!list_empty(&q->queued)) {
+               list_add_tail(&buf->vb.queue,&q->queued);
+               buf->vb.state = VIDEOBUF_QUEUED;
+               dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
+                       buf, buf->vb.i);
+
+       } else if (list_empty(&q->active)) {
+               list_add_tail(&buf->vb.queue,&q->active);
+               start_video_dma(dev, q, buf);
+               buf->vb.state = VIDEOBUF_ACTIVE;
+               buf->count    = q->count++;
+               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+               dprintk(2,"[%p/%d] buffer_queue - first active\n",
+                       buf, buf->vb.i);
+
+       } else {
+               prev = list_entry(q->active.prev, struct cx88_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,&q->active);
+                       buf->vb.state = VIDEOBUF_ACTIVE;
+                       buf->count    = q->count++;
+                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+                       dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+                               buf, buf->vb.i);
+
+               } else {
+                       list_add_tail(&buf->vb.queue,&q->queued);
+                       buf->vb.state = VIDEOBUF_QUEUED;
+                       dprintk(2,"[%p/%d] buffer_queue - first queued\n",
+                               buf, buf->vb.i);
+               }
+       }
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+
+       cx88_free_buffer(q,buf);
+}
+
+static const struct videobuf_queue_ops cx8800_video_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+
+/* ------------------------------------------------------------------ */
+
+static struct videobuf_queue *get_queue(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8800_fh *fh = file->private_data;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               return &fh->vidq;
+       case VFL_TYPE_VBI:
+               return &fh->vbiq;
+       default:
+               BUG();
+               return NULL;
+       }
+}
+
+static int get_resource(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               return RESOURCE_VIDEO;
+       case VFL_TYPE_VBI:
+               return RESOURCE_VBI;
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static int video_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8800_dev *dev = video_drvdata(file);
+       struct cx88_core *core = dev->core;
+       struct cx8800_fh *fh;
+       enum v4l2_buf_type type = 0;
+       int radio = 0;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       dprintk(1, "open dev=%s radio=%d type=%s\n",
+               video_device_node_name(vdev), radio, v4l2_type_names[type]);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+       if (unlikely(!fh))
+               return -ENOMEM;
+
+       v4l2_fh_init(&fh->fh, vdev);
+       file->private_data = fh;
+       fh->dev      = dev;
+
+       mutex_lock(&core->lock);
+
+       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, NULL);
+       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),
+                           fh, NULL);
+
+       if (vdev->vfl_type == VFL_TYPE_RADIO) {
+               dprintk(1,"video_open: setting radio device\n");
+               cx_write(MO_GP3_IO, core->board.radio.gpio3);
+               cx_write(MO_GP0_IO, core->board.radio.gpio0);
+               cx_write(MO_GP1_IO, core->board.radio.gpio1);
+               cx_write(MO_GP2_IO, core->board.radio.gpio2);
+               if (core->board.radio.audioroute) {
+                       if(core->board.audio_chip &&
+                               core->board.audio_chip == V4L2_IDENT_WM8775) {
+                               call_all(core, audio, s_routing,
+                                       core->board.radio.audioroute, 0, 0);
+                       }
+                       /* "I2S ADC mode" */
+                       core->tvaudio = WW_I2SADC;
+                       cx88_set_tvaudio(core);
+               } else {
+                       /* FM Mode */
+                       core->tvaudio = WW_FM;
+                       cx88_set_tvaudio(core);
+                       cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+               }
+               call_all(core, tuner, s_radio);
+       }
+
+       core->users++;
+       mutex_unlock(&core->lock);
+       v4l2_fh_add(&fh->fh);
+
+       return 0;
+}
+
+static ssize_t
+video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8800_fh *fh = file->private_data;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               if (res_locked(fh->dev,RESOURCE_VIDEO))
+                       return -EBUSY;
+               return videobuf_read_one(&fh->vidq, data, count, ppos,
+                                        file->f_flags & O_NONBLOCK);
+       case VFL_TYPE_VBI:
+               if (!res_get(fh->dev,fh,RESOURCE_VBI))
+                       return -EBUSY;
+               return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
+                                           file->f_flags & O_NONBLOCK);
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static unsigned int
+video_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8800_fh *fh = file->private_data;
+       struct cx88_buffer *buf;
+       unsigned int rc = v4l2_ctrl_poll(file, wait);
+
+       if (vdev->vfl_type == VFL_TYPE_VBI) {
+               if (!res_get(fh->dev,fh,RESOURCE_VBI))
+                       return rc | POLLERR;
+               return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
+       }
+       mutex_lock(&fh->vidq.vb_lock);
+       if (res_check(fh,RESOURCE_VIDEO)) {
+               /* streaming capture */
+               if (list_empty(&fh->vidq.stream))
+                       goto done;
+               buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
+       } else {
+               /* read() capture */
+               buf = (struct cx88_buffer*)fh->vidq.read_buf;
+               if (NULL == buf)
+                       goto done;
+       }
+       poll_wait(file, &buf->vb.done, wait);
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               rc |= POLLIN|POLLRDNORM;
+done:
+       mutex_unlock(&fh->vidq.vb_lock);
+       return rc;
+}
+
+static int video_release(struct file *file)
+{
+       struct cx8800_fh  *fh  = file->private_data;
+       struct cx8800_dev *dev = fh->dev;
+
+       /* turn off overlay */
+       if (res_check(fh, RESOURCE_OVERLAY)) {
+               /* FIXME */
+               res_free(dev,fh,RESOURCE_OVERLAY);
+       }
+
+       /* stop video capture */
+       if (res_check(fh, RESOURCE_VIDEO)) {
+               videobuf_queue_cancel(&fh->vidq);
+               res_free(dev,fh,RESOURCE_VIDEO);
+       }
+       if (fh->vidq.read_buf) {
+               buffer_release(&fh->vidq,fh->vidq.read_buf);
+               kfree(fh->vidq.read_buf);
+       }
+
+       /* stop vbi capture */
+       if (res_check(fh, RESOURCE_VBI)) {
+               videobuf_stop(&fh->vbiq);
+               res_free(dev,fh,RESOURCE_VBI);
+       }
+
+       videobuf_mmap_free(&fh->vidq);
+       videobuf_mmap_free(&fh->vbiq);
+
+       mutex_lock(&dev->core->lock);
+       v4l2_fh_del(&fh->fh);
+       v4l2_fh_exit(&fh->fh);
+       file->private_data = NULL;
+       kfree(fh);
+
+       dev->core->users--;
+       if (!dev->core->users)
+               call_all(dev->core, core, s_power, 0);
+       mutex_unlock(&dev->core->lock);
+
+       return 0;
+}
+
+static int
+video_mmap(struct file *file, struct vm_area_struct * vma)
+{
+       return videobuf_mmap_mapper(get_queue(file), vma);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct cx88_core *core =
+               container_of(ctrl->handler, struct cx88_core, video_hdl);
+       const struct cx88_ctrl *cc = ctrl->priv;
+       u32 value, mask;
+
+       mask = cc->mask;
+       switch (ctrl->id) {
+       case V4L2_CID_SATURATION:
+               /* special v_sat handling */
+
+               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+
+               if (core->tvnorm & V4L2_STD_SECAM) {
+                       /* For SECAM, both U and V sat should be equal */
+                       value = value << 8 | value;
+               } else {
+                       /* Keeps U Saturation proportional to V Sat */
+                       value = (value * 0x5a) / 0x7f << 8 | value;
+               }
+               mask = 0xffff;
+               break;
+       case V4L2_CID_SHARPNESS:
+               /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
+               value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
+               /* needs to be set for both fields */
+               cx_andor(MO_FILTER_EVEN, mask, value);
+               break;
+       case V4L2_CID_CHROMA_AGC:
+               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+               break;
+       default:
+               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+               break;
+       }
+       dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+                               ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
+                               mask, cc->sreg ? " [shadowed]" : "");
+       if (cc->sreg)
+               cx_sandor(cc->sreg, cc->reg, mask, value);
+       else
+               cx_andor(cc->reg, mask, value);
+       return 0;
+}
+
+static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct cx88_core *core =
+               container_of(ctrl->handler, struct cx88_core, audio_hdl);
+       const struct cx88_ctrl *cc = ctrl->priv;
+       u32 value,mask;
+
+       /* Pass changes onto any WM8775 */
+       if (core->board.audio_chip == V4L2_IDENT_WM8775) {
+               switch (ctrl->id) {
+               case V4L2_CID_AUDIO_MUTE:
+                       wm8775_s_ctrl(core, ctrl->id, ctrl->val);
+                       break;
+               case V4L2_CID_AUDIO_VOLUME:
+                       wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ?
+                                               (0x90 + ctrl->val) << 8 : 0);
+                       break;
+               case V4L2_CID_AUDIO_BALANCE:
+                       wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       mask = cc->mask;
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_BALANCE:
+               value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40);
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               value = 0x3f - (ctrl->val & 0x3f);
+               break;
+       default:
+               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+               break;
+       }
+       dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+                               ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
+                               mask, cc->sreg ? " [shadowed]" : "");
+       if (cc->sreg)
+               cx_sandor(cc->sreg, cc->reg, mask, value);
+       else
+               cx_andor(cc->reg, mask, value);
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO IOCTLS                                                       */
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev = fh->dev;
+
+       f->fmt.pix.width        = dev->width;
+       f->fmt.pix.height       = dev->height;
+       f->fmt.pix.field        = fh->vidq.field;
+       f->fmt.pix.pixelformat  = dev->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * dev->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       const struct cx8800_fmt *fmt;
+       enum v4l2_field   field;
+       unsigned int      maxw, maxh;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       maxw  = norm_maxw(core->tvnorm);
+       maxh  = norm_maxh(core->tvnorm);
+
+       if (V4L2_FIELD_ANY == field) {
+               field = (f->fmt.pix.height > maxh/2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+       }
+
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       f->fmt.pix.field = field;
+       v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+                             &f->fmt.pix.height, 32, maxh, 0, 0);
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev = fh->dev;
+       int err = vidioc_try_fmt_vid_cap (file,priv,f);
+
+       if (0 != err)
+               return err;
+       dev->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+       dev->width      = f->fmt.pix.width;
+       dev->height     = f->fmt.pix.height;
+       fh->vidq.field = f->fmt.pix.field;
+       return 0;
+}
+
+void cx88_querycap(struct file *file, struct cx88_core *core,
+               struct v4l2_capability *cap)
+{
+       struct video_device *vdev = video_devdata(file);
+
+       strlcpy(cap->card, core->board.name, sizeof(cap->card));
+       cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+       if (UNSET != core->board.tuner_type)
+               cap->device_caps |= V4L2_CAP_TUNER;
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_RADIO:
+               cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
+               break;
+       case VFL_TYPE_GRABBER:
+               cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+               break;
+       }
+       cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;
+       if (core->board.radio.type == CX88_RADIO)
+               cap->capabilities |= V4L2_CAP_RADIO;
+}
+EXPORT_SYMBOL(cx88_querycap);
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
+       struct cx88_core  *core = dev->core;
+
+       strcpy(cap->driver, "cx8800");
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+       cx88_querycap(file, core, cap);
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(formats)))
+               return -EINVAL;
+
+       strlcpy(f->description,formats[f->index].name,sizeof(f->description));
+       f->pixelformat = formats[f->index].fourcc;
+
+       return 0;
+}
+
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+       return videobuf_reqbufs(get_queue(file), p);
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       return videobuf_querybuf(get_queue(file), p);
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       return videobuf_qbuf(get_queue(file), p);
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       return videobuf_dqbuf(get_queue(file), p,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev  = fh->dev;
+
+       if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+           (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       if (unlikely(!res_get(dev, fh, get_resource(file))))
+               return -EBUSY;
+       return videobuf_streamon(get_queue(file));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct cx8800_fh  *fh   = priv;
+       struct cx8800_dev *dev  = fh->dev;
+       int               err, res;
+
+       if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+           (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+               return -EINVAL;
+
+       res = get_resource(file);
+       err = videobuf_streamoff(get_queue(file));
+       if (err < 0)
+               return err;
+       res_free(dev,fh,res);
+       return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
+{
+       struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       *tvnorm = core->tvnorm;
+       return 0;
+}
+
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       mutex_lock(&core->lock);
+       cx88_set_tvnorm(core,*tvnorms);
+       mutex_unlock(&core->lock);
+
+       return 0;
+}
+
+/* only one input in this sample driver */
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i)
+{
+       static const char * const iname[] = {
+               [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
+               [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
+               [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
+               [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
+               [ CX88_VMUX_SVIDEO     ] = "S-Video",
+               [ CX88_VMUX_TELEVISION ] = "Television",
+               [ CX88_VMUX_CABLE      ] = "Cable TV",
+               [ CX88_VMUX_DVB        ] = "DVB",
+               [ CX88_VMUX_DEBUG      ] = "for debug only",
+       };
+       unsigned int n = i->index;
+
+       if (n >= 4)
+               return -EINVAL;
+       if (0 == INPUT(n).type)
+               return -EINVAL;
+       i->type  = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(i->name,iname[INPUT(n).type]);
+       if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
+           (CX88_VMUX_CABLE      == INPUT(n).type)) {
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       }
+       i->std = CX88_NORMS;
+       return 0;
+}
+EXPORT_SYMBOL(cx88_enum_input);
+
+static int vidioc_enum_input (struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       *i = core->input;
+       return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       if (i >= 4)
+               return -EINVAL;
+       if (0 == INPUT(i).type)
+               return -EINVAL;
+
+       mutex_lock(&core->lock);
+       cx88_newstation(core);
+       cx88_video_mux(core,i);
+       mutex_unlock(&core->lock);
+       return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+       u32 reg;
+
+       if (unlikely(UNSET == core->board.tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh  = 0xffffffffUL;
+       call_all(core, tuner, g_tuner, t);
+
+       cx88_get_stereo(core ,t);
+       reg = cx_read(MO_DEVICE_STATUS);
+       t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+       return 0;
+}
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       if (UNSET == core->board.tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       cx88_set_stereo(core, t->audmode, 1);
+       return 0;
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx88_core  *core = fh->dev->core;
+
+       if (unlikely(UNSET == core->board.tuner_type))
+               return -EINVAL;
+       if (f->tuner)
+               return -EINVAL;
+
+       f->frequency = core->freq;
+
+       call_all(core, tuner, g_frequency, f);
+
+       return 0;
+}
+
+int cx88_set_freq (struct cx88_core  *core,
+                               struct v4l2_frequency *f)
+{
+       if (unlikely(UNSET == core->board.tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+
+       mutex_lock(&core->lock);
+       cx88_newstation(core);
+       call_all(core, tuner, s_frequency, f);
+       call_all(core, tuner, g_frequency, f);
+       core->freq = f->frequency;
+
+       /* When changing channels it is required to reset TVAUDIO */
+       msleep (10);
+       cx88_set_tvaudio(core);
+
+       mutex_unlock(&core->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL(cx88_set_freq);
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct cx8800_fh  *fh   = priv;
+       struct cx88_core  *core = fh->dev->core;
+
+       return cx88_set_freq(core, f);
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+                               struct v4l2_dbg_chip_ident *chip)
+{
+       if (!v4l2_chip_match_host(&chip->match))
+               return -EINVAL;
+       chip->revision = 0;
+       chip->ident = V4L2_IDENT_UNKNOWN;
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *fh,
+                               struct v4l2_dbg_register *reg)
+{
+       struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+       /* cx2388x has a 24-bit register space */
+       reg->val = cx_read(reg->reg & 0xffffff);
+       reg->size = 4;
+       return 0;
+}
+
+static int vidioc_s_register (struct file *file, void *fh,
+                               struct v4l2_dbg_register *reg)
+{
+       struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+       cx_write(reg->reg & 0xffffff, reg->val);
+       return 0;
+}
+#endif
+
+/* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
+
+static int radio_g_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       if (unlikely(t->index > 0))
+               return -EINVAL;
+
+       strcpy(t->name, "Radio");
+
+       call_all(core, tuner, g_tuner, t);
+       return 0;
+}
+
+/* FIXME: Should add a standard for radio */
+
+static int radio_s_tuner (struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+       if (0 != t->index)
+               return -EINVAL;
+       if (t->audmode > V4L2_TUNER_MODE_STEREO)
+               t->audmode = V4L2_TUNER_MODE_STEREO;
+
+       call_all(core, tuner, s_tuner, t);
+
+       return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+static void cx8800_vid_timeout(unsigned long data)
+{
+       struct cx8800_dev *dev = (struct cx8800_dev*)data;
+       struct cx88_core *core = dev->core;
+       struct cx88_dmaqueue *q = &dev->vidq;
+       struct cx88_buffer *buf;
+       unsigned long flags;
+
+       cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+
+       cx_clear(MO_VID_DMACNTRL, 0x11);
+       cx_clear(VID_CAPTURE_CONTROL, 0x06);
+
+       spin_lock_irqsave(&dev->slock,flags);
+       while (!list_empty(&q->active)) {
+               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+               list_del(&buf->vb.queue);
+               buf->vb.state = VIDEOBUF_ERROR;
+               wake_up(&buf->vb.done);
+               printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
+                      buf, buf->vb.i, (unsigned long)buf->risc.dma);
+       }
+       restart_video_queue(dev,q);
+       spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+static const char *cx88_vid_irqs[32] = {
+       "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
+       "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
+       "y_oflow",  "u_oflow",  "v_oflow",  "vbi_oflow",
+       "y_sync",   "u_sync",   "v_sync",   "vbi_sync",
+       "opc_err",  "par_err",  "rip_err",  "pci_abort",
+};
+
+static void cx8800_vid_irq(struct cx8800_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       u32 status, mask, count;
+
+       status = cx_read(MO_VID_INTSTAT);
+       mask   = cx_read(MO_VID_INTMSK);
+       if (0 == (status & mask))
+               return;
+       cx_write(MO_VID_INTSTAT, status);
+       if (irq_debug  ||  (status & mask & ~0xff))
+               cx88_print_irqbits(core->name, "irq vid",
+                                  cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
+                                  status, mask);
+
+       /* risc op code error */
+       if (status & (1 << 16)) {
+               printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
+               cx_clear(MO_VID_DMACNTRL, 0x11);
+               cx_clear(VID_CAPTURE_CONTROL, 0x06);
+               cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+       }
+
+       /* risc1 y */
+       if (status & 0x01) {
+               spin_lock(&dev->slock);
+               count = cx_read(MO_VIDY_GPCNT);
+               cx88_wakeup(core, &dev->vidq, count);
+               spin_unlock(&dev->slock);
+       }
+
+       /* risc1 vbi */
+       if (status & 0x08) {
+               spin_lock(&dev->slock);
+               count = cx_read(MO_VBI_GPCNT);
+               cx88_wakeup(core, &dev->vbiq, count);
+               spin_unlock(&dev->slock);
+       }
+
+       /* risc2 y */
+       if (status & 0x10) {
+               dprintk(2,"stopper video\n");
+               spin_lock(&dev->slock);
+               restart_video_queue(dev,&dev->vidq);
+               spin_unlock(&dev->slock);
+       }
+
+       /* risc2 vbi */
+       if (status & 0x80) {
+               dprintk(2,"stopper vbi\n");
+               spin_lock(&dev->slock);
+               cx8800_restart_vbi_queue(dev,&dev->vbiq);
+               spin_unlock(&dev->slock);
+       }
+}
+
+static irqreturn_t cx8800_irq(int irq, void *dev_id)
+{
+       struct cx8800_dev *dev = dev_id;
+       struct cx88_core *core = dev->core;
+       u32 status;
+       int loop, handled = 0;
+
+       for (loop = 0; loop < 10; loop++) {
+               status = cx_read(MO_PCI_INTSTAT) &
+                       (core->pci_irqmask | PCI_INT_VIDINT);
+               if (0 == status)
+                       goto out;
+               cx_write(MO_PCI_INTSTAT, status);
+               handled = 1;
+
+               if (status & core->pci_irqmask)
+                       cx88_core_irq(core,status);
+               if (status & PCI_INT_VIDINT)
+                       cx8800_vid_irq(dev);
+       };
+       if (10 == loop) {
+               printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
+                      core->name);
+               cx_write(MO_PCI_INTMSK,0);
+       }
+
+ out:
+       return IRQ_RETVAL(handled);
+}
+
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+static const struct v4l2_file_operations video_fops =
+{
+       .owner         = THIS_MODULE,
+       .open          = video_open,
+       .release       = video_release,
+       .read          = video_read,
+       .poll          = video_poll,
+       .mmap          = video_mmap,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+       .vidioc_g_chip_ident  = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = vidioc_g_register,
+       .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static const struct video_device cx8800_video_template = {
+       .name                 = "cx8800-video",
+       .fops                 = &video_fops,
+       .ioctl_ops            = &video_ioctl_ops,
+       .tvnorms              = CX88_NORMS,
+};
+
+static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_g_fmt_vbi_cap     = cx8800_vbi_fmt,
+       .vidioc_try_fmt_vbi_cap   = cx8800_vbi_fmt,
+       .vidioc_s_fmt_vbi_cap     = cx8800_vbi_fmt,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_g_chip_ident  = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = vidioc_g_register,
+       .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static const struct video_device cx8800_vbi_template = {
+       .name                 = "cx8800-vbi",
+       .fops                 = &video_fops,
+       .ioctl_ops            = &vbi_ioctl_ops,
+       .tvnorms              = CX88_NORMS,
+};
+
+static const struct v4l2_file_operations radio_fops =
+{
+       .owner         = THIS_MODULE,
+       .open          = video_open,
+       .poll          = v4l2_ctrl_poll,
+       .release       = video_release,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_g_tuner       = radio_g_tuner,
+       .vidioc_s_tuner       = radio_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+       .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+       .vidioc_g_chip_ident  = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = vidioc_g_register,
+       .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static const struct video_device cx8800_radio_template = {
+       .name                 = "cx8800-radio",
+       .fops                 = &radio_fops,
+       .ioctl_ops            = &radio_ioctl_ops,
+};
+
+static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = {
+       .s_ctrl = cx8800_s_vid_ctrl,
+};
+
+static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = {
+       .s_ctrl = cx8800_s_aud_ctrl,
+};
+
+/* ----------------------------------------------------------- */
+
+static void cx8800_unregister_video(struct cx8800_dev *dev)
+{
+       if (dev->radio_dev) {
+               if (video_is_registered(dev->radio_dev))
+                       video_unregister_device(dev->radio_dev);
+               else
+                       video_device_release(dev->radio_dev);
+               dev->radio_dev = NULL;
+       }
+       if (dev->vbi_dev) {
+               if (video_is_registered(dev->vbi_dev))
+                       video_unregister_device(dev->vbi_dev);
+               else
+                       video_device_release(dev->vbi_dev);
+               dev->vbi_dev = NULL;
+       }
+       if (dev->video_dev) {
+               if (video_is_registered(dev->video_dev))
+                       video_unregister_device(dev->video_dev);
+               else
+                       video_device_release(dev->video_dev);
+               dev->video_dev = NULL;
+       }
+}
+
+static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
+                                   const struct pci_device_id *pci_id)
+{
+       struct cx8800_dev *dev;
+       struct cx88_core *core;
+       int err;
+       int i;
+
+       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+       if (NULL == dev)
+               return -ENOMEM;
+
+       /* pci init */
+       dev->pci = pci_dev;
+       if (pci_enable_device(pci_dev)) {
+               err = -EIO;
+               goto fail_free;
+       }
+       core = cx88_core_get(dev->pci);
+       if (NULL == core) {
+               err = -EINVAL;
+               goto fail_free;
+       }
+       dev->core = core;
+
+       /* print pci info */
+       dev->pci_rev = pci_dev->revision;
+       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+       printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+              "latency: %d, mmio: 0x%llx\n", core->name,
+              pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+              dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
+
+       pci_set_master(pci_dev);
+       if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) {
+               printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
+               err = -EIO;
+               goto fail_core;
+       }
+
+       /* initialize driver struct */
+       spin_lock_init(&dev->slock);
+       core->tvnorm = V4L2_STD_NTSC_M;
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vidq.queued);
+       dev->vidq.timeout.function = cx8800_vid_timeout;
+       dev->vidq.timeout.data     = (unsigned long)dev;
+       init_timer(&dev->vidq.timeout);
+       cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
+                         MO_VID_DMACNTRL,0x11,0x00);
+
+       /* init vbi dma queues */
+       INIT_LIST_HEAD(&dev->vbiq.active);
+       INIT_LIST_HEAD(&dev->vbiq.queued);
+       dev->vbiq.timeout.function = cx8800_vbi_timeout;
+       dev->vbiq.timeout.data     = (unsigned long)dev;
+       init_timer(&dev->vbiq.timeout);
+       cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
+                         MO_VID_DMACNTRL,0x88,0x00);
+
+       /* get irq */
+       err = request_irq(pci_dev->irq, cx8800_irq,
+                         IRQF_SHARED | IRQF_DISABLED, core->name, dev);
+       if (err < 0) {
+               printk(KERN_ERR "%s/0: can't get IRQ %d\n",
+                      core->name,pci_dev->irq);
+               goto fail_core;
+       }
+       cx_set(MO_PCI_INTMSK, core->pci_irqmask);
+
+       for (i = 0; i < CX8800_AUD_CTLS; i++) {
+               const struct cx88_ctrl *cc = &cx8800_aud_ctls[i];
+               struct v4l2_ctrl *vc;
+
+               vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops,
+                       cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
+               if (vc == NULL) {
+                       err = core->audio_hdl.error;
+                       goto fail_core;
+               }
+               vc->priv = (void *)cc;
+       }
+
+       for (i = 0; i < CX8800_VID_CTLS; i++) {
+               const struct cx88_ctrl *cc = &cx8800_vid_ctls[i];
+               struct v4l2_ctrl *vc;
+
+               vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops,
+                       cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
+               if (vc == NULL) {
+                       err = core->video_hdl.error;
+                       goto fail_core;
+               }
+               vc->priv = (void *)cc;
+               if (vc->id == V4L2_CID_CHROMA_AGC)
+                       core->chroma_agc = vc;
+       }
+       v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl);
+
+       /* load and configure helper modules */
+
+       if (core->board.audio_chip == V4L2_IDENT_WM8775) {
+               struct i2c_board_info wm8775_info = {
+                       .type = "wm8775",
+                       .addr = 0x36 >> 1,
+                       .platform_data = &core->wm8775_data,
+               };
+               struct v4l2_subdev *sd;
+
+               if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
+                       core->wm8775_data.is_nova_s = true;
+               else
+                       core->wm8775_data.is_nova_s = false;
+
+               sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
+                               &wm8775_info, NULL);
+               if (sd != NULL) {
+                       core->sd_wm8775 = sd;
+                       sd->grp_id = WM8775_GID;
+               }
+       }
+
+       if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
+               /* This probes for a tda9874 as is used on some
+                  Pixelview Ultra boards. */
+               v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
+                               "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
+       }
+
+       switch (core->boardnr) {
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
+               static const struct i2c_board_info rtc_info = {
+                       I2C_BOARD_INFO("isl1208", 0x6f)
+               };
+
+               request_module("rtc-isl1208");
+               core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info);
+       }
+               /* break intentionally omitted */
+       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+               request_module("ir-kbd-i2c");
+       }
+
+       /* Sets device info at pci_dev */
+       pci_set_drvdata(pci_dev, dev);
+
+       dev->width   = 320;
+       dev->height  = 240;
+       dev->fmt     = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+
+       /* initial device configuration */
+       mutex_lock(&core->lock);
+       cx88_set_tvnorm(core, core->tvnorm);
+       v4l2_ctrl_handler_setup(&core->video_hdl);
+       v4l2_ctrl_handler_setup(&core->audio_hdl);
+       cx88_video_mux(core, 0);
+
+       /* register v4l devices */
+       dev->video_dev = cx88_vdev_init(core,dev->pci,
+                                       &cx8800_video_template,"video");
+       video_set_drvdata(dev->video_dev, dev);
+       dev->video_dev->ctrl_handler = &core->video_hdl;
+       err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
+                                   video_nr[core->nr]);
+       if (err < 0) {
+               printk(KERN_ERR "%s/0: can't register video device\n",
+                      core->name);
+               goto fail_unreg;
+       }
+       printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+              core->name, video_device_node_name(dev->video_dev));
+
+       dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
+       video_set_drvdata(dev->vbi_dev, dev);
+       err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
+                                   vbi_nr[core->nr]);
+       if (err < 0) {
+               printk(KERN_ERR "%s/0: can't register vbi device\n",
+                      core->name);
+               goto fail_unreg;
+       }
+       printk(KERN_INFO "%s/0: registered device %s\n",
+              core->name, video_device_node_name(dev->vbi_dev));
+
+       if (core->board.radio.type == CX88_RADIO) {
+               dev->radio_dev = cx88_vdev_init(core,dev->pci,
+                                               &cx8800_radio_template,"radio");
+               video_set_drvdata(dev->radio_dev, dev);
+               dev->radio_dev->ctrl_handler = &core->audio_hdl;
+               err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
+                                           radio_nr[core->nr]);
+               if (err < 0) {
+                       printk(KERN_ERR "%s/0: can't register radio device\n",
+                              core->name);
+                       goto fail_unreg;
+               }
+               printk(KERN_INFO "%s/0: registered device %s\n",
+                      core->name, video_device_node_name(dev->radio_dev));
+       }
+
+       /* start tvaudio thread */
+       if (core->board.tuner_type != TUNER_ABSENT) {
+               core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
+               if (IS_ERR(core->kthread)) {
+                       err = PTR_ERR(core->kthread);
+                       printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n",
+                              core->name, err);
+               }
+       }
+       mutex_unlock(&core->lock);
+
+       return 0;
+
+fail_unreg:
+       cx8800_unregister_video(dev);
+       free_irq(pci_dev->irq, dev);
+       mutex_unlock(&core->lock);
+fail_core:
+       cx88_core_put(core,dev->pci);
+fail_free:
+       kfree(dev);
+       return err;
+}
+
+static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
+{
+       struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx88_core *core = dev->core;
+
+       /* stop thread */
+       if (core->kthread) {
+               kthread_stop(core->kthread);
+               core->kthread = NULL;
+       }
+
+       if (core->ir)
+               cx88_ir_stop(core);
+
+       cx88_shutdown(core); /* FIXME */
+       pci_disable_device(pci_dev);
+
+       /* unregister stuff */
+
+       free_irq(pci_dev->irq, dev);
+       cx8800_unregister_video(dev);
+       pci_set_drvdata(pci_dev, NULL);
+
+       /* free memory */
+       btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
+       cx88_core_put(core,dev->pci);
+       kfree(dev);
+}
+
+#ifdef CONFIG_PM
+static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+       struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx88_core *core = dev->core;
+
+       /* stop video+vbi capture */
+       spin_lock(&dev->slock);
+       if (!list_empty(&dev->vidq.active)) {
+               printk("%s/0: suspend video\n", core->name);
+               stop_video_dma(dev);
+               del_timer(&dev->vidq.timeout);
+       }
+       if (!list_empty(&dev->vbiq.active)) {
+               printk("%s/0: suspend vbi\n", core->name);
+               cx8800_stop_vbi_dma(dev);
+               del_timer(&dev->vbiq.timeout);
+       }
+       spin_unlock(&dev->slock);
+
+       if (core->ir)
+               cx88_ir_stop(core);
+       /* FIXME -- shutdown device */
+       cx88_shutdown(core);
+
+       pci_save_state(pci_dev);
+       if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+               pci_disable_device(pci_dev);
+               dev->state.disabled = 1;
+       }
+       return 0;
+}
+
+static int cx8800_resume(struct pci_dev *pci_dev)
+{
+       struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+       struct cx88_core *core = dev->core;
+       int err;
+
+       if (dev->state.disabled) {
+               err=pci_enable_device(pci_dev);
+               if (err) {
+                       printk(KERN_ERR "%s/0: can't enable device\n",
+                              core->name);
+                       return err;
+               }
+
+               dev->state.disabled = 0;
+       }
+       err= pci_set_power_state(pci_dev, PCI_D0);
+       if (err) {
+               printk(KERN_ERR "%s/0: can't set power state\n", core->name);
+               pci_disable_device(pci_dev);
+               dev->state.disabled = 1;
+
+               return err;
+       }
+       pci_restore_state(pci_dev);
+
+       /* FIXME: re-initialize hardware */
+       cx88_reset(core);
+       if (core->ir)
+               cx88_ir_start(core);
+
+       cx_set(MO_PCI_INTMSK, core->pci_irqmask);
+
+       /* restart video+vbi capture */
+       spin_lock(&dev->slock);
+       if (!list_empty(&dev->vidq.active)) {
+               printk("%s/0: resume video\n", core->name);
+               restart_video_queue(dev,&dev->vidq);
+       }
+       if (!list_empty(&dev->vbiq.active)) {
+               printk("%s/0: resume vbi\n", core->name);
+               cx8800_restart_vbi_queue(dev,&dev->vbiq);
+       }
+       spin_unlock(&dev->slock);
+
+       return 0;
+}
+#endif
+
+/* ----------------------------------------------------------- */
+
+static const struct pci_device_id cx8800_pci_tbl[] = {
+       {
+               .vendor       = 0x14f1,
+               .device       = 0x8800,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       },{
+               /* --- end of list --- */
+       }
+};
+MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
+
+static struct pci_driver cx8800_pci_driver = {
+       .name     = "cx8800",
+       .id_table = cx8800_pci_tbl,
+       .probe    = cx8800_initdev,
+       .remove   = __devexit_p(cx8800_finidev),
+#ifdef CONFIG_PM
+       .suspend  = cx8800_suspend,
+       .resume   = cx8800_resume,
+#endif
+};
+
+static int __init cx8800_init(void)
+{
+       printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
+              CX88_VERSION);
+       return pci_register_driver(&cx8800_pci_driver);
+}
+
+static void __exit cx8800_fini(void)
+{
+       pci_unregister_driver(&cx8800_pci_driver);
+}
+
+module_init(cx8800_init);
+module_exit(cx8800_fini);
diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c
new file mode 100644 (file)
index 0000000..d77f8ec
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+
+    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
+                          DNTV Live! DVB-T Pro (VP-3054), wired as:
+                          GPIO[0] -> SCL, GPIO[1] -> SDA
+
+    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+    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/slab.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "cx88.h"
+#include "cx88-vp3054-i2c.h"
+
+MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_LICENSE("GPL");
+
+/* ----------------------------------------------------------------------- */
+
+static void vp3054_bit_setscl(void *data, int state)
+{
+       struct cx8802_dev *dev = data;
+       struct cx88_core *core = dev->core;
+       struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
+
+       if (state) {
+               vp3054_i2c->state |=  0x0001;   /* SCL high */
+               vp3054_i2c->state &= ~0x0100;   /* external pullup */
+       } else {
+               vp3054_i2c->state &= ~0x0001;   /* SCL low */
+               vp3054_i2c->state |=  0x0100;   /* drive pin */
+       }
+       cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
+       cx_read(MO_GP0_IO);
+}
+
+static void vp3054_bit_setsda(void *data, int state)
+{
+       struct cx8802_dev *dev = data;
+       struct cx88_core *core = dev->core;
+       struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
+
+       if (state) {
+               vp3054_i2c->state |=  0x0002;   /* SDA high */
+               vp3054_i2c->state &= ~0x0200;   /* tristate pin */
+       } else {
+               vp3054_i2c->state &= ~0x0002;   /* SDA low */
+               vp3054_i2c->state |=  0x0200;   /* drive pin */
+       }
+       cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
+       cx_read(MO_GP0_IO);
+}
+
+static int vp3054_bit_getscl(void *data)
+{
+       struct cx8802_dev *dev = data;
+       struct cx88_core *core = dev->core;
+       u32 state;
+
+       state = cx_read(MO_GP0_IO);
+       return (state & 0x01) ? 1 : 0;
+}
+
+static int vp3054_bit_getsda(void *data)
+{
+       struct cx8802_dev *dev = data;
+       struct cx88_core *core = dev->core;
+       u32 state;
+
+       state = cx_read(MO_GP0_IO);
+       return (state & 0x02) ? 1 : 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
+       .setsda  = vp3054_bit_setsda,
+       .setscl  = vp3054_bit_setscl,
+       .getsda  = vp3054_bit_getsda,
+       .getscl  = vp3054_bit_getscl,
+       .udelay  = 16,
+       .timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+int vp3054_i2c_probe(struct cx8802_dev *dev)
+{
+       struct cx88_core *core = dev->core;
+       struct vp3054_i2c_state *vp3054_i2c;
+       int rc;
+
+       if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+               return 0;
+
+       vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
+       if (vp3054_i2c == NULL)
+               return -ENOMEM;
+       dev->vp3054 = vp3054_i2c;
+
+       memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
+              sizeof(vp3054_i2c->algo));
+
+       vp3054_i2c->adap.dev.parent = &dev->pci->dev;
+       strlcpy(vp3054_i2c->adap.name, core->name,
+               sizeof(vp3054_i2c->adap.name));
+       vp3054_i2c->adap.owner = THIS_MODULE;
+       vp3054_i2c->algo.data = dev;
+       i2c_set_adapdata(&vp3054_i2c->adap, dev);
+       vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
+
+       vp3054_bit_setscl(dev,1);
+       vp3054_bit_setsda(dev,1);
+
+       rc = i2c_bit_add_bus(&vp3054_i2c->adap);
+       if (0 != rc) {
+               printk("%s: vp3054_i2c register FAILED\n", core->name);
+
+               kfree(dev->vp3054);
+               dev->vp3054 = NULL;
+       }
+
+       return rc;
+}
+
+void vp3054_i2c_remove(struct cx8802_dev *dev)
+{
+       struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
+
+       if (vp3054_i2c == NULL ||
+           dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+               return;
+
+       i2c_del_adapter(&vp3054_i2c->adap);
+       kfree(vp3054_i2c);
+}
+
+EXPORT_SYMBOL(vp3054_i2c_probe);
+EXPORT_SYMBOL(vp3054_i2c_remove);
diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.h b/drivers/media/pci/cx88/cx88-vp3054-i2c.h
new file mode 100644 (file)
index 0000000..be99c93
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+
+    cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
+                          DNTV Live! DVB-T Pro (VP-3054), wired as:
+                          GPIO[0] -> SCL, GPIO[1] -> SDA
+
+    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+    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.
+
+*/
+
+/* ----------------------------------------------------------------------- */
+struct vp3054_i2c_state {
+       struct i2c_adapter         adap;
+       struct i2c_algo_bit_data   algo;
+       u32                        state;
+};
+
+/* ----------------------------------------------------------------------- */
+#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
+int  vp3054_i2c_probe(struct cx8802_dev *dev);
+void vp3054_i2c_remove(struct cx8802_dev *dev);
+#else
+static inline int  vp3054_i2c_probe(struct cx8802_dev *dev)
+{ return 0; }
+static inline void vp3054_i2c_remove(struct cx8802_dev *dev)
+{ }
+#endif
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
new file mode 100644 (file)
index 0000000..44ffc8b
--- /dev/null
@@ -0,0 +1,748 @@
+/*
+ *
+ * v4l2 device driver for cx2388x based TV cards
+ *
+ * (c) 2003,04 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, 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/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/cx2341x.h>
+#include <media/videobuf-dvb.h>
+#include <media/ir-kbd-i2c.h>
+#include <media/wm8775.h>
+
+#include "btcx-risc.h"
+#include "cx88-reg.h"
+#include "tuner-xc2028.h"
+
+#include <linux/mutex.h>
+
+#define CX88_VERSION "0.0.9"
+
+#define UNSET (-1U)
+
+#define CX88_MAXBOARDS 8
+
+/* Max number of inputs by card */
+#define MAX_CX88_INPUT 8
+
+/* ----------------------------------------------------------- */
+/* defines and enums                                           */
+
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
+#define CX88_NORMS (V4L2_STD_ALL               \
+                   & ~V4L2_STD_PAL_H           \
+                   & ~V4L2_STD_NTSC_M_KR       \
+                   & ~V4L2_STD_SECAM_LC)
+
+#define FORMAT_FLAGS_PACKED       0x01
+#define FORMAT_FLAGS_PLANAR       0x02
+
+#define VBI_LINE_COUNT              17
+#define VBI_LINE_LENGTH           2048
+
+#define AUD_RDS_LINES               4
+
+/* need "shadow" registers for some write-only ones ... */
+#define SHADOW_AUD_VOL_CTL           1
+#define SHADOW_AUD_BAL_CTL           2
+#define SHADOW_MAX                   3
+
+/* FM Radio deemphasis type */
+enum cx88_deemph_type {
+       FM_NO_DEEMPH = 0,
+       FM_DEEMPH_50,
+       FM_DEEMPH_75
+};
+
+enum cx88_board_type {
+       CX88_BOARD_NONE = 0,
+       CX88_MPEG_DVB,
+       CX88_MPEG_BLACKBIRD
+};
+
+enum cx8802_board_access {
+       CX8802_DRVCTL_SHARED    = 1,
+       CX8802_DRVCTL_EXCLUSIVE = 2,
+};
+
+/* ----------------------------------------------------------- */
+/* tv norms                                                    */
+
+static unsigned int inline norm_maxw(v4l2_std_id norm)
+{
+       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+}
+
+
+static unsigned int inline norm_maxh(v4l2_std_id norm)
+{
+       return (norm & V4L2_STD_625_50) ? 576 : 480;
+}
+
+/* ----------------------------------------------------------- */
+/* static data                                                 */
+
+struct cx8800_fmt {
+       const char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+       int   flags;
+       u32   cxformat;
+};
+
+/* ----------------------------------------------------------- */
+/* SRAM memory management data (see cx88-core.c)               */
+
+#define SRAM_CH21 0   /* video */
+#define SRAM_CH22 1
+#define SRAM_CH23 2
+#define SRAM_CH24 3   /* vbi   */
+#define SRAM_CH25 4   /* audio */
+#define SRAM_CH26 5
+#define SRAM_CH28 6   /* mpeg */
+#define SRAM_CH27 7   /* audio rds */
+/* more */
+
+struct sram_channel {
+       const char *name;
+       u32  cmds_start;
+       u32  ctrl_start;
+       u32  cdt;
+       u32  fifo_start;
+       u32  fifo_size;
+       u32  ptr1_reg;
+       u32  ptr2_reg;
+       u32  cnt1_reg;
+       u32  cnt2_reg;
+};
+extern const struct sram_channel cx88_sram_channels[];
+
+/* ----------------------------------------------------------- */
+/* card configuration                                          */
+
+#define CX88_BOARD_NOAUTO               UNSET
+#define CX88_BOARD_UNKNOWN                  0
+#define CX88_BOARD_HAUPPAUGE                1
+#define CX88_BOARD_GDI                      2
+#define CX88_BOARD_PIXELVIEW                3
+#define CX88_BOARD_ATI_WONDER_PRO           4
+#define CX88_BOARD_WINFAST2000XP_EXPERT     5
+#define CX88_BOARD_AVERTV_STUDIO_303        6
+#define CX88_BOARD_MSI_TVANYWHERE_MASTER    7
+#define CX88_BOARD_WINFAST_DV2000           8
+#define CX88_BOARD_LEADTEK_PVR2000          9
+#define CX88_BOARD_IODATA_GVVCP3PCI        10
+#define CX88_BOARD_PROLINK_PLAYTVPVR       11
+#define CX88_BOARD_ASUS_PVR_416            12
+#define CX88_BOARD_MSI_TVANYWHERE          13
+#define CX88_BOARD_KWORLD_DVB_T            14
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
+#define CX88_BOARD_KWORLD_LTV883           16
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q  17
+#define CX88_BOARD_HAUPPAUGE_DVB_T1        18
+#define CX88_BOARD_CONEXANT_DVB_T1         19
+#define CX88_BOARD_PROVIDEO_PV259          20
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
+#define CX88_BOARD_PCHDTV_HD3000           22
+#define CX88_BOARD_DNTV_LIVE_DVB_T         23
+#define CX88_BOARD_HAUPPAUGE_ROSLYN        24
+#define CX88_BOARD_DIGITALLOGIC_MEC        25
+#define CX88_BOARD_IODATA_GVBCTV7E         26
+#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T  28
+#define CX88_BOARD_ADSTECH_DVB_T_PCI          29
+#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1  30
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
+#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32
+#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33
+#define CX88_BOARD_ATI_HDTVWONDER          34
+#define CX88_BOARD_WINFAST_DTV1000         35
+#define CX88_BOARD_AVERTV_303              36
+#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1  37
+#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1    38
+#define CX88_BOARD_KWORLD_DVBS_100         39
+#define CX88_BOARD_HAUPPAUGE_HVR1100       40
+#define CX88_BOARD_HAUPPAUGE_HVR1100LP     41
+#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO     42
+#define CX88_BOARD_KWORLD_DVB_T_CX22702    43
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
+#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
+#define CX88_BOARD_PCHDTV_HD5500           47
+#define CX88_BOARD_KWORLD_MCE200_DELUXE    48
+#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000  49
+#define CX88_BOARD_NPGTECH_REALTV_TOP10FM  50
+#define CX88_BOARD_WINFAST_DTV2000H        51
+#define CX88_BOARD_GENIATECH_DVBS          52
+#define CX88_BOARD_HAUPPAUGE_HVR3000       53
+#define CX88_BOARD_NORWOOD_MICRO           54
+#define CX88_BOARD_TE_DTV_250_OEM_SWANN    55
+#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
+#define CX88_BOARD_HAUPPAUGE_HVR4000       68
+#define CX88_BOARD_HAUPPAUGE_HVR4000LITE   69
+#define CX88_BOARD_TEVII_S460              70
+#define CX88_BOARD_OMICOM_SS4_PCI          71
+#define CX88_BOARD_TBS_8920                72
+#define CX88_BOARD_TEVII_S420              73
+#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
+#define CX88_BOARD_PROF_7300               75
+#define CX88_BOARD_SATTRADE_ST4200         76
+#define CX88_BOARD_TBS_8910                77
+#define CX88_BOARD_PROF_6200               78
+#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
+#define CX88_BOARD_HAUPPAUGE_IRONLY        80
+#define CX88_BOARD_WINFAST_DTV1800H        81
+#define CX88_BOARD_WINFAST_DTV2000H_J      82
+#define CX88_BOARD_PROF_7301               83
+#define CX88_BOARD_SAMSUNG_SMT_7020        84
+#define CX88_BOARD_TWINHAN_VP1027_DVBS     85
+#define CX88_BOARD_TEVII_S464              86
+#define CX88_BOARD_WINFAST_DTV2000H_PLUS   87
+#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
+
+enum cx88_itype {
+       CX88_VMUX_COMPOSITE1 = 1,
+       CX88_VMUX_COMPOSITE2,
+       CX88_VMUX_COMPOSITE3,
+       CX88_VMUX_COMPOSITE4,
+       CX88_VMUX_SVIDEO,
+       CX88_VMUX_TELEVISION,
+       CX88_VMUX_CABLE,
+       CX88_VMUX_DVB,
+       CX88_VMUX_DEBUG,
+       CX88_RADIO,
+};
+
+struct cx88_input {
+       enum cx88_itype type;
+       u32             gpio0, gpio1, gpio2, gpio3;
+       unsigned int    vmux:2;
+       unsigned int    audioroute:4;
+};
+
+struct cx88_board {
+       const char              *name;
+       unsigned int            tuner_type;
+       unsigned int            radio_type;
+       unsigned char           tuner_addr;
+       unsigned char           radio_addr;
+       int                     tda9887_conf;
+       struct cx88_input       input[MAX_CX88_INPUT];
+       struct cx88_input       radio;
+       enum cx88_board_type    mpeg;
+       unsigned int            audio_chip;
+       int                     num_frontends;
+
+       /* Used for I2S devices */
+       int                     i2sinputcntl;
+};
+
+struct cx88_subid {
+       u16     subvendor;
+       u16     subdevice;
+       u32     card;
+};
+
+enum cx88_tvaudio {
+       WW_NONE = 1,
+       WW_BTSC,
+       WW_BG,
+       WW_DK,
+       WW_I,
+       WW_L,
+       WW_EIAJ,
+       WW_I2SPT,
+       WW_FM,
+       WW_I2SADC,
+       WW_M
+};
+
+#define INPUT(nr) (core->board.input[nr])
+
+/* ----------------------------------------------------------- */
+/* device / file handle status                                 */
+
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO         2
+#define RESOURCE_VBI           4
+
+#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)
+
+/* buffer for one video frame */
+struct cx88_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       /* cx88 specific */
+       unsigned int           bpl;
+       struct btcx_riscmem    risc;
+       const struct cx8800_fmt *fmt;
+       u32                    count;
+};
+
+struct cx88_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+       struct timer_list      timeout;
+       struct btcx_riscmem    stopper;
+       u32                    count;
+};
+
+struct cx88_core {
+       struct list_head           devlist;
+       atomic_t                   refcount;
+
+       /* board name */
+       int                        nr;
+       char                       name[32];
+
+       /* pci stuff */
+       int                        pci_bus;
+       int                        pci_slot;
+       u32                        __iomem *lmmio;
+       u8                         __iomem *bmmio;
+       u32                        shadow[SHADOW_MAX];
+       int                        pci_irqmask;
+
+       /* i2c i/o */
+       struct i2c_adapter         i2c_adap;
+       struct i2c_algo_bit_data   i2c_algo;
+       struct i2c_client          i2c_client;
+       u32                        i2c_state, i2c_rc;
+
+       /* config info -- analog */
+       struct v4l2_device         v4l2_dev;
+       struct v4l2_ctrl_handler   video_hdl;
+       struct v4l2_ctrl           *chroma_agc;
+       struct v4l2_ctrl_handler   audio_hdl;
+       struct v4l2_subdev         *sd_wm8775;
+       struct i2c_client          *i2c_rtc;
+       unsigned int               boardnr;
+       struct cx88_board          board;
+
+       /* Supported V4L _STD_ tuner formats */
+       unsigned int               tuner_formats;
+
+       /* config info -- dvb */
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
+       int                        (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+#endif
+       void                       (*gate_ctrl)(struct cx88_core  *core, int open);
+
+       /* state info */
+       struct task_struct         *kthread;
+       v4l2_std_id                tvnorm;
+       enum cx88_tvaudio          tvaudio;
+       u32                        audiomode_manual;
+       u32                        audiomode_current;
+       u32                        input;
+       u32                        last_analog_input;
+       u32                        astat;
+       u32                        use_nicam;
+       unsigned long              last_change;
+
+       /* IR remote control state */
+       struct cx88_IR             *ir;
+
+       /* I2C remote data */
+       struct IR_i2c_init_data    init_data;
+       struct wm8775_platform_data wm8775_data;
+
+       struct mutex               lock;
+       /* various v4l controls */
+       u32                        freq;
+       int                        users;
+       int                        mpeg_users;
+
+       /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
+       struct cx8802_dev          *dvbdev;
+       enum cx88_board_type       active_type_id;
+       int                        active_ref;
+       int                        active_fe_id;
+};
+
+static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
+}
+
+#define call_hw(core, grpid, o, f, args...) \
+       do {                                                    \
+               if (!core->i2c_rc) {                            \
+                       if (core->gate_ctrl)                    \
+                               core->gate_ctrl(core, 1);       \
+                       v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
+                       if (core->gate_ctrl)                    \
+                               core->gate_ctrl(core, 0);       \
+               }                                               \
+       } while (0)
+
+#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
+
+#define WM8775_GID      (1 << 0)
+
+#define wm8775_s_ctrl(core, id, val) \
+       do {                                                                    \
+               struct v4l2_ctrl *ctrl_ =                                       \
+                       v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);      \
+               if (ctrl_ && !core->i2c_rc) {                                   \
+                       if (core->gate_ctrl)                                    \
+                               core->gate_ctrl(core, 1);                       \
+                       v4l2_ctrl_s_ctrl(ctrl_, val);                           \
+                       if (core->gate_ctrl)                                    \
+                               core->gate_ctrl(core, 0);                       \
+               }                                                               \
+       } while (0)
+
+#define wm8775_g_ctrl(core, id) \
+       ({                                                                      \
+               struct v4l2_ctrl *ctrl_ =                                       \
+                       v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);      \
+               s32 val = 0;                                                    \
+               if (ctrl_ && !core->i2c_rc) {                                   \
+                       if (core->gate_ctrl)                                    \
+                               core->gate_ctrl(core, 1);                       \
+                       val = v4l2_ctrl_g_ctrl(ctrl_);                          \
+                       if (core->gate_ctrl)                                    \
+                               core->gate_ctrl(core, 0);                       \
+               }                                                               \
+               val;                                                            \
+       })
+
+struct cx8800_dev;
+struct cx8802_dev;
+
+/* ----------------------------------------------------------- */
+/* function 0: video stuff                                     */
+
+struct cx8800_fh {
+       struct v4l2_fh             fh;
+       struct cx8800_dev          *dev;
+       unsigned int               resources;
+
+       /* video capture */
+       struct videobuf_queue      vidq;
+
+       /* vbi capture */
+       struct videobuf_queue      vbiq;
+};
+
+struct cx8800_suspend_state {
+       int                        disabled;
+};
+
+struct cx8800_dev {
+       struct cx88_core           *core;
+       spinlock_t                 slock;
+
+       /* various device info */
+       unsigned int               resources;
+       struct video_device        *video_dev;
+       struct video_device        *vbi_dev;
+       struct video_device        *radio_dev;
+
+       /* pci i/o */
+       struct pci_dev             *pci;
+       unsigned char              pci_rev,pci_lat;
+
+       const struct cx8800_fmt    *fmt;
+       unsigned int               width, height;
+
+       /* capture queues */
+       struct cx88_dmaqueue       vidq;
+       struct cx88_dmaqueue       vbiq;
+
+       /* various v4l controls */
+
+       /* other global state info */
+       struct cx8800_suspend_state state;
+};
+
+/* ----------------------------------------------------------- */
+/* function 1: audio/alsa stuff                                */
+/* =============> moved to cx88-alsa.c <====================== */
+
+
+/* ----------------------------------------------------------- */
+/* function 2: mpeg stuff                                      */
+
+struct cx8802_fh {
+       struct v4l2_fh             fh;
+       struct cx8802_dev          *dev;
+       struct videobuf_queue      mpegq;
+};
+
+struct cx8802_suspend_state {
+       int                        disabled;
+};
+
+struct cx8802_driver {
+       struct cx88_core *core;
+
+       /* List of drivers attached to device */
+       struct list_head drvlist;
+
+       /* Type of driver and access required */
+       enum cx88_board_type type_id;
+       enum cx8802_board_access hw_access;
+
+       /* MPEG 8802 internal only */
+       int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
+       int (*resume)(struct pci_dev *pci_dev);
+
+       /* Callers to the following functions must hold core->lock */
+
+       /* MPEG 8802 -> mini driver - Driver probe and configuration */
+       int (*probe)(struct cx8802_driver *drv);
+       int (*remove)(struct cx8802_driver *drv);
+
+       /* MPEG 8802 -> mini driver - Access for hardware control */
+       int (*advise_acquire)(struct cx8802_driver *drv);
+       int (*advise_release)(struct cx8802_driver *drv);
+
+       /* MPEG 8802 <- mini driver - Access for hardware control */
+       int (*request_acquire)(struct cx8802_driver *drv);
+       int (*request_release)(struct cx8802_driver *drv);
+};
+
+struct cx8802_dev {
+       struct cx88_core           *core;
+       spinlock_t                 slock;
+
+       /* pci i/o */
+       struct pci_dev             *pci;
+       unsigned char              pci_rev,pci_lat;
+
+       /* dma queues */
+       struct cx88_dmaqueue       mpegq;
+       u32                        ts_packet_size;
+       u32                        ts_packet_count;
+
+       /* other global state info */
+       struct cx8802_suspend_state state;
+
+       /* for blackbird only */
+       struct list_head           devlist;
+#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
+    defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
+       struct video_device        *mpeg_dev;
+       u32                        mailbox;
+       int                        width;
+       int                        height;
+       unsigned char              mpeg_active; /* nonzero if mpeg encoder is active */
+
+       /* mpeg params */
+       struct cx2341x_handler     cxhdl;
+#endif
+
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
+       /* for dvb only */
+       struct videobuf_dvb_frontends frontends;
+#endif
+
+#if defined(CONFIG_VIDEO_CX88_VP3054) || \
+    defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
+       /* For VP3045 secondary I2C bus support */
+       struct vp3054_i2c_state    *vp3054;
+#endif
+       /* for switching modulation types */
+       unsigned char              ts_gen_cntrl;
+
+       /* List of attached drivers; must hold core->lock to access */
+       struct list_head           drvlist;
+
+       struct work_struct         request_module_wk;
+};
+
+/* ----------------------------------------------------------- */
+
+#define cx_read(reg)             readl(core->lmmio + ((reg)>>2))
+#define cx_write(reg,value)      writel((value), core->lmmio + ((reg)>>2))
+#define cx_writeb(reg,value)     writeb((value), core->bmmio + (reg))
+
+#define cx_andor(reg,mask,value) \
+  writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
+  ((value) & (mask)), core->lmmio+((reg)>>2))
+#define cx_set(reg,bit)          cx_andor((reg),(bit),(bit))
+#define cx_clear(reg,bit)        cx_andor((reg),(bit),0)
+
+#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
+
+/* shadow registers */
+#define cx_sread(sreg)             (core->shadow[sreg])
+#define cx_swrite(sreg,reg,value) \
+  (core->shadow[sreg] = value, \
+   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
+#define cx_sandor(sreg,reg,mask,value) \
+  (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
+   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
+
+/* ----------------------------------------------------------- */
+/* cx88-core.c                                                 */
+
+extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
+                              int len, u32 bits, u32 mask);
+
+extern int cx88_core_irq(struct cx88_core *core, u32 status);
+extern void cx88_wakeup(struct cx88_core *core,
+                       struct cx88_dmaqueue *q, u32 count);
+extern void cx88_shutdown(struct cx88_core *core);
+extern int cx88_reset(struct cx88_core *core);
+
+extern int
+cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                struct scatterlist *sglist,
+                unsigned int top_offset, unsigned int bottom_offset,
+                unsigned int bpl, unsigned int padding, unsigned int lines);
+extern int
+cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+                    struct scatterlist *sglist, unsigned int bpl,
+                    unsigned int lines, unsigned int lpi);
+extern int
+cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+                 u32 reg, u32 mask, u32 value);
+extern void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
+
+extern void cx88_risc_disasm(struct cx88_core *core,
+                            struct btcx_riscmem *risc);
+extern int cx88_sram_channel_setup(struct cx88_core *core,
+                                  const struct sram_channel *ch,
+                                  unsigned int bpl, u32 risc);
+extern void cx88_sram_channel_dump(struct cx88_core *core,
+                                  const struct sram_channel *ch);
+
+extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
+                         unsigned int height, enum v4l2_field field);
+extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
+
+extern struct video_device *cx88_vdev_init(struct cx88_core *core,
+                                          struct pci_dev *pci,
+                                          const struct video_device *template_,
+                                          const char *type);
+extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
+extern void cx88_core_put(struct cx88_core *core,
+                         struct pci_dev *pci);
+
+extern int cx88_start_audio_dma(struct cx88_core *core);
+extern int cx88_stop_audio_dma(struct cx88_core *core);
+
+
+/* ----------------------------------------------------------- */
+/* cx88-vbi.c                                                  */
+
+/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
+int cx8800_vbi_fmt (struct file *file, void *priv,
+                                       struct v4l2_format *f);
+
+/*
+int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
+                        struct cx88_dmaqueue *q,
+                        struct cx88_buffer   *buf);
+*/
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
+int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
+                            struct cx88_dmaqueue *q);
+void cx8800_vbi_timeout(unsigned long data);
+
+extern const struct videobuf_queue_ops cx8800_vbi_qops;
+
+/* ----------------------------------------------------------- */
+/* cx88-i2c.c                                                  */
+
+extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
+
+
+/* ----------------------------------------------------------- */
+/* cx88-cards.c                                                */
+
+extern int cx88_tuner_callback(void *dev, int component, 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                                              */
+
+void cx88_set_tvaudio(struct cx88_core *core);
+void cx88_newstation(struct cx88_core *core);
+void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
+int cx88_audio_thread(void *data);
+
+int cx8802_register_driver(struct cx8802_driver *drv);
+int cx8802_unregister_driver(struct cx8802_driver *drv);
+
+/* Caller must hold core->lock */
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+
+/* ----------------------------------------------------------- */
+/* cx88-dsp.c                                                  */
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
+/* cx88-input.c                                                */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
+int cx88_ir_fini(struct cx88_core *core);
+void cx88_ir_irq(struct cx88_core *core);
+int cx88_ir_start(struct cx88_core *core);
+void cx88_ir_stop(struct cx88_core *core);
+extern void cx88_i2c_init_ir(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
+/* cx88-mpeg.c                                                 */
+
+int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
+                       struct cx88_buffer *buf, enum v4l2_field field);
+void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
+void cx8802_cancel_buffers(struct cx8802_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* cx88-video.c*/
+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_video_mux(struct cx88_core *core, unsigned int input);
+void cx88_querycap(struct file *file, struct cx88_core *core,
+               struct v4l2_capability *cap);
diff --git a/drivers/media/pci/ivtv/Kconfig b/drivers/media/pci/ivtv/Kconfig
new file mode 100644 (file)
index 0000000..89f6591
--- /dev/null
@@ -0,0 +1,45 @@
+config VIDEO_IVTV
+       tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
+       depends on VIDEO_V4L2 && PCI && I2C
+       select I2C_ALGOBIT
+       depends on RC_CORE
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_CX2341X
+       select VIDEO_CX25840
+       select VIDEO_MSP3400
+       select VIDEO_SAA711X
+       select VIDEO_SAA717X
+       select VIDEO_SAA7127
+       select VIDEO_CS53L32A
+       select VIDEO_M52790
+       select VIDEO_WM8775
+       select VIDEO_WM8739
+       select VIDEO_VP27SMPX
+       select VIDEO_UPD64031A
+       select VIDEO_UPD64083
+       ---help---
+         This is a video4linux driver for Conexant cx23416 or cx23415 based
+         PCI personal video recorder devices.
+
+         This is used in devices such as the Hauppauge PVR-150/250/350/500
+         cards. There is a driver homepage at <http://www.ivtvdriver.org>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ivtv.
+
+config VIDEO_FB_IVTV
+       tristate "Conexant cx23415 framebuffer support"
+       depends on VIDEO_IVTV && FB
+       select FB_CFB_FILLRECT
+       select FB_CFB_COPYAREA
+       select FB_CFB_IMAGEBLIT
+       ---help---
+         This is a framebuffer driver for the Conexant cx23415 MPEG
+         encoder/decoder.
+
+         This is used in the Hauppauge PVR-350 card. There is a driver
+         homepage at <http://www.ivtvdriver.org>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ivtvfb.
diff --git a/drivers/media/pci/ivtv/Makefile b/drivers/media/pci/ivtv/Makefile
new file mode 100644 (file)
index 0000000..80b4ec1
--- /dev/null
@@ -0,0 +1,14 @@
+ivtv-objs      := ivtv-routing.o ivtv-cards.o ivtv-controls.o \
+                  ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \
+                  ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \
+                  ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \
+                  ivtv-vbi.o ivtv-yuv.o
+
+obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
+obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
+
+ccflags-y += -I$(srctree)/drivers/media/video
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
+
diff --git a/drivers/media/pci/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c
new file mode 100644 (file)
index 0000000..145e474
--- /dev/null
@@ -0,0 +1,1370 @@
+/*
+    Functions to query card hardware
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-i2c.h"
+
+#include <media/msp3400.h>
+#include <media/m52790.h>
+#include <media/wm8775.h>
+#include <media/cs53l32a.h>
+#include <media/cx25840.h>
+#include <media/upd64031a.h>
+
+#define MSP_TUNER  MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+                               MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER)
+#define MSP_SCART1 MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define MSP_SCART2 MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, \
+                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define MSP_SCART3 MSP_INPUT(MSP_IN_SCART3, MSP_IN_TUNER1, \
+                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define MSP_MONO   MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
+                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+
+#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
+
+/* usual i2c tuner addresses to probe */
+static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
+       .radio = { I2C_CLIENT_END },
+       .demod = { 0x43, I2C_CLIENT_END },
+       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/* as above, but with possible radio tuner */
+static struct ivtv_card_tuner_i2c ivtv_i2c_radio = {
+       .radio = { 0x60, I2C_CLIENT_END },
+       .demod = { 0x43, I2C_CLIENT_END },
+       .tv    = { 0x61, I2C_CLIENT_END },
+};
+
+/* using the tda8290+75a combo */
+static struct ivtv_card_tuner_i2c ivtv_i2c_tda8290 = {
+       .radio = { I2C_CLIENT_END },
+       .demod = { I2C_CLIENT_END },
+       .tv    = { 0x4b, I2C_CLIENT_END },
+};
+
+/********************** card configuration *******************************/
+
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ 
+   This keeps the PCI ID database up to date. Note that the entries
+   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
+   New vendor IDs should still be added to the vendor ID list. */
+
+/* Hauppauge PVR-250 cards */
+
+/* Note: for Hauppauge cards the tveeprom information is used instead of PCI IDs */
+static const struct ivtv_card ivtv_card_pvr250 = {
+       .type = IVTV_CARD_PVR_250,
+       .name = "Hauppauge WinTV PVR-250",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_MSP34XX,
+       .hw_audio_ctrl = IVTV_HW_MSP34XX,
+       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
+                 IVTV_HW_TVEEPROM | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+               { IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
+               { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
+               { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  MSP_TUNER  },
+               { IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
+               { IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Hauppauge PVR-350 cards */
+
+/* Outputs for Hauppauge PVR350 cards */
+static struct ivtv_card_output ivtv_pvr350_outputs[] = {
+       {
+               .name = "S-Video + Composite",
+               .video_output = 0,
+       }, {
+               .name = "Composite",
+               .video_output = 1,
+       }, {
+               .name = "S-Video",
+               .video_output = 2,
+       }, {
+               .name = "RGB",
+               .video_output = 3,
+       }, {
+               .name = "YUV C",
+               .video_output = 4,
+       }, {
+               .name = "YUV V",
+               .video_output = 5,
+       }
+};
+
+static const struct ivtv_card ivtv_card_pvr350 = {
+       .type = IVTV_CARD_PVR_350,
+       .name = "Hauppauge WinTV PVR-350",
+       .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER,
+       .video_outputs = ivtv_pvr350_outputs,
+       .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs),
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_MSP34XX,
+       .hw_audio_ctrl = IVTV_HW_MSP34XX,
+       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
+                 IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER |
+                 IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+               { IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
+               { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
+               { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  MSP_TUNER  },
+               { IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
+               { IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
+       .i2c = &ivtv_i2c_std,
+};
+
+/* PVR-350 V1 boards have a different audio tuner input and use a
+   saa7114 instead of a saa7115.
+   Note that the info below comes from a pre-production model so it may
+   not be correct. Especially the audio behaves strangely (mono only it seems) */
+static const struct ivtv_card ivtv_card_pvr350_v1 = {
+       .type = IVTV_CARD_PVR_350_V1,
+       .name = "Hauppauge WinTV PVR-350 (V1)",
+       .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER,
+       .video_outputs = ivtv_pvr350_outputs,
+       .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs),
+       .hw_video = IVTV_HW_SAA7114,
+       .hw_audio = IVTV_HW_MSP34XX,
+       .hw_audio_ctrl = IVTV_HW_MSP34XX,
+       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7114 |
+                 IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+               { IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
+               { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
+               { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  MSP_MONO   },
+               { IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
+               { IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Hauppauge PVR-150/PVR-500 cards */
+
+static const struct ivtv_card ivtv_card_pvr150 = {
+       .type = IVTV_CARD_PVR_150,
+       .name = "Hauppauge WinTV PVR-150",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_muxer = IVTV_HW_WM8775,
+       .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 |
+                 IVTV_HW_TVEEPROM | IVTV_HW_TUNER |
+                 IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT |
+                 IVTV_HW_Z8F0811_IR_HAUP,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE7 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO1    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 },
+               { IVTV_CARD_INPUT_SVIDEO2,    2, CX25840_SVIDEO2    },
+               { IVTV_CARD_INPUT_COMPOSITE2, 2, CX25840_COMPOSITE4 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,
+                 CX25840_AUDIO8, WM8775_AIN2 },
+               { IVTV_CARD_INPUT_LINE_IN1,
+                 CX25840_AUDIO_SERIAL, WM8775_AIN2 },
+               { IVTV_CARD_INPUT_LINE_IN2,
+                 CX25840_AUDIO_SERIAL, WM8775_AIN3 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER,
+                        CX25840_AUDIO_SERIAL, WM8775_AIN4 },
+       /* apparently needed for the IR blaster */
+       .gpio_init = { .direction = 0x1f01, .initial_value = 0x26f3 },
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M179 cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_m179[] = {
+       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3cf },
+       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3ce },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_m179 = {
+       .type = IVTV_CARD_M179,
+       .name = "AVerMedia M179",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7114,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0xe380, .initial_value = 0x8290 },
+       .gpio_audio_input  = { .mask = 0x8040, .tuner  = 0x8000, .linein = 0x0000 },
+       .gpio_audio_mute   = { .mask = 0x2000, .mute   = 0x2000 },
+       .gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
+                             .lang1 = 0x0200, .lang2  = 0x0100, .both   = 0x0000 },
+       .gpio_audio_freq   = { .mask = 0x0018, .f32000 = 0x0000,
+                            .f44100 = 0x0008, .f48000 = 0x0010 },
+       .gpio_audio_detect = { .mask = 0x4000, .stereo = 0x0000 },
+       .tuners = {
+               /* As far as we know all M179 cards use this tuner */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_NTSC },
+       },
+       .pci_list = ivtv_pci_m179,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPG600/Kuroutoshikou ITVC16-STVLP cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_mpg600[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xfff3 },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xffff },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_mpg600 = {
+       .type = IVTV_CARD_MPG600,
+       .name = "Yuan MPG600, Kuroutoshikou ITVC16-STVLP",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0x3080, .initial_value = 0x0004 },
+       .gpio_audio_input  = { .mask = 0x3000, .tuner  = 0x0000, .linein = 0x2000 },
+       .gpio_audio_mute   = { .mask = 0x0001, .mute   = 0x0001 },
+       .gpio_audio_mode   = { .mask = 0x000e, .mono   = 0x0006, .stereo = 0x0004,
+                             .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
+       .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
+       .tuners = {
+               /* The PAL tuner is confirmed */
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+       },
+       .pci_list = ivtv_pci_mpg600,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPG160/Kuroutoshikou ITVC15-STVLP cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_mpg160[] = {
+       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_YUAN1, 0 },
+       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_IODATA, 0x40a0 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_mpg160 = {
+       .type = IVTV_CARD_MPG160,
+       .name = "YUAN MPG160, Kuroutoshikou ITVC15-STVLP, I/O Data GV-M2TV/PCI",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7114,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0x7080, .initial_value = 0x400c },
+       .gpio_audio_input  = { .mask = 0x3000, .tuner  = 0x0000, .linein = 0x2000 },
+       .gpio_audio_mute   = { .mask = 0x0001, .mute   = 0x0001 },
+       .gpio_audio_mode   = { .mask = 0x000e, .mono   = 0x0006, .stereo = 0x0004,
+                             .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
+       .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+       },
+       .pci_list = ivtv_pci_mpg160,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan PG600/Diamond PVR-550 cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_pg600[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_DIAMONDMM, 0x0070 },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_pg600 = {
+       .type = IVTV_CARD_PG600,
+       .name = "Yuan PG600, Diamond PVR-550",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1,
+                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+       },
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+       },
+       .pci_list = ivtv_pci_pg600,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Adaptec VideOh! AVC-2410 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_avc2410[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0093 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_avc2410 = {
+       .type = IVTV_CARD_AVC2410,
+       .name = "Adaptec VideOh! AVC-2410",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_MSP34XX,
+       .hw_audio_ctrl = IVTV_HW_MSP34XX,
+       .hw_muxer = IVTV_HW_CS53L32A,
+       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A |
+                 IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+                 IVTV_HW_I2C_IR_RX_ADAPTEC,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,
+                 MSP_TUNER, CS53L32A_IN0 },
+               { IVTV_CARD_INPUT_LINE_IN1,
+                 MSP_SCART1, CS53L32A_IN2 },
+       },
+       /* This card has no eeprom and in fact the Windows driver relies
+          on the country/region setting of the user to decide which tuner
+          is available. */
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_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,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Adaptec VideOh! AVC-2010 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_avc2010[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0092 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_avc2010 = {
+       .type = IVTV_CARD_AVC2010,
+       .name = "Adaptec VideOh! AVC-2010",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_CS53L32A,
+       .hw_audio_ctrl = IVTV_HW_CS53L32A,
+       .hw_all = IVTV_HW_CS53L32A | IVTV_HW_SAA7115,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_SVIDEO1,    0, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 0, IVTV_SAA71XX_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_LINE_IN1,   CS53L32A_IN2 },
+       },
+       /* Does not have a tuner */
+       .pci_list = ivtv_pci_avc2010,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Nagase Transgear 5000TV card */
+
+static const struct ivtv_card_pci_info ivtv_pci_tg5000tv[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_tg5000tv = {
+       .type = IVTV_CARD_TG5000TV,
+       .name = "Nagase Transgear 5000TV",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7114 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X |
+       IVTV_HW_GPIO,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER |
+                 IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO2 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gr_config = UPD64031A_VERTICAL_EXTERNAL,
+       .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 },
+       .gpio_audio_input  = { .mask = 0x8080, .tuner  = 0x8000, .linein = 0x0080 },
+       .gpio_audio_mute   = { .mask = 0x6000, .mute   = 0x6000 },
+       .gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
+                             .lang1 = 0x0300, .lang2  = 0x0000, .both   = 0x0200 },
+       .gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
+                         .composite = 0x0010, .svideo = 0x0020 },
+       .tuners = {
+               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+       },
+       .pci_list = ivtv_pci_tg5000tv,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AOpen VA2000MAX-SNT6 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_va2000[] = {
+       { PCI_DEVICE_ID_IVTV16, 0, 0xff5f },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_va2000 = {
+       .type = IVTV_CARD_VA2000MAX_SNT6,
+       .name = "AOpen VA2000MAX-SNT6",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD6408X,
+       .hw_audio = IVTV_HW_MSP34XX,
+       .hw_audio_ctrl = IVTV_HW_MSP34XX,
+       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
+                 IVTV_HW_UPD6408X | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
+       },
+       .tuners = {
+               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+       },
+       .pci_list = ivtv_pci_va2000,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPG600GR/Kuroutoshikou CX23416GYC-STVLP cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_cx23416gyc[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN4, 0x0600 },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x0523 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_cx23416gyc = {
+       .type = IVTV_CARD_CX23416GYC,
+       .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO |
+               IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+       .hw_audio = IVTV_HW_SAA717X,
+       .hw_audio_ctrl = IVTV_HW_SAA717X,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER |
+                 IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO3 |
+                                                IVTV_SAA717X_TUNER_FLAG },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
+       },
+       .gr_config = UPD64031A_VERTICAL_EXTERNAL,
+       .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
+       .gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
+                              .composite = 0x0020, .svideo = 0x0020 },
+       .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
+                            .f44100 = 0x4000, .f48000 = 0x8000 },
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+       },
+       .pci_list = ivtv_pci_cx23416gyc,
+       .i2c = &ivtv_i2c_std,
+};
+
+static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
+       .type = IVTV_CARD_CX23416GYC_NOGR,
+       .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR)",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | IVTV_HW_UPD6408X,
+       .hw_audio = IVTV_HW_SAA717X,
+       .hw_audio_ctrl = IVTV_HW_SAA717X,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER |
+                 IVTV_HW_UPD6408X,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 |
+                                                IVTV_SAA717X_TUNER_FLAG },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
+       },
+       .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
+       .gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
+                              .composite = 0x0020, .svideo = 0x0020 },
+       .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
+                            .f44100 = 0x4000, .f48000 = 0x8000 },
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+       },
+       .i2c = &ivtv_i2c_std,
+};
+
+static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
+       .type = IVTV_CARD_CX23416GYC_NOGRYCS,
+       .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR/YCS)",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO,
+       .hw_audio = IVTV_HW_SAA717X,
+       .hw_audio_ctrl = IVTV_HW_SAA717X,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 |
+                                                IVTV_SAA717X_TUNER_FLAG },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
+       },
+       .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
+       .gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
+                              .composite = 0x0020, .svideo = 0x0020 },
+       .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
+                            .f44100 = 0x4000, .f48000 = 0x8000 },
+       .tuners = {
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+       },
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* I/O Data GV-MVP/RX & GV-MVP/RX2W (dual tuner) cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd01e },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd038 }, /* 2W unit #1 */
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd039 }, /* 2W unit #2 */
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_gv_mvprx = {
+       .type = IVTV_CARD_GV_MVPRX,
+       .name = "I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_WM8739,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_VP27SMPX |
+                 IVTV_HW_TUNER | IVTV_HW_WM8739 |
+                 IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO1    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2    },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 },
+       .gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
+       .tuners = {
+               /* This card has the Panasonic VP27 tuner */
+               { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
+       },
+       .pci_list = ivtv_pci_gv_mvprx,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* I/O Data GV-MVP/RX2E card */
+
+static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx2e[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd025 },
+       {0, 0, 0}
+};
+
+static const struct ivtv_card ivtv_card_gv_mvprx2e = {
+       .type = IVTV_CARD_GV_MVPRX2E,
+       .name = "I/O Data GV-MVP/RX2E",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_WM8739,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+                 IVTV_HW_VP27SMPX | IVTV_HW_WM8739,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 },
+       .gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
+       .tuners = {
+               /* This card has the Panasonic VP27 tuner */
+               { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
+       },
+       .pci_list = ivtv_pci_gv_mvprx2e,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* GotVIEW PCI DVD card */
+
+static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
+       .type = IVTV_CARD_GOTVIEW_PCI_DVD,
+       .name = "GotView PCI DVD",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA717X,
+       .hw_audio = IVTV_HW_SAA717X,
+       .hw_audio_ctrl = IVTV_HW_SAA717X,
+       .hw_all = IVTV_HW_SAA717X | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE1 },  /* pin 116 */
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0 },     /* pin 114/109 */
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },  /* pin 118 */
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN0 },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN2 },
+       },
+       .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
+       .tuners = {
+               /* This card has a Philips FQ1216ME MK3 tuner */
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+       },
+       .pci_list = ivtv_pci_gotview_pci_dvd,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* GotVIEW PCI DVD2 Deluxe card */
+
+static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd2[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW1, 0x0600 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
+       .type = IVTV_CARD_GOTVIEW_PCI_DVD2,
+       .name = "GotView PCI DVD2 Deluxe",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_muxer = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1,
+                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+       .gpio_init = { .direction = 0x0800, .initial_value = 0 },
+       .gpio_audio_input  = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
+       .tuners = {
+               /* This card has a Philips FQ1216ME MK5 tuner */
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+       },
+       .pci_list = ivtv_pci_gotview_pci_dvd2,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPC622 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_yuan_mpc622[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN2, 0xd998 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_yuan_mpc622 = {
+       .type = IVTV_CARD_YUAN_MPC622,
+       .name = "Yuan MPC622",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1,
+                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+       },
+       .gpio_init = { .direction = 0x00ff, .initial_value = 0x0002 },
+       .tuners = {
+               /* This card has the TDA8290/TDA8275 tuner chips */
+               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_TDA8290 },
+       },
+       .pci_list = ivtv_pci_yuan_mpc622,
+       .i2c = &ivtv_i2c_tda8290,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* DIGITAL COWBOY DCT-MTVP1 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_dctmvtvp1[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_dctmvtvp1 = {
+       .type = IVTV_CARD_DCTMTVP1,
+       .name = "Digital Cowboy DCT-MTVP1",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X |
+               IVTV_HW_GPIO,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+               IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0    },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO2    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 },
+       .gpio_audio_input  = { .mask = 0x8080, .tuner  = 0x8000, .linein = 0x0080 },
+       .gpio_audio_mute   = { .mask = 0x6000, .mute   = 0x6000 },
+       .gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
+                             .lang1 = 0x0300, .lang2  = 0x0000, .both   = 0x0200 },
+       .gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
+                              .composite = 0x0010, .svideo = 0x0020},
+       .tuners = {
+               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+       },
+       .pci_list = ivtv_pci_dctmvtvp1,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan PG600-2/GotView PCI DVD Lite cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW2,  0x0600 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_pg600v2 = {
+       .type = IVTV_CARD_PG600V2,
+       .name = "Yuan PG600-2, GotView PCI DVD Lite",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+       /* XC2028 support apparently works for the Yuan, it's still
+          uncertain whether it also works with the GotView. */
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1,
+                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+       .xceive_pin = 12,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .pci_list = ivtv_pci_pg600v2,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Club3D ZAP-TV1x01 cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_club3d[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_club3d = {
+       .type = IVTV_CARD_CLUB3D,
+       .name = "Club3D ZAP-TV1x01",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1,
+                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+       .xceive_pin = 12,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .pci_list = ivtv_pci_club3d,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerTV MCE 116 Plus (M116) card */
+
+static const struct ivtv_card_pci_info ivtv_pci_avertv_mce116[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc439 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_avertv_mce116 = {
+       .type = IVTV_CARD_AVERTV_MCE116,
+       .name = "AVerTV MCE 116 Plus",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739 |
+                 IVTV_HW_I2C_IR_RX_AVER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5 },
+       /* enable line-in */
+       .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
+       .xceive_pin = 10,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .pci_list = ivtv_pci_avertv_mce116,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia PVR-150 Plus / AVerTV M113 cards with a Daewoo/Partsnic Tuner */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_pvr150[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc034 }, /* NTSC */
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc035 }, /* NTSC FM */
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_pvr150 = {
+       .type = IVTV_CARD_AVER_PVR150PLUS,
+       .name = "AVerMedia PVR-150 Plus / AVerTV M113 Partsnic (Daewoo) Tuner",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_muxer = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER |
+                 IVTV_HW_WM8739 | IVTV_HW_GPIO,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+       /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */
+       .gpio_init = { .direction = 0xc000, .initial_value = 0 },
+       .gpio_audio_input  = { .mask   = 0xc000,
+                              .tuner  = 0x0000,
+                              .linein = 0x4000,
+                              .radio  = 0x8000 },
+       .tuners = {
+               /* Subsystem ID's 0xc03[45] have a Partsnic PTI-5NF05 tuner */
+               { .std = V4L2_STD_MN, .tuner = TUNER_PARTSNIC_PTI_5NF05 },
+       },
+       .pci_list = ivtv_pci_aver_pvr150,
+       /* Subsystem ID 0xc035 has a TEA5767(?) FM tuner, 0xc034 does not */
+       .i2c = &ivtv_i2c_radio,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, /* NTSC */
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc01b }, /* PAL/SECAM */
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_ultra1500mce = {
+       .type = IVTV_CARD_AVER_ULTRA1500MCE,
+       .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner",
+       .comment = "For non-NTSC tuners, use the pal= or secam= module options",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_muxer = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER |
+                 IVTV_HW_WM8739 | IVTV_HW_GPIO,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+       /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */
+       .gpio_init = { .direction = 0xc000, .initial_value = 0 },
+       .gpio_audio_input  = { .mask   = 0xc000,
+                              .tuner  = 0x0000,
+                              .linein = 0x4000,
+                              .radio  = 0x8000 },
+       .tuners = {
+               /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */
+               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216MK5 },
+       },
+       .pci_list = ivtv_pci_aver_ultra1500mce,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia EZMaker PCI Deluxe card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_ezmaker[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc03f },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_ezmaker = {
+       .type = IVTV_CARD_AVER_EZMAKER,
+       .name = "AVerMedia EZMaker PCI Deluxe",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 0 },
+       },
+       .gpio_init = { .direction = 0x4000, .initial_value = 0x4000 },
+       /* Does not have a tuner */
+       .pci_list = ivtv_pci_aver_ezmaker,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* ASUS Falcon2 */
+
+static const struct ivtv_card_pci_info ivtv_pci_asus_falcon2[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b66 },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x462e },
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b2e },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_asus_falcon2 = {
+       .type = IVTV_CARD_ASUS_FALCON2,
+       .name = "ASUS Falcon2",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_muxer = IVTV_HW_M52790,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_M52790 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 2, CX25840_COMPOSITE2 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, M52790_IN_TUNER },
+               { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL,
+                       M52790_IN_V2 | M52790_SW1_YCMIX | M52790_SW2_YCMIX },
+               { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, M52790_IN_V2 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
+       .tuners = {
+               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+       },
+       .pci_list = ivtv_pci_asus_falcon2,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M104 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_m104 = {
+       .type = IVTV_CARD_AVER_M104,
+       .name = "AVerMedia M104",
+       .comment = "Not yet supported!\n",
+       .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3    },
+               { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+       },
+       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+       /* enable line-in + reset tuner */
+       .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
+       .xceive_pin = 10,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .pci_list = ivtv_pci_aver_m104,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Buffalo PC-MV5L/PCI cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_buffalo[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x052b },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_buffalo = {
+       .type = IVTV_CARD_BUFFALO_MV5L,
+       .name = "Buffalo PC-MV5L/PCI",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_CX25840,
+       .hw_audio = IVTV_HW_CX25840,
+       .hw_audio_ctrl = IVTV_HW_CX25840,
+       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+       .video_inputs = {
+               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+               { IVTV_CARD_INPUT_SVIDEO1,    1,
+                       CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+       },
+       .audio_inputs = {
+               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+       },
+       .xceive_pin = 12,
+       .tuners = {
+               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+       },
+       .pci_list = ivtv_pci_buffalo,
+       .i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+/* Sony Kikyou */
+
+static const struct ivtv_card_pci_info ivtv_pci_kikyou[] = {
+       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_SONY, 0x813d },
+       { 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_kikyou = {
+       .type = IVTV_CARD_KIKYOU,
+       .name = "Sony VAIO Giga Pocket (ENX Kikyou)",
+       .v4l2_capabilities = IVTV_CAP_ENCODER,
+       .hw_video = IVTV_HW_SAA7115,
+       .hw_audio = IVTV_HW_GPIO,
+       .hw_audio_ctrl = IVTV_HW_GPIO,
+       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER,
+       .video_inputs = {
+       { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE1 },
+       { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE1 },
+       { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO1 },
+       },
+       .audio_inputs = {
+            { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER },
+            { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+            { IVTV_CARD_INPUT_LINE_IN2,   IVTV_GPIO_LINE_IN },
+       },
+       .gpio_init = { .direction = 0x03e1, .initial_value = 0x0320 },
+       .gpio_audio_input = { .mask   = 0x0060,
+                             .tuner  = 0x0020,
+                             .linein = 0x0000,
+                             .radio  = 0x0060 },
+       .gpio_audio_mute  = { .mask = 0x0000,
+                             .mute = 0x0000 }, /* 0x200? Disable for now. */
+       .gpio_audio_mode  = { .mask   = 0x0080,
+                             .mono   = 0x0000,
+                             .stereo = 0x0000, /* SAP */
+                             .lang1  = 0x0080,
+                             .lang2  = 0x0000,
+                             .both   = 0x0080 },
+       .tuners = {
+            { .std = V4L2_STD_ALL, .tuner = TUNER_SONY_BTF_PXN01Z },
+       },
+       .pci_list = ivtv_pci_kikyou,
+       .i2c = &ivtv_i2c_std,
+};
+
+
+static const struct ivtv_card *ivtv_card_list[] = {
+       &ivtv_card_pvr250,
+       &ivtv_card_pvr350,
+       &ivtv_card_pvr150,
+       &ivtv_card_m179,
+       &ivtv_card_mpg600,
+       &ivtv_card_mpg160,
+       &ivtv_card_pg600,
+       &ivtv_card_avc2410,
+       &ivtv_card_avc2010,
+       &ivtv_card_tg5000tv,
+       &ivtv_card_va2000,
+       &ivtv_card_cx23416gyc,
+       &ivtv_card_gv_mvprx,
+       &ivtv_card_gv_mvprx2e,
+       &ivtv_card_gotview_pci_dvd,
+       &ivtv_card_gotview_pci_dvd2,
+       &ivtv_card_yuan_mpc622,
+       &ivtv_card_dctmvtvp1,
+       &ivtv_card_pg600v2,
+       &ivtv_card_club3d,
+       &ivtv_card_avertv_mce116,
+       &ivtv_card_asus_falcon2,
+       &ivtv_card_aver_pvr150,
+       &ivtv_card_aver_ezmaker,
+       &ivtv_card_aver_m104,
+       &ivtv_card_buffalo,
+       &ivtv_card_aver_ultra1500mce,
+       &ivtv_card_kikyou,
+
+       /* Variations of standard cards but with the same PCI IDs.
+          These cards must come last in this list. */
+       &ivtv_card_pvr350_v1,
+       &ivtv_card_cx23416gyc_nogr,
+       &ivtv_card_cx23416gyc_nogrycs,
+};
+
+const struct ivtv_card *ivtv_get_card(u16 index)
+{
+       if (index >= ARRAY_SIZE(ivtv_card_list))
+               return NULL;
+       return ivtv_card_list[index];
+}
+
+int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
+{
+       const struct ivtv_card_video_input *card_input = itv->card->video_inputs + index;
+       static const char * const input_strs[] = {
+               "Tuner 1",
+               "S-Video 1",
+               "S-Video 2",
+               "Composite 1",
+               "Composite 2",
+               "Composite 3"
+       };
+
+       if (index >= itv->nof_inputs)
+               return -EINVAL;
+       input->index = index;
+       strlcpy(input->name, input_strs[card_input->video_type - 1],
+                       sizeof(input->name));
+       input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
+                       V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+       input->audioset = (1 << itv->nof_audio_inputs) - 1;
+       input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
+                               itv->tuner_std : V4L2_STD_ALL;
+       return 0;
+}
+
+int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
+{
+       const struct ivtv_card_output *card_output = itv->card->video_outputs + index;
+
+       if (index >= itv->card->nof_outputs)
+               return -EINVAL;
+       output->index = index;
+       strlcpy(output->name, card_output->name, sizeof(output->name));
+       output->type = V4L2_OUTPUT_TYPE_ANALOG;
+       output->audioset = 1;
+       output->std = V4L2_STD_ALL;
+       return 0;
+}
+
+int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
+{
+       const struct ivtv_card_audio_input *aud_input = itv->card->audio_inputs + index;
+       static const char * const input_strs[] = {
+               "Tuner 1",
+               "Line In 1",
+               "Line In 2"
+       };
+
+       memset(audio, 0, sizeof(*audio));
+       if (index >= itv->nof_audio_inputs)
+               return -EINVAL;
+       strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+                       sizeof(audio->name));
+       audio->index = index;
+       audio->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
+
+int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud_output)
+{
+       memset(aud_output, 0, sizeof(*aud_output));
+       if (itv->card->video_outputs == NULL || index != 0)
+               return -EINVAL;
+       strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
+       return 0;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-cards.h b/drivers/media/pci/ivtv/ivtv-cards.h
new file mode 100644 (file)
index 0000000..e6f5c02
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+    Functions to query card hardware
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_CARDS_H
+#define IVTV_CARDS_H
+
+/* Supported cards */
+#define IVTV_CARD_PVR_250            0 /* WinTV PVR 250 */
+#define IVTV_CARD_PVR_350            1 /* encoder, decoder, tv-out */
+#define IVTV_CARD_PVR_150            2 /* WinTV PVR 150 and PVR 500 (really just two
+                                          PVR150s on one PCI board) */
+#define IVTV_CARD_M179               3 /* AVerMedia M179 (encoder only) */
+#define IVTV_CARD_MPG600             4 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */
+#define IVTV_CARD_MPG160             5 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160
+                                          cx23415 based, but does not have tv-out */
+#define IVTV_CARD_PG600              6 /* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */
+#define IVTV_CARD_AVC2410            7 /* Adaptec AVC-2410 */
+#define IVTV_CARD_AVC2010            8 /* Adaptec AVD-2010 (No Tuner) */
+#define IVTV_CARD_TG5000TV           9 /* NAGASE TRANSGEAR 5000TV, encoder only */
+#define IVTV_CARD_VA2000MAX_SNT6     10 /* VA2000MAX-STN6 */
+#define IVTV_CARD_CX23416GYC        11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */
+#define IVTV_CARD_GV_MVPRX          12 /* I/O Data GV-MVP/RX, RX2, RX2W */
+#define IVTV_CARD_GV_MVPRX2E        13 /* I/O Data GV-MVP/RX2E */
+#define IVTV_CARD_GOTVIEW_PCI_DVD    14        /* GotView PCI DVD */
+#define IVTV_CARD_GOTVIEW_PCI_DVD2   15        /* GotView PCI DVD2 */
+#define IVTV_CARD_YUAN_MPC622        16        /* Yuan MPC622 miniPCI */
+#define IVTV_CARD_DCTMTVP1          17 /* DIGITAL COWBOY DCT-MTVP1 */
+#define IVTV_CARD_PG600V2           18 /* Yuan PG600V2/GotView PCI DVD Lite */
+#define IVTV_CARD_CLUB3D            19 /* Club3D ZAP-TV1x01 */
+#define IVTV_CARD_AVERTV_MCE116             20 /* AVerTV MCE 116 Plus */
+#define IVTV_CARD_ASUS_FALCON2      21 /* ASUS Falcon2 */
+#define IVTV_CARD_AVER_PVR150PLUS    22 /* AVerMedia PVR-150 Plus */
+#define IVTV_CARD_AVER_EZMAKER       23 /* AVerMedia EZMaker PCI Deluxe */
+#define IVTV_CARD_AVER_M104          24 /* AverMedia M104 miniPCI card */
+#define IVTV_CARD_BUFFALO_MV5L       25 /* Buffalo PC-MV5L/PCI card */
+#define IVTV_CARD_AVER_ULTRA1500MCE  26 /* AVerMedia UltraTV 1500 MCE */
+#define IVTV_CARD_KIKYOU             27 /* Sony VAIO Giga Pocket (ENX Kikyou) */
+#define IVTV_CARD_LAST                      27
+
+/* Variants of existing cards but with the same PCI IDs. The driver
+   detects these based on other device information.
+   These cards must always come last.
+   New cards must be inserted above, and the indices of the cards below
+   must be adjusted accordingly. */
+
+/* PVR-350 V1 (uses saa7114) */
+#define IVTV_CARD_PVR_350_V1        (IVTV_CARD_LAST+1)
+/* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */
+#define IVTV_CARD_CX23416GYC_NOGR    (IVTV_CARD_LAST+2)
+#define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3)
+
+/* system vendor and device IDs */
+#define PCI_VENDOR_ID_ICOMP  0x4444
+#define PCI_DEVICE_ID_IVTV15 0x0803
+#define PCI_DEVICE_ID_IVTV16 0x0016
+
+/* subsystem vendor ID */
+#define IVTV_PCI_ID_HAUPPAUGE          0x0070
+#define IVTV_PCI_ID_HAUPPAUGE_ALT1     0x0270
+#define IVTV_PCI_ID_HAUPPAUGE_ALT2     0x4070
+#define IVTV_PCI_ID_ADAPTEC            0x9005
+#define IVTV_PCI_ID_ASUSTEK            0x1043
+#define IVTV_PCI_ID_AVERMEDIA          0x1461
+#define IVTV_PCI_ID_YUAN1              0x12ab
+#define IVTV_PCI_ID_YUAN2              0xff01
+#define IVTV_PCI_ID_YUAN3              0xffab
+#define IVTV_PCI_ID_YUAN4              0xfbab
+#define IVTV_PCI_ID_DIAMONDMM          0xff92
+#define IVTV_PCI_ID_IODATA             0x10fc
+#define IVTV_PCI_ID_MELCO              0x1154
+#define IVTV_PCI_ID_GOTVIEW1           0xffac
+#define IVTV_PCI_ID_GOTVIEW2           0xffad
+#define IVTV_PCI_ID_SONY               0x104d
+
+/* hardware flags, no gaps allowed */
+#define IVTV_HW_CX25840                        (1 << 0)
+#define IVTV_HW_SAA7115                        (1 << 1)
+#define IVTV_HW_SAA7127                        (1 << 2)
+#define IVTV_HW_MSP34XX                        (1 << 3)
+#define IVTV_HW_TUNER                  (1 << 4)
+#define IVTV_HW_WM8775                 (1 << 5)
+#define IVTV_HW_CS53L32A               (1 << 6)
+#define IVTV_HW_TVEEPROM               (1 << 7)
+#define IVTV_HW_SAA7114                        (1 << 8)
+#define IVTV_HW_UPD64031A              (1 << 9)
+#define IVTV_HW_UPD6408X               (1 << 10)
+#define IVTV_HW_SAA717X                        (1 << 11)
+#define IVTV_HW_WM8739                 (1 << 12)
+#define IVTV_HW_VP27SMPX               (1 << 13)
+#define IVTV_HW_M52790                 (1 << 14)
+#define IVTV_HW_GPIO                   (1 << 15)
+#define IVTV_HW_I2C_IR_RX_AVER         (1 << 16)
+#define IVTV_HW_I2C_IR_RX_HAUP_EXT     (1 << 17) /* External before internal */
+#define IVTV_HW_I2C_IR_RX_HAUP_INT     (1 << 18)
+#define IVTV_HW_Z8F0811_IR_TX_HAUP     (1 << 19)
+#define IVTV_HW_Z8F0811_IR_RX_HAUP     (1 << 20)
+#define IVTV_HW_I2C_IR_RX_ADAPTEC      (1 << 21)
+
+#define IVTV_HW_Z8F0811_IR_HAUP        (IVTV_HW_Z8F0811_IR_RX_HAUP | \
+                                IVTV_HW_Z8F0811_IR_TX_HAUP)
+
+#define IVTV_HW_SAA711X   (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)
+
+#define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \
+                          IVTV_HW_I2C_IR_RX_HAUP_EXT | \
+                          IVTV_HW_I2C_IR_RX_HAUP_INT | \
+                          IVTV_HW_Z8F0811_IR_RX_HAUP | \
+                          IVTV_HW_I2C_IR_RX_ADAPTEC)
+
+#define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP)
+
+#define IVTV_HW_IR_ANY   (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY)
+
+/* video inputs */
+#define        IVTV_CARD_INPUT_VID_TUNER       1
+#define        IVTV_CARD_INPUT_SVIDEO1         2
+#define        IVTV_CARD_INPUT_SVIDEO2         3
+#define        IVTV_CARD_INPUT_COMPOSITE1      4
+#define        IVTV_CARD_INPUT_COMPOSITE2      5
+#define        IVTV_CARD_INPUT_COMPOSITE3      6
+
+/* audio inputs */
+#define        IVTV_CARD_INPUT_AUD_TUNER       1
+#define        IVTV_CARD_INPUT_LINE_IN1        2
+#define        IVTV_CARD_INPUT_LINE_IN2        3
+
+#define IVTV_CARD_MAX_VIDEO_INPUTS 6
+#define IVTV_CARD_MAX_AUDIO_INPUTS 3
+#define IVTV_CARD_MAX_TUNERS      3
+
+/* SAA71XX HW inputs */
+#define IVTV_SAA71XX_COMPOSITE0 0
+#define IVTV_SAA71XX_COMPOSITE1 1
+#define IVTV_SAA71XX_COMPOSITE2 2
+#define IVTV_SAA71XX_COMPOSITE3 3
+#define IVTV_SAA71XX_COMPOSITE4 4
+#define IVTV_SAA71XX_COMPOSITE5 5
+#define IVTV_SAA71XX_SVIDEO0    6
+#define IVTV_SAA71XX_SVIDEO1    7
+#define IVTV_SAA71XX_SVIDEO2    8
+#define IVTV_SAA71XX_SVIDEO3    9
+
+/* SAA717X needs to mark the tuner input by ORing with this flag */
+#define IVTV_SAA717X_TUNER_FLAG 0x80
+
+/* Dummy HW input */
+#define IVTV_DUMMY_AUDIO        0
+
+/* GPIO HW inputs */
+#define IVTV_GPIO_TUNER   0
+#define IVTV_GPIO_LINE_IN 1
+
+/* SAA717X HW inputs */
+#define IVTV_SAA717X_IN0 0
+#define IVTV_SAA717X_IN1 1
+#define IVTV_SAA717X_IN2 2
+
+/* V4L2 capability aliases */
+#define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
+                         V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
+                         V4L2_CAP_SLICED_VBI_CAPTURE)
+#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \
+                         V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+
+struct ivtv_card_video_input {
+       u8  video_type;         /* video input type */
+       u8  audio_index;        /* index in ivtv_card_audio_input array */
+       u16 video_input;        /* hardware video input */
+};
+
+struct ivtv_card_audio_input {
+       u8  audio_type;         /* audio input type */
+       u32 audio_input;        /* hardware audio input */
+       u16 muxer_input;        /* hardware muxer input for boards with a
+                                  multiplexer chip */
+};
+
+struct ivtv_card_output {
+       u8  name[32];
+       u16 video_output;  /* hardware video output */
+};
+
+struct ivtv_card_pci_info {
+       u16 device;
+       u16 subsystem_vendor;
+       u16 subsystem_device;
+};
+
+/* GPIO definitions */
+
+/* The mask is the set of bits used by the operation */
+
+struct ivtv_gpio_init {        /* set initial GPIO DIR and OUT values */
+       u16 direction;          /* DIR setting. Leave to 0 if no init is needed */
+       u16 initial_value;
+};
+
+struct ivtv_gpio_video_input {         /* select tuner/line in input */
+       u16 mask;               /* leave to 0 if not supported */
+       u16 tuner;
+       u16 composite;
+       u16 svideo;
+};
+
+struct ivtv_gpio_audio_input {         /* select tuner/line in input */
+       u16 mask;               /* leave to 0 if not supported */
+       u16 tuner;
+       u16 linein;
+       u16 radio;
+};
+
+struct ivtv_gpio_audio_mute {
+       u16 mask;               /* leave to 0 if not supported */
+       u16 mute;               /* set this value to mute, 0 to unmute */
+};
+
+struct ivtv_gpio_audio_mode {
+       u16 mask;               /* leave to 0 if not supported */
+       u16 mono;               /* set audio to mono */
+       u16 stereo;             /* set audio to stereo */
+       u16 lang1;              /* set audio to the first language */
+       u16 lang2;              /* set audio to the second language */
+       u16 both;               /* both languages are output */
+};
+
+struct ivtv_gpio_audio_freq {
+       u16 mask;               /* leave to 0 if not supported */
+       u16 f32000;
+       u16 f44100;
+       u16 f48000;
+};
+
+struct ivtv_gpio_audio_detect {
+       u16 mask;               /* leave to 0 if not supported */
+       u16 stereo;             /* if the input matches this value then
+                                  stereo is detected */
+};
+
+struct ivtv_card_tuner {
+       v4l2_std_id std;        /* standard for which the tuner is suitable */
+       int         tuner;      /* tuner ID (from tuner.h) */
+};
+
+struct ivtv_card_tuner_i2c {
+       unsigned short radio[2];/* radio tuner i2c address to probe */
+       unsigned short demod[2];/* demodulator i2c address to probe */
+       unsigned short tv[4];   /* tv tuner i2c addresses to probe */
+};
+
+/* for card information/parameters */
+struct ivtv_card {
+       int type;
+       char *name;
+       char *comment;
+       u32 v4l2_capabilities;
+       u32 hw_video;           /* hardware used to process video */
+       u32 hw_audio;           /* hardware used to process audio */
+       u32 hw_audio_ctrl;      /* hardware used for the V4L2 controls (only 1 dev allowed) */
+       u32 hw_muxer;           /* hardware used to multiplex audio input */
+       u32 hw_all;             /* all hardware used by the board */
+       struct ivtv_card_video_input video_inputs[IVTV_CARD_MAX_VIDEO_INPUTS];
+       struct ivtv_card_audio_input audio_inputs[IVTV_CARD_MAX_AUDIO_INPUTS];
+       struct ivtv_card_audio_input radio_input;
+       int nof_outputs;
+       const struct ivtv_card_output *video_outputs;
+       u8 gr_config;           /* config byte for the ghost reduction device */
+       u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
+
+       /* GPIO card-specific settings */
+       struct ivtv_gpio_init           gpio_init;
+       struct ivtv_gpio_video_input    gpio_video_input;
+       struct ivtv_gpio_audio_input    gpio_audio_input;
+       struct ivtv_gpio_audio_mute     gpio_audio_mute;
+       struct ivtv_gpio_audio_mode     gpio_audio_mode;
+       struct ivtv_gpio_audio_freq     gpio_audio_freq;
+       struct ivtv_gpio_audio_detect   gpio_audio_detect;
+
+       struct ivtv_card_tuner tuners[IVTV_CARD_MAX_TUNERS];
+       struct ivtv_card_tuner_i2c *i2c;
+
+       /* list of device and subsystem vendor/devices that
+          correspond to this card type. */
+       const struct ivtv_card_pci_info *pci_list;
+};
+
+int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input);
+int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output);
+int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input);
+int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output);
+const struct ivtv_card *ivtv_get_card(u16 index);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
new file mode 100644 (file)
index 0000000..c604246
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+    ioctl control functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-controls.h"
+#include "ivtv-mailbox.h"
+
+static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
+{
+       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+
+       /* First try to allocate sliced VBI buffers if needed. */
+       if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) {
+               int i;
+
+               for (i = 0; i < IVTV_VBI_FRAMES; i++) {
+                       /* Yuck, hardcoded. Needs to be a define */
+                       itv->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
+                       if (itv->vbi.sliced_mpeg_data[i] == NULL) {
+                               while (--i >= 0) {
+                                       kfree(itv->vbi.sliced_mpeg_data[i]);
+                                       itv->vbi.sliced_mpeg_data[i] = NULL;
+                               }
+                               return -ENOMEM;
+                       }
+               }
+       }
+
+       itv->vbi.insert_mpeg = fmt;
+
+       if (itv->vbi.insert_mpeg == 0) {
+               return 0;
+       }
+       /* Need sliced data for mpeg insertion */
+       if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) {
+               if (itv->is_60hz)
+                       itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
+               else
+                       itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
+               ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz);
+       }
+       return 0;
+}
+
+static int ivtv_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
+{
+       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+       int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+       struct v4l2_mbus_framefmt fmt;
+
+       /* fix videodecoder resolution */
+       fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+       fmt.height = cxhdl->height;
+       fmt.code = V4L2_MBUS_FMT_FIXED;
+       v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
+       return 0;
+}
+
+static int ivtv_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
+{
+       static const u32 freqs[3] = { 44100, 48000, 32000 };
+       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+
+       /* The audio clock of the digitizer must match the codec sample
+          rate otherwise you get some very strange effects. */
+       if (idx < ARRAY_SIZE(freqs))
+               ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
+       return 0;
+}
+
+static int ivtv_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
+{
+       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+
+       itv->dualwatch_stereo_mode = val;
+       return 0;
+}
+
+struct cx2341x_handler_ops ivtv_cxhdl_ops = {
+       .s_audio_mode = ivtv_s_audio_mode,
+       .s_audio_sampling_freq = ivtv_s_audio_sampling_freq,
+       .s_video_encoding = ivtv_s_video_encoding,
+       .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt,
+};
+
+int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+
+       if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
+               *pts = (s64)((u64)itv->last_dec_timing[2] << 32) |
+                       (u64)itv->last_dec_timing[1];
+               *frame = itv->last_dec_timing[0];
+               return 0;
+       }
+       *pts = 0;
+       *frame = 0;
+       if (atomic_read(&itv->decoding)) {
+               if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
+                       IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
+                       return -EIO;
+               }
+               memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
+               set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
+               *pts = (s64)((u64) data[2] << 32) | (u64) data[1];
+               *frame = data[0];
+               /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
+       }
+       return 0;
+}
+
+static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl);
+
+       switch (ctrl->id) {
+       /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
+          control cluster */
+       case V4L2_CID_MPEG_VIDEO_DEC_PTS:
+               return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
+                                            &itv->ctrl_frame->val64);
+       }
+       return 0;
+}
+
+static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl);
+
+       switch (ctrl->id) {
+       /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK
+          control cluster */
+       case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
+               itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1;
+               itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1;
+               ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
+               break;
+       }
+       return 0;
+}
+
+const struct v4l2_ctrl_ops ivtv_hdl_out_ops = {
+       .s_ctrl = ivtv_s_ctrl,
+       .g_volatile_ctrl = ivtv_g_volatile_ctrl,
+};
diff --git a/drivers/media/pci/ivtv/ivtv-controls.h b/drivers/media/pci/ivtv/ivtv-controls.h
new file mode 100644 (file)
index 0000000..3999e63
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+    ioctl control functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_CONTROLS_H
+#define IVTV_CONTROLS_H
+
+extern struct cx2341x_handler_ops ivtv_cxhdl_ops;
+extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops;
+int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c
new file mode 100644 (file)
index 0000000..5462ce2
--- /dev/null
@@ -0,0 +1,1498 @@
+/*
+    ivtv driver initialization and card probing
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    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
+ */
+
+/* Main Driver file for the ivtv project:
+ * Driver for the Conexant CX23415/CX23416 chip.
+ * Author: Kevin Thayer (nufan_wfk at yahoo.com)
+ * License: GPL
+ * http://www.ivtvdriver.org
+ *
+ * -----
+ * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
+ *                      and Takeru KOMORIYA<komoriya@paken.org>
+ *
+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
+ *                using information provided by Jiun-Kuei Jung @ AVerMedia.
+ *
+ * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp>
+ *                using information from T.Adachi,Takeru KOMORIYA and others :-)
+ *
+ * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX
+ *                version by T.Adachi. Special thanks  Mr.Suzuki
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-version.h"
+#include "ivtv-fileops.h"
+#include "ivtv-i2c.h"
+#include "ivtv-firmware.h"
+#include "ivtv-queue.h"
+#include "ivtv-udma.h"
+#include "ivtv-irq.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-streams.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include "ivtv-vbi.h"
+#include "ivtv-routing.h"
+#include "ivtv-controls.h"
+#include "ivtv-gpio.h"
+#include <linux/dma-mapping.h>
+#include <media/tveeprom.h>
+#include <media/saa7115.h>
+#include <media/v4l2-chip-ident.h>
+#include "tuner-xc2028.h"
+
+/* If you have already X v4l cards, then set this to X. This way
+   the device numbers stay matched. Example: you have a WinTV card
+   without radio and a PVR-350 with. Normally this would give a
+   video1 device together with a radio0 device for the PVR. By
+   setting this to 1 you ensure that radio0 is now also radio1. */
+int ivtv_first_minor;
+
+/* add your revision and whatnot here */
+static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
+       {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16,
+        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+
+MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
+
+/* ivtv instance counter */
+static atomic_t ivtv_instance = ATOMIC_INIT(0);
+
+/* Parameter declarations */
+static int cardtype[IVTV_MAX_CARDS];
+static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1 };
+static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1,
+                                    -1, -1, -1, -1, -1, -1, -1, -1 };
+static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+                                              -1, -1, -1, -1, -1, -1, -1, -1,
+                                              -1, -1, -1, -1, -1, -1, -1, -1,
+                                              -1, -1, -1, -1, -1, -1, -1, -1 };
+
+static unsigned int cardtype_c = 1;
+static unsigned int tuner_c = 1;
+static int radio_c = 1;
+static unsigned int i2c_clock_period_c = 1;
+static char pal[] = "---";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+/* Buffers */
+
+/* DMA Buffers, Default size in MB allocated */
+#define IVTV_DEFAULT_ENC_MPG_BUFFERS 4
+#define IVTV_DEFAULT_ENC_YUV_BUFFERS 2
+#define IVTV_DEFAULT_ENC_VBI_BUFFERS 1
+/* Exception: size in kB for this stream (MB is overkill) */
+#define IVTV_DEFAULT_ENC_PCM_BUFFERS 320
+#define IVTV_DEFAULT_DEC_MPG_BUFFERS 1
+#define IVTV_DEFAULT_DEC_YUV_BUFFERS 1
+/* Exception: size in kB for this stream (MB is way overkill) */
+#define IVTV_DEFAULT_DEC_VBI_BUFFERS 64
+
+static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS;
+static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS;
+static int enc_pcm_buffers = IVTV_DEFAULT_ENC_PCM_BUFFERS;
+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;
+static int ivtv_yuv_threshold = -1;
+static int ivtv_pci_latency = 1;
+
+int ivtv_debug;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int ivtv_fw_debug;
+#endif
+
+static int tunertype = -1;
+static int newi2c = -1;
+
+module_param_array(tuner, int, &tuner_c, 0644);
+module_param_array(radio, int, &radio_c, 0644);
+module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+module_param_named(debug,ivtv_debug, int, 0644);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+module_param_named(fw_debug, ivtv_fw_debug, int, 0644);
+#endif
+module_param(ivtv_pci_latency, int, 0644);
+module_param(ivtv_yuv_mode, int, 0644);
+module_param(ivtv_yuv_threshold, int, 0644);
+module_param(ivtv_first_minor, int, 0644);
+
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_yuv_buffers, int, 0644);
+module_param(enc_vbi_buffers, int, 0644);
+module_param(enc_pcm_buffers, int, 0644);
+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_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644);
+
+MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+                       "\t\t\tsee tuner.h for values");
+MODULE_PARM_DESC(radio,
+                "Enable or disable the radio. Use only if autodetection\n"
+                "\t\t\tfails. 0 = disable, 1 = enable");
+MODULE_PARM_DESC(cardtype,
+                "Only use this option if your card is not detected properly.\n"
+                "\t\tSpecify card type:\n"
+                "\t\t\t 1 = WinTV PVR 250\n"
+                "\t\t\t 2 = WinTV PVR 350\n"
+                "\t\t\t 3 = WinTV PVR-150 or PVR-500\n"
+                "\t\t\t 4 = AVerMedia M179\n"
+                "\t\t\t 5 = YUAN MPG600/Kuroutoshikou iTVC16-STVLP\n"
+                "\t\t\t 6 = YUAN MPG160/Kuroutoshikou iTVC15-STVLP\n"
+                "\t\t\t 7 = YUAN PG600/DIAMONDMM PVR-550 (CX Falcon 2)\n"
+                "\t\t\t 8 = Adaptec AVC-2410\n"
+                "\t\t\t 9 = Adaptec AVC-2010\n"
+                "\t\t\t10 = NAGASE TRANSGEAR 5000TV\n"
+                "\t\t\t11 = AOpen VA2000MAX-STN6\n"
+                "\t\t\t12 = YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP\n"
+                "\t\t\t13 = I/O Data GV-MVP/RX\n"
+                "\t\t\t14 = I/O Data GV-MVP/RX2E\n"
+                "\t\t\t15 = GOTVIEW PCI DVD\n"
+                "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n"
+                "\t\t\t17 = Yuan MPC622\n"
+                "\t\t\t18 = Digital Cowboy DCT-MTVP1\n"
+                "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite\n"
+                "\t\t\t20 = Club3D ZAP-TV1x01\n"
+                "\t\t\t21 = AverTV MCE 116 Plus\n"
+                "\t\t\t22 = ASUS Falcon2\n"
+                "\t\t\t23 = AverMedia PVR-150 Plus\n"
+                "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+                "\t\t\t25 = AverMedia M104 (not yet working)\n"
+                "\t\t\t26 = Buffalo PC-MV5L/PCI\n"
+                "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n"
+                "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\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: 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"
+                "\t\t\t   2/0x0002: info\n"
+                "\t\t\t   4/0x0004: mailbox\n"
+                "\t\t\t   8/0x0008: ioctl\n"
+                "\t\t\t  16/0x0010: file\n"
+                "\t\t\t  32/0x0020: dma\n"
+                "\t\t\t  64/0x0040: irq\n"
+                "\t\t\t 128/0x0080: decoder\n"
+                "\t\t\t 256/0x0100: yuv\n"
+                "\t\t\t 512/0x0200: i2c\n"
+                "\t\t\t1024/0x0400: high volume\n");
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+MODULE_PARM_DESC(fw_debug,
+                "Enable code for debugging firmware problems.  Default: 0\n");
+#endif
+MODULE_PARM_DESC(ivtv_pci_latency,
+                "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
+                "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(ivtv_yuv_mode,
+                "Specify the yuv playback mode:\n"
+                "\t\t\t0 = interlaced\n\t\t\t1 = progressive\n\t\t\t2 = auto\n"
+                "\t\t\tDefault: 0 (interlaced)");
+MODULE_PARM_DESC(ivtv_yuv_threshold,
+                "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n"
+                "\t\t\tDefault: 480");
+MODULE_PARM_DESC(enc_mpg_buffers,
+                "Encoder MPG Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_buffers,
+                "Encoder YUV Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_buffers,
+                "Encoder VBI Buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_buffers,
+                "Encoder PCM buffers (in kB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS));
+MODULE_PARM_DESC(dec_mpg_buffers,
+                "Decoder MPG buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_MPG_BUFFERS));
+MODULE_PARM_DESC(dec_yuv_buffers,
+                "Decoder YUV buffers (in MB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS));
+MODULE_PARM_DESC(dec_vbi_buffers,
+                "Decoder VBI buffers (in kB)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS));
+MODULE_PARM_DESC(newi2c,
+                "Use new I2C implementation\n"
+                "\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
+                "\t\t\tDefault is autodetect");
+MODULE_PARM_DESC(i2c_clock_period,
+                "Period of SCL for the I2C bus controlled by the CX23415/6\n"
+                "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n"
+                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD));
+
+MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card");
+
+MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
+MODULE_DESCRIPTION("CX23415/CX23416 driver");
+MODULE_SUPPORTED_DEVICE
+    ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n"
+               "\t\t\tYuan MPG series and similar)");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(IVTV_VERSION);
+
+void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask)
+{
+       itv->irqmask &= ~mask;
+       write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK);
+}
+
+void ivtv_set_irq_mask(struct ivtv *itv, u32 mask)
+{
+       itv->irqmask |= mask;
+       write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK);
+}
+
+int ivtv_set_output_mode(struct ivtv *itv, int mode)
+{
+    int old_mode;
+
+    spin_lock(&itv->lock);
+    old_mode = itv->output_mode;
+    if (old_mode == 0)
+       itv->output_mode = old_mode = mode;
+    spin_unlock(&itv->lock);
+    return old_mode;
+}
+
+struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv)
+{
+       switch (itv->output_mode) {
+       case OUT_MPG:
+               return &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
+       case OUT_YUV:
+               return &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
+       default:
+               return NULL;
+       }
+}
+
+int ivtv_waitq(wait_queue_head_t *waitq)
+{
+       DEFINE_WAIT(wait);
+
+       prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE);
+       schedule();
+       finish_wait(waitq, &wait);
+       return signal_pending(current) ? -EINTR : 0;
+}
+
+/* Generic utility functions */
+int ivtv_msleep_timeout(unsigned int msecs, int intr)
+{
+       int timeout = msecs_to_jiffies(msecs);
+
+       do {
+               set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+               timeout = schedule_timeout(timeout);
+               if (intr) {
+                       int ret = signal_pending(current);
+
+                       if (ret)
+                               return ret;
+               }
+       } while (timeout);
+       return 0;
+}
+
+/* Release ioremapped memory */
+static void ivtv_iounmap(struct ivtv *itv)
+{
+       if (itv == NULL)
+               return;
+
+       /* Release registers memory */
+       if (itv->reg_mem != NULL) {
+               IVTV_DEBUG_INFO("releasing reg_mem\n");
+               iounmap(itv->reg_mem);
+               itv->reg_mem = NULL;
+       }
+       /* Release io memory */
+       if (itv->has_cx23415 && itv->dec_mem != NULL) {
+               IVTV_DEBUG_INFO("releasing dec_mem\n");
+               iounmap(itv->dec_mem);
+       }
+       itv->dec_mem = NULL;
+
+       /* Release io memory */
+       if (itv->enc_mem != NULL) {
+               IVTV_DEBUG_INFO("releasing enc_mem\n");
+               iounmap(itv->enc_mem);
+               itv->enc_mem = NULL;
+       }
+}
+
+/* Hauppauge card? get values from tveeprom */
+void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
+{
+       u8 eedata[256];
+
+       itv->i2c_client.addr = 0xA0 >> 1;
+       tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata));
+       tveeprom_hauppauge_analog(&itv->i2c_client, tv, eedata);
+}
+
+static void ivtv_process_eeprom(struct ivtv *itv)
+{
+       struct tveeprom tv;
+       int pci_slot = PCI_SLOT(itv->pdev->devfn);
+
+       ivtv_read_eeprom(itv, &tv);
+
+       /* Many thanks to Steven Toth from Hauppauge for providing the
+          model numbers */
+       switch (tv.model) {
+               /* In a few cases the PCI subsystem IDs do not correctly
+                  identify the card. A better method is to check the
+                  model number from the eeprom instead. */
+               case 30012 ... 30039:  /* Low profile PVR250 */
+               case 32000 ... 32999:
+               case 48000 ... 48099:  /* 48??? range are PVR250s with a cx23415 */
+               case 48400 ... 48599:
+                       itv->card = ivtv_get_card(IVTV_CARD_PVR_250);
+                       break;
+               case 48100 ... 48399:
+               case 48600 ... 48999:
+                       itv->card = ivtv_get_card(IVTV_CARD_PVR_350);
+                       break;
+               case 23000 ... 23999:  /* PVR500 */
+               case 25000 ... 25999:  /* Low profile PVR150 */
+               case 26000 ... 26999:  /* Regular PVR150 */
+                       itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
+                       break;
+               case 0:
+                       IVTV_ERR("Invalid EEPROM\n");
+                       return;
+               default:
+                       IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model);
+                       itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
+                       break;
+       }
+
+       switch (tv.model) {
+               /* Old style PVR350 (with an saa7114) uses this input for
+                  the tuner. */
+               case 48254:
+                       itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1);
+                       break;
+               default:
+                       break;
+       }
+
+       itv->v4l2_cap = itv->card->v4l2_capabilities;
+       itv->card_name = itv->card->name;
+       itv->card_i2c = itv->card->i2c;
+
+       /* If this is a PVR500 then it should be possible to detect whether it is the
+          first or second unit by looking at the subsystem device ID: is bit 4 is
+          set, then it is the second unit (according to info from Hauppauge).
+
+          However, while this works for most cards, I have seen a few PVR500 cards
+          where both units have the same subsystem ID.
+
+          So instead I look at the reported 'PCI slot' (which is the slot on the PVR500
+          PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise
+          it is the second unit. It is possible that it is a different slot when ivtv is
+          used in Xen, in that case I ignore this card here. The worst that can happen
+          is that the card presents itself with a non-working radio device.
+
+          This detection is needed since the eeprom reports incorrectly that a radio is
+          present on the second unit. */
+       if (tv.model / 1000 == 23) {
+               static const struct ivtv_card_tuner_i2c ivtv_i2c_radio = {
+                       .radio = { 0x60, I2C_CLIENT_END },
+                       .demod = { 0x43, I2C_CLIENT_END },
+                       .tv = { 0x61, I2C_CLIENT_END },
+               };
+
+               itv->card_name = "WinTV PVR 500";
+               itv->card_i2c = &ivtv_i2c_radio;
+               if (pci_slot == 8 || pci_slot == 9) {
+                       int is_first = (pci_slot & 1) == 0;
+
+                       itv->card_name = is_first ? "WinTV PVR 500 (unit #1)" :
+                                                   "WinTV PVR 500 (unit #2)";
+                       if (!is_first) {
+                               IVTV_INFO("Correcting tveeprom data: no radio present on second unit\n");
+                               tv.has_radio = 0;
+                       }
+               }
+       }
+       IVTV_INFO("Autodetected %s\n", itv->card_name);
+
+       switch (tv.tuner_hauppauge_model) {
+               case 85:
+               case 99:
+               case 112:
+                       itv->pvr150_workaround = 1;
+                       break;
+               default:
+                       break;
+       }
+       if (tv.tuner_type == TUNER_ABSENT)
+               IVTV_ERR("tveeprom cannot autodetect tuner!\n");
+
+       if (itv->options.tuner == -1)
+               itv->options.tuner = tv.tuner_type;
+       if (itv->options.radio == -1)
+               itv->options.radio = (tv.has_radio != 0);
+       /* only enable newi2c if an IR blaster is present */
+       if (itv->options.newi2c == -1 && tv.has_ir) {
+               itv->options.newi2c = (tv.has_ir & 4) ? 1 : 0;
+               if (itv->options.newi2c) {
+                   IVTV_INFO("Reopen i2c bus for IR-blaster support\n");
+                   exit_ivtv_i2c(itv);
+                   init_ivtv_i2c(itv);
+               }
+       }
+
+       if (itv->std != 0)
+               /* user specified tuner standard */
+               return;
+
+       /* autodetect tuner standard */
+       if (tv.tuner_formats & V4L2_STD_PAL) {
+               IVTV_DEBUG_INFO("PAL tuner detected\n");
+               itv->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+       } else if (tv.tuner_formats & V4L2_STD_NTSC) {
+               IVTV_DEBUG_INFO("NTSC tuner detected\n");
+               itv->std |= V4L2_STD_NTSC_M;
+       } else if (tv.tuner_formats & V4L2_STD_SECAM) {
+               IVTV_DEBUG_INFO("SECAM tuner detected\n");
+               itv->std |= V4L2_STD_SECAM_L;
+       } else {
+               IVTV_INFO("No tuner detected, default to NTSC-M\n");
+               itv->std |= V4L2_STD_NTSC_M;
+       }
+}
+
+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':
+               case 'h':
+               case '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;
+               default:
+                       IVTV_WARN("pal= argument not recognised\n");
+                       return 0;
+       }
+
+       switch (secam[0]) {
+               case 'b':
+               case 'B':
+               case 'g':
+               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;
+               case '-':
+                       break;
+               default:
+                       IVTV_WARN("secam= argument not recognised\n");
+                       return 0;
+       }
+
+       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;
+               default:
+                       IVTV_WARN("ntsc= argument not recognised\n");
+                       return 0;
+       }
+
+       /* no match found */
+       return 0;
+}
+
+static void ivtv_process_options(struct ivtv *itv)
+{
+       const char *chipname;
+       int i, j;
+
+       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers * 1024;
+       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers * 1024;
+       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers * 1024;
+       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+       itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024;
+       itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024;
+       itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers;
+       itv->options.cardtype = cardtype[itv->instance];
+       itv->options.tuner = tuner[itv->instance];
+       itv->options.radio = radio[itv->instance];
+
+       itv->options.i2c_clock_period = i2c_clock_period[itv->instance];
+       if (itv->options.i2c_clock_period == -1)
+               itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD;
+       else if (itv->options.i2c_clock_period < 10)
+               itv->options.i2c_clock_period = 10;
+       else if (itv->options.i2c_clock_period > 4500)
+               itv->options.i2c_clock_period = 4500;
+
+       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->pdev->device == PCI_DEVICE_ID_IVTV15);
+       chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
+       if (itv->options.cardtype == -1) {
+               IVTV_INFO("Ignore card (detected %s based chip)\n", chipname);
+               return;
+       }
+       if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) {
+               IVTV_INFO("User specified %s card (detected %s based chip)\n",
+                               itv->card->name, chipname);
+       } else if (itv->options.cardtype != 0) {
+               IVTV_ERR("Unknown user specified type, trying to autodetect card\n");
+       }
+       if (itv->card == NULL) {
+               if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE ||
+                   itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 ||
+                   itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) {
+                       itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150);
+                       IVTV_INFO("Autodetected Hauppauge card (%s based)\n",
+                                       chipname);
+               }
+       }
+       if (itv->card == NULL) {
+               for (i = 0; (itv->card = ivtv_get_card(i)); i++) {
+                       if (itv->card->pci_list == NULL)
+                               continue;
+                       for (j = 0; itv->card->pci_list[j].device; j++) {
+                               if (itv->pdev->device !=
+                                   itv->card->pci_list[j].device)
+                                       continue;
+                               if (itv->pdev->subsystem_vendor !=
+                                   itv->card->pci_list[j].subsystem_vendor)
+                                       continue;
+                               if (itv->pdev->subsystem_device !=
+                                   itv->card->pci_list[j].subsystem_device)
+                                       continue;
+                               IVTV_INFO("Autodetected %s card (%s based)\n",
+                                               itv->card->name, chipname);
+                               goto done;
+                       }
+               }
+       }
+done:
+
+       if (itv->card == NULL) {
+               itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
+               IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
+                    itv->pdev->vendor, itv->pdev->device);
+               IVTV_ERR("              subsystem vendor/device: [%04x:%04x]\n",
+                    itv->pdev->subsystem_vendor, itv->pdev->subsystem_device);
+               IVTV_ERR("              %s based\n", chipname);
+               IVTV_ERR("Defaulting to %s card\n", itv->card->name);
+               IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
+               IVTV_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
+               IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n");
+       }
+       itv->v4l2_cap = itv->card->v4l2_capabilities;
+       itv->card_name = itv->card->name;
+       itv->card_i2c = itv->card->i2c;
+}
+
+/* Precondition: the ivtv structure has been memset to 0. Only
+   the dev and num fields have been filled in.
+   No assumptions on the card type may be made here (see ivtv_init_struct2
+   for that).
+ */
+static int __devinit ivtv_init_struct1(struct ivtv *itv)
+{
+       struct sched_param param = { .sched_priority = 99 };
+
+       itv->base_addr = pci_resource_start(itv->pdev, 0);
+       itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
+       itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */
+
+       mutex_init(&itv->serialize_lock);
+       mutex_init(&itv->i2c_bus_lock);
+       mutex_init(&itv->udma.lock);
+
+       spin_lock_init(&itv->lock);
+       spin_lock_init(&itv->dma_reg_lock);
+
+       init_kthread_worker(&itv->irq_worker);
+       itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker,
+                                          itv->v4l2_dev.name);
+       if (IS_ERR(itv->irq_worker_task)) {
+               IVTV_ERR("Could not create ivtv task\n");
+               return -1;
+       }
+       /* must use the FIFO scheduler as it is realtime sensitive */
+       sched_setscheduler(itv->irq_worker_task, SCHED_FIFO, &param);
+
+       init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
+
+       /* Initial settings */
+       itv->cxhdl.port = CX2341X_PORT_MEMORY;
+       itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
+       init_waitqueue_head(&itv->eos_waitq);
+       init_waitqueue_head(&itv->event_waitq);
+       init_waitqueue_head(&itv->vsync_waitq);
+       init_waitqueue_head(&itv->dma_waitq);
+       init_timer(&itv->dma_timer);
+       itv->dma_timer.function = ivtv_unfinished_dma;
+       itv->dma_timer.data = (unsigned long)itv;
+
+       itv->cur_dma_stream = -1;
+       itv->cur_pio_stream = -1;
+
+       /* Ctrls */
+       itv->speed = 1000;
+
+       /* VBI */
+       itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
+
+       /* Init the sg table for osd/yuv output */
+       sg_init_table(itv->udma.SGlist, IVTV_DMA_SG_OSD_ENT);
+
+       /* OSD */
+       itv->osd_global_alpha_state = 1;
+       itv->osd_global_alpha = 255;
+
+       /* YUV */
+       atomic_set(&itv->yuv_info.next_dma_frame, -1);
+       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;
+}
+
+/* Second initialization part. Here the card type has been
+   autodetected. */
+static void __devinit ivtv_init_struct2(struct ivtv *itv)
+{
+       int i;
+
+       for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
+               if (itv->card->video_inputs[i].video_type == 0)
+                       break;
+       itv->nof_inputs = i;
+       for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
+               if (itv->card->audio_inputs[i].audio_type == 0)
+                       break;
+       itv->nof_audio_inputs = i;
+
+       if (itv->card->hw_all & IVTV_HW_CX25840) {
+               itv->vbi.sliced_size = 288;  /* multiple of 16, real size = 284 */
+       } else {
+               itv->vbi.sliced_size = 64;   /* multiple of 16, real size = 52 */
+       }
+
+       /* Find tuner input */
+       for (i = 0; i < itv->nof_inputs; i++) {
+               if (itv->card->video_inputs[i].video_type ==
+                               IVTV_CARD_INPUT_VID_TUNER)
+                       break;
+       }
+       if (i == itv->nof_inputs)
+               i = 0;
+       itv->active_input = i;
+       itv->audio_input = itv->card->video_inputs[i].audio_index;
+}
+
+static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
+                         const struct pci_device_id *pci_id)
+{
+       u16 cmd;
+       unsigned char pci_latency;
+
+       IVTV_DEBUG_INFO("Enabling pci device\n");
+
+       if (pci_enable_device(pdev)) {
+               IVTV_ERR("Can't enable device!\n");
+               return -EIO;
+       }
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               IVTV_ERR("No suitable DMA available.\n");
+               return -EIO;
+       }
+       if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) {
+               IVTV_ERR("Cannot request encoder memory region.\n");
+               return -EIO;
+       }
+
+       if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,
+                               IVTV_REG_SIZE, "ivtv registers")) {
+               IVTV_ERR("Cannot request register memory region.\n");
+               release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+               return -EIO;
+       }
+
+       if (itv->has_cx23415 &&
+           !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
+                               IVTV_DECODER_SIZE, "ivtv decoder")) {
+               IVTV_ERR("Cannot request decoder memory region.\n");
+               release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+               release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+               return -EIO;
+       }
+
+       /* Check for bus mastering */
+       pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+       if (!(cmd & PCI_COMMAND_MASTER)) {
+               IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n");
+               pci_set_master(pdev);
+               pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+               if (!(cmd & PCI_COMMAND_MASTER)) {
+                       IVTV_ERR("Bus Mastering is not enabled\n");
+                       return -ENXIO;
+               }
+       }
+       IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
+
+       pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+
+       if (pci_latency < 64 && ivtv_pci_latency) {
+               IVTV_INFO("Unreasonably low latency timer, "
+                              "setting to 64 (was %d)\n", pci_latency);
+               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
+       }
+       /* This config space value relates to DMA latencies. The
+          default value 0x8080 is too low however and will lead
+          to DMA errors. 0xffff is the max value which solves
+          these problems. */
+       pci_write_config_dword(pdev, 0x40, 0xffff);
+
+       IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
+                  "irq: %d, latency: %d, memory: 0x%llx\n",
+                  pdev->device, pdev->revision, pdev->bus->number,
+                  PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+                  pdev->irq, pci_latency, (u64)itv->base_addr);
+
+       return 0;
+}
+
+static void ivtv_load_and_init_modules(struct ivtv *itv)
+{
+       u32 hw = itv->card->hw_all;
+       unsigned i;
+
+       /* check which i2c devices are actually found */
+       for (i = 0; i < 32; i++) {
+               u32 device = 1 << i;
+
+               if (!(device & hw))
+                       continue;
+               if (device == IVTV_HW_GPIO || device == IVTV_HW_TVEEPROM) {
+                       /* GPIO and TVEEPROM do not use i2c probing */
+                       itv->hw_flags |= device;
+                       continue;
+               }
+               if (ivtv_i2c_register(itv, i) == 0)
+                       itv->hw_flags |= device;
+       }
+
+       /* probe for legacy IR controllers that aren't in card definitions */
+       if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0)
+               ivtv_i2c_new_ir_legacy(itv);
+
+       if (itv->card->hw_all & IVTV_HW_CX25840)
+               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840);
+       else if (itv->card->hw_all & IVTV_HW_SAA717X)
+               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X);
+       else if (itv->card->hw_all & IVTV_HW_SAA7114)
+               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114);
+       else
+               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115);
+       itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl);
+       itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer);
+
+       hw = itv->hw_flags;
+
+       if (itv->card->type == IVTV_CARD_CX23416GYC) {
+               /* Several variations of this card exist, detect which card
+                  type should be used. */
+               if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0)
+                       itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS);
+               else if ((hw & IVTV_HW_UPD64031A) == 0)
+                       itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR);
+       }
+       else if (itv->card->type == IVTV_CARD_GV_MVPRX ||
+                itv->card->type == IVTV_CARD_GV_MVPRX2E) {
+               /* The crystal frequency of GVMVPRX is 24.576MHz */
+               v4l2_subdev_call(itv->sd_video, video, s_crystal_freq,
+                       SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC);
+       }
+
+       if (hw & IVTV_HW_CX25840) {
+               itv->vbi.raw_decoder_line_size = 1444;
+               itv->vbi.raw_decoder_sav_odd_field = 0x20;
+               itv->vbi.raw_decoder_sav_even_field = 0x60;
+               itv->vbi.sliced_decoder_line_size = 272;
+               itv->vbi.sliced_decoder_sav_odd_field = 0xB0;
+               itv->vbi.sliced_decoder_sav_even_field = 0xF0;
+       }
+
+       if (hw & IVTV_HW_SAA711X) {
+               struct v4l2_dbg_chip_ident v;
+
+               /* determine the exact saa711x model */
+               itv->hw_flags &= ~IVTV_HW_SAA711X;
+
+               v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
+               strlcpy(v.match.name, "saa7115", sizeof(v.match.name));
+               ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v);
+               if (v.ident == V4L2_IDENT_SAA7114) {
+                       itv->hw_flags |= IVTV_HW_SAA7114;
+                       /* VBI is not yet supported by the saa7114 driver. */
+                       itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE);
+               } else {
+                       itv->hw_flags |= IVTV_HW_SAA7115;
+               }
+               itv->vbi.raw_decoder_line_size = 1443;
+               itv->vbi.raw_decoder_sav_odd_field = 0x25;
+               itv->vbi.raw_decoder_sav_even_field = 0x62;
+               itv->vbi.sliced_decoder_line_size = 51;
+               itv->vbi.sliced_decoder_sav_odd_field = 0xAB;
+               itv->vbi.sliced_decoder_sav_even_field = 0xEC;
+       }
+
+       if (hw & IVTV_HW_SAA717X) {
+               itv->vbi.raw_decoder_line_size = 1443;
+               itv->vbi.raw_decoder_sav_odd_field = 0x25;
+               itv->vbi.raw_decoder_sav_even_field = 0x62;
+               itv->vbi.sliced_decoder_line_size = 51;
+               itv->vbi.sliced_decoder_sav_odd_field = 0xAB;
+               itv->vbi.sliced_decoder_sav_even_field = 0xEC;
+       }
+}
+
+static int __devinit ivtv_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *pci_id)
+{
+       int retval = 0;
+       int vbi_buf_size;
+       struct ivtv *itv;
+
+       itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC);
+       if (itv == NULL)
+               return -ENOMEM;
+       itv->pdev = pdev;
+       itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv",
+                                               &ivtv_instance);
+
+       retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev);
+       if (retval) {
+               kfree(itv);
+               return retval;
+       }
+       IVTV_INFO("Initializing card %d\n", itv->instance);
+
+       ivtv_process_options(itv);
+       if (itv->options.cardtype == -1) {
+               retval = -ENODEV;
+               goto err;
+       }
+       if (ivtv_init_struct1(itv)) {
+               retval = -ENOMEM;
+               goto err;
+       }
+       retval = cx2341x_handler_init(&itv->cxhdl, 50);
+       if (retval)
+               goto err;
+       itv->v4l2_dev.ctrl_handler = &itv->cxhdl.hdl;
+       itv->cxhdl.ops = &ivtv_cxhdl_ops;
+       itv->cxhdl.priv = itv;
+       itv->cxhdl.func = ivtv_api_func;
+
+       IVTV_DEBUG_INFO("base addr: 0x%llx\n", (u64)itv->base_addr);
+
+       /* PCI Device Setup */
+       retval = ivtv_setup_pci(itv, pdev, pci_id);
+       if (retval == -EIO)
+               goto free_worker;
+       if (retval == -ENXIO)
+               goto free_mem;
+
+       /* map io memory */
+       IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+                  (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
+       itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET,
+                                      IVTV_ENCODER_SIZE);
+       if (!itv->enc_mem) {
+               IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
+                        "encoder memory\n");
+               IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of "
+                        "vmalloc address space for this window\n");
+               IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+               IVTV_ERR("Use the vmalloc= kernel command line option to set "
+                        "VmallocTotal to a larger value\n");
+               retval = -ENOMEM;
+               goto free_mem;
+       }
+
+       if (itv->has_cx23415) {
+               IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+                               (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+               itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET,
+                               IVTV_DECODER_SIZE);
+               if (!itv->dec_mem) {
+                       IVTV_ERR("ioremap failed. Can't get a window into "
+                                "CX23415 decoder memory\n");
+                       IVTV_ERR("Each capture card with a CX23415 needs 8 MB "
+                                "of vmalloc address space for this window\n");
+                       IVTV_ERR("Check the output of 'grep Vmalloc "
+                                "/proc/meminfo'\n");
+                       IVTV_ERR("Use the vmalloc= kernel command line option "
+                                "to set VmallocTotal to a larger value\n");
+                       retval = -ENOMEM;
+                       goto free_mem;
+               }
+       }
+       else {
+               itv->dec_mem = itv->enc_mem;
+       }
+
+       /* map registers memory */
+       IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+                  (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+       itv->reg_mem =
+           ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+       if (!itv->reg_mem) {
+               IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
+                        "register space\n");
+               IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of "
+                        "vmalloc address space for this window\n");
+               IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+               IVTV_ERR("Use the vmalloc= kernel command line option to set "
+                        "VmallocTotal to a larger value\n");
+               retval = -ENOMEM;
+               goto free_io;
+       }
+
+       retval = ivtv_gpio_init(itv);
+       if (retval)
+               goto free_io;
+
+       /* active i2c  */
+       IVTV_DEBUG_INFO("activating i2c...\n");
+       if (init_ivtv_i2c(itv)) {
+               IVTV_ERR("Could not initialize i2c\n");
+               goto free_io;
+       }
+
+       if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
+               /* Based on the model number the cardtype may be changed.
+                  The PCI IDs are not always reliable. */
+               ivtv_process_eeprom(itv);
+       }
+       if (itv->card->comment)
+               IVTV_INFO("%s", itv->card->comment);
+       if (itv->card->v4l2_capabilities == 0) {
+               /* card was detected but is not supported */
+               retval = -ENODEV;
+               goto free_i2c;
+       }
+
+       if (itv->std == 0) {
+               itv->std = V4L2_STD_NTSC_M;
+       }
+
+       if (itv->options.tuner == -1) {
+               int i;
+
+               for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) {
+                       if ((itv->std & itv->card->tuners[i].std) == 0)
+                               continue;
+                       itv->options.tuner = itv->card->tuners[i].tuner;
+                       break;
+               }
+       }
+       /* if no tuner was found, then pick the first tuner in the card list */
+       if (itv->options.tuner == -1 && itv->card->tuners[0].std) {
+               itv->std = itv->card->tuners[0].std;
+               if (itv->std & V4L2_STD_PAL)
+                       itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+               else if (itv->std & V4L2_STD_NTSC)
+                       itv->std = V4L2_STD_NTSC_M;
+               else if (itv->std & V4L2_STD_SECAM)
+                       itv->std = V4L2_STD_SECAM_L;
+               itv->options.tuner = itv->card->tuners[0].tuner;
+       }
+       if (itv->options.radio == -1)
+               itv->options.radio = (itv->card->radio_input.audio_type != 0);
+
+       /* The card is now fully identified, continue with card-specific
+          initialization. */
+       ivtv_init_struct2(itv);
+
+       ivtv_load_and_init_modules(itv);
+
+       if (itv->std & V4L2_STD_525_60) {
+               itv->is_60hz = 1;
+               itv->is_out_60hz = 1;
+       } else {
+               itv->is_50hz = 1;
+               itv->is_out_50hz = 1;
+       }
+
+       itv->yuv_info.osd_full_w = 720;
+       itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480;
+       itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w;
+       itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h;
+
+       cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
+
+       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
+       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200;
+       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000;
+       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000;
+       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000;
+
+       /* Setup VBI Raw Size. Should be big enough to hold PAL.
+          It is possible to switch between PAL and NTSC, so we need to
+          take the largest size here. */
+       /* 1456 is multiple of 16, real size = 1444 */
+       itv->vbi.raw_size = 1456;
+       /* We use a buffer size of 1/2 of the total size needed for a
+          frame. This is actually very useful, since we now receive
+          a field at a time and that makes 'compressing' the raw data
+          down to size by stripping off the SAV codes a lot easier.
+          Note: having two different buffer sizes prevents standard
+          switching on the fly. We need to find a better solution... */
+       vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2;
+       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
+       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36;
+
+       if (itv->options.radio > 0)
+               itv->v4l2_cap |= V4L2_CAP_RADIO;
+
+       if (itv->options.tuner > -1) {
+               struct tuner_setup setup;
+
+               setup.addr = ADDR_UNSET;
+               setup.type = itv->options.tuner;
+               setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+               if (itv->options.radio > 0)
+                       setup.mode_mask |= T_RADIO;
+               setup.tuner_callback = (setup.type == TUNER_XC2028) ?
+                       ivtv_reset_tuner_gpio : NULL;
+               ivtv_call_all(itv, tuner, s_type_addr, &setup);
+               if (setup.type == TUNER_XC2028) {
+                       static struct xc2028_ctrl ctrl = {
+                               .fname = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                       };
+                       struct v4l2_priv_tun_config cfg = {
+                               .tuner = itv->options.tuner,
+                               .priv = &ctrl,
+                       };
+                       ivtv_call_all(itv, tuner, s_config, &cfg);
+               }
+       }
+
+       /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
+          are not. */
+       itv->tuner_std = itv->std;
+
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+               struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler;
+
+               itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
+                               V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 0, 0);
+               itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
+                               V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0, 0, 0);
+               /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported,
+                  mask that menu item. */
+               itv->ctrl_audio_playback =
+                       v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
+                               V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK,
+                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
+                               1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
+                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO);
+               itv->ctrl_audio_multilingual_playback =
+                       v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
+                               V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK,
+                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
+                               1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
+                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT);
+               if (hdl->error) {
+                       retval = hdl->error;
+                       goto free_i2c;
+               }
+               v4l2_ctrl_cluster(2, &itv->ctrl_pts);
+               v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback);
+               ivtv_call_all(itv, video, s_std_output, itv->std);
+               /* Turn off the output signal. The mpeg decoder is not yet
+                  active so without this you would get a green image until the
+                  mpeg decoder becomes active. */
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
+       }
+
+       /* clear interrupt mask, effectively disabling interrupts */
+       ivtv_set_irq_mask(itv, 0xffffffff);
+
+       /* Register IRQ */
+       retval = request_irq(itv->pdev->irq, ivtv_irq_handler,
+            IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv);
+       if (retval) {
+               IVTV_ERR("Failed to register irq %d\n", retval);
+               goto free_i2c;
+       }
+
+       retval = ivtv_streams_setup(itv);
+       if (retval) {
+               IVTV_ERR("Error %d setting up streams\n", retval);
+               goto free_irq;
+       }
+       retval = ivtv_streams_register(itv);
+       if (retval) {
+               IVTV_ERR("Error %d registering devices\n", retval);
+               goto free_streams;
+       }
+       IVTV_INFO("Initialized card: %s\n", itv->card_name);
+       return 0;
+
+free_streams:
+       ivtv_streams_cleanup(itv, 1);
+free_irq:
+       free_irq(itv->pdev->irq, (void *)itv);
+free_i2c:
+       v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
+       exit_ivtv_i2c(itv);
+free_io:
+       ivtv_iounmap(itv);
+free_mem:
+       release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+       release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+       if (itv->has_cx23415)
+               release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+free_worker:
+       kthread_stop(itv->irq_worker_task);
+err:
+       if (retval == 0)
+               retval = -ENODEV;
+       IVTV_ERR("Error %d on initialization\n", retval);
+
+       v4l2_device_unregister(&itv->v4l2_dev);
+       kfree(itv);
+       return retval;
+}
+
+int ivtv_init_on_first_open(struct ivtv *itv)
+{
+       struct v4l2_frequency vf;
+       /* Needed to call ioctls later */
+       struct ivtv_open_id fh;
+       int fw_retry_count = 3;
+       int video_input;
+
+       fh.itv = itv;
+
+       if (test_bit(IVTV_F_I_FAILED, &itv->i_flags))
+               return -ENXIO;
+
+       if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags))
+               return 0;
+
+       while (--fw_retry_count > 0) {
+               /* load firmware */
+               if (ivtv_firmware_init(itv) == 0)
+                       break;
+               if (fw_retry_count > 1)
+                       IVTV_WARN("Retry loading firmware\n");
+       }
+
+       if (fw_retry_count == 0) {
+               set_bit(IVTV_F_I_FAILED, &itv->i_flags);
+               return -ENXIO;
+       }
+
+       /* Try and get firmware versions */
+       IVTV_DEBUG_INFO("Getting firmware version..\n");
+       ivtv_firmware_versions(itv);
+
+       if (itv->card->hw_all & IVTV_HW_CX25840)
+               v4l2_subdev_call(itv->sd_video, core, load_fw);
+
+       vf.tuner = 0;
+       vf.type = V4L2_TUNER_ANALOG_TV;
+       vf.frequency = 6400; /* the tuner 'baseline' frequency */
+
+       /* Set initial frequency. For PAL/SECAM broadcasts no
+          'default' channel exists AFAIK. */
+       if (itv->std == V4L2_STD_NTSC_M_JP) {
+               vf.frequency = 1460;    /* ch. 1 91250*16/1000 */
+       }
+       else if (itv->std & V4L2_STD_NTSC_M) {
+               vf.frequency = 1076;    /* ch. 4 67250*16/1000 */
+       }
+
+       video_input = itv->active_input;
+       itv->active_input++;    /* Force update of input */
+       ivtv_s_input(NULL, &fh, video_input);
+
+       /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
+          in one place. */
+       itv->std++;             /* Force full standard initialization */
+       itv->std_out = itv->std;
+       ivtv_s_frequency(NULL, &fh, &vf);
+
+       if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+               /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes
+                  the mpeg decoder so now the saa7127 receives a proper
+                  signal. */
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
+               ivtv_init_mpeg_decoder(itv);
+       }
+
+       /* On a cx23416 this seems to be able to enable DMA to the chip? */
+       if (!itv->has_cx23415)
+               write_reg_sync(0x03, IVTV_REG_DMACONTROL);
+
+       ivtv_s_std_enc(itv, &itv->tuner_std);
+
+       /* Default interrupts enabled. For the PVR350 this includes the
+          decoder VSYNC interrupt, which is always on. It is not only used
+          during decoding but also by the OSD.
+          Some old PVR250 cards had a cx23415, so testing for that is too
+          general. Instead test if the card has video output capability. */
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+               ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
+               ivtv_set_osd_alpha(itv);
+               ivtv_s_std_dec(itv, &itv->tuner_std);
+       } else {
+               ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
+       }
+
+       /* Setup initial controls */
+       cx2341x_handler_setup(&itv->cxhdl);
+       return 0;
+}
+
+static void ivtv_remove(struct pci_dev *pdev)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+       struct ivtv *itv = to_ivtv(v4l2_dev);
+       int i;
+
+       IVTV_DEBUG_INFO("Removing card\n");
+
+       if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
+               /* Stop all captures */
+               IVTV_DEBUG_INFO("Stopping all streams\n");
+               if (atomic_read(&itv->capturing) > 0)
+                       ivtv_stop_all_captures(itv);
+
+               /* Stop all decoding */
+               IVTV_DEBUG_INFO("Stopping decoding\n");
+
+               /* Turn off the TV-out */
+               if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+                       ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
+               if (atomic_read(&itv->decoding) > 0) {
+                       int type;
+
+                       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+                               type = IVTV_DEC_STREAM_TYPE_YUV;
+                       else
+                               type = IVTV_DEC_STREAM_TYPE_MPG;
+                       ivtv_stop_v4l2_decode_stream(&itv->streams[type],
+                               V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
+               }
+               ivtv_halt_firmware(itv);
+       }
+
+       /* Interrupts */
+       ivtv_set_irq_mask(itv, 0xffffffff);
+       del_timer_sync(&itv->dma_timer);
+
+       /* Kill irq worker */
+       flush_kthread_worker(&itv->irq_worker);
+       kthread_stop(itv->irq_worker_task);
+
+       ivtv_streams_cleanup(itv, 1);
+       ivtv_udma_free(itv);
+
+       v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
+
+       exit_ivtv_i2c(itv);
+
+       free_irq(itv->pdev->irq, (void *)itv);
+       ivtv_iounmap(itv);
+
+       release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+       release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+       if (itv->has_cx23415)
+               release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+
+       pci_disable_device(itv->pdev);
+       for (i = 0; i < IVTV_VBI_FRAMES; i++)
+               kfree(itv->vbi.sliced_mpeg_data[i]);
+
+       printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name);
+
+       v4l2_device_unregister(&itv->v4l2_dev);
+       kfree(itv);
+}
+
+/* define a pci_driver for card detection */
+static struct pci_driver ivtv_pci_driver = {
+      .name =     "ivtv",
+      .id_table = ivtv_pci_tbl,
+      .probe =    ivtv_probe,
+      .remove =   ivtv_remove,
+};
+
+static int __init module_start(void)
+{
+       printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION);
+
+       /* Validate parameters */
+       if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) {
+               printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n",
+                    IVTV_MAX_CARDS - 1);
+               return -1;
+       }
+
+       if (ivtv_debug < 0 || ivtv_debug > 2047) {
+               ivtv_debug = 0;
+               printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n");
+       }
+
+       if (pci_register_driver(&ivtv_pci_driver)) {
+               printk(KERN_ERR "ivtv: Error detecting PCI card\n");
+               return -ENODEV;
+       }
+       printk(KERN_INFO "ivtv: End initialization\n");
+       return 0;
+}
+
+static void __exit module_cleanup(void)
+{
+       pci_unregister_driver(&ivtv_pci_driver);
+}
+
+/* Note: These symbols are exported because they are used by the ivtvfb
+   framebuffer module and an infrared module for the IR-blaster. */
+EXPORT_SYMBOL(ivtv_set_irq_mask);
+EXPORT_SYMBOL(ivtv_api);
+EXPORT_SYMBOL(ivtv_vapi);
+EXPORT_SYMBOL(ivtv_vapi_result);
+EXPORT_SYMBOL(ivtv_clear_irq_mask);
+EXPORT_SYMBOL(ivtv_debug);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+EXPORT_SYMBOL(ivtv_fw_debug);
+#endif
+EXPORT_SYMBOL(ivtv_reset_ir_gpio);
+EXPORT_SYMBOL(ivtv_udma_setup);
+EXPORT_SYMBOL(ivtv_udma_unmap);
+EXPORT_SYMBOL(ivtv_udma_alloc);
+EXPORT_SYMBOL(ivtv_udma_prepare);
+EXPORT_SYMBOL(ivtv_init_on_first_open);
+EXPORT_SYMBOL(ivtv_firmware_check);
+
+module_init(module_start);
+module_exit(module_cleanup);
diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h
new file mode 100644 (file)
index 0000000..a7e00f8
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+    ivtv driver internal defines and structures
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_DRIVER_H
+#define IVTV_DRIVER_H
+
+/* Internal header for ivtv project:
+ * Driver for the cx23415/6 chip.
+ * Author: Kevin Thayer (nufan_wfk at yahoo.com)
+ * License: GPL
+ * http://www.ivtvdriver.org
+ *
+ * -----
+ * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
+ *                      and Takeru KOMORIYA<komoriya@paken.org>
+ *
+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
+ *                using information provided by Jiun-Kuei Jung @ AVerMedia.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/tuner.h>
+#include <media/cx2341x.h>
+#include <media/ir-kbd-i2c.h>
+
+#include <linux/ivtv.h>
+
+/* Memory layout */
+#define IVTV_ENCODER_OFFSET    0x00000000
+#define IVTV_ENCODER_SIZE      0x00800000      /* Total size is 0x01000000, but only first half is used */
+#define IVTV_DECODER_OFFSET    0x01000000
+#define IVTV_DECODER_SIZE      0x00800000      /* Total size is 0x01000000, but only first half is used */
+#define IVTV_REG_OFFSET        0x02000000
+#define IVTV_REG_SIZE          0x00010000
+
+/* Maximum ivtv driver instances. Some people have a huge number of
+   capture cards, so set this to a high value. */
+#define IVTV_MAX_CARDS 32
+
+#define IVTV_ENC_STREAM_TYPE_MPG  0
+#define IVTV_ENC_STREAM_TYPE_YUV  1
+#define IVTV_ENC_STREAM_TYPE_VBI  2
+#define IVTV_ENC_STREAM_TYPE_PCM  3
+#define IVTV_ENC_STREAM_TYPE_RAD  4
+#define IVTV_DEC_STREAM_TYPE_MPG  5
+#define IVTV_DEC_STREAM_TYPE_VBI  6
+#define IVTV_DEC_STREAM_TYPE_VOUT 7
+#define IVTV_DEC_STREAM_TYPE_YUV  8
+#define IVTV_MAX_STREAMS         9
+
+#define IVTV_DMA_SG_OSD_ENT    (2883584/PAGE_SIZE)     /* sg entities */
+
+/* DMA Registers */
+#define IVTV_REG_DMAXFER       (0x0000)
+#define IVTV_REG_DMASTATUS     (0x0004)
+#define IVTV_REG_DECDMAADDR    (0x0008)
+#define IVTV_REG_ENCDMAADDR    (0x000c)
+#define IVTV_REG_DMACONTROL    (0x0010)
+#define IVTV_REG_IRQSTATUS     (0x0040)
+#define IVTV_REG_IRQMASK       (0x0048)
+
+/* Setup Registers */
+#define IVTV_REG_ENC_SDRAM_REFRESH     (0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE   (0x07FC)
+#define IVTV_REG_DEC_SDRAM_REFRESH     (0x08F8)
+#define IVTV_REG_DEC_SDRAM_PRECHARGE   (0x08FC)
+#define IVTV_REG_VDM                   (0x2800)
+#define IVTV_REG_AO                    (0x2D00)
+#define IVTV_REG_BYTEFLUSH             (0x2D24)
+#define IVTV_REG_SPU                   (0x9050)
+#define IVTV_REG_HW_BLOCKS             (0x9054)
+#define IVTV_REG_VPU                   (0x9058)
+#define IVTV_REG_APU                   (0xA064)
+
+/* Other registers */
+#define IVTV_REG_DEC_LINE_FIELD                (0x28C0)
+
+/* debugging */
+extern int ivtv_debug;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+extern int ivtv_fw_debug;
+#endif
+
+#define IVTV_DBGFLG_WARN    (1 << 0)
+#define IVTV_DBGFLG_INFO    (1 << 1)
+#define IVTV_DBGFLG_MB      (1 << 2)
+#define IVTV_DBGFLG_IOCTL   (1 << 3)
+#define IVTV_DBGFLG_FILE    (1 << 4)
+#define IVTV_DBGFLG_DMA     (1 << 5)
+#define IVTV_DBGFLG_IRQ     (1 << 6)
+#define IVTV_DBGFLG_DEC     (1 << 7)
+#define IVTV_DBGFLG_YUV     (1 << 8)
+#define IVTV_DBGFLG_I2C     (1 << 9)
+/* Flag to turn on high volume debugging */
+#define IVTV_DBGFLG_HIGHVOL (1 << 10)
+
+#define IVTV_DEBUG(x, type, fmt, args...) \
+       do { \
+               if ((x) & ivtv_debug) \
+                       v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args);  \
+       } while (0)
+#define IVTV_DEBUG_WARN(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_WARN,  "warn",  fmt , ## args)
+#define IVTV_DEBUG_INFO(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_INFO,  "info",  fmt , ## args)
+#define IVTV_DEBUG_MB(fmt, args...)    IVTV_DEBUG(IVTV_DBGFLG_MB,    "mb",    fmt , ## args)
+#define IVTV_DEBUG_DMA(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_DMA,   "dma",   fmt , ## args)
+#define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define IVTV_DEBUG_FILE(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_FILE,  "file",  fmt , ## args)
+#define IVTV_DEBUG_I2C(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_I2C,   "i2c",   fmt , ## args)
+#define IVTV_DEBUG_IRQ(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_IRQ,   "irq",   fmt , ## args)
+#define IVTV_DEBUG_DEC(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_DEC,   "dec",   fmt , ## args)
+#define IVTV_DEBUG_YUV(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_YUV,   "yuv",   fmt , ## args)
+
+#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \
+       do { \
+               if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL))   \
+                       v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args);  \
+       } while (0)
+#define IVTV_DEBUG_HI_WARN(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN,  "warn",  fmt , ## args)
+#define IVTV_DEBUG_HI_INFO(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO,  "info",  fmt , ## args)
+#define IVTV_DEBUG_HI_MB(fmt, args...)    IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_MB,    "mb",    fmt , ## args)
+#define IVTV_DEBUG_HI_DMA(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA,   "dma",   fmt , ## args)
+#define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define IVTV_DEBUG_HI_FILE(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_FILE,  "file",  fmt , ## args)
+#define IVTV_DEBUG_HI_I2C(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C,   "i2c",   fmt , ## args)
+#define IVTV_DEBUG_HI_IRQ(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ,   "irq",   fmt , ## args)
+#define IVTV_DEBUG_HI_DEC(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC,   "dec",   fmt , ## args)
+#define IVTV_DEBUG_HI_YUV(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV,   "yuv",   fmt , ## args)
+
+/* Standard kernel messages */
+#define IVTV_ERR(fmt, args...)      v4l2_err(&itv->v4l2_dev, fmt , ## args)
+#define IVTV_WARN(fmt, args...)     v4l2_warn(&itv->v4l2_dev, fmt , ## args)
+#define IVTV_INFO(fmt, args...)     v4l2_info(&itv->v4l2_dev, fmt , ## args)
+
+/* output modes (cx23415 only) */
+#define OUT_NONE        0
+#define OUT_MPG         1
+#define OUT_YUV         2
+#define OUT_UDMA_YUV    3
+#define OUT_PASSTHROUGH 4
+
+#define IVTV_MAX_PGM_INDEX (400)
+
+/* Default I2C SCL period in microseconds */
+#define IVTV_DEFAULT_I2C_CLOCK_PERIOD  20
+
+struct ivtv_options {
+       int kilobytes[IVTV_MAX_STREAMS];        /* size in kilobytes of each stream */
+       int cardtype;                           /* force card type on load */
+       int tuner;                              /* set tuner on load */
+       int radio;                              /* enable/disable radio */
+       int newi2c;                             /* new I2C algorithm */
+       int i2c_clock_period;                   /* period of SCL for I2C bus */
+};
+
+/* ivtv-specific mailbox template */
+struct ivtv_mailbox {
+       u32 flags;
+       u32 cmd;
+       u32 retval;
+       u32 timeout;
+       u32 data[CX2341X_MBOX_MAX_DATA];
+};
+
+struct ivtv_api_cache {
+       unsigned long last_jiffies;             /* when last command was issued */
+       u32 data[CX2341X_MBOX_MAX_DATA];        /* last sent api data */
+};
+
+struct ivtv_mailbox_data {
+       volatile struct ivtv_mailbox __iomem *mbox;
+       /* Bits 0-2 are for the encoder mailboxes, 0-1 are for the decoder mailboxes.
+          If the bit is set, then the corresponding mailbox is in use by the driver. */
+       unsigned long busy;
+       u8 max_mbox;
+};
+
+/* per-buffer bit flags */
+#define IVTV_F_B_NEED_BUF_SWAP  (1 << 0)       /* this buffer should be byte swapped */
+
+/* per-stream, s_flags */
+#define IVTV_F_S_DMA_PENDING   0       /* this stream has pending DMA */
+#define IVTV_F_S_DMA_HAS_VBI   1       /* the current DMA request also requests VBI data */
+#define IVTV_F_S_NEEDS_DATA    2       /* this decoding stream needs more data */
+
+#define IVTV_F_S_CLAIMED       3       /* this stream is claimed */
+#define IVTV_F_S_STREAMING      4      /* the fw is decoding/encoding this stream */
+#define IVTV_F_S_INTERNAL_USE  5       /* this stream is used internally (sliced VBI processing) */
+#define IVTV_F_S_PASSTHROUGH   6       /* this stream is in passthrough mode */
+#define IVTV_F_S_STREAMOFF     7       /* signal end of stream EOS */
+#define IVTV_F_S_APPL_IO        8      /* this stream is used read/written by an application */
+
+#define IVTV_F_S_PIO_PENDING   9       /* this stream has pending PIO */
+#define IVTV_F_S_PIO_HAS_VBI   1       /* the current PIO request also requests VBI data */
+
+/* per-ivtv, i_flags */
+#define IVTV_F_I_DMA              0    /* DMA in progress */
+#define IVTV_F_I_UDMA             1    /* UDMA in progress */
+#define IVTV_F_I_UDMA_PENDING     2    /* UDMA pending */
+#define IVTV_F_I_SPEED_CHANGE     3    /* a speed change is in progress */
+#define IVTV_F_I_EOS              4    /* end of encoder stream reached */
+#define IVTV_F_I_RADIO_USER       5    /* the radio tuner is selected */
+#define IVTV_F_I_DIG_RST          6    /* reset digitizer */
+#define IVTV_F_I_DEC_YUV          7    /* YUV instead of MPG is being decoded */
+#define IVTV_F_I_UPDATE_CC        9    /* CC should be updated */
+#define IVTV_F_I_UPDATE_WSS       10   /* WSS should be updated */
+#define IVTV_F_I_UPDATE_VPS       11   /* VPS should be updated */
+#define IVTV_F_I_DECODING_YUV     12   /* this stream is YUV frame decoding */
+#define IVTV_F_I_ENC_PAUSED       13   /* the encoder is paused */
+#define IVTV_F_I_VALID_DEC_TIMINGS 14  /* last_dec_timing is valid */
+#define IVTV_F_I_HAVE_WORK        15   /* used in the interrupt handler: there is work to be done */
+#define IVTV_F_I_WORK_HANDLER_VBI  16  /* there is work to be done for VBI */
+#define IVTV_F_I_WORK_HANDLER_YUV  17  /* there is work to be done for YUV */
+#define IVTV_F_I_WORK_HANDLER_PIO  18  /* there is work to be done for PIO */
+#define IVTV_F_I_PIO              19   /* PIO in progress */
+#define IVTV_F_I_DEC_PAUSED       20   /* the decoder is paused */
+#define IVTV_F_I_INITED                   21   /* set after first open */
+#define IVTV_F_I_FAILED                   22   /* set if first open failed */
+
+/* Event notifications */
+#define IVTV_F_I_EV_DEC_STOPPED           28   /* decoder stopped event */
+#define IVTV_F_I_EV_VSYNC         29   /* VSYNC event */
+#define IVTV_F_I_EV_VSYNC_FIELD    30  /* VSYNC event field (0 = first, 1 = second field) */
+#define IVTV_F_I_EV_VSYNC_ENABLED  31  /* VSYNC event enabled */
+
+/* Scatter-Gather array element, used in DMA transfers */
+struct ivtv_sg_element {
+       __le32 src;
+       __le32 dst;
+       __le32 size;
+};
+
+struct ivtv_sg_host_element {
+       u32 src;
+       u32 dst;
+       u32 size;
+};
+
+struct ivtv_user_dma {
+       struct mutex lock;
+       int page_count;
+       struct page *map[IVTV_DMA_SG_OSD_ENT];
+       /* Needed when dealing with highmem userspace buffers */
+       struct page *bouncemap[IVTV_DMA_SG_OSD_ENT];
+
+       /* Base Dev SG Array for cx23415/6 */
+       struct ivtv_sg_element SGarray[IVTV_DMA_SG_OSD_ENT];
+       dma_addr_t SG_handle;
+       int SG_length;
+
+       /* SG List of Buffers */
+       struct scatterlist SGlist[IVTV_DMA_SG_OSD_ENT];
+};
+
+struct ivtv_dma_page_info {
+       unsigned long uaddr;
+       unsigned long first;
+       unsigned long last;
+       unsigned int offset;
+       unsigned int tail;
+       int page_count;
+};
+
+struct ivtv_buffer {
+       struct list_head list;
+       dma_addr_t dma_handle;
+       unsigned short b_flags;
+       unsigned short dma_xfer_cnt;
+       char *buf;
+       u32 bytesused;
+       u32 readpos;
+};
+
+struct ivtv_queue {
+       struct list_head list;          /* the list of buffers in this queue */
+       u32 buffers;                    /* number of buffers in this queue */
+       u32 length;                     /* total number of bytes of available buffer space */
+       u32 bytesused;                  /* total number of bytes used in this queue */
+};
+
+struct ivtv;                           /* forward reference */
+
+struct ivtv_stream {
+       /* These first four fields are always set, even if the stream
+          is not actually created. */
+       struct video_device *vdev;      /* NULL when stream not created */
+       struct ivtv *itv;               /* for ease of use */
+       const char *name;               /* name of the stream */
+       int type;                       /* stream type */
+       u32 caps;                       /* V4L2 capabilities */
+
+       struct v4l2_fh *fh;             /* pointer to the streaming filehandle */
+       spinlock_t qlock;               /* locks access to the queues */
+       unsigned long s_flags;          /* status flags, see above */
+       int dma;                        /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
+       u32 pending_offset;
+       u32 pending_backup;
+       u64 pending_pts;
+
+       u32 dma_offset;
+       u32 dma_backup;
+       u64 dma_pts;
+
+       int subtype;
+       wait_queue_head_t waitq;
+       u32 dma_last_offset;
+
+       /* Buffer Stats */
+       u32 buffers;
+       u32 buf_size;
+       u32 buffers_stolen;
+
+       /* Buffer Queues */
+       struct ivtv_queue q_free;       /* free buffers */
+       struct ivtv_queue q_full;       /* full buffers */
+       struct ivtv_queue q_io;         /* waiting for I/O */
+       struct ivtv_queue q_dma;        /* waiting for DMA */
+       struct ivtv_queue q_predma;     /* waiting for DMA */
+
+       /* DMA xfer counter, buffers belonging to the same DMA
+          xfer will have the same dma_xfer_cnt. */
+       u16 dma_xfer_cnt;
+
+       /* Base Dev SG Array for cx23415/6 */
+       struct ivtv_sg_host_element *sg_pending;
+       struct ivtv_sg_host_element *sg_processing;
+       struct ivtv_sg_element *sg_dma;
+       dma_addr_t sg_handle;
+       int sg_pending_size;
+       int sg_processing_size;
+       int sg_processed;
+
+       /* SG List of Buffers */
+       struct scatterlist *SGlist;
+};
+
+struct ivtv_open_id {
+       struct v4l2_fh fh;
+       int type;                       /* stream type */
+       int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode */
+       struct ivtv *itv;
+};
+
+static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh)
+{
+       return container_of(fh, struct ivtv_open_id, fh);
+}
+
+struct yuv_frame_info
+{
+       u32 update;
+       s32 src_x;
+       s32 src_y;
+       u32 src_w;
+       u32 src_h;
+       s32 dst_x;
+       s32 dst_y;
+       u32 dst_w;
+       u32 dst_h;
+       s32 pan_x;
+       s32 pan_y;
+       u32 vis_w;
+       u32 vis_h;
+       u32 interlaced_y;
+       u32 interlaced_uv;
+       s32 tru_x;
+       u32 tru_w;
+       u32 tru_h;
+       u32 offset_y;
+       s32 lace_mode;
+       u32 sync_field;
+       u32 delay;
+       u32 interlaced;
+};
+
+#define IVTV_YUV_MODE_INTERLACED       0x00
+#define IVTV_YUV_MODE_PROGRESSIVE      0x01
+#define IVTV_YUV_MODE_AUTO             0x02
+#define IVTV_YUV_MODE_MASK             0x03
+
+#define IVTV_YUV_SYNC_EVEN             0x00
+#define IVTV_YUV_SYNC_ODD              0x04
+#define IVTV_YUV_SYNC_MASK             0x04
+
+#define IVTV_YUV_BUFFERS 8
+
+struct yuv_playback_info
+{
+       u32 reg_2834;
+       u32 reg_2838;
+       u32 reg_283c;
+       u32 reg_2840;
+       u32 reg_2844;
+       u32 reg_2848;
+       u32 reg_2854;
+       u32 reg_285c;
+       u32 reg_2864;
+
+       u32 reg_2870;
+       u32 reg_2874;
+       u32 reg_2890;
+       u32 reg_2898;
+       u32 reg_289c;
+
+       u32 reg_2918;
+       u32 reg_291c;
+       u32 reg_2920;
+       u32 reg_2924;
+       u32 reg_2928;
+       u32 reg_292c;
+       u32 reg_2930;
+
+       u32 reg_2934;
+
+       u32 reg_2938;
+       u32 reg_293c;
+       u32 reg_2940;
+       u32 reg_2944;
+       u32 reg_2948;
+       u32 reg_294c;
+       u32 reg_2950;
+       u32 reg_2954;
+       u32 reg_2958;
+       u32 reg_295c;
+       u32 reg_2960;
+       u32 reg_2964;
+       u32 reg_2968;
+       u32 reg_296c;
+
+       u32 reg_2970;
+
+       int v_filter_1;
+       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;
+
+       u32 osd_x_pan;
+       u32 osd_y_pan;
+
+       u32 osd_vis_w;
+       u32 osd_vis_h;
+
+       u32 osd_full_w;
+       u32 osd_full_h;
+
+       int decode_height;
+
+       int lace_mode;
+       int lace_threshold;
+       int lace_sync_field;
+
+       atomic_t next_dma_frame;
+       atomic_t next_fill_frame;
+
+       u32 yuv_forced_update;
+       int update_frame;
+
+       u8 fields_lapsed;   /* Counter used when delaying a frame */
+
+       struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS];
+       struct yuv_frame_info old_frame_info;
+       struct yuv_frame_info old_frame_info_args;
+
+       void *blanking_ptr;
+       dma_addr_t blanking_dmaptr;
+
+       int stream_size;
+
+       u8 draw_frame; /* PVR350 buffer to draw into */
+       u8 max_frames_buffered; /* Maximum number of frames to buffer */
+
+       struct v4l2_rect main_rect;
+       u32 v4l2_src_w;
+       u32 v4l2_src_h;
+
+       u8 running; /* Have any frames been displayed */
+};
+
+#define IVTV_VBI_FRAMES 32
+
+/* VBI data */
+struct vbi_cc {
+       u8 odd[2];      /* two-byte payload of odd field */
+       u8 even[2];     /* two-byte payload of even field */;
+};
+
+struct vbi_vps {
+       u8 data[5];     /* five-byte VPS payload */
+};
+
+struct vbi_info {
+       /* VBI general data, does not change during streaming */
+
+       u32 raw_decoder_line_size;              /* raw VBI line size from digitizer */
+       u8 raw_decoder_sav_odd_field;           /* raw VBI Start Active Video digitizer code of odd field */
+       u8 raw_decoder_sav_even_field;          /* raw VBI Start Active Video digitizer code of even field */
+       u32 sliced_decoder_line_size;           /* sliced VBI line size from digitizer */
+       u8 sliced_decoder_sav_odd_field;        /* sliced VBI Start Active Video digitizer code of odd field */
+       u8 sliced_decoder_sav_even_field;       /* sliced VBI Start Active Video digitizer code of even field */
+
+       u32 start[2];                           /* start of first VBI line in the odd/even fields */
+       u32 count;                              /* number of VBI lines per field */
+       u32 raw_size;                           /* size of raw VBI line from the digitizer */
+       u32 sliced_size;                        /* size of sliced VBI line from the digitizer */
+
+       u32 dec_start;                          /* start in decoder memory of VBI re-insertion buffers */
+       u32 enc_start;                          /* start in encoder memory of VBI capture buffers */
+       u32 enc_size;                           /* size of VBI capture area */
+       int fpi;                                /* number of VBI frames per interrupt */
+
+       struct v4l2_format in;                  /* current VBI capture format */
+       struct v4l2_sliced_vbi_format *sliced_in; /* convenience pointer to sliced struct in vbi.in union */
+       int insert_mpeg;                        /* if non-zero, then embed VBI data in MPEG stream */
+
+       /* Raw VBI compatibility hack */
+
+       u32 frame;                              /* frame counter hack needed for backwards compatibility
+                                                  of old VBI software */
+
+       /* Sliced VBI output data */
+
+       struct vbi_cc cc_payload[256];          /* sliced VBI CC payload array: it is an array to
+                                                  prevent dropping CC data if they couldn't be
+                                                  processed fast enough */
+       int cc_payload_idx;                     /* index in cc_payload */
+       u8 cc_missing_cnt;                      /* counts number of frames without CC for passthrough mode */
+       int wss_payload;                        /* sliced VBI WSS payload */
+       u8 wss_missing_cnt;                     /* counts number of frames without WSS for passthrough mode */
+       struct vbi_vps vps_payload;             /* sliced VBI VPS payload */
+
+       /* Sliced VBI capture data */
+
+       struct v4l2_sliced_vbi_data sliced_data[36];    /* sliced VBI storage for VBI encoder stream */
+       struct v4l2_sliced_vbi_data sliced_dec_data[36];/* sliced VBI storage for VBI decoder stream */
+
+       /* VBI Embedding data */
+
+       /* Buffer for VBI data inserted into MPEG stream.
+          The first byte is a dummy byte that's never used.
+          The next 16 bytes contain the MPEG header for the VBI data,
+          the remainder is the actual VBI data.
+          The max size accepted by the MPEG VBI reinsertion turns out
+          to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
+          where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
+          a single line header byte and 2 * 18 is the number of VBI lines per frame.
+
+          However, it seems that the data must be 1K aligned, so we have to
+          pad the data until the 1 or 2 K boundary.
+
+          This pointer array will allocate 2049 bytes to store each VBI frame. */
+       u8 *sliced_mpeg_data[IVTV_VBI_FRAMES];
+       u32 sliced_mpeg_size[IVTV_VBI_FRAMES];
+       struct ivtv_buffer sliced_mpeg_buf;     /* temporary buffer holding data from sliced_mpeg_data */
+       u32 inserted_frame;                     /* index in sliced_mpeg_size of next sliced data
+                                                  to be inserted in the MPEG stream */
+};
+
+/* forward declaration of struct defined in ivtv-cards.h */
+struct ivtv_card;
+
+/* Struct to hold info about ivtv cards */
+struct ivtv {
+       /* General fixed card data */
+       struct pci_dev *pdev;           /* PCI device */
+       const struct ivtv_card *card;   /* card information */
+       const char *card_name;          /* full name of the card */
+       const struct ivtv_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
+       u8 has_cx23415;                 /* 1 if it is a cx23415 based card, 0 for cx23416 */
+       u8 pvr150_workaround;           /* 1 if the cx25840 needs to workaround a PVR150 bug */
+       u8 nof_inputs;                  /* number of video inputs */
+       u8 nof_audio_inputs;            /* number of audio inputs */
+       u32 v4l2_cap;                   /* V4L2 capabilities of card */
+       u32 hw_flags;                   /* hardware description of the board */
+       v4l2_std_id tuner_std;          /* the norm of the card's tuner (fixed) */
+       struct v4l2_subdev *sd_video;   /* controlling video decoder subdev */
+       struct v4l2_subdev *sd_audio;   /* controlling audio subdev */
+       struct v4l2_subdev *sd_muxer;   /* controlling audio muxer subdev */
+       resource_size_t base_addr;      /* PCI resource base address */
+       volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */
+       volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */
+       volatile void __iomem *reg_mem; /* pointer to mapped registers */
+       struct ivtv_options options;    /* user options */
+
+       struct v4l2_device v4l2_dev;
+       struct cx2341x_handler cxhdl;
+       struct {
+               /* PTS/Frame count control cluster */
+               struct v4l2_ctrl *ctrl_pts;
+               struct v4l2_ctrl *ctrl_frame;
+       };
+       struct {
+               /* Audio Playback control cluster */
+               struct v4l2_ctrl *ctrl_audio_playback;
+               struct v4l2_ctrl *ctrl_audio_multilingual_playback;
+       };
+       struct v4l2_ctrl_handler hdl_gpio;
+       struct v4l2_subdev sd_gpio;     /* GPIO sub-device */
+       u16 instance;
+
+       /* High-level state info */
+       unsigned long i_flags;          /* global ivtv flags */
+       u8 is_50hz;                     /* 1 if the current capture standard is 50 Hz */
+       u8 is_60hz                      /* 1 if the current capture standard is 60 Hz */;
+       u8 is_out_50hz                  /* 1 if the current TV output standard is 50 Hz */;
+       u8 is_out_60hz                  /* 1 if the current TV output standard is 60 Hz */;
+       int output_mode;                /* decoder output mode: NONE, MPG, YUV, UDMA YUV, passthrough */
+       u32 audio_input;                /* current audio input */
+       u32 active_input;               /* current video input */
+       u32 active_output;              /* current video output */
+       v4l2_std_id std;                /* current capture TV standard */
+       v4l2_std_id std_out;            /* current TV output standard */
+       u8 audio_stereo_mode;           /* decoder setting how to handle stereo MPEG audio */
+       u8 audio_bilingual_mode;        /* decoder setting how to handle bilingual MPEG audio */
+
+       /* Locking */
+       spinlock_t lock;                /* lock access to this struct */
+       struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
+
+       /* Streams */
+       int stream_buf_size[IVTV_MAX_STREAMS];          /* stream buffer size */
+       struct ivtv_stream streams[IVTV_MAX_STREAMS];   /* stream data */
+       atomic_t capturing;             /* count number of active capture streams */
+       atomic_t decoding;              /* count number of active decoding streams */
+
+
+       /* Interrupts & DMA */
+       u32 irqmask;                    /* active interrupts */
+       u32 irq_rr_idx;                 /* round-robin stream index */
+       struct kthread_worker irq_worker;               /* kthread worker for PIO/YUV/VBI actions */
+       struct task_struct *irq_worker_task;            /* task for irq_worker */
+       struct kthread_work irq_work;   /* kthread work entry */
+       spinlock_t dma_reg_lock;        /* lock access to DMA engine registers */
+       int cur_dma_stream;             /* index of current stream doing DMA (-1 if none) */
+       int cur_pio_stream;             /* index of current stream doing PIO (-1 if none) */
+       u32 dma_data_req_offset;        /* store offset in decoder memory of current DMA request */
+       u32 dma_data_req_size;          /* store size of current DMA request */
+       int dma_retries;                /* current DMA retry attempt */
+       struct ivtv_user_dma udma;      /* user based DMA for OSD */
+       struct timer_list dma_timer;    /* timer used to catch unfinished DMAs */
+       u32 last_vsync_field;           /* last seen vsync field */
+       wait_queue_head_t dma_waitq;    /* wake up when the current DMA is finished */
+       wait_queue_head_t eos_waitq;    /* wake up when EOS arrives */
+       wait_queue_head_t event_waitq;  /* wake up when the next decoder event arrives */
+       wait_queue_head_t vsync_waitq;  /* wake up when the next decoder vsync arrives */
+
+
+       /* Mailbox */
+       struct ivtv_mailbox_data enc_mbox;              /* encoder mailboxes */
+       struct ivtv_mailbox_data dec_mbox;              /* decoder mailboxes */
+       struct ivtv_api_cache api_cache[256];           /* cached API commands */
+
+
+       /* I2C */
+       struct i2c_adapter i2c_adap;
+       struct i2c_algo_bit_data i2c_algo;
+       struct i2c_client i2c_client;
+       int i2c_state;                  /* i2c bit state */
+       struct mutex i2c_bus_lock;      /* lock i2c bus */
+
+       struct IR_i2c_init_data ir_i2c_init_data;
+
+       /* Program Index information */
+       u32 pgm_info_offset;            /* start of pgm info in encoder memory */
+       u32 pgm_info_num;               /* number of elements in the pgm cyclic buffer in encoder memory */
+       u32 pgm_info_write_idx;         /* last index written by the card that was transferred to pgm_info[] */
+       u32 pgm_info_read_idx;          /* last index in pgm_info read by the application */
+       struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; /* filled from the pgm cyclic buffer on the card */
+
+
+       /* Miscellaneous */
+       u32 open_id;                    /* incremented each time an open occurs, is >= 1 */
+       int search_pack_header;         /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */
+       int speed;                      /* current playback speed setting */
+       u8 speed_mute_audio;            /* 1 if audio should be muted when fast forward */
+       u64 mpg_data_received;          /* number of bytes received from the MPEG stream */
+       u64 vbi_data_inserted;          /* number of VBI bytes inserted into the MPEG stream */
+       u32 last_dec_timing[3];         /* cache last retrieved pts/scr/frame values */
+       unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */
+       u32 dualwatch_stereo_mode;      /* current detected dualwatch stereo mode */
+
+
+       /* VBI state info */
+       struct vbi_info vbi;            /* VBI-specific data */
+
+
+       /* YUV playback */
+       struct yuv_playback_info yuv_info;              /* YUV playback data */
+
+
+       /* OSD support */
+       unsigned long osd_video_pbase;
+       int osd_global_alpha_state;     /* 1 = global alpha is on */
+       int osd_local_alpha_state;      /* 1 = local alpha is on */
+       int osd_chroma_key_state;       /* 1 = chroma-keying is on */
+       u8  osd_global_alpha;           /* current global alpha */
+       u32 osd_chroma_key;             /* current chroma key */
+       struct v4l2_rect osd_rect;      /* current OSD position and size */
+       struct v4l2_rect main_rect;     /* current Main window position and size */
+       struct osd_info *osd_info;      /* ivtvfb private OSD info */
+       void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */
+};
+
+static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct ivtv, v4l2_dev);
+}
+
+/* Globals */
+extern int ivtv_first_minor;
+
+/*==============Prototypes==================*/
+
+/* Hardware/IRQ */
+void ivtv_set_irq_mask(struct ivtv *itv, u32 mask);
+void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask);
+
+/* try to set output mode, return current mode. */
+int ivtv_set_output_mode(struct ivtv *itv, int mode);
+
+/* return current output stream based on current mode */
+struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv);
+
+/* Return non-zero if a signal is pending */
+int ivtv_msleep_timeout(unsigned int msecs, int intr);
+
+/* Wait on queue, returns -EINTR if interrupted */
+int ivtv_waitq(wait_queue_head_t *waitq);
+
+/* Read Hauppauge eeprom */
+struct tveeprom; /* forward reference */
+void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
+
+/* First-open initialization: load firmware, init cx25840, etc. */
+int ivtv_init_on_first_open(struct ivtv *itv);
+
+/* Test if the current VBI mode is raw (1) or sliced (0) */
+static inline int ivtv_raw_vbi(const struct ivtv *itv)
+{
+       return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
+}
+
+/* This is a PCI post thing, where if the pci register is not read, then
+   the write doesn't always take effect right away. By reading back the
+   register any pending PCI writes will be performed (in order), and so
+   you can be sure that the writes are guaranteed to be done.
+
+   Rarely needed, only in some timing sensitive cases.
+   Apparently if this is not done some motherboards seem
+   to kill the firmware and get into the broken state until computer is
+   rebooted. */
+#define write_sync(val, reg) \
+       do { writel(val, reg); readl(reg); } while (0)
+
+#define read_reg(reg) readl(itv->reg_mem + (reg))
+#define write_reg(val, reg) writel(val, itv->reg_mem + (reg))
+#define write_reg_sync(val, reg) \
+       do { write_reg(val, reg); read_reg(reg); } while (0)
+
+#define read_enc(addr) readl(itv->enc_mem + (u32)(addr))
+#define write_enc(val, addr) writel(val, itv->enc_mem + (u32)(addr))
+#define write_enc_sync(val, addr) \
+       do { write_enc(val, addr); read_enc(addr); } while (0)
+
+#define read_dec(addr) readl(itv->dec_mem + (u32)(addr))
+#define write_dec(val, addr) writel(val, itv->dec_mem + (u32)(addr))
+#define write_dec_sync(val, addr) \
+       do { write_dec(val, addr); read_dec(addr); } while (0)
+
+/* Call the specified callback for all subdevs matching hw (if 0, then
+   match them all). Ignore any errors. */
+#define ivtv_call_hw(itv, hw, o, f, args...)                           \
+       do {                                                            \
+               struct v4l2_subdev *__sd;                               \
+               __v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd,    \
+                       !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
+       } while (0)
+
+#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
+
+/* Call the specified callback for all subdevs matching hw (if 0, then
+   match them all). If the callback returns an error other than 0 or
+   -ENOIOCTLCMD, then return with that error code. */
+#define ivtv_call_hw_err(itv, hw, o, f, args...)                       \
+({                                                                     \
+       struct v4l2_subdev *__sd;                                       \
+       __v4l2_device_call_subdevs_until_err_p(&(itv)->v4l2_dev, __sd,  \
+               !(hw) || (__sd->grp_id & (hw)), o, f , ##args);         \
+})
+
+#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args)
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c
new file mode 100644 (file)
index 0000000..88bce90
--- /dev/null
@@ -0,0 +1,1070 @@
+/*
+    file operation functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-fileops.h"
+#include "ivtv-i2c.h"
+#include "ivtv-queue.h"
+#include "ivtv-udma.h"
+#include "ivtv-irq.h"
+#include "ivtv-vbi.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-routing.h"
+#include "ivtv-streams.h"
+#include "ivtv-yuv.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include "ivtv-firmware.h"
+#include <media/v4l2-event.h>
+#include <media/saa7115.h>
+
+/* This function tries to claim the stream for a specific file descriptor.
+   If no one else is using this stream then the stream is claimed and
+   associated VBI streams are also automatically claimed.
+   Possible error returns: -EBUSY if someone else has claimed
+   the stream or 0 on success. */
+static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
+{
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[type];
+       struct ivtv_stream *s_vbi;
+       int vbi_type;
+
+       if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
+               /* someone already claimed this stream */
+               if (s->fh == &id->fh) {
+                       /* yes, this file descriptor did. So that's OK. */
+                       return 0;
+               }
+               if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
+                                        type == IVTV_ENC_STREAM_TYPE_VBI)) {
+                       /* VBI is handled already internally, now also assign
+                          the file descriptor to this stream for external
+                          reading of the stream. */
+                       s->fh = &id->fh;
+                       IVTV_DEBUG_INFO("Start Read VBI\n");
+                       return 0;
+               }
+               /* someone else is using this stream already */
+               IVTV_DEBUG_INFO("Stream %d is busy\n", type);
+               return -EBUSY;
+       }
+       s->fh = &id->fh;
+       if (type == IVTV_DEC_STREAM_TYPE_VBI) {
+               /* Enable reinsertion interrupt */
+               ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+       }
+
+       /* IVTV_DEC_STREAM_TYPE_MPG needs to claim IVTV_DEC_STREAM_TYPE_VBI,
+          IVTV_ENC_STREAM_TYPE_MPG needs to claim IVTV_ENC_STREAM_TYPE_VBI
+          (provided VBI insertion is on and sliced VBI is selected), for all
+          other streams we're done */
+       if (type == IVTV_DEC_STREAM_TYPE_MPG) {
+               vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
+       } else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
+                  itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) {
+               vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
+       } else {
+               return 0;
+       }
+       s_vbi = &itv->streams[vbi_type];
+
+       if (!test_and_set_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags)) {
+               /* Enable reinsertion interrupt */
+               if (vbi_type == IVTV_DEC_STREAM_TYPE_VBI)
+                       ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+       }
+       /* mark that it is used internally */
+       set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags);
+       return 0;
+}
+
+/* This function releases a previously claimed stream. It will take into
+   account associated VBI streams. */
+void ivtv_release_stream(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+       struct ivtv_stream *s_vbi;
+
+       s->fh = NULL;
+       if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
+               test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
+               /* this stream is still in use internally */
+               return;
+       }
+       if (!test_and_clear_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
+               IVTV_DEBUG_WARN("Release stream %s not in use!\n", s->name);
+               return;
+       }
+
+       ivtv_flush_queues(s);
+
+       /* disable reinsertion interrupt */
+       if (s->type == IVTV_DEC_STREAM_TYPE_VBI)
+               ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+
+       /* IVTV_DEC_STREAM_TYPE_MPG needs to release IVTV_DEC_STREAM_TYPE_VBI,
+          IVTV_ENC_STREAM_TYPE_MPG needs to release IVTV_ENC_STREAM_TYPE_VBI,
+          for all other streams we're done */
+       if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+               s_vbi = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
+       else if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+               s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+       else
+               return;
+
+       /* clear internal use flag */
+       if (!test_and_clear_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
+               /* was already cleared */
+               return;
+       }
+       if (s_vbi->fh) {
+               /* VBI stream still claimed by a file descriptor */
+               return;
+       }
+       /* disable reinsertion interrupt */
+       if (s_vbi->type == IVTV_DEC_STREAM_TYPE_VBI)
+               ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+       clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags);
+       ivtv_flush_queues(s_vbi);
+}
+
+static void ivtv_dualwatch(struct ivtv *itv)
+{
+       struct v4l2_tuner vt;
+       u32 new_stereo_mode;
+       const u32 dual = 0x02;
+
+       new_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
+       memset(&vt, 0, sizeof(vt));
+       ivtv_call_all(itv, tuner, g_tuner, &vt);
+       if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
+               new_stereo_mode = dual;
+
+       if (new_stereo_mode == itv->dualwatch_stereo_mode)
+               return;
+
+       IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
+                          itv->dualwatch_stereo_mode, new_stereo_mode);
+       if (v4l2_ctrl_s_ctrl(itv->cxhdl.audio_mode, new_stereo_mode))
+               IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+}
+
+static void ivtv_update_pgm_info(struct ivtv *itv)
+{
+       u32 wr_idx = (read_enc(itv->pgm_info_offset) - itv->pgm_info_offset - 4) / 24;
+       int cnt;
+       int i = 0;
+
+       if (wr_idx >= itv->pgm_info_num) {
+               IVTV_DEBUG_WARN("Invalid PGM index %d (>= %d)\n", wr_idx, itv->pgm_info_num);
+               return;
+       }
+       cnt = (wr_idx + itv->pgm_info_num - itv->pgm_info_write_idx) % itv->pgm_info_num;
+       while (i < cnt) {
+               int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
+               struct v4l2_enc_idx_entry *e = itv->pgm_info + idx;
+               u32 addr = itv->pgm_info_offset + 4 + idx * 24;
+               const int mapping[8] = { -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, -1,
+                       V4L2_ENC_IDX_FRAME_B, -1, -1, -1 };
+                                       // 1=I, 2=P, 4=B
+
+               e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32);
+               if (e->offset > itv->mpg_data_received) {
+                       break;
+               }
+               e->offset += itv->vbi_data_inserted;
+               e->length = read_enc(addr);
+               e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32);
+               e->flags = mapping[read_enc(addr + 12) & 7];
+               i++;
+       }
+       itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
+}
+
+static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)
+{
+       struct ivtv *itv = s->itv;
+       struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+       struct ivtv_buffer *buf;
+       DEFINE_WAIT(wait);
+
+       *err = 0;
+       while (1) {
+               if (s->type == IVTV_ENC_STREAM_TYPE_MPG) {
+                       /* Process pending program info updates and pending VBI data */
+                       ivtv_update_pgm_info(itv);
+
+                       if (time_after(jiffies,
+                                      itv->dualwatch_jiffies +
+                                      msecs_to_jiffies(1000))) {
+                               itv->dualwatch_jiffies = jiffies;
+                               ivtv_dualwatch(itv);
+                       }
+
+                       if (test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+                           !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) {
+                               while ((buf = ivtv_dequeue(s_vbi, &s_vbi->q_full))) {
+                                       /* byteswap and process VBI data */
+                                       ivtv_process_vbi_data(itv, buf, s_vbi->dma_pts, s_vbi->type);
+                                       ivtv_enqueue(s_vbi, buf, &s_vbi->q_free);
+                               }
+                       }
+                       buf = &itv->vbi.sliced_mpeg_buf;
+                       if (buf->readpos != buf->bytesused) {
+                               return buf;
+                       }
+               }
+
+               /* do we have leftover data? */
+               buf = ivtv_dequeue(s, &s->q_io);
+               if (buf)
+                       return buf;
+
+               /* do we have new data? */
+               buf = ivtv_dequeue(s, &s->q_full);
+               if (buf) {
+                       if ((buf->b_flags & IVTV_F_B_NEED_BUF_SWAP) == 0)
+                               return buf;
+                       buf->b_flags &= ~IVTV_F_B_NEED_BUF_SWAP;
+                       if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+                               /* byteswap MPG data */
+                               ivtv_buf_swap(buf);
+                       else if (s->type != IVTV_DEC_STREAM_TYPE_VBI) {
+                               /* byteswap and process VBI data */
+                               ivtv_process_vbi_data(itv, buf, s->dma_pts, s->type);
+                       }
+                       return buf;
+               }
+
+               /* return if end of stream */
+               if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+                       IVTV_DEBUG_INFO("EOS %s\n", s->name);
+                       return NULL;
+               }
+
+               /* return if file was opened with O_NONBLOCK */
+               if (non_block) {
+                       *err = -EAGAIN;
+                       return NULL;
+               }
+
+               /* wait for more data to arrive */
+               mutex_unlock(&itv->serialize_lock);
+               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+               /* New buffers might have become available before we were added to the waitqueue */
+               if (!s->q_full.buffers)
+                       schedule();
+               finish_wait(&s->waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
+               if (signal_pending(current)) {
+                       /* return if a signal was received */
+                       IVTV_DEBUG_INFO("User stopped %s\n", s->name);
+                       *err = -EINTR;
+                       return NULL;
+               }
+       }
+}
+
+static void ivtv_setup_sliced_vbi_buf(struct ivtv *itv)
+{
+       int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES;
+
+       itv->vbi.sliced_mpeg_buf.buf = itv->vbi.sliced_mpeg_data[idx];
+       itv->vbi.sliced_mpeg_buf.bytesused = itv->vbi.sliced_mpeg_size[idx];
+       itv->vbi.sliced_mpeg_buf.readpos = 0;
+}
+
+static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *buf,
+               char __user *ubuf, size_t ucount)
+{
+       struct ivtv *itv = s->itv;
+       size_t len = buf->bytesused - buf->readpos;
+
+       if (len > ucount) len = ucount;
+       if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
+           !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) {
+               const char *start = buf->buf + buf->readpos;
+               const char *p = start + 1;
+               const u8 *q;
+               u8 ch = itv->search_pack_header ? 0xba : 0xe0;
+               int stuffing, i;
+
+               while (start + len > p && (q = memchr(p, 0, start + len - p))) {
+                       p = q + 1;
+                       if ((char *)q + 15 >= buf->buf + buf->bytesused ||
+                           q[1] != 0 || q[2] != 1 || q[3] != ch) {
+                               continue;
+                       }
+                       if (!itv->search_pack_header) {
+                               if ((q[6] & 0xc0) != 0x80)
+                                       continue;
+                               if (((q[7] & 0xc0) == 0x80 && (q[9] & 0xf0) == 0x20) ||
+                                   ((q[7] & 0xc0) == 0xc0 && (q[9] & 0xf0) == 0x30)) {
+                                       ch = 0xba;
+                                       itv->search_pack_header = 1;
+                                       p = q + 9;
+                               }
+                               continue;
+                       }
+                       stuffing = q[13] & 7;
+                       /* all stuffing bytes must be 0xff */
+                       for (i = 0; i < stuffing; i++)
+                               if (q[14 + i] != 0xff)
+                                       break;
+                       if (i == stuffing && (q[4] & 0xc4) == 0x44 && (q[12] & 3) == 3 &&
+                                       q[14 + stuffing] == 0 && q[15 + stuffing] == 0 &&
+                                       q[16 + stuffing] == 1) {
+                               itv->search_pack_header = 0;
+                               len = (char *)q - start;
+                               ivtv_setup_sliced_vbi_buf(itv);
+                               break;
+                       }
+               }
+       }
+       if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
+               IVTV_DEBUG_WARN("copy %zd bytes to user failed for %s\n", len, s->name);
+               return -EFAULT;
+       }
+       /*IVTV_INFO("copied %lld %d %d %d %d %d vbi %d\n", itv->mpg_data_received, len, ucount,
+                       buf->readpos, buf->bytesused, buf->bytesused - buf->readpos - len,
+                       buf == &itv->vbi.sliced_mpeg_buf); */
+       buf->readpos += len;
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG && buf != &itv->vbi.sliced_mpeg_buf)
+               itv->mpg_data_received += len;
+       return len;
+}
+
+static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_count, int non_block)
+{
+       struct ivtv *itv = s->itv;
+       size_t tot_written = 0;
+       int single_frame = 0;
+
+       if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
+               /* shouldn't happen */
+               IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
+               return -EIO;
+       }
+
+       /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
+          arrive one-by-one, so make sure we never output more than one VBI frame at a time */
+       if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
+           (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv)))
+               single_frame = 1;
+
+       for (;;) {
+               struct ivtv_buffer *buf;
+               int rc;
+
+               buf = ivtv_get_buffer(s, non_block, &rc);
+               /* if there is no data available... */
+               if (buf == NULL) {
+                       /* if we got data, then return that regardless */
+                       if (tot_written)
+                               break;
+                       /* EOS condition */
+                       if (rc == 0) {
+                               clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+                               clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+                               ivtv_release_stream(s);
+                       }
+                       /* set errno */
+                       return rc;
+               }
+               rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written);
+               if (buf != &itv->vbi.sliced_mpeg_buf) {
+                       ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io);
+               }
+               else if (buf->readpos == buf->bytesused) {
+                       int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES;
+                       itv->vbi.sliced_mpeg_size[idx] = 0;
+                       itv->vbi.inserted_frame++;
+                       itv->vbi_data_inserted += buf->bytesused;
+               }
+               if (rc < 0)
+                       return rc;
+               tot_written += rc;
+
+               if (tot_written == tot_count || single_frame)
+                       break;
+       }
+       return tot_written;
+}
+
+static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t count,
+                       loff_t *pos, int non_block)
+{
+       ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0;
+       struct ivtv *itv = s->itv;
+
+       IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
+       if (rc > 0)
+               pos += rc;
+       return rc;
+}
+
+int ivtv_start_capture(struct ivtv_open_id *id)
+{
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       struct ivtv_stream *s_vbi;
+
+       if (s->type == IVTV_ENC_STREAM_TYPE_RAD ||
+           s->type == IVTV_DEC_STREAM_TYPE_MPG ||
+           s->type == IVTV_DEC_STREAM_TYPE_YUV ||
+           s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
+               /* you cannot read from these stream types. */
+               return -EPERM;
+       }
+
+       /* Try to claim this stream. */
+       if (ivtv_claim_stream(id, s->type))
+               return -EBUSY;
+
+       /* This stream does not need to start capturing */
+       if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+               return 0;
+       }
+
+       /* If capture is already in progress, then we also have to
+          do nothing extra. */
+       if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+               return 0;
+       }
+
+       /* Start VBI capture if required */
+       s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG &&
+           test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+           !test_and_set_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) {
+               /* Note: the IVTV_ENC_STREAM_TYPE_VBI is claimed
+                  automatically when the MPG stream is claimed.
+                  We only need to start the VBI capturing. */
+               if (ivtv_start_v4l2_encode_stream(s_vbi)) {
+                       IVTV_DEBUG_WARN("VBI capture start failed\n");
+
+                       /* Failure, clean up and return an error */
+                       clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags);
+                       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+                       /* also releases the associated VBI stream */
+                       ivtv_release_stream(s);
+                       return -EIO;
+               }
+               IVTV_DEBUG_INFO("VBI insertion started\n");
+       }
+
+       /* Tell the card to start capturing */
+       if (!ivtv_start_v4l2_encode_stream(s)) {
+               /* We're done */
+               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+               /* Resume a possibly paused encoder */
+               if (test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
+                       ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
+               return 0;
+       }
+
+       /* failure, clean up */
+       IVTV_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
+
+       /* Note: the IVTV_ENC_STREAM_TYPE_VBI is released
+          automatically when the MPG stream is released.
+          We only need to stop the VBI capturing. */
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG &&
+           test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) {
+               ivtv_stop_v4l2_encode_stream(s_vbi, 0);
+               clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags);
+       }
+       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+       ivtv_release_stream(s);
+       return -EIO;
+}
+
+ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos)
+{
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       ssize_t rc;
+
+       IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+
+       if (mutex_lock_interruptible(&itv->serialize_lock))
+               return -ERESTARTSYS;
+       rc = ivtv_start_capture(id);
+       if (!rc)
+               rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+       mutex_unlock(&itv->serialize_lock);
+       return rc;
+}
+
+int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
+{
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       int rc;
+
+       if (atomic_read(&itv->decoding) == 0) {
+               if (ivtv_claim_stream(id, s->type)) {
+                       /* someone else is using this stream already */
+                       IVTV_DEBUG_WARN("start decode, stream already claimed\n");
+                       return -EBUSY;
+               }
+               rc = ivtv_start_v4l2_decode_stream(s, 0);
+               if (rc < 0) {
+                       if (rc == -EAGAIN)
+                               rc = ivtv_start_v4l2_decode_stream(s, 0);
+                       if (rc < 0)
+                               return rc;
+               }
+       }
+       if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+               return ivtv_set_speed(itv, speed);
+       return 0;
+}
+
+static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
+{
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       struct ivtv_buffer *buf;
+       struct ivtv_queue q;
+       int bytes_written = 0;
+       int mode;
+       int rc;
+       DEFINE_WAIT(wait);
+
+       IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);
+
+       if (s->type != IVTV_DEC_STREAM_TYPE_MPG &&
+           s->type != IVTV_DEC_STREAM_TYPE_YUV &&
+           s->type != IVTV_DEC_STREAM_TYPE_VOUT)
+               /* not decoder streams */
+               return -EPERM;
+
+       /* Try to claim this stream */
+       if (ivtv_claim_stream(id, s->type))
+               return -EBUSY;
+
+       /* This stream does not need to start any decoding */
+       if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
+               int elems = count / sizeof(struct v4l2_sliced_vbi_data);
+
+               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+               return ivtv_write_vbi_from_user(itv,
+                  (const struct v4l2_sliced_vbi_data __user *)user_buf, elems);
+       }
+
+       mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
+
+       if (ivtv_set_output_mode(itv, mode) != mode) {
+           ivtv_release_stream(s);
+           return -EBUSY;
+       }
+       ivtv_queue_init(&q);
+       set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+
+       /* Start decoder (returns 0 if already started) */
+       rc = ivtv_start_decoding(id, itv->speed);
+       if (rc) {
+               IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
+
+               /* failure, clean up */
+               clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+               clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+               return rc;
+       }
+
+retry:
+       /* If possible, just DMA the entire frame - Check the data transfer size
+       since we may get here before the stream has been fully set-up */
+       if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
+               while (count >= itv->dma_data_req_size) {
+                       rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf);
+
+                       if (rc < 0)
+                               return rc;
+
+                       bytes_written += itv->dma_data_req_size;
+                       user_buf += itv->dma_data_req_size;
+                       count -= itv->dma_data_req_size;
+               }
+               if (count == 0) {
+                       IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
+                       return bytes_written;
+               }
+       }
+
+       for (;;) {
+               /* Gather buffers */
+               while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io)))
+                       ivtv_enqueue(s, buf, &q);
+               while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_free))) {
+                       ivtv_enqueue(s, buf, &q);
+               }
+               if (q.buffers)
+                       break;
+               if (filp->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               mutex_unlock(&itv->serialize_lock);
+               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+               /* New buffers might have become free before we were added to the waitqueue */
+               if (!s->q_free.buffers)
+                       schedule();
+               finish_wait(&s->waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
+               if (signal_pending(current)) {
+                       IVTV_DEBUG_INFO("User stopped %s\n", s->name);
+                       return -EINTR;
+               }
+       }
+
+       /* copy user data into buffers */
+       while ((buf = ivtv_dequeue(s, &q))) {
+               /* yuv is a pain. Don't copy more data than needed for a single
+                  frame, otherwise we lose sync with the incoming stream */
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
+                   yi->stream_size + count > itv->dma_data_req_size)
+                       rc  = ivtv_buf_copy_from_user(s, buf, user_buf,
+                               itv->dma_data_req_size - yi->stream_size);
+               else
+                       rc = ivtv_buf_copy_from_user(s, buf, user_buf, count);
+
+               /* Make sure we really got all the user data */
+               if (rc < 0) {
+                       ivtv_queue_move(s, &q, NULL, &s->q_free, 0);
+                       return rc;
+               }
+               user_buf += rc;
+               count -= rc;
+               bytes_written += rc;
+
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+                       yi->stream_size += rc;
+                       /* If we have a complete yuv frame, break loop now */
+                       if (yi->stream_size == itv->dma_data_req_size) {
+                               ivtv_enqueue(s, buf, &s->q_full);
+                               yi->stream_size = 0;
+                               break;
+                       }
+               }
+
+               if (buf->bytesused != s->buf_size) {
+                       /* incomplete, leave in q_io for next time */
+                       ivtv_enqueue(s, buf, &s->q_io);
+                       break;
+               }
+               /* Byteswap MPEG buffer */
+               if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+                       ivtv_buf_swap(buf);
+               ivtv_enqueue(s, buf, &s->q_full);
+       }
+
+       if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
+               if (s->q_full.length >= itv->dma_data_req_size) {
+                       int got_sig;
+
+                       if (mode == OUT_YUV)
+                               ivtv_yuv_setup_stream_frame(itv);
+
+                       mutex_unlock(&itv->serialize_lock);
+                       prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+                       while (!(got_sig = signal_pending(current)) &&
+                                       test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
+                               schedule();
+                       }
+                       finish_wait(&itv->dma_waitq, &wait);
+                       mutex_lock(&itv->serialize_lock);
+                       if (got_sig) {
+                               IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
+                               return -EINTR;
+                       }
+
+                       clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+                       ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
+                       ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 1);
+               }
+       }
+       /* more user data is available, wait until buffers become free
+          to transfer the rest. */
+       if (count && !(filp->f_flags & O_NONBLOCK))
+               goto retry;
+       IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
+       return bytes_written;
+}
+
+ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
+{
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       ssize_t res;
+
+       if (mutex_lock_interruptible(&itv->serialize_lock))
+               return -ERESTARTSYS;
+       res = ivtv_write(filp, user_buf, count, pos);
+       mutex_unlock(&itv->serialize_lock);
+       return res;
+}
+
+unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
+{
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       int res = 0;
+
+       /* add stream's waitq to the poll list */
+       IVTV_DEBUG_HI_FILE("Decoder poll\n");
+
+       /* If there are subscribed events, then only use the new event
+          API instead of the old video.h based API. */
+       if (!list_empty(&id->fh.subscribed)) {
+               poll_wait(filp, &id->fh.wait, wait);
+               /* Turn off the old-style vsync events */
+               clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+               if (v4l2_event_pending(&id->fh))
+                       res = POLLPRI;
+       } else {
+               /* This is the old-style API which is here only for backwards
+                  compatibility. */
+               poll_wait(filp, &s->waitq, wait);
+               set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+               if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) ||
+                   test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
+                       res = POLLPRI;
+       }
+
+       /* Allow write if buffers are available for writing */
+       if (s->q_free.buffers)
+               res |= POLLOUT | POLLWRNORM;
+       return res;
+}
+
+unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait)
+{
+       unsigned long req_events = poll_requested_events(wait);
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+       unsigned res = 0;
+
+       /* Start a capture if there is none */
+       if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) &&
+                       (req_events & (POLLIN | POLLRDNORM))) {
+               int rc;
+
+               mutex_lock(&itv->serialize_lock);
+               rc = ivtv_start_capture(id);
+               mutex_unlock(&itv->serialize_lock);
+               if (rc) {
+                       IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
+                                       s->name, rc);
+                       return POLLERR;
+               }
+               IVTV_DEBUG_FILE("Encoder poll started capture\n");
+       }
+
+       /* add stream's waitq to the poll list */
+       IVTV_DEBUG_HI_FILE("Encoder poll\n");
+       poll_wait(filp, &s->waitq, wait);
+       if (v4l2_event_pending(&id->fh))
+               res |= POLLPRI;
+       else
+               poll_wait(filp, &id->fh.wait, wait);
+
+       if (s->q_full.length || s->q_io.length)
+               return res | POLLIN | POLLRDNORM;
+       if (eof)
+               return res | POLLHUP;
+       return res;
+}
+
+void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
+{
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+
+       IVTV_DEBUG_FILE("close() of %s\n", s->name);
+
+       /* 'Unclaim' this stream */
+
+       /* Stop capturing */
+       if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+               struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+
+               IVTV_DEBUG_INFO("close stopping capture\n");
+               /* Special case: a running VBI capture for VBI insertion
+                  in the mpeg stream. Need to stop that too. */
+               if (id->type == IVTV_ENC_STREAM_TYPE_MPG &&
+                   test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags) &&
+                   !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) {
+                       IVTV_DEBUG_INFO("close stopping embedded VBI capture\n");
+                       ivtv_stop_v4l2_encode_stream(s_vbi, 0);
+               }
+               if ((id->type == IVTV_DEC_STREAM_TYPE_VBI ||
+                    id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
+                   test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
+                       /* Also used internally, don't stop capturing */
+                       s->fh = NULL;
+               }
+               else {
+                       ivtv_stop_v4l2_encode_stream(s, gop_end);
+               }
+       }
+       if (!gop_end) {
+               clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+               clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+               ivtv_release_stream(s);
+       }
+}
+
+static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
+{
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+
+       IVTV_DEBUG_FILE("close() of %s\n", s->name);
+
+       if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
+               test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
+               /* Restore registers we've changed & clean up any mess */
+               ivtv_yuv_close(itv);
+       }
+
+       /* Stop decoding */
+       if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+               IVTV_DEBUG_INFO("close stopping decode\n");
+
+               ivtv_stop_v4l2_decode_stream(s, flags, pts);
+               itv->output_mode = OUT_NONE;
+       }
+       clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+       clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+
+       if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
+               itv->output_mode = OUT_NONE;
+
+       itv->speed = 0;
+       clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
+       ivtv_release_stream(s);
+}
+
+int ivtv_v4l2_close(struct file *filp)
+{
+       struct v4l2_fh *fh = filp->private_data;
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+
+       IVTV_DEBUG_FILE("close %s\n", s->name);
+
+       mutex_lock(&itv->serialize_lock);
+
+       /* Stop radio */
+       if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
+               /* Closing radio device, return to TV mode */
+               ivtv_mute(itv);
+               /* Mark that the radio is no longer in use */
+               clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
+               /* Switch tuner to TV */
+               ivtv_call_all(itv, core, s_std, itv->std);
+               /* Select correct audio input (i.e. TV tuner or Line in) */
+               ivtv_audio_set_io(itv);
+               if (itv->hw_flags & IVTV_HW_SAA711X) {
+                       ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
+                                       SAA7115_FREQ_32_11_MHZ, 0);
+               }
+               if (atomic_read(&itv->capturing) > 0) {
+                       /* Undo video mute */
+                       ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+                                       v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
+                                       (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+               }
+               /* Done! Unmute and continue. */
+               ivtv_unmute(itv);
+       }
+
+       v4l2_fh_del(fh);
+       v4l2_fh_exit(fh);
+
+       /* Easy case first: this stream was never claimed by us */
+       if (s->fh != &id->fh)
+               goto close_done;
+
+       /* 'Unclaim' this stream */
+
+       if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+               struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
+
+               ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
+
+               /* If all output streams are closed, and if the user doesn't have
+                  IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */
+               if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) {
+                       /* disable CC on TV-out */
+                       ivtv_disable_cc(itv);
+               }
+       } else {
+               ivtv_stop_capture(id, 0);
+       }
+close_done:
+       kfree(id);
+       mutex_unlock(&itv->serialize_lock);
+       return 0;
+}
+
+static int ivtv_open(struct file *filp)
+{
+       struct video_device *vdev = video_devdata(filp);
+       struct ivtv_stream *s = video_get_drvdata(vdev);
+       struct ivtv *itv = s->itv;
+       struct ivtv_open_id *item;
+       int res = 0;
+
+       IVTV_DEBUG_FILE("open %s\n", s->name);
+
+       if (ivtv_init_on_first_open(itv)) {
+               IVTV_ERR("Failed to initialize on device %s\n",
+                        video_device_node_name(vdev));
+               return -ENXIO;
+       }
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       /* Unless ivtv_fw_debug is set, error out if firmware dead. */
+       if (ivtv_fw_debug) {
+               IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
+                         video_device_node_name(vdev));
+               IVTV_WARN("Selected firmware errors will be ignored\n");
+       } else {
+#else
+       if (1) {
+#endif
+               res = ivtv_firmware_check(itv, "ivtv_serialized_open");
+               if (res == -EAGAIN)
+                       res = ivtv_firmware_check(itv, "ivtv_serialized_open");
+               if (res < 0)
+                       return -EIO;
+       }
+
+       if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
+               test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
+               return -EBUSY;
+
+       if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
+               test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags))
+               return -EBUSY;
+
+       if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+               if (read_reg(0x82c) == 0) {
+                       IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n");
+                       /* return -ENODEV; */
+               }
+               ivtv_udma_alloc(itv);
+       }
+
+       /* Allocate memory */
+       item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
+       if (NULL == item) {
+               IVTV_DEBUG_WARN("nomem on v4l2 open\n");
+               return -ENOMEM;
+       }
+       v4l2_fh_init(&item->fh, s->vdev);
+       item->itv = itv;
+       item->type = s->type;
+
+       filp->private_data = &item->fh;
+       v4l2_fh_add(&item->fh);
+
+       if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
+                       v4l2_fh_is_singular_file(filp)) {
+               if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
+                       if (atomic_read(&itv->capturing) > 0) {
+                               /* switching to radio while capture is
+                                  in progress is not polite */
+                               v4l2_fh_del(&item->fh);
+                               v4l2_fh_exit(&item->fh);
+                               kfree(item);
+                               return -EBUSY;
+                       }
+               }
+               /* Mark that the radio is being used. */
+               set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
+               /* We have the radio */
+               ivtv_mute(itv);
+               /* Switch tuner to radio */
+               ivtv_call_all(itv, tuner, s_radio);
+               /* Select the correct audio input (i.e. radio tuner) */
+               ivtv_audio_set_io(itv);
+               if (itv->hw_flags & IVTV_HW_SAA711X) {
+                       ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
+                               SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL);
+               }
+               /* Done! Unmute and continue. */
+               ivtv_unmute(itv);
+       }
+
+       /* YUV or MPG Decoding Mode? */
+       if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
+               clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
+       } else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+               set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
+               /* For yuv, we need to know the dma size before we start */
+               itv->dma_data_req_size =
+                               1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
+               itv->yuv_info.stream_size = 0;
+       }
+       return 0;
+}
+
+int ivtv_v4l2_open(struct file *filp)
+{
+       struct video_device *vdev = video_devdata(filp);
+       int res;
+
+       if (mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
+       res = ivtv_open(filp);
+       mutex_unlock(vdev->lock);
+       return res;
+}
+
+void ivtv_mute(struct ivtv *itv)
+{
+       if (atomic_read(&itv->capturing))
+               ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1);
+       IVTV_DEBUG_INFO("Mute\n");
+}
+
+void ivtv_unmute(struct ivtv *itv)
+{
+       if (atomic_read(&itv->capturing)) {
+               ivtv_msleep_timeout(100, 0);
+               ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
+               ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
+       }
+       IVTV_DEBUG_INFO("Unmute\n");
+}
diff --git a/drivers/media/pci/ivtv/ivtv-fileops.h b/drivers/media/pci/ivtv/ivtv-fileops.h
new file mode 100644 (file)
index 0000000..049a292
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    file operation functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_FILEOPS_H
+#define IVTV_FILEOPS_H
+
+/* Testing/Debugging */
+int ivtv_v4l2_open(struct file *filp);
+ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                     loff_t * pos);
+ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count,
+                      loff_t * pos);
+int ivtv_v4l2_close(struct file *filp);
+unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait);
+unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait);
+int ivtv_start_capture(struct ivtv_open_id *id);
+void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end);
+int ivtv_start_decoding(struct ivtv_open_id *id, int speed);
+void ivtv_mute(struct ivtv *itv);
+void ivtv_unmute(struct ivtv *itv);
+
+/* Utilities */
+
+/* Release a previously claimed stream. */
+void ivtv_release_stream(struct ivtv_stream *s);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c
new file mode 100644 (file)
index 0000000..6ec7705
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+    ivtv firmware functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-firmware.h"
+#include "ivtv-yuv.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include <linux/firmware.h>
+#include <media/saa7127.h>
+
+#define IVTV_MASK_SPU_ENABLE           0xFFFFFFFE
+#define IVTV_MASK_VPU_ENABLE15                 0xFFFFFFF6
+#define IVTV_MASK_VPU_ENABLE16                 0xFFFFFFFB
+#define IVTV_CMD_VDM_STOP              0x00000000
+#define IVTV_CMD_AO_STOP               0x00000005
+#define IVTV_CMD_APU_PING              0x00000000
+#define IVTV_CMD_VPU_STOP15            0xFFFFFFFE
+#define IVTV_CMD_VPU_STOP16            0xFFFFFFEE
+#define IVTV_CMD_HW_BLOCKS_RST                 0xFFFFFFFF
+#define IVTV_CMD_SPU_STOP              0x00000001
+#define IVTV_CMD_SDRAM_PRECHARGE_INIT  0x0000001A
+#define IVTV_CMD_SDRAM_REFRESH_INIT    0x80000640
+#define IVTV_SDRAM_SLEEPTIME           600
+
+#define IVTV_DECODE_INIT_MPEG_FILENAME         "v4l-cx2341x-init.mpg"
+#define IVTV_DECODE_INIT_MPEG_SIZE     (152*1024)
+
+/* Encoder/decoder firmware sizes */
+#define IVTV_FW_ENC_SIZE               (376836)
+#define IVTV_FW_DEC_SIZE               (256*1024)
+
+static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size)
+{
+       const struct firmware *fw = NULL;
+       int retries = 3;
+
+retry:
+       if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) {
+               int i;
+               volatile u32 __iomem *dst = (volatile u32 __iomem *)mem;
+               const u32 *src = (const u32 *)fw->data;
+
+               if (fw->size != size) {
+                       /* Due to race conditions in firmware loading (esp. with udev <0.95)
+                          the wrong file was sometimes loaded. So we check filesizes to
+                          see if at least the right-sized file was loaded. If not, then we
+                          retry. */
+                       IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size);
+                       release_firmware(fw);
+                       retries--;
+                       goto retry;
+               }
+               for (i = 0; i < fw->size; i += 4) {
+                       /* no need for endianness conversion on the ppc */
+                       __raw_writel(*src, dst);
+                       dst++;
+                       src++;
+               }
+               IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size);
+               release_firmware(fw);
+               return size;
+       }
+       IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size);
+       IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n");
+       return -ENOMEM;
+}
+
+void ivtv_halt_firmware(struct ivtv *itv)
+{
+       IVTV_DEBUG_INFO("Preparing for firmware halt.\n");
+       if (itv->has_cx23415 && itv->dec_mbox.mbox)
+               ivtv_vapi(itv, CX2341X_DEC_HALT_FW, 0);
+       if (itv->enc_mbox.mbox)
+               ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0);
+
+       ivtv_msleep_timeout(10, 0);
+       itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL;
+
+       IVTV_DEBUG_INFO("Stopping VDM\n");
+       write_reg(IVTV_CMD_VDM_STOP, IVTV_REG_VDM);
+
+       IVTV_DEBUG_INFO("Stopping AO\n");
+       write_reg(IVTV_CMD_AO_STOP, IVTV_REG_AO);
+
+       IVTV_DEBUG_INFO("pinging (?) APU\n");
+       write_reg(IVTV_CMD_APU_PING, IVTV_REG_APU);
+
+       IVTV_DEBUG_INFO("Stopping VPU\n");
+       if (!itv->has_cx23415)
+               write_reg(IVTV_CMD_VPU_STOP16, IVTV_REG_VPU);
+       else
+               write_reg(IVTV_CMD_VPU_STOP15, IVTV_REG_VPU);
+
+       IVTV_DEBUG_INFO("Resetting Hw Blocks\n");
+       write_reg(IVTV_CMD_HW_BLOCKS_RST, IVTV_REG_HW_BLOCKS);
+
+       IVTV_DEBUG_INFO("Stopping SPU\n");
+       write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU);
+
+       ivtv_msleep_timeout(10, 0);
+
+       IVTV_DEBUG_INFO("init Encoder SDRAM pre-charge\n");
+       write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_ENC_SDRAM_PRECHARGE);
+
+       IVTV_DEBUG_INFO("init Encoder SDRAM refresh to 1us\n");
+       write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_ENC_SDRAM_REFRESH);
+
+       if (itv->has_cx23415) {
+               IVTV_DEBUG_INFO("init Decoder SDRAM pre-charge\n");
+               write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_DEC_SDRAM_PRECHARGE);
+
+               IVTV_DEBUG_INFO("init Decoder SDRAM refresh to 1us\n");
+               write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH);
+       }
+
+       IVTV_DEBUG_INFO("Sleeping for %dms\n", IVTV_SDRAM_SLEEPTIME);
+       ivtv_msleep_timeout(IVTV_SDRAM_SLEEPTIME, 0);
+}
+
+void ivtv_firmware_versions(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+
+       /* Encoder */
+       ivtv_vapi_result(itv, data, CX2341X_ENC_GET_VERSION, 0);
+       IVTV_INFO("Encoder revision: 0x%08x\n", data[0]);
+
+       if (data[0] != 0x02060039)
+               IVTV_WARN("Recommended firmware version is 0x02060039.\n");
+
+       if (itv->has_cx23415) {
+               /* Decoder */
+               ivtv_vapi_result(itv, data, CX2341X_DEC_GET_VERSION, 0);
+               IVTV_INFO("Decoder revision: 0x%08x\n", data[0]);
+       }
+}
+
+static int ivtv_firmware_copy(struct ivtv *itv)
+{
+       IVTV_DEBUG_INFO("Loading encoder image\n");
+       if (load_fw_direct(CX2341X_FIRM_ENC_FILENAME,
+                  itv->enc_mem, itv, IVTV_FW_ENC_SIZE) != IVTV_FW_ENC_SIZE) {
+               IVTV_DEBUG_WARN("failed loading encoder firmware\n");
+               return -3;
+       }
+       if (!itv->has_cx23415)
+               return 0;
+
+       IVTV_DEBUG_INFO("Loading decoder image\n");
+       if (load_fw_direct(CX2341X_FIRM_DEC_FILENAME,
+                  itv->dec_mem, itv, IVTV_FW_DEC_SIZE) != IVTV_FW_DEC_SIZE) {
+               IVTV_DEBUG_WARN("failed loading decoder firmware\n");
+               return -1;
+       }
+       return 0;
+}
+
+static volatile struct ivtv_mailbox __iomem *ivtv_search_mailbox(const volatile u8 __iomem *mem, u32 size)
+{
+       int i;
+
+       /* mailbox is preceded by a 16 byte 'magic cookie' starting at a 256-byte
+          address boundary */
+       for (i = 0; i < size; i += 0x100) {
+               if (readl(mem + i)      == 0x12345678 &&
+                   readl(mem + i + 4)  == 0x34567812 &&
+                   readl(mem + i + 8)  == 0x56781234 &&
+                   readl(mem + i + 12) == 0x78123456) {
+                       return (volatile struct ivtv_mailbox __iomem *)(mem + i + 16);
+               }
+       }
+       return NULL;
+}
+
+int ivtv_firmware_init(struct ivtv *itv)
+{
+       int err;
+
+       ivtv_halt_firmware(itv);
+
+       /* load firmware */
+       err = ivtv_firmware_copy(itv);
+       if (err) {
+               IVTV_DEBUG_WARN("Error %d loading firmware\n", err);
+               return err;
+       }
+
+       /* start firmware */
+       write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU);
+       ivtv_msleep_timeout(100, 0);
+       if (itv->has_cx23415)
+               write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE15, IVTV_REG_VPU);
+       else
+               write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE16, IVTV_REG_VPU);
+       ivtv_msleep_timeout(100, 0);
+
+       /* find mailboxes and ping firmware */
+       itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE);
+       if (itv->enc_mbox.mbox == NULL)
+               IVTV_ERR("Encoder mailbox not found\n");
+       else if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0)) {
+               IVTV_ERR("Encoder firmware dead!\n");
+               itv->enc_mbox.mbox = NULL;
+       }
+       if (itv->enc_mbox.mbox == NULL)
+               return -ENODEV;
+
+       if (!itv->has_cx23415)
+               return 0;
+
+       itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE);
+       if (itv->dec_mbox.mbox == NULL) {
+               IVTV_ERR("Decoder mailbox not found\n");
+       } else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) {
+               IVTV_ERR("Decoder firmware dead!\n");
+               itv->dec_mbox.mbox = NULL;
+       } else {
+               /* Firmware okay, so check yuv output filter table */
+               ivtv_yuv_filter_check(itv);
+       }
+       return itv->dec_mbox.mbox ? 0 : -ENODEV;
+}
+
+void ivtv_init_mpeg_decoder(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       long readbytes;
+       volatile u8 __iomem *mem_offset;
+
+       data[0] = 0;
+       data[1] = itv->cxhdl.width;     /* YUV source width */
+       data[2] = itv->cxhdl.height;
+       data[3] = itv->cxhdl.audio_properties;  /* Audio settings to use,
+                                                          bitmap. see docs. */
+       if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) {
+               IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n");
+               return;
+       }
+
+       if (ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1) != 0) {
+               IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n");
+               return;
+       }
+       ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
+       mem_offset = itv->dec_mem + data[1];
+
+       if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME,
+               mem_offset, itv, IVTV_DECODE_INIT_MPEG_SIZE)) <= 0) {
+               IVTV_DEBUG_WARN("failed to read mpeg decoder initialisation file %s\n",
+                               IVTV_DECODE_INIT_MPEG_FILENAME);
+       } else {
+               ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0);
+               ivtv_msleep_timeout(100, 0);
+       }
+       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1);
+}
+
+/* Try to restart the card & restore previous settings */
+int ivtv_firmware_restart(struct ivtv *itv)
+{
+       int rc = 0;
+       v4l2_std_id std;
+
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+               /* Display test image during restart */
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
+                   SAA7127_INPUT_TYPE_TEST_IMAGE,
+                   itv->card->video_outputs[itv->active_output].video_output,
+                   0);
+
+       mutex_lock(&itv->udma.lock);
+
+       rc = ivtv_firmware_init(itv);
+       if (rc) {
+               mutex_unlock(&itv->udma.lock);
+               return rc;
+       }
+
+       /* Allow settings to reload */
+       ivtv_mailbox_cache_invalidate(itv);
+
+       /* Restore encoder video standard */
+       std = itv->std;
+       itv->std = 0;
+       ivtv_s_std_enc(itv, &std);
+
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+               ivtv_init_mpeg_decoder(itv);
+
+               /* Restore decoder video standard */
+               std = itv->std_out;
+               itv->std_out = 0;
+               ivtv_s_std_dec(itv, &std);
+
+               /* Restore framebuffer if active */
+               if (itv->ivtvfb_restore)
+                       itv->ivtvfb_restore(itv);
+
+               /* Restore alpha settings */
+               ivtv_set_osd_alpha(itv);
+
+               /* Restore normal output */
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
+                   SAA7127_INPUT_TYPE_NORMAL,
+                   itv->card->video_outputs[itv->active_output].video_output,
+                   0);
+       }
+
+       mutex_unlock(&itv->udma.lock);
+       return rc;
+}
+
+/* Check firmware running state. The checks fall through
+   allowing multiple failures to be logged. */
+int ivtv_firmware_check(struct ivtv *itv, char *where)
+{
+       int res = 0;
+
+       /* Check encoder is still running */
+       if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) {
+               IVTV_WARN("Encoder has died : %s\n", where);
+               res = -1;
+       }
+
+       /* Also check audio. Only check if not in use & encoder is okay */
+       if (!res && !atomic_read(&itv->capturing) &&
+           (!atomic_read(&itv->decoding) ||
+            (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV,
+                                                            &itv->i_flags)))) {
+
+               if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) {
+                       IVTV_WARN("Audio has died (Encoder OK) : %s\n", where);
+                       res = -2;
+               }
+       }
+
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+               /* Second audio check. Skip if audio already failed */
+               if (res != -2 && read_dec(0x100) != read_dec(0x104)) {
+                       /* Wait & try again to be certain. */
+                       ivtv_msleep_timeout(14, 0);
+                       if (read_dec(0x100) != read_dec(0x104)) {
+                               IVTV_WARN("Audio has died (Decoder) : %s\n",
+                                         where);
+                               res = -1;
+                       }
+               }
+
+               /* Check decoder is still running */
+               if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) {
+                       IVTV_WARN("Decoder has died : %s\n", where);
+                       res = -1;
+               }
+       }
+
+       /* If something failed & currently idle, try to reload */
+       if (res && !atomic_read(&itv->capturing) &&
+                                               !atomic_read(&itv->decoding)) {
+               IVTV_INFO("Detected in %s that firmware had failed - "
+                         "Reloading\n", where);
+               res = ivtv_firmware_restart(itv);
+               /*
+                * Even if restarted ok, still signal a problem had occurred.
+                * The caller can come through this function again to check
+                * if things are really ok after the restart.
+                */
+               if (!res) {
+                       IVTV_INFO("Firmware restart okay\n");
+                       res = -EAGAIN;
+               } else {
+                       IVTV_INFO("Firmware restart failed\n");
+               }
+       } else if (res) {
+               res = -EIO;
+       }
+
+       return res;
+}
+
+MODULE_FIRMWARE(CX2341X_FIRM_ENC_FILENAME);
+MODULE_FIRMWARE(CX2341X_FIRM_DEC_FILENAME);
+MODULE_FIRMWARE(IVTV_DECODE_INIT_MPEG_FILENAME);
diff --git a/drivers/media/pci/ivtv/ivtv-firmware.h b/drivers/media/pci/ivtv/ivtv-firmware.h
new file mode 100644 (file)
index 0000000..52bb4e5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+    ivtv firmware functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_FIRMWARE_H
+#define IVTV_FIRMWARE_H
+
+int ivtv_firmware_init(struct ivtv *itv);
+void ivtv_firmware_versions(struct ivtv *itv);
+void ivtv_halt_firmware(struct ivtv *itv);
+void ivtv_init_mpeg_decoder(struct ivtv *itv);
+int ivtv_firmware_check(struct ivtv *itv, char *where);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-gpio.c b/drivers/media/pci/ivtv/ivtv-gpio.c
new file mode 100644 (file)
index 0000000..8f0d077
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+    gpio functions.
+    Merging GPIO support into driver:
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "tuner-xc2028.h"
+#include <media/tuner.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * GPIO assignment of Yuan MPG600/MPG160
+ *
+ *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
+ * OUTPUT         IN1 IN0                                       AM3 AM2 AM1 AM0
+ *  INPUT                   DM1         DM0
+ *
+ *   IN* : Input selection
+ *          IN1 IN0
+ *           1   1  N/A
+ *           1   0  Line
+ *           0   1  N/A
+ *           0   0  Tuner
+ *
+ *   AM* : Audio Mode
+ *          AM3  0: Normal        1: Mixed(Sub+Main channel)
+ *          AM2  0: Subchannel    1: Main channel
+ *          AM1  0: Stereo        1: Mono
+ *          AM0  0: Normal        1: Mute
+ *
+ *   DM* : Detected tuner audio Mode
+ *          DM1  0: Stereo        1: Mono
+ *          DM0  0: Multiplex     1: Normal
+ *
+ * GPIO Initial Settings
+ *           MPG600   MPG160
+ *     DIR   0x3080   0x7080
+ *  OUTPUT   0x000C   0x400C
+ *
+ *  Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous
+ *  for analyzing GPIO of MPG160.
+ *
+ *****************************************************************************
+ *
+ * GPIO assignment of Avermedia M179 (per information direct from AVerMedia)
+ *
+ *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
+ * OUTPUT IN0 AM0 IN1               AM1 AM2       IN2     BR0   BR1
+ *  INPUT
+ *
+ *   IN* : Input selection
+ *          IN0 IN1 IN2
+ *           *   1   *  Mute
+ *           0   0   0  Line-In
+ *           1   0   0  TV Tuner Audio
+ *           0   0   1  FM Audio
+ *           1   0   1  Mute
+ *
+ *   AM* : Audio Mode
+ *          AM0 AM1 AM2
+ *           0   0   0  TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP
+ *           0   0   1  TV Tuner Audio: L_OUT=R_OUT=SAP   (SAP)
+ *           0   1   0  TV Tuner Audio: L_OUT=L, R_OUT=R   (stereo)
+ *           0   1   1  TV Tuner Audio: mute
+ *           1   *   *  TV Tuner Audio: L_OUT=R_OUT=(L+R)/2   (mono)
+ *
+ *   BR* : Audio Sample Rate (BR stands for bitrate for some reason)
+ *          BR0 BR1
+ *           0   0   32 kHz
+ *           0   1   44.1 kHz
+ *           1   0   48 kHz
+ *
+ *   DM* : Detected tuner audio Mode
+ *         Unknown currently
+ *
+ * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at
+ * AVerMedia for providing the GPIO information used to add support
+ * for the M179 cards.
+ */
+
+/********************* GPIO stuffs *********************/
+
+/* GPIO registers */
+#define IVTV_REG_GPIO_IN    0x9008
+#define IVTV_REG_GPIO_OUT   0x900c
+#define IVTV_REG_GPIO_DIR   0x9020
+
+void ivtv_reset_ir_gpio(struct ivtv *itv)
+{
+       int curdir, curout;
+
+       if (itv->card->type != IVTV_CARD_PVR_150)
+               return;
+       IVTV_DEBUG_INFO("Resetting PVR150 IR\n");
+       curout = read_reg(IVTV_REG_GPIO_OUT);
+       curdir = read_reg(IVTV_REG_GPIO_DIR);
+       curdir |= 0x80;
+       write_reg(curdir, IVTV_REG_GPIO_DIR);
+       curout = (curout & ~0xF) | 1;
+       write_reg(curout, IVTV_REG_GPIO_OUT);
+       /* We could use something else for smaller time */
+       schedule_timeout_interruptible(msecs_to_jiffies(1));
+       curout |= 2;
+       write_reg(curout, IVTV_REG_GPIO_OUT);
+       curdir &= ~0x80;
+       write_reg(curdir, IVTV_REG_GPIO_DIR);
+}
+
+/* Xceive tuner reset function */
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
+{
+       struct i2c_algo_bit_data *algo = dev;
+       struct ivtv *itv = algo->data;
+       u32 curout;
+
+       if (cmd != XC2028_TUNER_RESET)
+               return 0;
+       IVTV_DEBUG_INFO("Resetting tuner\n");
+       curout = read_reg(IVTV_REG_GPIO_OUT);
+       curout &= ~(1 << itv->card->xceive_pin);
+       write_reg(curout, IVTV_REG_GPIO_OUT);
+       schedule_timeout_interruptible(msecs_to_jiffies(1));
+
+       curout |= 1 << itv->card->xceive_pin;
+       write_reg(curout, IVTV_REG_GPIO_OUT);
+       schedule_timeout_interruptible(msecs_to_jiffies(1));
+       return 0;
+}
+
+static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct ivtv, sd_gpio);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+       return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio;
+}
+
+static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask, data;
+
+       mask = itv->card->gpio_audio_freq.mask;
+       switch (freq) {
+       case 32000:
+               data = itv->card->gpio_audio_freq.f32000;
+               break;
+       case 44100:
+               data = itv->card->gpio_audio_freq.f44100;
+               break;
+       case 48000:
+       default:
+               data = itv->card->gpio_audio_freq.f48000;
+               break;
+       }
+       if (mask)
+               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+       return 0;
+}
+
+static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask;
+
+       mask = itv->card->gpio_audio_detect.mask;
+       if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
+               vt->rxsubchans = V4L2_TUNER_SUB_STEREO |
+                       V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+       else
+               vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+       return 0;
+}
+
+static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask, data;
+
+       mask = itv->card->gpio_audio_mode.mask;
+       switch (vt->audmode) {
+       case V4L2_TUNER_MODE_LANG1:
+               data = itv->card->gpio_audio_mode.lang1;
+               break;
+       case V4L2_TUNER_MODE_LANG2:
+               data = itv->card->gpio_audio_mode.lang2;
+               break;
+       case V4L2_TUNER_MODE_MONO:
+               data = itv->card->gpio_audio_mode.mono;
+               break;
+       case V4L2_TUNER_MODE_STEREO:
+       case V4L2_TUNER_MODE_LANG1_LANG2:
+       default:
+               data = itv->card->gpio_audio_mode.stereo;
+               break;
+       }
+       if (mask)
+               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+       return 0;
+}
+
+static int subdev_s_radio(struct v4l2_subdev *sd)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask, data;
+
+       mask = itv->card->gpio_audio_input.mask;
+       data = itv->card->gpio_audio_input.radio;
+       if (mask)
+               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+       return 0;
+}
+
+static int subdev_s_audio_routing(struct v4l2_subdev *sd,
+                                 u32 input, u32 output, u32 config)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask, data;
+
+       if (input > 2)
+               return -EINVAL;
+       mask = itv->card->gpio_audio_input.mask;
+       switch (input) {
+       case 0:
+               data = itv->card->gpio_audio_input.tuner;
+               break;
+       case 1:
+               data = itv->card->gpio_audio_input.linein;
+               break;
+       case 2:
+       default:
+               data = itv->card->gpio_audio_input.radio;
+               break;
+       }
+       if (mask)
+               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+       return 0;
+}
+
+static int subdev_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = to_sd(ctrl);
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask, data;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               mask = itv->card->gpio_audio_mute.mask;
+               data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0;
+               if (mask)
+                       write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) |
+                                       (data & mask), IVTV_REG_GPIO_OUT);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+
+static int subdev_log_status(struct v4l2_subdev *sd)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+
+       IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
+                       read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
+                       read_reg(IVTV_REG_GPIO_IN));
+       v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name);
+       return 0;
+}
+
+static int subdev_s_video_routing(struct v4l2_subdev *sd,
+                                 u32 input, u32 output, u32 config)
+{
+       struct ivtv *itv = sd_to_ivtv(sd);
+       u16 mask, data;
+
+       if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */
+               return -EINVAL;
+       mask = itv->card->gpio_video_input.mask;
+       if (input == 0)
+               data = itv->card->gpio_video_input.tuner;
+       else if (input == 1)
+               data = itv->card->gpio_video_input.composite;
+       else
+               data = itv->card->gpio_video_input.svideo;
+       if (mask)
+               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
+       .s_ctrl = subdev_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops subdev_core_ops = {
+       .log_status = subdev_log_status,
+       .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+       .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+       .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+       .g_ctrl = v4l2_subdev_g_ctrl,
+       .s_ctrl = v4l2_subdev_s_ctrl,
+       .queryctrl = v4l2_subdev_queryctrl,
+       .querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
+       .s_radio = subdev_s_radio,
+       .g_tuner = subdev_g_tuner,
+       .s_tuner = subdev_s_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
+       .s_clock_freq = subdev_s_clock_freq,
+       .s_routing = subdev_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops subdev_video_ops = {
+       .s_routing = subdev_s_video_routing,
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+       .core = &subdev_core_ops,
+       .tuner = &subdev_tuner_ops,
+       .audio = &subdev_audio_ops,
+       .video = &subdev_video_ops,
+};
+
+int ivtv_gpio_init(struct ivtv *itv)
+{
+       u16 pin = 0;
+
+       if (itv->card->xceive_pin)
+               pin = 1 << itv->card->xceive_pin;
+
+       if ((itv->card->gpio_init.direction | pin) == 0)
+               return 0;
+
+       IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
+                  read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
+
+       /* init output data then direction */
+       write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
+       write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
+       v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
+       snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
+       itv->sd_gpio.grp_id = IVTV_HW_GPIO;
+       v4l2_ctrl_handler_init(&itv->hdl_gpio, 1);
+       v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops,
+                       V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+       if (itv->hdl_gpio.error)
+               return itv->hdl_gpio.error;
+       itv->sd_gpio.ctrl_handler = &itv->hdl_gpio;
+       v4l2_ctrl_handler_setup(&itv->hdl_gpio);
+       return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-gpio.h b/drivers/media/pci/ivtv/ivtv-gpio.h
new file mode 100644 (file)
index 0000000..0b5d19c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+    gpio functions.
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_GPIO_H
+#define IVTV_GPIO_H
+
+/* GPIO stuff */
+int ivtv_gpio_init(struct ivtv *itv);
+void ivtv_reset_ir_gpio(struct ivtv *itv);
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
new file mode 100644 (file)
index 0000000..d47f41a
--- /dev/null
@@ -0,0 +1,760 @@
+/*
+    I2C functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+    This file includes an i2c implementation that was reverse engineered
+    from the Hauppauge windows driver.  Older ivtv versions used i2c-algo-bit,
+    which whilst fine under most circumstances, had trouble with the Zilog
+    CPU on the PVR-150 which handles IR functions (occasional inability to
+    communicate with the chip until it was reset) and also with the i2c
+    bus being completely unreachable when multiple PVR cards were present.
+
+    The implementation is very similar to i2c-algo-bit, but there are enough
+    subtle differences that the two are hard to merge.  The general strategy
+    employed by i2c-algo-bit is to use udelay() to implement the timing
+    when putting out bits on the scl/sda lines.  The general strategy taken
+    here is to poll the lines for state changes (see ivtv_waitscl and
+    ivtv_waitsda).  In addition there are small delays at various locations
+    which poll the SCL line 5 times (ivtv_scldelay).  I would guess that
+    since this is memory mapped I/O that the length of those delays is tied
+    to the PCI bus clock.  There is some extra code to do with recovery
+    and retries.  Since it is not known what causes the actual i2c problems
+    in the first place, the only goal if one was to attempt to use
+    i2c-algo-bit would be to try to make it follow the same code path.
+    This would be a lot of work, and I'm also not convinced that it would
+    provide a generic benefit to i2c-algo-bit.  Therefore consider this
+    an engineering solution -- not pretty, but it works.
+
+    Some more general comments about what we are doing:
+
+    The i2c bus is a 2 wire serial bus, with clock (SCL) and data (SDA)
+    lines.  To communicate on the bus (as a master, we don't act as a slave),
+    we first initiate a start condition (ivtv_start).  We then write the
+    address of the device that we want to communicate with, along with a flag
+    that indicates whether this is a read or a write.  The slave then issues
+    an ACK signal (ivtv_ack), which tells us that it is ready for reading /
+    writing.  We then proceed with reading or writing (ivtv_read/ivtv_write),
+    and finally issue a stop condition (ivtv_stop) to make the bus available
+    to other masters.
+
+    There is an additional form of transaction where a write may be
+    immediately followed by a read.  In this case, there is no intervening
+    stop condition.  (Only the msp3400 chip uses this method of data transfer).
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "ivtv-i2c.h"
+#include <media/cx25840.h>
+
+/* i2c implementation for cx23415/6 chip, ivtv project.
+ * Author: Kevin Thayer (nufan_wfk at yahoo.com)
+ */
+/* i2c stuff */
+#define IVTV_REG_I2C_SETSCL_OFFSET 0x7000
+#define IVTV_REG_I2C_SETSDA_OFFSET 0x7004
+#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008
+#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c
+
+#define IVTV_CS53L32A_I2C_ADDR         0x11
+#define IVTV_M52790_I2C_ADDR           0x48
+#define IVTV_CX25840_I2C_ADDR          0x44
+#define IVTV_SAA7115_I2C_ADDR          0x21
+#define IVTV_SAA7127_I2C_ADDR          0x44
+#define IVTV_SAA717x_I2C_ADDR          0x21
+#define IVTV_MSP3400_I2C_ADDR          0x40
+#define IVTV_HAUPPAUGE_I2C_ADDR        0x50
+#define IVTV_WM8739_I2C_ADDR           0x1a
+#define IVTV_WM8775_I2C_ADDR           0x1b
+#define IVTV_TEA5767_I2C_ADDR          0x60
+#define IVTV_UPD64031A_I2C_ADDR        0x12
+#define IVTV_UPD64083_I2C_ADDR                 0x5c
+#define IVTV_VP27SMPX_I2C_ADDR         0x5b
+#define IVTV_M52790_I2C_ADDR           0x48
+#define IVTV_AVERMEDIA_IR_RX_I2C_ADDR  0x40
+#define IVTV_HAUP_EXT_IR_RX_I2C_ADDR   0x1a
+#define IVTV_HAUP_INT_IR_RX_I2C_ADDR   0x18
+#define IVTV_Z8F0811_IR_TX_I2C_ADDR    0x70
+#define IVTV_Z8F0811_IR_RX_I2C_ADDR    0x71
+#define IVTV_ADAPTEC_IR_ADDR           0x6b
+
+/* This array should match the IVTV_HW_ defines */
+static const u8 hw_addrs[] = {
+       IVTV_CX25840_I2C_ADDR,
+       IVTV_SAA7115_I2C_ADDR,
+       IVTV_SAA7127_I2C_ADDR,
+       IVTV_MSP3400_I2C_ADDR,
+       0,
+       IVTV_WM8775_I2C_ADDR,
+       IVTV_CS53L32A_I2C_ADDR,
+       0,
+       IVTV_SAA7115_I2C_ADDR,
+       IVTV_UPD64031A_I2C_ADDR,
+       IVTV_UPD64083_I2C_ADDR,
+       IVTV_SAA717x_I2C_ADDR,
+       IVTV_WM8739_I2C_ADDR,
+       IVTV_VP27SMPX_I2C_ADDR,
+       IVTV_M52790_I2C_ADDR,
+       0,                              /* IVTV_HW_GPIO dummy driver ID */
+       IVTV_AVERMEDIA_IR_RX_I2C_ADDR,  /* IVTV_HW_I2C_IR_RX_AVER */
+       IVTV_HAUP_EXT_IR_RX_I2C_ADDR,   /* IVTV_HW_I2C_IR_RX_HAUP_EXT */
+       IVTV_HAUP_INT_IR_RX_I2C_ADDR,   /* IVTV_HW_I2C_IR_RX_HAUP_INT */
+       IVTV_Z8F0811_IR_TX_I2C_ADDR,    /* IVTV_HW_Z8F0811_IR_TX_HAUP */
+       IVTV_Z8F0811_IR_RX_I2C_ADDR,    /* IVTV_HW_Z8F0811_IR_RX_HAUP */
+       IVTV_ADAPTEC_IR_ADDR,           /* IVTV_HW_I2C_IR_RX_ADAPTEC */
+};
+
+/* This array should match the IVTV_HW_ defines */
+static const char * const hw_devicenames[] = {
+       "cx25840",
+       "saa7115",
+       "saa7127_auto", /* saa7127 or saa7129 */
+       "msp3400",
+       "tuner",
+       "wm8775",
+       "cs53l32a",
+       "tveeprom",
+       "saa7114",
+       "upd64031a",
+       "upd64083",
+       "saa717x",
+       "wm8739",
+       "vp27smpx",
+       "m52790",
+       "gpio",
+       "ir_video",             /* IVTV_HW_I2C_IR_RX_AVER */
+       "ir_video",             /* IVTV_HW_I2C_IR_RX_HAUP_EXT */
+       "ir_video",             /* IVTV_HW_I2C_IR_RX_HAUP_INT */
+       "ir_tx_z8f0811_haup",   /* IVTV_HW_Z8F0811_IR_TX_HAUP */
+       "ir_rx_z8f0811_haup",   /* IVTV_HW_Z8F0811_IR_RX_HAUP */
+       "ir_video",             /* IVTV_HW_I2C_IR_RX_ADAPTEC */
+};
+
+static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char keybuf[4];
+
+       keybuf[0] = 0x00;
+       i2c_master_send(ir->c, keybuf, 1);
+       /* poll IR chip */
+       if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) {
+               return 0;
+       }
+
+       /* key pressed ? */
+       if (keybuf[2] == 0xff)
+               return 0;
+
+       /* remove repeat bit */
+       keybuf[2] &= 0x7f;
+       keybuf[3] |= 0x80;
+
+       *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
+       *ir_raw = *ir_key;
+
+       return 1;
+}
+
+static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
+{
+       struct i2c_board_info info;
+       struct i2c_adapter *adap = &itv->i2c_adap;
+       struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data;
+       unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
+
+       /* Only allow one IR transmitter to be registered per board */
+       if (hw & IVTV_HW_IR_TX_ANY) {
+               if (itv->hw_flags & IVTV_HW_IR_TX_ANY)
+                       return -1;
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, type, I2C_NAME_SIZE);
+               return i2c_new_probed_device(adap, &info, addr_list, NULL)
+                                                          == NULL ? -1 : 0;
+       }
+
+       /* Only allow one IR receiver to be registered per board */
+       if (itv->hw_flags & IVTV_HW_IR_RX_ANY)
+               return -1;
+
+       /* Our default information for ir-kbd-i2c.c to use */
+       switch (hw) {
+       case IVTV_HW_I2C_IR_RX_AVER:
+               init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
+               init_data->internal_get_key_func =
+                                       IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
+               init_data->type = RC_TYPE_OTHER;
+               init_data->name = "AVerMedia AVerTV card";
+               break;
+       case IVTV_HW_I2C_IR_RX_HAUP_EXT:
+       case IVTV_HW_I2C_IR_RX_HAUP_INT:
+               init_data->ir_codes = RC_MAP_HAUPPAUGE;
+               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
+               init_data->type = RC_TYPE_RC5;
+               init_data->name = itv->card_name;
+               break;
+       case IVTV_HW_Z8F0811_IR_RX_HAUP:
+               /* Default to grey remote */
+               init_data->ir_codes = RC_MAP_HAUPPAUGE;
+               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+               init_data->type = RC_TYPE_RC5;
+               init_data->name = itv->card_name;
+               break;
+       case IVTV_HW_I2C_IR_RX_ADAPTEC:
+               init_data->get_key = get_key_adaptec;
+               init_data->name = itv->card_name;
+               /* FIXME: The protocol and RC_MAP needs to be corrected */
+               init_data->ir_codes = RC_MAP_EMPTY;
+               init_data->type = RC_TYPE_UNKNOWN;
+               break;
+       }
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       info.platform_data = init_data;
+       strlcpy(info.type, type, I2C_NAME_SIZE);
+
+       return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
+              -1 : 0;
+}
+
+/* Instantiate the IR receiver device using probing -- undesirable */
+struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv)
+{
+       struct i2c_board_info info;
+       /*
+        * The external IR receiver is at i2c address 0x34.
+        * The internal IR receiver is at i2c address 0x30.
+        *
+        * In theory, both can be fitted, and Hauppauge suggests an external
+        * overrides an internal.  That's why we probe 0x1a (~0x34) first. CB
+        *
+        * Some of these addresses we probe may collide with other i2c address
+        * allocations, so this function must be called after all other i2c
+        * devices we care about are registered.
+        */
+       const unsigned short addr_list[] = {
+               0x1a,   /* Hauppauge IR external - collides with WM8739 */
+               0x18,   /* Hauppauge IR internal */
+               I2C_CLIENT_END
+       };
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+       return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL);
+}
+
+int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+{
+       struct v4l2_subdev *sd;
+       struct i2c_adapter *adap = &itv->i2c_adap;
+       const char *type = hw_devicenames[idx];
+       u32 hw = 1 << idx;
+
+       if (idx >= ARRAY_SIZE(hw_addrs))
+               return -1;
+       if (hw == IVTV_HW_TUNER) {
+               /* special tuner handling */
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+                               itv->card_i2c->radio);
+               if (sd)
+                       sd->grp_id = 1 << idx;
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+                               itv->card_i2c->demod);
+               if (sd)
+                       sd->grp_id = 1 << idx;
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+                               itv->card_i2c->tv);
+               if (sd)
+                       sd->grp_id = 1 << idx;
+               return sd ? 0 : -1;
+       }
+
+       if (hw & IVTV_HW_IR_ANY)
+               return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]);
+
+       /* Is it not an I2C device or one we do not wish to register? */
+       if (!hw_addrs[idx])
+               return -1;
+
+       /* It's an I2C device other than an analog tuner or IR chip */
+       if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+                               adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
+       } else if (hw == IVTV_HW_CX25840) {
+               struct cx25840_platform_data pdata;
+               struct i2c_board_info cx25840_info = {
+                       .type = "cx25840",
+                       .addr = hw_addrs[idx],
+                       .platform_data = &pdata,
+               };
+
+               pdata.pvr150_workaround = itv->pvr150_workaround;
+               sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap,
+                               &cx25840_info, NULL);
+       } else {
+               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+                               adap, type, hw_addrs[idx], NULL);
+       }
+       if (sd)
+               sd->grp_id = 1 << idx;
+       return sd ? 0 : -1;
+}
+
+struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw)
+{
+       struct v4l2_subdev *result = NULL;
+       struct v4l2_subdev *sd;
+
+       spin_lock(&itv->v4l2_dev.lock);
+       v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) {
+               if (sd->grp_id == hw) {
+                       result = sd;
+                       break;
+               }
+       }
+       spin_unlock(&itv->v4l2_dev.lock);
+       return result;
+}
+
+/* Set the serial clock line to the desired state */
+static void ivtv_setscl(struct ivtv *itv, int state)
+{
+       /* write them out */
+       /* write bits are inverted */
+       write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET);
+}
+
+/* Set the serial data line to the desired state */
+static void ivtv_setsda(struct ivtv *itv, int state)
+{
+       /* write them out */
+       /* write bits are inverted */
+       write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET);
+}
+
+/* Read the serial clock line */
+static int ivtv_getscl(struct ivtv *itv)
+{
+       return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
+}
+
+/* Read the serial data line */
+static int ivtv_getsda(struct ivtv *itv)
+{
+       return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
+}
+
+/* Implement a short delay by polling the serial clock line */
+static void ivtv_scldelay(struct ivtv *itv)
+{
+       int i;
+
+       for (i = 0; i < 5; ++i)
+               ivtv_getscl(itv);
+}
+
+/* Wait for the serial clock line to become set to a specific value */
+static int ivtv_waitscl(struct ivtv *itv, int val)
+{
+       int i;
+
+       ivtv_scldelay(itv);
+       for (i = 0; i < 1000; ++i) {
+               if (ivtv_getscl(itv) == val)
+                       return 1;
+       }
+       return 0;
+}
+
+/* Wait for the serial data line to become set to a specific value */
+static int ivtv_waitsda(struct ivtv *itv, int val)
+{
+       int i;
+
+       ivtv_scldelay(itv);
+       for (i = 0; i < 1000; ++i) {
+               if (ivtv_getsda(itv) == val)
+                       return 1;
+       }
+       return 0;
+}
+
+/* Wait for the slave to issue an ACK */
+static int ivtv_ack(struct ivtv *itv)
+{
+       int ret = 0;
+
+       if (ivtv_getscl(itv) == 1) {
+               IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n");
+               ivtv_setscl(itv, 0);
+               if (!ivtv_waitscl(itv, 0)) {
+                       IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n");
+                       return -EREMOTEIO;
+               }
+       }
+       ivtv_setsda(itv, 1);
+       ivtv_scldelay(itv);
+       ivtv_setscl(itv, 1);
+       if (!ivtv_waitsda(itv, 0)) {
+               IVTV_DEBUG_I2C("Slave did not ack\n");
+               ret = -EREMOTEIO;
+       }
+       ivtv_setscl(itv, 0);
+       if (!ivtv_waitscl(itv, 0)) {
+               IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n");
+               ret = -EREMOTEIO;
+       }
+       return ret;
+}
+
+/* Write a single byte to the i2c bus and wait for the slave to ACK */
+static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte)
+{
+       int i, bit;
+
+       IVTV_DEBUG_HI_I2C("write %x\n",byte);
+       for (i = 0; i < 8; ++i, byte<<=1) {
+               ivtv_setscl(itv, 0);
+               if (!ivtv_waitscl(itv, 0)) {
+                       IVTV_DEBUG_I2C("Error setting SCL low\n");
+                       return -EREMOTEIO;
+               }
+               bit = (byte>>7)&1;
+               ivtv_setsda(itv, bit);
+               if (!ivtv_waitsda(itv, bit)) {
+                       IVTV_DEBUG_I2C("Error setting SDA\n");
+                       return -EREMOTEIO;
+               }
+               ivtv_setscl(itv, 1);
+               if (!ivtv_waitscl(itv, 1)) {
+                       IVTV_DEBUG_I2C("Slave not ready for bit\n");
+                       return -EREMOTEIO;
+               }
+       }
+       ivtv_setscl(itv, 0);
+       if (!ivtv_waitscl(itv, 0)) {
+               IVTV_DEBUG_I2C("Error setting SCL low\n");
+               return -EREMOTEIO;
+       }
+       return ivtv_ack(itv);
+}
+
+/* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the
+   final byte) */
+static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack)
+{
+       int i;
+
+       *byte = 0;
+
+       ivtv_setsda(itv, 1);
+       ivtv_scldelay(itv);
+       for (i = 0; i < 8; ++i) {
+               ivtv_setscl(itv, 0);
+               ivtv_scldelay(itv);
+               ivtv_setscl(itv, 1);
+               if (!ivtv_waitscl(itv, 1)) {
+                       IVTV_DEBUG_I2C("Error setting SCL high\n");
+                       return -EREMOTEIO;
+               }
+               *byte = ((*byte)<<1)|ivtv_getsda(itv);
+       }
+       ivtv_setscl(itv, 0);
+       ivtv_scldelay(itv);
+       ivtv_setsda(itv, nack);
+       ivtv_scldelay(itv);
+       ivtv_setscl(itv, 1);
+       ivtv_scldelay(itv);
+       ivtv_setscl(itv, 0);
+       ivtv_scldelay(itv);
+       IVTV_DEBUG_HI_I2C("read %x\n",*byte);
+       return 0;
+}
+
+/* Issue a start condition on the i2c bus to alert slaves to prepare for
+   an address write */
+static int ivtv_start(struct ivtv *itv)
+{
+       int sda;
+
+       sda = ivtv_getsda(itv);
+       if (sda != 1) {
+               IVTV_DEBUG_HI_I2C("SDA was low at start\n");
+               ivtv_setsda(itv, 1);
+               if (!ivtv_waitsda(itv, 1)) {
+                       IVTV_DEBUG_I2C("SDA stuck low\n");
+                       return -EREMOTEIO;
+               }
+       }
+       if (ivtv_getscl(itv) != 1) {
+               ivtv_setscl(itv, 1);
+               if (!ivtv_waitscl(itv, 1)) {
+                       IVTV_DEBUG_I2C("SCL stuck low at start\n");
+                       return -EREMOTEIO;
+               }
+       }
+       ivtv_setsda(itv, 0);
+       ivtv_scldelay(itv);
+       return 0;
+}
+
+/* Issue a stop condition on the i2c bus to release it */
+static int ivtv_stop(struct ivtv *itv)
+{
+       int i;
+
+       if (ivtv_getscl(itv) != 0) {
+               IVTV_DEBUG_HI_I2C("SCL not low when stopping\n");
+               ivtv_setscl(itv, 0);
+               if (!ivtv_waitscl(itv, 0)) {
+                       IVTV_DEBUG_I2C("SCL could not be set low\n");
+               }
+       }
+       ivtv_setsda(itv, 0);
+       ivtv_scldelay(itv);
+       ivtv_setscl(itv, 1);
+       if (!ivtv_waitscl(itv, 1)) {
+               IVTV_DEBUG_I2C("SCL could not be set high\n");
+               return -EREMOTEIO;
+       }
+       ivtv_scldelay(itv);
+       ivtv_setsda(itv, 1);
+       if (!ivtv_waitsda(itv, 1)) {
+               IVTV_DEBUG_I2C("resetting I2C\n");
+               for (i = 0; i < 16; ++i) {
+                       ivtv_setscl(itv, 0);
+                       ivtv_scldelay(itv);
+                       ivtv_setscl(itv, 1);
+                       ivtv_scldelay(itv);
+                       ivtv_setsda(itv, 1);
+               }
+               ivtv_waitsda(itv, 1);
+               return -EREMOTEIO;
+       }
+       return 0;
+}
+
+/* Write a message to the given i2c slave.  do_stop may be 0 to prevent
+   issuing the i2c stop condition (when following with a read) */
+static int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop)
+{
+       int retry, ret = -EREMOTEIO;
+       u32 i;
+
+       for (retry = 0; ret != 0 && retry < 8; ++retry) {
+               ret = ivtv_start(itv);
+
+               if (ret == 0) {
+                       ret = ivtv_sendbyte(itv, addr<<1);
+                       for (i = 0; ret == 0 && i < len; ++i)
+                               ret = ivtv_sendbyte(itv, data[i]);
+               }
+               if (ret != 0 || do_stop) {
+                       ivtv_stop(itv);
+               }
+       }
+       if (ret)
+               IVTV_DEBUG_I2C("i2c write to %x failed\n", addr);
+       return ret;
+}
+
+/* Read data from the given i2c slave.  A stop condition is always issued. */
+static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len)
+{
+       int retry, ret = -EREMOTEIO;
+       u32 i;
+
+       for (retry = 0; ret != 0 && retry < 8; ++retry) {
+               ret = ivtv_start(itv);
+               if (ret == 0)
+                       ret = ivtv_sendbyte(itv, (addr << 1) | 1);
+               for (i = 0; ret == 0 && i < len; ++i) {
+                       ret = ivtv_readbyte(itv, &data[i], i == len - 1);
+               }
+               ivtv_stop(itv);
+       }
+       if (ret)
+               IVTV_DEBUG_I2C("i2c read from %x failed\n", addr);
+       return ret;
+}
+
+/* Kernel i2c transfer implementation.  Takes a number of messages to be read
+   or written.  If a read follows a write, this will occur without an
+   intervening stop condition */
+static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+       struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+       struct ivtv *itv = to_ivtv(v4l2_dev);
+       int retval;
+       int i;
+
+       mutex_lock(&itv->i2c_bus_lock);
+       for (i = retval = 0; retval == 0 && i < num; i++) {
+               if (msgs[i].flags & I2C_M_RD)
+                       retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len);
+               else {
+                       /* if followed by a read, don't stop */
+                       int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD);
+
+                       retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop);
+               }
+       }
+       mutex_unlock(&itv->i2c_bus_lock);
+       return retval ? retval : num;
+}
+
+/* Kernel i2c capabilities */
+static u32 ivtv_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm ivtv_algo = {
+       .master_xfer   = ivtv_xfer,
+       .functionality = ivtv_functionality,
+};
+
+/* template for our-bit banger */
+static struct i2c_adapter ivtv_i2c_adap_hw_template = {
+       .name = "ivtv i2c driver",
+       .algo = &ivtv_algo,
+       .algo_data = NULL,                      /* filled from template */
+       .owner = THIS_MODULE,
+};
+
+static void ivtv_setscl_old(void *data, int state)
+{
+       struct ivtv *itv = (struct ivtv *)data;
+
+       if (state)
+               itv->i2c_state |= 0x01;
+       else
+               itv->i2c_state &= ~0x01;
+
+       /* write them out */
+       /* write bits are inverted */
+       write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET);
+}
+
+static void ivtv_setsda_old(void *data, int state)
+{
+       struct ivtv *itv = (struct ivtv *)data;
+
+       if (state)
+               itv->i2c_state |= 0x01;
+       else
+               itv->i2c_state &= ~0x01;
+
+       /* write them out */
+       /* write bits are inverted */
+       write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET);
+}
+
+static int ivtv_getscl_old(void *data)
+{
+       struct ivtv *itv = (struct ivtv *)data;
+
+       return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
+}
+
+static int ivtv_getsda_old(void *data)
+{
+       struct ivtv *itv = (struct ivtv *)data;
+
+       return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter ivtv_i2c_adap_template = {
+       .name = "ivtv i2c driver",
+       .algo = NULL,                   /* set by i2c-algo-bit */
+       .algo_data = NULL,              /* filled from template */
+       .owner = THIS_MODULE,
+};
+
+#define IVTV_ALGO_BIT_TIMEOUT  (2)     /* seconds */
+
+static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
+       .setsda         = ivtv_setsda_old,
+       .setscl         = ivtv_setscl_old,
+       .getsda         = ivtv_getsda_old,
+       .getscl         = ivtv_getscl_old,
+       .udelay         = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2,  /* microseconds */
+       .timeout        = IVTV_ALGO_BIT_TIMEOUT * HZ,         /* jiffies */
+};
+
+static struct i2c_client ivtv_i2c_client_template = {
+       .name = "ivtv internal",
+};
+
+/* init + register i2c adapter */
+int init_ivtv_i2c(struct ivtv *itv)
+{
+       int retval;
+
+       IVTV_DEBUG_I2C("i2c init\n");
+
+       /* Sanity checks for the I2C hardware arrays. They must be the
+        * same size.
+        */
+       if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs)) {
+               IVTV_ERR("Mismatched I2C hardware arrays\n");
+               return -ENODEV;
+       }
+       if (itv->options.newi2c > 0) {
+               memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template,
+                      sizeof(struct i2c_adapter));
+       } else {
+               memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template,
+                      sizeof(struct i2c_adapter));
+               memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,
+                      sizeof(struct i2c_algo_bit_data));
+       }
+       itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2;
+       itv->i2c_algo.data = itv;
+       itv->i2c_adap.algo_data = &itv->i2c_algo;
+
+       sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
+               itv->instance);
+       i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev);
+
+       memcpy(&itv->i2c_client, &ivtv_i2c_client_template,
+              sizeof(struct i2c_client));
+       itv->i2c_client.adapter = &itv->i2c_adap;
+       itv->i2c_adap.dev.parent = &itv->pdev->dev;
+
+       IVTV_DEBUG_I2C("setting scl and sda to 1\n");
+       ivtv_setscl(itv, 1);
+       ivtv_setsda(itv, 1);
+
+       if (itv->options.newi2c > 0)
+               retval = i2c_add_adapter(&itv->i2c_adap);
+       else
+               retval = i2c_bit_add_bus(&itv->i2c_adap);
+
+       return retval;
+}
+
+void exit_ivtv_i2c(struct ivtv *itv)
+{
+       IVTV_DEBUG_I2C("i2c exit\n");
+
+       i2c_del_adapter(&itv->i2c_adap);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.h b/drivers/media/pci/ivtv/ivtv-i2c.h
new file mode 100644 (file)
index 0000000..7b9ec1c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+    I2C functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_I2C_H
+#define IVTV_I2C_H
+
+struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv);
+int ivtv_i2c_register(struct ivtv *itv, unsigned idx);
+struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw);
+
+/* init + register i2c adapter */
+int init_ivtv_i2c(struct ivtv *itv);
+void exit_ivtv_i2c(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
new file mode 100644 (file)
index 0000000..32a5910
--- /dev/null
@@ -0,0 +1,1899 @@
+/*
+    ioctl system call
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-version.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-i2c.h"
+#include "ivtv-queue.h"
+#include "ivtv-fileops.h"
+#include "ivtv-vbi.h"
+#include "ivtv-routing.h"
+#include "ivtv-streams.h"
+#include "ivtv-yuv.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-gpio.h"
+#include "ivtv-controls.h"
+#include "ivtv-cards.h"
+#include <media/saa7127.h>
+#include <media/tveeprom.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-event.h>
+#include <linux/dvb/audio.h>
+
+u16 ivtv_service2vbi(int type)
+{
+       switch (type) {
+               case V4L2_SLICED_TELETEXT_B:
+                       return IVTV_SLICED_TYPE_TELETEXT_B;
+               case V4L2_SLICED_CAPTION_525:
+                       return IVTV_SLICED_TYPE_CAPTION_525;
+               case V4L2_SLICED_WSS_625:
+                       return IVTV_SLICED_TYPE_WSS_625;
+               case V4L2_SLICED_VPS:
+                       return IVTV_SLICED_TYPE_VPS;
+               default:
+                       return 0;
+       }
+}
+
+static int valid_service_line(int field, int line, int is_pal)
+{
+       return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
+              (!is_pal && line >= 10 && line < 22);
+}
+
+static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
+{
+       u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
+       int i;
+
+       set = set & valid_set;
+       if (set == 0 || !valid_service_line(field, line, is_pal)) {
+               return 0;
+       }
+       if (!is_pal) {
+               if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
+                       return V4L2_SLICED_CAPTION_525;
+       }
+       else {
+               if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
+                       return V4L2_SLICED_VPS;
+               if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
+                       return V4L2_SLICED_WSS_625;
+               if (line == 23)
+                       return 0;
+       }
+       for (i = 0; i < 32; i++) {
+               if ((1 << i) & set)
+                       return 1 << i;
+       }
+       return 0;
+}
+
+void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+       u16 set = fmt->service_set;
+       int f, l;
+
+       fmt->service_set = 0;
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++) {
+                       fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
+               }
+       }
+}
+
+static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+       int f, l;
+
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++) {
+                       fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
+               }
+       }
+}
+
+u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
+{
+       int f, l;
+       u16 set = 0;
+
+       for (f = 0; f < 2; f++) {
+               for (l = 0; l < 24; l++) {
+                       set |= fmt->service_lines[f][l];
+               }
+       }
+       return set;
+}
+
+void ivtv_set_osd_alpha(struct ivtv *itv)
+{
+       ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
+               itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
+       ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);
+}
+
+int ivtv_set_speed(struct ivtv *itv, int speed)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       int single_step = (speed == 1 || speed == -1);
+       DEFINE_WAIT(wait);
+
+       if (speed == 0) speed = 1000;
+
+       /* No change? */
+       if (speed == itv->speed && !single_step)
+               return 0;
+
+       if (single_step && (speed < 0) == (itv->speed < 0)) {
+               /* Single step video and no need to change direction */
+               ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
+               itv->speed = speed;
+               return 0;
+       }
+       if (single_step)
+               /* Need to change direction */
+               speed = speed < 0 ? -1000 : 1000;
+
+       data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
+       data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
+       data[1] = (speed < 0);
+       data[2] = speed < 0 ? 3 : 7;
+       data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);
+       data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
+       data[5] = 0;
+       data[6] = 0;
+
+       if (speed == 1500 || speed == -1500) data[0] |= 1;
+       else if (speed == 2000 || speed == -2000) data[0] |= 2;
+       else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
+       else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
+
+       /* If not decoding, just change speed setting */
+       if (atomic_read(&itv->decoding) > 0) {
+               int got_sig = 0;
+
+               /* Stop all DMA and decoding activity */
+               ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
+
+               /* Wait for any DMA to finish */
+               mutex_unlock(&itv->serialize_lock);
+               prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+               while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
+                       got_sig = signal_pending(current);
+                       if (got_sig)
+                               break;
+                       got_sig = 0;
+                       schedule();
+               }
+               finish_wait(&itv->dma_waitq, &wait);
+               mutex_lock(&itv->serialize_lock);
+               if (got_sig)
+                       return -EINTR;
+
+               /* Change Speed safely */
+               ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
+               IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+                               data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
+       }
+       if (single_step) {
+               speed = (speed < 0) ? -1 : 1;
+               ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
+       }
+       itv->speed = speed;
+       return 0;
+}
+
+static int ivtv_validate_speed(int cur_speed, int new_speed)
+{
+       int fact = new_speed < 0 ? -1 : 1;
+       int s;
+
+       if (cur_speed == 0)
+               cur_speed = 1000;
+       if (new_speed < 0)
+               new_speed = -new_speed;
+       if (cur_speed < 0)
+               cur_speed = -cur_speed;
+
+       if (cur_speed <= new_speed) {
+               if (new_speed > 1500)
+                       return fact * 2000;
+               if (new_speed > 1000)
+                       return fact * 1500;
+       }
+       else {
+               if (new_speed >= 2000)
+                       return fact * 2000;
+               if (new_speed >= 1500)
+                       return fact * 1500;
+               if (new_speed >= 1000)
+                       return fact * 1000;
+       }
+       if (new_speed == 0)
+               return 1000;
+       if (new_speed == 1 || new_speed == 1000)
+               return fact * new_speed;
+
+       s = new_speed;
+       new_speed = 1000 / new_speed;
+       if (1000 / cur_speed == new_speed)
+               new_speed += (cur_speed < s) ? -1 : 1;
+       if (new_speed > 60) return 1000 / (fact * 60);
+       return 1000 / (fact * new_speed);
+}
+
+static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
+               struct v4l2_decoder_cmd *dc, int try)
+{
+       struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+
+       switch (dc->cmd) {
+       case V4L2_DEC_CMD_START: {
+               dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
+               dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
+               if (dc->start.speed < 0)
+                       dc->start.format = V4L2_DEC_START_FMT_GOP;
+               else
+                       dc->start.format = V4L2_DEC_START_FMT_NONE;
+               if (dc->start.speed != 500 && dc->start.speed != 1500)
+                       dc->flags = dc->start.speed == 1000 ? 0 :
+                                       V4L2_DEC_CMD_START_MUTE_AUDIO;
+               if (try) break;
+
+               itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
+               if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
+                       return -EBUSY;
+               if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
+                       /* forces ivtv_set_speed to be called */
+                       itv->speed = 0;
+               }
+               return ivtv_start_decoding(id, dc->start.speed);
+       }
+
+       case V4L2_DEC_CMD_STOP:
+               dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
+               if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
+                       dc->stop.pts = 0;
+               if (try) break;
+               if (atomic_read(&itv->decoding) == 0)
+                       return 0;
+               if (itv->output_mode != OUT_MPG)
+                       return -EBUSY;
+
+               itv->output_mode = OUT_NONE;
+               return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
+
+       case V4L2_DEC_CMD_PAUSE:
+               dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
+               if (try) break;
+               if (itv->output_mode != OUT_MPG)
+                       return -EBUSY;
+               if (atomic_read(&itv->decoding) > 0) {
+                       ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
+                               (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
+                       set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
+               }
+               break;
+
+       case V4L2_DEC_CMD_RESUME:
+               dc->flags = 0;
+               if (try) break;
+               if (itv->output_mode != OUT_MPG)
+                       return -EBUSY;
+               if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
+                       int speed = itv->speed;
+                       itv->speed = 0;
+                       return ivtv_start_decoding(id, speed);
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+       if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
+               return -EINVAL;
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       if (itv->is_60hz) {
+               vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+               vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
+       } else {
+               vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
+               vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
+       }
+       vbifmt->service_set = ivtv_get_service_set(vbifmt);
+       return 0;
+}
+
+static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+       pixfmt->width = itv->cxhdl.width;
+       pixfmt->height = itv->cxhdl.height;
+       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       pixfmt->field = V4L2_FIELD_INTERLACED;
+       pixfmt->priv = 0;
+       if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
+               pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
+               /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
+               pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
+               pixfmt->bytesperline = 720;
+       } else {
+               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+               pixfmt->sizeimage = 128 * 1024;
+               pixfmt->bytesperline = 0;
+       }
+       return 0;
+}
+
+static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
+
+       vbifmt->sampling_rate = 27000000;
+       vbifmt->offset = 248;
+       vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
+       vbifmt->sample_format = V4L2_PIX_FMT_GREY;
+       vbifmt->start[0] = itv->vbi.start[0];
+       vbifmt->start[1] = itv->vbi.start[1];
+       vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
+       vbifmt->flags = 0;
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+       return 0;
+}
+
+static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+
+       if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
+               vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
+                       V4L2_SLICED_VBI_525;
+               ivtv_expand_service_set(vbifmt, itv->is_50hz);
+               return 0;
+       }
+
+       v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);
+       vbifmt->service_set = ivtv_get_service_set(vbifmt);
+       return 0;
+}
+
+static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+       pixfmt->width = itv->main_rect.width;
+       pixfmt->height = itv->main_rect.height;
+       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       pixfmt->field = V4L2_FIELD_INTERLACED;
+       pixfmt->priv = 0;
+       if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
+               switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
+               case IVTV_YUV_MODE_INTERLACED:
+                       pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
+                               V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
+                       break;
+               case IVTV_YUV_MODE_PROGRESSIVE:
+                       pixfmt->field = V4L2_FIELD_NONE;
+                       break;
+               default:
+                       pixfmt->field = V4L2_FIELD_ANY;
+                       break;
+               }
+               pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
+               pixfmt->bytesperline = 720;
+               pixfmt->width = itv->yuv_info.v4l2_src_w;
+               pixfmt->height = itv->yuv_info.v4l2_src_h;
+               /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
+               pixfmt->sizeimage =
+                       1080 * ((pixfmt->height + 31) & ~31);
+       } else {
+               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+               pixfmt->sizeimage = 128 * 1024;
+               pixfmt->bytesperline = 0;
+       }
+       return 0;
+}
+
+static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       struct v4l2_window *winfmt = &fmt->fmt.win;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+       winfmt->chromakey = itv->osd_chroma_key;
+       winfmt->global_alpha = itv->osd_global_alpha;
+       winfmt->field = V4L2_FIELD_INTERLACED;
+       winfmt->clips = NULL;
+       winfmt->clipcount = 0;
+       winfmt->bitmap = NULL;
+       winfmt->w.top = winfmt->w.left = 0;
+       winfmt->w.width = itv->osd_rect.width;
+       winfmt->w.height = itv->osd_rect.height;
+       return 0;
+}
+
+static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
+}
+
+static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       int w = fmt->fmt.pix.width;
+       int h = fmt->fmt.pix.height;
+       int min_h = 2;
+
+       w = min(w, 720);
+       w = max(w, 2);
+       if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
+               /* YUV height must be a multiple of 32 */
+               h &= ~0x1f;
+               min_h = 32;
+       }
+       h = min(h, itv->is_50hz ? 576 : 480);
+       h = max(h, min_h);
+       ivtv_g_fmt_vid_cap(file, fh, fmt);
+       fmt->fmt.pix.width = w;
+       fmt->fmt.pix.height = h;
+       return 0;
+}
+
+static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       return ivtv_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+
+       if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
+               return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
+
+       /* set sliced VBI capture format */
+       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       vbifmt->reserved[0] = 0;
+       vbifmt->reserved[1] = 0;
+
+       if (vbifmt->service_set)
+               ivtv_expand_service_set(vbifmt, itv->is_50hz);
+       check_service_set(vbifmt, itv->is_50hz);
+       vbifmt->service_set = ivtv_get_service_set(vbifmt);
+       return 0;
+}
+
+static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       s32 w = fmt->fmt.pix.width;
+       s32 h = fmt->fmt.pix.height;
+       int field = fmt->fmt.pix.field;
+       int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
+
+       w = min(w, 720);
+       w = max(w, 2);
+       /* Why can the height be 576 even when the output is NTSC?
+
+          Internally the buffers of the PVR350 are always set to 720x576. The
+          decoded video frame will always be placed in the top left corner of
+          this buffer. For any video which is not 720x576, the buffer will
+          then be cropped to remove the unused right and lower areas, with
+          the remaining image being scaled by the hardware to fit the display
+          area. The video can be scaled both up and down, so a 720x480 video
+          can be displayed full-screen on PAL and a 720x576 video can be
+          displayed without cropping on NTSC.
+
+          Note that the scaling only occurs on the video stream, the osd
+          resolution is locked to the broadcast standard and not scaled.
+
+          Thanks to Ian Armstrong for this explanation. */
+       h = min(h, 576);
+       h = max(h, 2);
+       if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
+               fmt->fmt.pix.field = field;
+       fmt->fmt.pix.width = w;
+       fmt->fmt.pix.height = h;
+       return ret;
+}
+
+static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       u32 chromakey = fmt->fmt.win.chromakey;
+       u8 global_alpha = fmt->fmt.win.global_alpha;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+       ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
+       fmt->fmt.win.chromakey = chromakey;
+       fmt->fmt.win.global_alpha = global_alpha;
+       return 0;
+}
+
+static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
+}
+
+static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
+       int w = fmt->fmt.pix.width;
+       int h = fmt->fmt.pix.height;
+
+       if (ret)
+               return ret;
+
+       if (itv->cxhdl.width == w && itv->cxhdl.height == h)
+               return 0;
+
+       if (atomic_read(&itv->capturing) > 0)
+               return -EBUSY;
+
+       itv->cxhdl.width = w;
+       itv->cxhdl.height = h;
+       if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+               fmt->fmt.pix.width /= 2;
+       mbus_fmt.width = fmt->fmt.pix.width;
+       mbus_fmt.height = h;
+       mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+       v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
+       return ivtv_g_fmt_vid_cap(file, fh, fmt);
+}
+
+static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
+               return -EBUSY;
+       itv->vbi.sliced_in->service_set = 0;
+       itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);
+       return ivtv_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
+
+       if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
+               return ret;
+
+       check_service_set(vbifmt, itv->is_50hz);
+       if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
+               return -EBUSY;
+       itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+       v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);
+       memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
+       return 0;
+}
+
+static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
+
+       if (ret)
+               return ret;
+
+       if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
+               return 0;
+
+       /* Return now if we already have some frame data */
+       if (yi->stream_size)
+               return -EBUSY;
+
+       yi->v4l2_src_w = fmt->fmt.pix.width;
+       yi->v4l2_src_h = fmt->fmt.pix.height;
+
+       switch (fmt->fmt.pix.field) {
+       case V4L2_FIELD_NONE:
+               yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
+               break;
+       case V4L2_FIELD_ANY:
+               yi->lace_mode = IVTV_YUV_MODE_AUTO;
+               break;
+       case V4L2_FIELD_INTERLACED_BT:
+               yi->lace_mode =
+                       IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
+               break;
+       case V4L2_FIELD_INTERLACED_TB:
+       default:
+               yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
+               break;
+       }
+       yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
+
+       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+               itv->dma_data_req_size =
+                       1080 * ((yi->v4l2_src_h + 31) & ~31);
+
+       return 0;
+}
+
+static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
+
+       if (ret == 0) {
+               itv->osd_chroma_key = fmt->fmt.win.chromakey;
+               itv->osd_global_alpha = fmt->fmt.win.global_alpha;
+               ivtv_set_osd_alpha(itv);
+       }
+       return ret;
+}
+
+static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+               if (v4l2_chip_match_host(&chip->match))
+                       chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
+               return 0;
+       }
+       if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+           chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+               return -EINVAL;
+       /* TODO: is this correct? */
+       return ivtv_call_all_err(itv, core, g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
+{
+       struct v4l2_dbg_register *regs = arg;
+       volatile u8 __iomem *reg_start;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
+               reg_start = itv->reg_mem - IVTV_REG_OFFSET;
+       else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
+                       regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
+               reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
+       else if (regs->reg < IVTV_ENCODER_SIZE)
+               reg_start = itv->enc_mem;
+       else
+               return -EINVAL;
+
+       regs->size = 4;
+       if (cmd == VIDIOC_DBG_G_REGISTER)
+               regs->val = readl(regs->reg + reg_start);
+       else
+               writel(regs->val, regs->reg + reg_start);
+       return 0;
+}
+
+static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (v4l2_chip_match_host(&reg->match))
+               return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
+       /* TODO: subdev errors should not be ignored, this should become a
+          subdev helper function. */
+       ivtv_call_all(itv, core, g_register, reg);
+       return 0;
+}
+
+static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (v4l2_chip_match_host(&reg->match))
+               return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
+       /* TODO: subdev errors should not be ignored, this should become a
+          subdev helper function. */
+       ivtv_call_all(itv, core, s_register, reg);
+       return 0;
+}
+#endif
+
+static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
+{
+       struct ivtv_open_id *id = fh2id(file->private_data);
+       struct ivtv *itv = id->itv;
+       struct ivtv_stream *s = &itv->streams[id->type];
+
+       strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
+       strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
+       snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
+       vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
+       vcap->device_caps = s->caps;
+       return 0;
+}
+
+static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       return ivtv_get_audio_input(itv, vin->index, vin);
+}
+
+static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       vin->index = itv->audio_input;
+       return ivtv_get_audio_input(itv, vin->index, vin);
+}
+
+static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (vout->index >= itv->nof_audio_inputs)
+               return -EINVAL;
+
+       itv->audio_input = vout->index;
+       ivtv_audio_set_io(itv);
+
+       return 0;
+}
+
+static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       /* set it to defaults from our table */
+       return ivtv_get_audio_output(itv, vin->index, vin);
+}
+
+static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       vin->index = 0;
+       return ivtv_get_audio_output(itv, vin->index, vin);
+}
+
+static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       return ivtv_get_audio_output(itv, vout->index, vout);
+}
+
+static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       /* set it to defaults from our table */
+       return ivtv_get_input(itv, vin->index, vin);
+}
+
+static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       return ivtv_get_output(itv, vout->index, vout);
+}
+
+static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       int streamtype;
+
+       streamtype = id->type;
+
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return -EINVAL;
+       cropcap->bounds.top = cropcap->bounds.left = 0;
+       cropcap->bounds.width = 720;
+       if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               cropcap->bounds.height = itv->is_50hz ? 576 : 480;
+               cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+               cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+       } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+               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 {
+               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;
+       }
+       cropcap->defrect = cropcap->bounds;
+       return 0;
+}
+
+static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       int streamtype;
+
+       streamtype = id->type;
+
+       if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+                       yi->main_rect = crop->c;
+                       return 0;
+               } else {
+                       if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+                               crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
+                               itv->main_rect = crop->c;
+                               return 0;
+                       }
+               }
+               return -EINVAL;
+       }
+       return -EINVAL;
+}
+
+static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       int streamtype;
+
+       streamtype = id->type;
+
+       if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
+                       crop->c = yi->main_rect;
+               else
+                       crop->c = itv->main_rect;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+       static struct v4l2_fmtdesc formats[] = {
+               { 0, 0, 0,
+                 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
+                 { 0, 0, 0, 0 }
+               },
+               { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
+                 "MPEG", V4L2_PIX_FMT_MPEG,
+                 { 0, 0, 0, 0 }
+               }
+       };
+       enum v4l2_buf_type type = fmt->type;
+
+       if (fmt->index > 1)
+               return -EINVAL;
+
+       *fmt = formats[fmt->index];
+       fmt->type = type;
+       return 0;
+}
+
+static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       static struct v4l2_fmtdesc formats[] = {
+               { 0, 0, 0,
+                 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
+                 { 0, 0, 0, 0 }
+               },
+               { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
+                 "MPEG", V4L2_PIX_FMT_MPEG,
+                 { 0, 0, 0, 0 }
+               }
+       };
+       enum v4l2_buf_type type = fmt->type;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+
+       if (fmt->index > 1)
+               return -EINVAL;
+
+       *fmt = formats[fmt->index];
+       fmt->type = type;
+
+       return 0;
+}
+
+static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       *i = itv->active_input;
+
+       return 0;
+}
+
+int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (inp < 0 || inp >= itv->nof_inputs)
+               return -EINVAL;
+
+       if (inp == itv->active_input) {
+               IVTV_DEBUG_INFO("Input unchanged\n");
+               return 0;
+       }
+
+       if (atomic_read(&itv->capturing) > 0) {
+               return -EBUSY;
+       }
+
+       IVTV_DEBUG_INFO("Changing input from %d to %d\n",
+                       itv->active_input, inp);
+
+       itv->active_input = inp;
+       /* Set the audio input to whatever is appropriate for the
+          input type. */
+       itv->audio_input = itv->card->video_inputs[inp].audio_index;
+
+       /* prevent others from messing with the streams until
+          we're finished changing inputs. */
+       ivtv_mute(itv);
+       ivtv_video_set_io(itv);
+       ivtv_audio_set_io(itv);
+       ivtv_unmute(itv);
+
+       return 0;
+}
+
+static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return -EINVAL;
+
+       *i = itv->active_output;
+
+       return 0;
+}
+
+static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (outp >= itv->card->nof_outputs)
+               return -EINVAL;
+
+       if (outp == itv->active_output) {
+               IVTV_DEBUG_INFO("Output unchanged\n");
+               return 0;
+       }
+       IVTV_DEBUG_INFO("Changing output from %d to %d\n",
+                  itv->active_output, outp);
+
+       itv->active_output = outp;
+       ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
+                       SAA7127_INPUT_TYPE_NORMAL,
+                       itv->card->video_outputs[outp].video_output, 0);
+
+       return 0;
+}
+
+static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (vf->tuner != 0)
+               return -EINVAL;
+
+       ivtv_call_all(itv, tuner, g_frequency, vf);
+       return 0;
+}
+
+int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (vf->tuner != 0)
+               return -EINVAL;
+
+       ivtv_mute(itv);
+       IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
+       ivtv_call_all(itv, tuner, s_frequency, vf);
+       ivtv_unmute(itv);
+       return 0;
+}
+
+static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       *std = itv->std;
+       return 0;
+}
+
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
+{
+       itv->std = *std;
+       itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+       itv->is_50hz = !itv->is_60hz;
+       cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
+       itv->cxhdl.width = 720;
+       itv->cxhdl.height = itv->is_50hz ? 576 : 480;
+       itv->vbi.count = itv->is_50hz ? 18 : 12;
+       itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
+       itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
+
+       if (itv->hw_flags & IVTV_HW_CX25840)
+               itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
+
+       /* Tuner */
+       ivtv_call_all(itv, core, s_std, itv->std);
+}
+
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       DEFINE_WAIT(wait);
+       int f;
+
+       /* set display standard */
+       itv->std_out = *std;
+       itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+       itv->is_out_50hz = !itv->is_out_60hz;
+       ivtv_call_all(itv, video, s_std_output, itv->std_out);
+
+       /*
+        * The next firmware call is time sensitive. Time it to
+        * avoid risk of a hard lock, by trying to ensure the call
+        * happens within the first 100 lines of the top field.
+        * Make 4 attempts to sync to the decoder before giving up.
+        */
+       mutex_unlock(&itv->serialize_lock);
+       for (f = 0; f < 4; f++) {
+               prepare_to_wait(&itv->vsync_waitq, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
+                       break;
+               schedule_timeout(msecs_to_jiffies(25));
+       }
+       finish_wait(&itv->vsync_waitq, &wait);
+       mutex_lock(&itv->serialize_lock);
+
+       if (f == 4)
+               IVTV_WARN("Mode change failed to sync to decoder\n");
+
+       ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
+       itv->main_rect.left = 0;
+       itv->main_rect.top = 0;
+       itv->main_rect.width = 720;
+       itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
+       ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+               720, itv->main_rect.height, 0, 0);
+       yi->main_rect = itv->main_rect;
+       if (!itv->osd_info) {
+               yi->osd_full_w = 720;
+               yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
+       }
+}
+
+int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if ((*std & V4L2_STD_ALL) == 0)
+               return -EINVAL;
+
+       if (*std == itv->std)
+               return 0;
+
+       if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
+           atomic_read(&itv->capturing) > 0 ||
+           atomic_read(&itv->decoding) > 0) {
+               /* Switching standard would mess with already running
+                  streams, prevent that by returning EBUSY. */
+               return -EBUSY;
+       }
+
+       IVTV_DEBUG_INFO("Switching standard to %llx.\n",
+               (unsigned long long)itv->std);
+
+       ivtv_s_std_enc(itv, std);
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+               ivtv_s_std_dec(itv, std);
+
+       return 0;
+}
+
+static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+
+       if (vt->index != 0)
+               return -EINVAL;
+
+       ivtv_call_all(itv, tuner, s_tuner, vt);
+
+       return 0;
+}
+
+static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (vt->index != 0)
+               return -EINVAL;
+
+       ivtv_call_all(itv, tuner, g_tuner, vt);
+
+       if (vt->type == V4L2_TUNER_RADIO)
+               strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
+       else
+               strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
+       return 0;
+}
+
+static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
+       int f, l;
+
+       if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+               for (f = 0; f < 2; f++) {
+                       for (l = 0; l < 24; l++) {
+                               if (valid_service_line(f, l, itv->is_50hz))
+                                       cap->service_lines[f][l] = set;
+                       }
+               }
+       } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+               if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
+                       return -EINVAL;
+               if (itv->is_60hz) {
+                       cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+                       cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
+               } else {
+                       cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
+                       cap->service_lines[0][16] = V4L2_SLICED_VPS;
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       set = 0;
+       for (f = 0; f < 2; f++)
+               for (l = 0; l < 24; l++)
+                       set |= cap->service_lines[f][l];
+       cap->service_set = set;
+       return 0;
+}
+
+static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       struct v4l2_enc_idx_entry *e = idx->entry;
+       int entries;
+       int i;
+
+       entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
+                               IVTV_MAX_PGM_INDEX;
+       if (entries > V4L2_ENC_IDX_ENTRIES)
+               entries = V4L2_ENC_IDX_ENTRIES;
+       idx->entries = 0;
+       for (i = 0; i < entries; i++) {
+               *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
+               if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
+                       idx->entries++;
+                       e++;
+               }
+       }
+       itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
+       return 0;
+}
+
+static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+
+
+       switch (enc->cmd) {
+       case V4L2_ENC_CMD_START:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+               enc->flags = 0;
+               return ivtv_start_capture(id);
+
+       case V4L2_ENC_CMD_STOP:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+               ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
+               return 0;
+
+       case V4L2_ENC_CMD_PAUSE:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+               enc->flags = 0;
+
+               if (!atomic_read(&itv->capturing))
+                       return -EPERM;
+               if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
+                       return 0;
+
+               ivtv_mute(itv);
+               ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
+               break;
+
+       case V4L2_ENC_CMD_RESUME:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+               enc->flags = 0;
+
+               if (!atomic_read(&itv->capturing))
+                       return -EPERM;
+
+               if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
+                       return 0;
+
+               ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
+               ivtv_unmute(itv);
+               break;
+       default:
+               IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       switch (enc->cmd) {
+       case V4L2_ENC_CMD_START:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+               enc->flags = 0;
+               return 0;
+
+       case V4L2_ENC_CMD_STOP:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+               return 0;
+
+       case V4L2_ENC_CMD_PAUSE:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+               enc->flags = 0;
+               return 0;
+
+       case V4L2_ENC_CMD_RESUME:
+               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+               enc->flags = 0;
+               return 0;
+       default:
+               IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+               return -EINVAL;
+       }
+}
+
+static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct yuv_playback_info *yi = &itv->yuv_info;
+
+       int pixfmt;
+       static u32 pixel_format[16] = {
+               V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
+               V4L2_PIX_FMT_RGB565,
+               V4L2_PIX_FMT_RGB555,
+               V4L2_PIX_FMT_RGB444,
+               V4L2_PIX_FMT_RGB32,
+               0,
+               0,
+               0,
+               V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
+               V4L2_PIX_FMT_YUV565,
+               V4L2_PIX_FMT_YUV555,
+               V4L2_PIX_FMT_YUV444,
+               V4L2_PIX_FMT_YUV32,
+               0,
+               0,
+               0,
+       };
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -EINVAL;
+       if (!itv->osd_video_pbase)
+               return -EINVAL;
+
+       fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
+               V4L2_FBUF_CAP_GLOBAL_ALPHA;
+
+       ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
+       data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
+       pixfmt = (data[0] >> 3) & 0xf;
+
+       fb->fmt.pixelformat = pixel_format[pixfmt];
+       fb->fmt.width = itv->osd_rect.width;
+       fb->fmt.height = itv->osd_rect.height;
+       fb->fmt.field = V4L2_FIELD_INTERLACED;
+       fb->fmt.bytesperline = fb->fmt.width;
+       fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       fb->fmt.field = V4L2_FIELD_INTERLACED;
+       fb->fmt.priv = 0;
+       if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
+               fb->fmt.bytesperline *= 2;
+       if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
+           fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
+               fb->fmt.bytesperline *= 2;
+       fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
+       fb->base = (void *)itv->osd_video_pbase;
+       fb->flags = 0;
+
+       if (itv->osd_chroma_key_state)
+               fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+
+       if (itv->osd_global_alpha_state)
+               fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+
+       if (yi->track_osd)
+               fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
+
+       pixfmt &= 7;
+
+       /* no local alpha for RGB565 or unknown formats */
+       if (pixfmt == 1 || pixfmt > 4)
+               return 0;
+
+       /* 16-bit formats have inverted local alpha */
+       if (pixfmt == 2 || pixfmt == 3)
+               fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
+       else
+               fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
+
+       if (itv->osd_local_alpha_state) {
+               /* 16-bit formats have inverted local alpha */
+               if (pixfmt == 2 || pixfmt == 3)
+                       fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
+               else
+                       fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+       }
+
+       return 0;
+}
+
+static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -EINVAL;
+       if (!itv->osd_video_pbase)
+               return -EINVAL;
+
+       itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
+       itv->osd_local_alpha_state =
+               (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;
+       return ivtv_g_fbuf(file, fh, fb);
+}
+
+static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
+{
+       struct ivtv_open_id *id = fh2id(fh);
+       struct ivtv *itv = id->itv;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+               return -EINVAL;
+
+       ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
+
+       return 0;
+}
+
+static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_VSYNC:
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 0, NULL);
+       case V4L2_EVENT_CTRL:
+               return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int ivtv_log_status(struct file *file, void *fh)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+       u32 data[CX2341X_MBOX_MAX_DATA];
+
+       int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
+       struct v4l2_input vidin;
+       struct v4l2_audio audin;
+       int i;
+
+       IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
+       if (itv->hw_flags & IVTV_HW_TVEEPROM) {
+               struct tveeprom tv;
+
+               ivtv_read_eeprom(itv, &tv);
+       }
+       ivtv_call_all(itv, core, log_status);
+       ivtv_get_input(itv, itv->active_input, &vidin);
+       ivtv_get_audio_input(itv, itv->audio_input, &audin);
+       IVTV_INFO("Video Input:  %s\n", vidin.name);
+       IVTV_INFO("Audio Input:  %s%s\n", audin.name,
+               (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
+       if (has_output) {
+               struct v4l2_output vidout;
+               struct v4l2_audioout audout;
+               int mode = itv->output_mode;
+               static const char * const output_modes[5] = {
+                       "None",
+                       "MPEG Streaming",
+                       "YUV Streaming",
+                       "YUV Frames",
+                       "Passthrough",
+               };
+               static const char * const alpha_mode[4] = {
+                       "None",
+                       "Global",
+                       "Local",
+                       "Global and Local"
+               };
+               static const char * const pixel_format[16] = {
+                       "ARGB Indexed",
+                       "RGB 5:6:5",
+                       "ARGB 1:5:5:5",
+                       "ARGB 1:4:4:4",
+                       "ARGB 8:8:8:8",
+                       "5",
+                       "6",
+                       "7",
+                       "AYUV Indexed",
+                       "YUV 5:6:5",
+                       "AYUV 1:5:5:5",
+                       "AYUV 1:4:4:4",
+                       "AYUV 8:8:8:8",
+                       "13",
+                       "14",
+                       "15",
+               };
+
+               ivtv_get_output(itv, itv->active_output, &vidout);
+               ivtv_get_audio_output(itv, 0, &audout);
+               IVTV_INFO("Video Output: %s\n", vidout.name);
+               if (mode < 0 || mode > OUT_PASSTHROUGH)
+                       mode = OUT_NONE;
+               IVTV_INFO("Output Mode:  %s\n", output_modes[mode]);
+               ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
+               data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
+               IVTV_INFO("Overlay:      %s, Alpha: %s, Pixel Format: %s\n",
+                       data[0] & 1 ? "On" : "Off",
+                       alpha_mode[(data[0] >> 1) & 0x3],
+                       pixel_format[(data[0] >> 3) & 0xf]);
+       }
+       IVTV_INFO("Tuner:  %s\n",
+               test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
+       v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
+       IVTV_INFO("Status flags:    0x%08lx\n", itv->i_flags);
+       for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+               struct ivtv_stream *s = &itv->streams[i];
+
+               if (s->vdev == NULL || s->buffers == 0)
+                       continue;
+               IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
+                               (s->buffers - s->q_free.buffers) * 100 / s->buffers,
+                               (s->buffers * s->buf_size) / 1024, s->buffers);
+       }
+
+       IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
+                       (long long)itv->mpg_data_received,
+                       (long long)itv->vbi_data_inserted);
+       return 0;
+}
+
+static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
+{
+       struct ivtv_open_id *id = fh2id(file->private_data);
+       struct ivtv *itv = id->itv;
+
+       IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
+       return ivtv_video_command(itv, id, dec, false);
+}
+
+static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
+{
+       struct ivtv_open_id *id = fh2id(file->private_data);
+       struct ivtv *itv = id->itv;
+
+       IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
+       return ivtv_video_command(itv, id, dec, true);
+}
+
+static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
+{
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       int nonblocking = filp->f_flags & O_NONBLOCK;
+       struct ivtv_stream *s = &itv->streams[id->type];
+       unsigned long iarg = (unsigned long)arg;
+
+       switch (cmd) {
+       case IVTV_IOC_DMA_FRAME: {
+               struct ivtv_dma_frame *args = arg;
+
+               IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
+               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+                       return -EINVAL;
+               if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+                       return -EINVAL;
+               if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
+                       return 0;
+               if (ivtv_start_decoding(id, id->type)) {
+                       return -EBUSY;
+               }
+               if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
+                       ivtv_release_stream(s);
+                       return -EBUSY;
+               }
+               /* Mark that this file handle started the UDMA_YUV mode */
+               id->yuv_frames = 1;
+               if (args->y_source == NULL)
+                       return 0;
+               return ivtv_yuv_prep_frame(itv, args);
+       }
+
+       case IVTV_IOC_PASSTHROUGH_MODE:
+               IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
+               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+                       return -EINVAL;
+               return ivtv_passthrough_mode(itv, *(int *)arg != 0);
+
+       case VIDEO_GET_PTS: {
+               s64 *pts = arg;
+               s64 frame;
+
+               IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
+               if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
+                       *pts = s->dma_pts;
+                       break;
+               }
+               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+                       return -EINVAL;
+               return ivtv_g_pts_frame(itv, pts, &frame);
+       }
+
+       case VIDEO_GET_FRAME_COUNT: {
+               s64 *frame = arg;
+               s64 pts;
+
+               IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
+               if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
+                       *frame = 0;
+                       break;
+               }
+               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+                       return -EINVAL;
+               return ivtv_g_pts_frame(itv, &pts, frame);
+       }
+
+       case VIDEO_PLAY: {
+               struct v4l2_decoder_cmd dc;
+
+               IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
+               memset(&dc, 0, sizeof(dc));
+               dc.cmd = V4L2_DEC_CMD_START;
+               return ivtv_video_command(itv, id, &dc, 0);
+       }
+
+       case VIDEO_STOP: {
+               struct v4l2_decoder_cmd dc;
+
+               IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
+               memset(&dc, 0, sizeof(dc));
+               dc.cmd = V4L2_DEC_CMD_STOP;
+               dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
+               return ivtv_video_command(itv, id, &dc, 0);
+       }
+
+       case VIDEO_FREEZE: {
+               struct v4l2_decoder_cmd dc;
+
+               IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
+               memset(&dc, 0, sizeof(dc));
+               dc.cmd = V4L2_DEC_CMD_PAUSE;
+               return ivtv_video_command(itv, id, &dc, 0);
+       }
+
+       case VIDEO_CONTINUE: {
+               struct v4l2_decoder_cmd dc;
+
+               IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
+               memset(&dc, 0, sizeof(dc));
+               dc.cmd = V4L2_DEC_CMD_RESUME;
+               return ivtv_video_command(itv, id, &dc, 0);
+       }
+
+       case VIDEO_COMMAND:
+       case VIDEO_TRY_COMMAND: {
+               /* Note: struct v4l2_decoder_cmd has the same layout as
+                  struct video_command */
+               struct v4l2_decoder_cmd *dc = arg;
+               int try = (cmd == VIDEO_TRY_COMMAND);
+
+               if (try)
+                       IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
+               else
+                       IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
+               return ivtv_video_command(itv, id, dc, try);
+       }
+
+       case VIDEO_GET_EVENT: {
+               struct video_event *ev = arg;
+               DEFINE_WAIT(wait);
+
+               IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
+               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+                       return -EINVAL;
+               memset(ev, 0, sizeof(*ev));
+               set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+
+               while (1) {
+                       if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
+                               ev->type = VIDEO_EVENT_DECODER_STOPPED;
+                       else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
+                               ev->type = VIDEO_EVENT_VSYNC;
+                               ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
+                                       VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
+                               if (itv->output_mode == OUT_UDMA_YUV &&
+                                       (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
+                                                               IVTV_YUV_MODE_PROGRESSIVE) {
+                                       ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
+                               }
+                       }
+                       if (ev->type)
+                               return 0;
+                       if (nonblocking)
+                               return -EAGAIN;
+                       /* Wait for event. Note that serialize_lock is locked,
+                          so to allow other processes to access the driver while
+                          we are waiting unlock first and later lock again. */
+                       mutex_unlock(&itv->serialize_lock);
+                       prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
+                       if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
+                           !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
+                               schedule();
+                       finish_wait(&itv->event_waitq, &wait);
+                       mutex_lock(&itv->serialize_lock);
+                       if (signal_pending(current)) {
+                               /* return if a signal was received */
+                               IVTV_DEBUG_INFO("User stopped wait for event\n");
+                               return -EINTR;
+                       }
+               }
+               break;
+       }
+
+       case VIDEO_SELECT_SOURCE:
+               IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
+               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+                       return -EINVAL;
+               return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
+
+       case AUDIO_SET_MUTE:
+               IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
+               itv->speed_mute_audio = iarg;
+               return 0;
+
+       case AUDIO_CHANNEL_SELECT:
+               IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
+               if (iarg > AUDIO_STEREO_SWAPPED)
+                       return -EINVAL;
+               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
+
+       case AUDIO_BILINGUAL_CHANNEL_SELECT:
+               IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
+               if (iarg > AUDIO_STEREO_SWAPPED)
+                       return -EINVAL;
+               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
+
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static long ivtv_default(struct file *file, void *fh, bool valid_prio,
+                        int cmd, void *arg)
+{
+       struct ivtv *itv = fh2id(fh)->itv;
+
+       if (!valid_prio) {
+               switch (cmd) {
+               case IVTV_IOC_PASSTHROUGH_MODE:
+               case VIDEO_PLAY:
+               case VIDEO_STOP:
+               case VIDEO_FREEZE:
+               case VIDEO_CONTINUE:
+               case VIDEO_COMMAND:
+               case VIDEO_SELECT_SOURCE:
+               case AUDIO_SET_MUTE:
+               case AUDIO_CHANNEL_SELECT:
+               case AUDIO_BILINGUAL_CHANNEL_SELECT:
+                       return -EBUSY;
+               }
+       }
+
+       switch (cmd) {
+       case VIDIOC_INT_RESET: {
+               u32 val = *(u32 *)arg;
+
+               if ((val == 0 && itv->options.newi2c) || (val & 0x01))
+                       ivtv_reset_ir_gpio(itv);
+               if (val & 0x02)
+                       v4l2_subdev_call(itv->sd_video, core, reset, 0);
+               break;
+       }
+
+       case IVTV_IOC_DMA_FRAME:
+       case IVTV_IOC_PASSTHROUGH_MODE:
+       case VIDEO_GET_PTS:
+       case VIDEO_GET_FRAME_COUNT:
+       case VIDEO_GET_EVENT:
+       case VIDEO_PLAY:
+       case VIDEO_STOP:
+       case VIDEO_FREEZE:
+       case VIDEO_CONTINUE:
+       case VIDEO_COMMAND:
+       case VIDEO_TRY_COMMAND:
+       case VIDEO_SELECT_SOURCE:
+       case AUDIO_SET_MUTE:
+       case AUDIO_CHANNEL_SELECT:
+       case AUDIO_BILINGUAL_CHANNEL_SELECT:
+               return ivtv_decoder_ioctls(file, cmd, (void *)arg);
+
+       default:
+               return -ENOTTY;
+       }
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
+       .vidioc_querycap                    = ivtv_querycap,
+       .vidioc_s_audio                     = ivtv_s_audio,
+       .vidioc_g_audio                     = ivtv_g_audio,
+       .vidioc_enumaudio                   = ivtv_enumaudio,
+       .vidioc_s_audout                    = ivtv_s_audout,
+       .vidioc_g_audout                    = ivtv_g_audout,
+       .vidioc_enum_input                  = ivtv_enum_input,
+       .vidioc_enum_output                 = ivtv_enum_output,
+       .vidioc_enumaudout                  = ivtv_enumaudout,
+       .vidioc_cropcap                     = ivtv_cropcap,
+       .vidioc_s_crop                      = ivtv_s_crop,
+       .vidioc_g_crop                      = ivtv_g_crop,
+       .vidioc_g_input                     = ivtv_g_input,
+       .vidioc_s_input                     = ivtv_s_input,
+       .vidioc_g_output                    = ivtv_g_output,
+       .vidioc_s_output                    = ivtv_s_output,
+       .vidioc_g_frequency                 = ivtv_g_frequency,
+       .vidioc_s_frequency                 = ivtv_s_frequency,
+       .vidioc_s_tuner                     = ivtv_s_tuner,
+       .vidioc_g_tuner                     = ivtv_g_tuner,
+       .vidioc_g_enc_index                 = ivtv_g_enc_index,
+       .vidioc_g_fbuf                      = ivtv_g_fbuf,
+       .vidioc_s_fbuf                      = ivtv_s_fbuf,
+       .vidioc_g_std                       = ivtv_g_std,
+       .vidioc_s_std                       = ivtv_s_std,
+       .vidioc_overlay                     = ivtv_overlay,
+       .vidioc_log_status                  = ivtv_log_status,
+       .vidioc_enum_fmt_vid_cap            = ivtv_enum_fmt_vid_cap,
+       .vidioc_encoder_cmd                 = ivtv_encoder_cmd,
+       .vidioc_try_encoder_cmd             = ivtv_try_encoder_cmd,
+       .vidioc_decoder_cmd                 = ivtv_decoder_cmd,
+       .vidioc_try_decoder_cmd             = ivtv_try_decoder_cmd,
+       .vidioc_enum_fmt_vid_out            = ivtv_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_cap               = ivtv_g_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap               = ivtv_g_fmt_vbi_cap,
+       .vidioc_g_fmt_sliced_vbi_cap        = ivtv_g_fmt_sliced_vbi_cap,
+       .vidioc_g_fmt_vid_out               = ivtv_g_fmt_vid_out,
+       .vidioc_g_fmt_vid_out_overlay       = ivtv_g_fmt_vid_out_overlay,
+       .vidioc_g_fmt_sliced_vbi_out        = ivtv_g_fmt_sliced_vbi_out,
+       .vidioc_s_fmt_vid_cap               = ivtv_s_fmt_vid_cap,
+       .vidioc_s_fmt_vbi_cap               = ivtv_s_fmt_vbi_cap,
+       .vidioc_s_fmt_sliced_vbi_cap        = ivtv_s_fmt_sliced_vbi_cap,
+       .vidioc_s_fmt_vid_out               = ivtv_s_fmt_vid_out,
+       .vidioc_s_fmt_vid_out_overlay       = ivtv_s_fmt_vid_out_overlay,
+       .vidioc_s_fmt_sliced_vbi_out        = ivtv_s_fmt_sliced_vbi_out,
+       .vidioc_try_fmt_vid_cap             = ivtv_try_fmt_vid_cap,
+       .vidioc_try_fmt_vbi_cap             = ivtv_try_fmt_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap      = ivtv_try_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_vid_out             = ivtv_try_fmt_vid_out,
+       .vidioc_try_fmt_vid_out_overlay     = ivtv_try_fmt_vid_out_overlay,
+       .vidioc_try_fmt_sliced_vbi_out      = ivtv_try_fmt_sliced_vbi_out,
+       .vidioc_g_sliced_vbi_cap            = ivtv_g_sliced_vbi_cap,
+       .vidioc_g_chip_ident                = ivtv_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register                  = ivtv_g_register,
+       .vidioc_s_register                  = ivtv_s_register,
+#endif
+       .vidioc_default                     = ivtv_default,
+       .vidioc_subscribe_event             = ivtv_subscribe_event,
+       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
+};
+
+void ivtv_set_funcs(struct video_device *vdev)
+{
+       vdev->ioctl_ops = &ivtv_ioctl_ops;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.h b/drivers/media/pci/ivtv/ivtv-ioctl.h
new file mode 100644 (file)
index 0000000..7c553d1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+    ioctl system call
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_IOCTL_H
+#define IVTV_IOCTL_H
+
+u16 ivtv_service2vbi(int type);
+void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
+void ivtv_set_osd_alpha(struct ivtv *itv);
+int ivtv_set_speed(struct ivtv *itv, int speed);
+void ivtv_set_funcs(struct video_device *vdev);
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
+int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
+int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c
new file mode 100644 (file)
index 0000000..1b3b957
--- /dev/null
@@ -0,0 +1,1038 @@
+/* interrupt handling
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-queue.h"
+#include "ivtv-udma.h"
+#include "ivtv-irq.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-vbi.h"
+#include "ivtv-yuv.h"
+#include <media/v4l2-event.h>
+
+#define DMA_MAGIC_COOKIE 0x000001fe
+
+static void ivtv_dma_dec_start(struct ivtv_stream *s);
+
+static const int ivtv_stream_map[] = {
+       IVTV_ENC_STREAM_TYPE_MPG,
+       IVTV_ENC_STREAM_TYPE_YUV,
+       IVTV_ENC_STREAM_TYPE_PCM,
+       IVTV_ENC_STREAM_TYPE_VBI,
+};
+
+
+static void ivtv_pio_work_handler(struct ivtv *itv)
+{
+       struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
+       struct ivtv_buffer *buf;
+       int i = 0;
+
+       IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
+       if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
+                       s->vdev == NULL || !ivtv_use_pio(s)) {
+               itv->cur_pio_stream = -1;
+               /* trigger PIO complete user interrupt */
+               write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
+               return;
+       }
+       IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name);
+       list_for_each_entry(buf, &s->q_dma.list, list) {
+               u32 size = s->sg_processing[i].size & 0x3ffff;
+
+               /* Copy the data from the card to the buffer */
+               if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+                       memcpy_fromio(buf->buf, itv->dec_mem + s->sg_processing[i].src - IVTV_DECODER_OFFSET, size);
+               }
+               else {
+                       memcpy_fromio(buf->buf, itv->enc_mem + s->sg_processing[i].src, size);
+               }
+               i++;
+               if (i == s->sg_processing_size)
+                       break;
+       }
+       write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
+}
+
+void ivtv_irq_work_handler(struct kthread_work *work)
+{
+       struct ivtv *itv = container_of(work, struct ivtv, irq_work);
+
+       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
+               ivtv_pio_work_handler(itv);
+
+       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
+               ivtv_vbi_work_handler(itv);
+
+       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
+               ivtv_yuv_work_handler(itv);
+}
+
+/* Determine the required DMA size, setup enough buffers in the predma queue and
+   actually copy the data from the card to the buffers in case a PIO transfer is
+   required for this stream.
+ */
+static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct ivtv *itv = s->itv;
+       struct ivtv_buffer *buf;
+       u32 bytes_needed = 0;
+       u32 offset, size;
+       u32 UVoffset = 0, UVsize = 0;
+       int skip_bufs = s->q_predma.buffers;
+       int idx = s->sg_pending_size;
+       int rc;
+
+       /* sanity checks */
+       if (s->vdev == NULL) {
+               IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
+               return -1;
+       }
+       if (!test_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
+               IVTV_DEBUG_WARN("Stream %s not open\n", s->name);
+               return -1;
+       }
+
+       /* determine offset, size and PTS for the various streams */
+       switch (s->type) {
+               case IVTV_ENC_STREAM_TYPE_MPG:
+                       offset = data[1];
+                       size = data[2];
+                       s->pending_pts = 0;
+                       break;
+
+               case IVTV_ENC_STREAM_TYPE_YUV:
+                       offset = data[1];
+                       size = data[2];
+                       UVoffset = data[3];
+                       UVsize = data[4];
+                       s->pending_pts = ((u64) data[5] << 32) | data[6];
+                       break;
+
+               case IVTV_ENC_STREAM_TYPE_PCM:
+                       offset = data[1] + 12;
+                       size = data[2] - 12;
+                       s->pending_pts = read_dec(offset - 8) |
+                               ((u64)(read_dec(offset - 12)) << 32);
+                       if (itv->has_cx23415)
+                               offset += IVTV_DECODER_OFFSET;
+                       break;
+
+               case IVTV_ENC_STREAM_TYPE_VBI:
+                       size = itv->vbi.enc_size * itv->vbi.fpi;
+                       offset = read_enc(itv->vbi.enc_start - 4) + 12;
+                       if (offset == 12) {
+                               IVTV_DEBUG_INFO("VBI offset == 0\n");
+                               return -1;
+                       }
+                       s->pending_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32);
+                       break;
+
+               case IVTV_DEC_STREAM_TYPE_VBI:
+                       size = read_dec(itv->vbi.dec_start + 4) + 8;
+                       offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start;
+                       s->pending_pts = 0;
+                       offset += IVTV_DECODER_OFFSET;
+                       break;
+               default:
+                       /* shouldn't happen */
+                       return -1;
+       }
+
+       /* if this is the start of the DMA then fill in the magic cookie */
+       if (s->sg_pending_size == 0 && ivtv_use_dma(s)) {
+               if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
+                   s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
+                       s->pending_backup = read_dec(offset - IVTV_DECODER_OFFSET);
+                       write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET);
+               }
+               else {
+                       s->pending_backup = read_enc(offset);
+                       write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset);
+               }
+               s->pending_offset = offset;
+       }
+
+       bytes_needed = size;
+       if (s->type == IVTV_ENC_STREAM_TYPE_YUV) {
+               /* The size for the Y samples needs to be rounded upwards to a
+                  multiple of the buf_size. The UV samples then start in the
+                  next buffer. */
+               bytes_needed = s->buf_size * ((bytes_needed + s->buf_size - 1) / s->buf_size);
+               bytes_needed += UVsize;
+       }
+
+       IVTV_DEBUG_HI_DMA("%s %s: 0x%08x bytes at 0x%08x\n",
+               ivtv_use_pio(s) ? "PIO" : "DMA", s->name, bytes_needed, offset);
+
+       rc = ivtv_queue_move(s, &s->q_free, &s->q_full, &s->q_predma, bytes_needed);
+       if (rc < 0) { /* Insufficient buffers */
+               IVTV_DEBUG_WARN("Cannot obtain %d bytes for %s data transfer\n",
+                               bytes_needed, s->name);
+               return -1;
+       }
+       if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) {
+               IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name);
+               IVTV_WARN("Cause: the application is not reading fast enough.\n");
+       }
+       s->buffers_stolen = rc;
+
+       /* got the buffers, now fill in sg_pending */
+       buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
+       memset(buf->buf, 0, 128);
+       list_for_each_entry(buf, &s->q_predma.list, list) {
+               if (skip_bufs-- > 0)
+                       continue;
+               s->sg_pending[idx].dst = buf->dma_handle;
+               s->sg_pending[idx].src = offset;
+               s->sg_pending[idx].size = s->buf_size;
+               buf->bytesused = min(size, s->buf_size);
+               buf->dma_xfer_cnt = s->dma_xfer_cnt;
+
+               s->q_predma.bytesused += buf->bytesused;
+               size -= buf->bytesused;
+               offset += s->buf_size;
+
+               /* Sync SG buffers */
+               ivtv_buf_sync_for_device(s, buf);
+
+               if (size == 0) {        /* YUV */
+                       /* process the UV section */
+                       offset = UVoffset;
+                       size = UVsize;
+               }
+               idx++;
+       }
+       s->sg_pending_size = idx;
+       return 0;
+}
+
+static void dma_post(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+       struct ivtv_buffer *buf = NULL;
+       struct list_head *p;
+       u32 offset;
+       __le32 *u32buf;
+       int x = 0;
+
+       IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
+                       s->name, s->dma_offset);
+       list_for_each(p, &s->q_dma.list) {
+               buf = list_entry(p, struct ivtv_buffer, list);
+               u32buf = (__le32 *)buf->buf;
+
+               /* Sync Buffer */
+               ivtv_buf_sync_for_cpu(s, buf);
+
+               if (x == 0 && ivtv_use_dma(s)) {
+                       offset = s->dma_last_offset;
+                       if (u32buf[offset / 4] != DMA_MAGIC_COOKIE)
+                       {
+                               for (offset = 0; offset < 64; offset++) {
+                                       if (u32buf[offset] == DMA_MAGIC_COOKIE) {
+                                               break;
+                                       }
+                               }
+                               offset *= 4;
+                               if (offset == 256) {
+                                       IVTV_DEBUG_WARN("%s: Couldn't find start of buffer within the first 256 bytes\n", s->name);
+                                       offset = s->dma_last_offset;
+                               }
+                               if (s->dma_last_offset != offset)
+                                       IVTV_DEBUG_WARN("%s: offset %d -> %d\n", s->name, s->dma_last_offset, offset);
+                               s->dma_last_offset = offset;
+                       }
+                       if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
+                                               s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
+                               write_dec_sync(0, s->dma_offset - IVTV_DECODER_OFFSET);
+                       }
+                       else {
+                               write_enc_sync(0, s->dma_offset);
+                       }
+                       if (offset) {
+                               buf->bytesused -= offset;
+                               memcpy(buf->buf, buf->buf + offset, buf->bytesused + offset);
+                       }
+                       *u32buf = cpu_to_le32(s->dma_backup);
+               }
+               x++;
+               /* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */
+               if (s->type == IVTV_ENC_STREAM_TYPE_MPG ||
+                   s->type == IVTV_ENC_STREAM_TYPE_VBI)
+                       buf->b_flags |= IVTV_F_B_NEED_BUF_SWAP;
+       }
+       if (buf)
+               buf->bytesused += s->dma_last_offset;
+       if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+               list_for_each_entry(buf, &s->q_dma.list, list) {
+                       /* Parse and Groom VBI Data */
+                       s->q_dma.bytesused -= buf->bytesused;
+                       ivtv_process_vbi_data(itv, buf, 0, s->type);
+                       s->q_dma.bytesused += buf->bytesused;
+               }
+               if (s->fh == NULL) {
+                       ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
+                       return;
+               }
+       }
+       ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
+       if (s->fh)
+               wake_up(&s->waitq);
+}
+
+void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
+{
+       struct ivtv *itv = s->itv;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       u8 frame = yi->draw_frame;
+       struct yuv_frame_info *f = &yi->new_frame_info[frame];
+       struct ivtv_buffer *buf;
+       u32 y_size = 720 * ((f->src_h + 31) & ~31);
+       u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
+       int y_done = 0;
+       int bytes_written = 0;
+       unsigned long flags = 0;
+       int idx = 0;
+
+       IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
+
+       /* Insert buffer block for YUV if needed */
+       if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) {
+               if (yi->blanking_dmaptr) {
+                       s->sg_pending[idx].src = yi->blanking_dmaptr;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = 720 * 16;
+               }
+               offset += 720 * 16;
+               idx++;
+       }
+
+       list_for_each_entry(buf, &s->q_predma.list, list) {
+               /* YUV UV Offset from Y Buffer */
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
+                               (bytes_written + buf->bytesused) >= y_size) {
+                       s->sg_pending[idx].src = buf->dma_handle;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = y_size - bytes_written;
+                       offset = uv_offset;
+                       if (s->sg_pending[idx].size != buf->bytesused) {
+                               idx++;
+                               s->sg_pending[idx].src =
+                                 buf->dma_handle + s->sg_pending[idx - 1].size;
+                               s->sg_pending[idx].dst = offset;
+                               s->sg_pending[idx].size =
+                                  buf->bytesused - s->sg_pending[idx - 1].size;
+                               offset += s->sg_pending[idx].size;
+                       }
+                       y_done = 1;
+               } else {
+                       s->sg_pending[idx].src = buf->dma_handle;
+                       s->sg_pending[idx].dst = offset;
+                       s->sg_pending[idx].size = buf->bytesused;
+                       offset += buf->bytesused;
+               }
+               bytes_written += buf->bytesused;
+
+               /* Sync SG buffers */
+               ivtv_buf_sync_for_device(s, buf);
+               idx++;
+       }
+       s->sg_pending_size = idx;
+
+       /* Sync Hardware SG List of buffers */
+       ivtv_stream_sync_for_device(s);
+       if (lock)
+               spin_lock_irqsave(&itv->dma_reg_lock, flags);
+       if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
+               ivtv_dma_dec_start(s);
+       }
+       else {
+               set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
+       }
+       if (lock)
+               spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
+}
+
+static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+
+       s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src);
+       s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst);
+       s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000);
+       s->sg_processed++;
+       /* Sync Hardware SG List of buffers */
+       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(300);
+       add_timer(&itv->dma_timer);
+}
+
+static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+
+       s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src);
+       s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst);
+       s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000);
+       s->sg_processed++;
+       /* Sync Hardware SG List of buffers */
+       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(300);
+       add_timer(&itv->dma_timer);
+}
+
+/* start the encoder DMA */
+static void ivtv_dma_enc_start(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+       struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+       int i;
+
+       IVTV_DEBUG_HI_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
+
+       if (s->q_predma.bytesused)
+               ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
+
+       if (ivtv_use_dma(s))
+               s->sg_pending[s->sg_pending_size - 1].size += 256;
+
+       /* If this is an MPEG stream, and VBI data is also pending, then append the
+          VBI DMA to the MPEG DMA and transfer both sets of data at once.
+
+          VBI DMA is a second class citizen compared to MPEG and mixing them together
+          will confuse the firmware (the end of a VBI DMA is seen as the end of a
+          MPEG DMA, thus effectively dropping an MPEG frame). So instead we make
+          sure we only use the MPEG DMA to transfer the VBI DMA if both are in
+          use. This way no conflicts occur. */
+       clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->sg_pending_size &&
+                       s->sg_pending_size + s_vbi->sg_pending_size <= s->buffers) {
+               ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
+               if (ivtv_use_dma(s_vbi))
+                       s_vbi->sg_pending[s_vbi->sg_pending_size - 1].size += 256;
+               for (i = 0; i < s_vbi->sg_pending_size; i++) {
+                       s->sg_pending[s->sg_pending_size++] = s_vbi->sg_pending[i];
+               }
+               s_vbi->dma_offset = s_vbi->pending_offset;
+               s_vbi->sg_pending_size = 0;
+               s_vbi->dma_xfer_cnt++;
+               set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
+               IVTV_DEBUG_HI_DMA("include DMA for %s\n", s_vbi->name);
+       }
+
+       s->dma_xfer_cnt++;
+       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
+       s->sg_processing_size = s->sg_pending_size;
+       s->sg_pending_size = 0;
+       s->sg_processed = 0;
+       s->dma_offset = s->pending_offset;
+       s->dma_backup = s->pending_backup;
+       s->dma_pts = s->pending_pts;
+
+       if (ivtv_use_pio(s)) {
+               set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
+               set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+               set_bit(IVTV_F_I_PIO, &itv->i_flags);
+               itv->cur_pio_stream = s->type;
+       }
+       else {
+               itv->dma_retries = 0;
+               ivtv_dma_enc_start_xfer(s);
+               set_bit(IVTV_F_I_DMA, &itv->i_flags);
+               itv->cur_dma_stream = s->type;
+       }
+}
+
+static void ivtv_dma_dec_start(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+
+       if (s->q_predma.bytesused)
+               ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
+       s->dma_xfer_cnt++;
+       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
+       s->sg_processing_size = s->sg_pending_size;
+       s->sg_pending_size = 0;
+       s->sg_processed = 0;
+
+       IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name);
+       itv->dma_retries = 0;
+       ivtv_dma_dec_start_xfer(s);
+       set_bit(IVTV_F_I_DMA, &itv->i_flags);
+       itv->cur_dma_stream = s->type;
+}
+
+static void ivtv_irq_dma_read(struct ivtv *itv)
+{
+       struct ivtv_stream *s = NULL;
+       struct ivtv_buffer *buf;
+       int hw_stream_type = 0;
+
+       IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
+
+       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];
+               ivtv_stream_sync_for_cpu(s);
+
+               if (read_reg(IVTV_REG_DMASTATUS) & 0x14) {
+                       IVTV_DEBUG_WARN("DEC DMA ERROR %x (xfer %d of %d, retry %d)\n",
+                                       read_reg(IVTV_REG_DMASTATUS),
+                                       s->sg_processed, s->sg_processing_size, itv->dma_retries);
+                       write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+                       if (itv->dma_retries == 3) {
+                               /* Too many retries, give up on this frame */
+                               itv->dma_retries = 0;
+                               s->sg_processed = s->sg_processing_size;
+                       }
+                       else {
+                               /* Retry, starting with the first xfer segment.
+                                  Just retrying the current segment is not sufficient. */
+                               s->sg_processed = 0;
+                               itv->dma_retries++;
+                       }
+               }
+               if (s->sg_processed < s->sg_processing_size) {
+                       /* DMA next buffer */
+                       ivtv_dma_dec_start_xfer(s);
+                       return;
+               }
+               if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
+                       hw_stream_type = 2;
+               IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused);
+
+               /* For some reason must kick the firmware, like PIO mode,
+                  I think this tells the firmware we are done and the size
+                  of the xfer so it can calculate what we need next.
+                  I think we can do this part ourselves but would have to
+                  fully calculate xfer info ourselves and not use interrupts
+                */
+               ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, s->q_dma.bytesused,
+                               hw_stream_type);
+
+               /* Free last DMA call */
+               while ((buf = ivtv_dequeue(s, &s->q_dma)) != NULL) {
+                       ivtv_buf_sync_for_cpu(s, buf);
+                       ivtv_enqueue(s, buf, &s->q_free);
+               }
+               wake_up(&s->waitq);
+       }
+       clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+       itv->cur_dma_stream = -1;
+       wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv_stream *s;
+
+       ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+       IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
+
+       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);
+
+       if (data[0] & 0x18) {
+               IVTV_DEBUG_WARN("ENC DMA ERROR %x (offset %08x, xfer %d of %d, retry %d)\n", data[0],
+                       s->dma_offset, s->sg_processed, s->sg_processing_size, itv->dma_retries);
+               write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+               if (itv->dma_retries == 3) {
+                       /* Too many retries, give up on this frame */
+                       itv->dma_retries = 0;
+                       s->sg_processed = s->sg_processing_size;
+               }
+               else {
+                       /* Retry, starting with the first xfer segment.
+                          Just retrying the current segment is not sufficient. */
+                       s->sg_processed = 0;
+                       itv->dma_retries++;
+               }
+       }
+       if (s->sg_processed < s->sg_processing_size) {
+               /* DMA next buffer */
+               ivtv_dma_enc_start_xfer(s);
+               return;
+       }
+       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+       itv->cur_dma_stream = -1;
+       dma_post(s);
+       if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+               s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+               dma_post(s);
+       }
+       s->sg_processing_size = 0;
+       s->sg_processed = 0;
+       wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
+{
+       struct ivtv_stream *s;
+
+       if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
+               itv->cur_pio_stream = -1;
+               return;
+       }
+       s = &itv->streams[itv->cur_pio_stream];
+       IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name);
+       clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+       itv->cur_pio_stream = -1;
+       dma_post(s);
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+               ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
+       else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
+               ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
+       else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
+               ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
+       clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+       if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+               s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+               dma_post(s);
+       }
+       wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_dma_err(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       u32 status;
+
+       del_timer(&itv->dma_timer);
+
+       ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+       status = read_reg(IVTV_REG_DMASTATUS);
+       IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
+                               status, itv->cur_dma_stream);
+       /*
+        * We do *not* write back to the IVTV_REG_DMASTATUS register to
+        * clear the error status, if either the encoder write (0x02) or
+        * decoder read (0x01) bus master DMA operation do not indicate
+        * completed.  We can race with the DMA engine, which may have
+        * transitioned to completed status *after* we read the register.
+        * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the
+        * DMA engine has completed, will cause the DMA engine to stop working.
+        */
+       status &= 0x3;
+       if (status == 0x3)
+               write_reg(status, IVTV_REG_DMASTATUS);
+
+       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) &&
+           itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) {
+               struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream];
+
+               if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+                       /* retry */
+                       /*
+                        * FIXME - handle cases of DMA error similar to
+                        * encoder below, except conditioned on status & 0x1
+                        */
+                       ivtv_dma_dec_start(s);
+                       return;
+               } else {
+                       if ((status & 0x2) == 0) {
+                               /*
+                                * CX2341x Bus Master DMA write is ongoing.
+                                * Reset the timer and let it complete.
+                                */
+                               itv->dma_timer.expires =
+                                               jiffies + msecs_to_jiffies(600);
+                               add_timer(&itv->dma_timer);
+                               return;
+                       }
+
+                       if (itv->dma_retries < 3) {
+                               /*
+                                * CX2341x Bus Master DMA write has ended.
+                                * Retry the write, starting with the first
+                                * xfer segment. Just retrying the current
+                                * segment is not sufficient.
+                                */
+                               s->sg_processed = 0;
+                               itv->dma_retries++;
+                               ivtv_dma_enc_start_xfer(s);
+                               return;
+                       }
+                       /* Too many retries, give up on this one */
+               }
+
+       }
+       if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+               ivtv_udma_start(itv);
+               return;
+       }
+       clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+       itv->cur_dma_stream = -1;
+       wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_enc_start_cap(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv_stream *s;
+
+       /* Get DMA destination and size arguments from card */
+       ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data);
+       IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]);
+
+       if (data[0] > 2 || data[1] == 0 || data[2] == 0) {
+               IVTV_DEBUG_WARN("Unknown input: %08x %08x %08x\n",
+                               data[0], data[1], data[2]);
+               return;
+       }
+       s = &itv->streams[ivtv_stream_map[data[0]]];
+       if (!stream_enc_dma_append(s, data)) {
+               set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
+       }
+}
+
+static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv_stream *s;
+
+       IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n");
+       s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+
+       if (!stream_enc_dma_append(s, data))
+               set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
+}
+
+static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
+
+       IVTV_DEBUG_HI_IRQ("DEC VBI REINSERT\n");
+       if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
+                       !stream_enc_dma_append(s, data)) {
+               set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
+       }
+}
+
+static void ivtv_irq_dec_data_req(struct ivtv *itv)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv_stream *s;
+
+       /* YUV or MPG */
+
+       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
+               ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
+               itv->dma_data_req_size =
+                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
+               itv->dma_data_req_offset = data[1];
+               if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0)
+                       ivtv_yuv_frame_complete(itv);
+               s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
+       }
+       else {
+               ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data);
+               itv->dma_data_req_size = min_t(u32, data[2], 0x10000);
+               itv->dma_data_req_offset = data[1];
+               s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
+       }
+       IVTV_DEBUG_HI_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused,
+                      itv->dma_data_req_offset, itv->dma_data_req_size);
+       if (itv->dma_data_req_size == 0 || s->q_full.bytesused < itv->dma_data_req_size) {
+               set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+       }
+       else {
+               if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+                       ivtv_yuv_setup_stream_frame(itv);
+               clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+               ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
+               ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0);
+       }
+}
+
+static void ivtv_irq_vsync(struct ivtv *itv)
+{
+       /* The vsync interrupt is unusual in that it won't clear until
+        * the end of the first line for the current field, at which
+        * point it clears itself. This can result in repeated vsync
+        * interrupts, or a missed vsync. Read some of the registers
+        * to determine the line being displayed and ensure we handle
+        * one vsync per frame.
+        */
+       unsigned int frame = read_reg(IVTV_REG_DEC_LINE_FIELD) & 1;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       int last_dma_frame = atomic_read(&yi->next_dma_frame);
+       struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
+
+       if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
+
+       if (((frame ^ f->sync_field) == 0 &&
+               ((itv->last_vsync_field & 1) ^ f->sync_field)) ||
+                       (frame != (itv->last_vsync_field & 1) && !f->interlaced)) {
+               int next_dma_frame = last_dma_frame;
+
+               if (!(f->interlaced && f->delay && yi->fields_lapsed < 1)) {
+                       if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) {
+                               write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
+                               write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
+                               write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
+                               write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
+                               next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
+                               atomic_set(&yi->next_dma_frame, next_dma_frame);
+                               yi->fields_lapsed = -1;
+                               yi->running = 1;
+                       }
+               }
+       }
+       if (frame != (itv->last_vsync_field & 1)) {
+               static const struct v4l2_event evtop = {
+                       .type = V4L2_EVENT_VSYNC,
+                       .u.vsync.field = V4L2_FIELD_TOP,
+               };
+               static const struct v4l2_event evbottom = {
+                       .type = V4L2_EVENT_VSYNC,
+                       .u.vsync.field = V4L2_FIELD_BOTTOM,
+               };
+               struct ivtv_stream *s = ivtv_get_output_stream(itv);
+
+               itv->last_vsync_field += 1;
+               if (frame == 0) {
+                       clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
+                       clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
+               }
+               else {
+                       set_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
+               }
+               if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) {
+                       set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags);
+                       wake_up(&itv->event_waitq);
+                       if (s)
+                               wake_up(&s->waitq);
+               }
+               if (s && s->vdev)
+                       v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom);
+               wake_up(&itv->vsync_waitq);
+
+               /* Send VBI to saa7127 */
+               if (frame && (itv->output_mode == OUT_PASSTHROUGH ||
+                       test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) ||
+                       test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) ||
+                       test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) {
+                       set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
+                       set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+               }
+
+               /* Check if we need to update the yuv registers */
+               if (yi->running && (yi->yuv_forced_update || f->update)) {
+                       if (!f->update) {
+                               last_dma_frame =
+                                       (u8)(atomic_read(&yi->next_dma_frame) -
+                                                1) % IVTV_YUV_BUFFERS;
+                               f = &yi->new_frame_info[last_dma_frame];
+                       }
+
+                       if (f->src_w) {
+                               yi->update_frame = last_dma_frame;
+                               f->update = 0;
+                               yi->yuv_forced_update = 0;
+                               set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
+                               set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+                       }
+               }
+
+               yi->fields_lapsed++;
+       }
+}
+
+#define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT)
+
+irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
+{
+       struct ivtv *itv = (struct ivtv *)dev_id;
+       u32 combo;
+       u32 stat;
+       int i;
+       u8 vsync_force = 0;
+
+       spin_lock(&itv->dma_reg_lock);
+       /* get contents of irq status register */
+       stat = read_reg(IVTV_REG_IRQSTATUS);
+
+       combo = ~itv->irqmask & stat;
+
+       /* Clear out IRQ */
+       if (combo) write_reg(combo, IVTV_REG_IRQSTATUS);
+
+       if (0 == combo) {
+               /* The vsync interrupt is unusual and clears itself. If we
+                * took too long, we may have missed it. Do some checks
+                */
+               if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
+                       /* vsync is enabled, see if we're in a new field */
+                       if ((itv->last_vsync_field & 1) !=
+                           (read_reg(IVTV_REG_DEC_LINE_FIELD) & 1)) {
+                               /* New field, looks like we missed it */
+                               IVTV_DEBUG_YUV("VSync interrupt missed %d\n",
+                                      read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16);
+                               vsync_force = 1;
+                       }
+               }
+
+               if (!vsync_force) {
+                       /* No Vsync expected, wasn't for us */
+                       spin_unlock(&itv->dma_reg_lock);
+                       return IRQ_NONE;
+               }
+       }
+
+       /* Exclude interrupts noted below from the output, otherwise the log is flooded with
+          these messages */
+       if (combo & ~0xff6d0400)
+               IVTV_DEBUG_HI_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo);
+
+       if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) {
+               IVTV_DEBUG_HI_IRQ("DEC DMA COMPLETE\n");
+       }
+
+       if (combo & IVTV_IRQ_DMA_READ) {
+               ivtv_irq_dma_read(itv);
+       }
+
+       if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) {
+               ivtv_irq_enc_dma_complete(itv);
+       }
+
+       if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
+               ivtv_irq_enc_pio_complete(itv);
+       }
+
+       if (combo & IVTV_IRQ_DMA_ERR) {
+               ivtv_irq_dma_err(itv);
+       }
+
+       if (combo & IVTV_IRQ_ENC_START_CAP) {
+               ivtv_irq_enc_start_cap(itv);
+       }
+
+       if (combo & IVTV_IRQ_ENC_VBI_CAP) {
+               ivtv_irq_enc_vbi_cap(itv);
+       }
+
+       if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
+               ivtv_irq_dec_vbi_reinsert(itv);
+       }
+
+       if (combo & IVTV_IRQ_ENC_EOS) {
+               IVTV_DEBUG_IRQ("ENC EOS\n");
+               set_bit(IVTV_F_I_EOS, &itv->i_flags);
+               wake_up(&itv->eos_waitq);
+       }
+
+       if (combo & IVTV_IRQ_DEC_DATA_REQ) {
+               ivtv_irq_dec_data_req(itv);
+       }
+
+       /* Decoder Vertical Sync - We can't rely on 'combo', so check if vsync enabled */
+       if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
+               ivtv_irq_vsync(itv);
+       }
+
+       if (combo & IVTV_IRQ_ENC_VIM_RST) {
+               IVTV_DEBUG_IRQ("VIM RST\n");
+               /*ivtv_vapi(itv, CX2341X_ENC_REFRESH_INPUT, 0); */
+       }
+
+       if (combo & IVTV_IRQ_DEC_AUD_MODE_CHG) {
+               IVTV_DEBUG_INFO("Stereo mode changed\n");
+       }
+
+       if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
+               itv->irq_rr_idx++;
+               for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+                       int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS;
+                       struct ivtv_stream *s = &itv->streams[idx];
+
+                       if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags))
+                               continue;
+                       if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
+                               ivtv_dma_dec_start(s);
+                       else
+                               ivtv_dma_enc_start(s);
+                       break;
+               }
+
+               if (i == IVTV_MAX_STREAMS &&
+                   test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
+                       ivtv_udma_start(itv);
+       }
+
+       if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
+               itv->irq_rr_idx++;
+               for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+                       int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS;
+                       struct ivtv_stream *s = &itv->streams[idx];
+
+                       if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
+                               continue;
+                       if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
+                               ivtv_dma_enc_start(s);
+                       break;
+               }
+       }
+
+       if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
+               queue_kthread_work(&itv->irq_worker, &itv->irq_work);
+       }
+
+       spin_unlock(&itv->dma_reg_lock);
+
+       /* If we've just handled a 'forced' vsync, it's safest to say it
+        * wasn't ours. Another device may have triggered it at just
+        * the right time.
+        */
+       return vsync_force ? IRQ_NONE : IRQ_HANDLED;
+}
+
+void ivtv_unfinished_dma(unsigned long arg)
+{
+       struct ivtv *itv = (struct ivtv *)arg;
+
+       if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
+               return;
+       IVTV_ERR("DMA TIMEOUT %08x %d\n", read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
+
+       write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+       clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+       itv->cur_dma_stream = -1;
+       wake_up(&itv->dma_waitq);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-irq.h b/drivers/media/pci/ivtv/ivtv-irq.h
new file mode 100644 (file)
index 0000000..1e84433
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    interrupt handling
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_IRQ_H
+#define IVTV_IRQ_H
+
+#define IVTV_IRQ_ENC_START_CAP         (0x1 << 31)
+#define IVTV_IRQ_ENC_EOS               (0x1 << 30)
+#define IVTV_IRQ_ENC_VBI_CAP           (0x1 << 29)
+#define IVTV_IRQ_ENC_VIM_RST           (0x1 << 28)
+#define IVTV_IRQ_ENC_DMA_COMPLETE      (0x1 << 27)
+#define IVTV_IRQ_ENC_PIO_COMPLETE      (0x1 << 25)
+#define IVTV_IRQ_DEC_AUD_MODE_CHG      (0x1 << 24)
+#define IVTV_IRQ_DEC_DATA_REQ          (0x1 << 22)
+#define IVTV_IRQ_DEC_DMA_COMPLETE      (0x1 << 20)
+#define IVTV_IRQ_DEC_VBI_RE_INSERT     (0x1 << 19)
+#define IVTV_IRQ_DMA_ERR               (0x1 << 18)
+#define IVTV_IRQ_DMA_WRITE             (0x1 << 17)
+#define IVTV_IRQ_DMA_READ              (0x1 << 16)
+#define IVTV_IRQ_DEC_VSYNC             (0x1 << 10)
+
+/* IRQ Masks */
+#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
+               IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
+
+#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
+#define IVTV_IRQ_MASK_DECODE  (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
+
+irqreturn_t ivtv_irq_handler(int irq, void *dev_id);
+
+void ivtv_irq_work_handler(struct kthread_work *work);
+void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock);
+void ivtv_unfinished_dma(unsigned long arg);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-mailbox.c b/drivers/media/pci/ivtv/ivtv-mailbox.c
new file mode 100644 (file)
index 0000000..e3ce967
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+    mailbox functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "ivtv-driver.h"
+#include "ivtv-mailbox.h"
+
+/* Firmware mailbox flags*/
+#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
+#define IVTV_MBOX_DRIVER_DONE   0x00000002
+#define IVTV_MBOX_DRIVER_BUSY   0x00000001
+#define IVTV_MBOX_FREE                 0x00000000
+
+/* Firmware mailbox standard timeout */
+#define IVTV_API_STD_TIMEOUT   0x02000000
+
+#define API_CACHE       (1 << 0)       /* Allow the command to be stored in the cache */
+#define API_RESULT      (1 << 1)       /* Allow 1 second for this cmd to end */
+#define API_FAST_RESULT         (3 << 1)       /* Allow 0.1 second for this cmd to end */
+#define API_DMA         (1 << 3)       /* DMA mailbox, has special handling */
+#define API_HIGH_VOL    (1 << 5)       /* High volume command (i.e. called during encoding or decoding) */
+#define API_NO_WAIT_MB          (1 << 4)       /* Command may not wait for a free mailbox */
+#define API_NO_WAIT_RES         (1 << 5)       /* Command may not wait for the result */
+#define API_NO_POLL     (1 << 6)       /* Avoid pointless polling */
+
+struct ivtv_api_info {
+       int flags;              /* Flags, see above */
+       const char *name;       /* The name of the command */
+};
+
+#define API_ENTRY(x, f) [x] = { (f), #x }
+
+static const struct ivtv_api_info api_info[256] = {
+       /* MPEG encoder API */
+       API_ENTRY(CX2341X_ENC_PING_FW,                  API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_START_CAPTURE,            API_RESULT | API_NO_POLL),
+       API_ENTRY(CX2341X_ENC_STOP_CAPTURE,             API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_AUDIO_ID,             API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_VIDEO_ID,             API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_PCR_ID,               API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_FRAME_RATE,           API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_FRAME_SIZE,           API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_BIT_RATE,             API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_GOP_PROPERTIES,       API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_ASPECT_RATIO,         API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_MODE,      API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_PROPS,     API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_CORING_LEVELS,        API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,  API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_VBI_LINE,             API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_STREAM_TYPE,          API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_OUTPUT_PORT,          API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_AUDIO_PROPERTIES,     API_CACHE),
+       API_ENTRY(CX2341X_ENC_HALT_FW,                  API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_GET_VERSION,              API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_GOP_CLOSURE,          API_CACHE),
+       API_ENTRY(CX2341X_ENC_GET_SEQ_END,              API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_PGM_INDEX_INFO,       API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_VBI_CONFIG,           API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE,       API_CACHE),
+       API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10,  API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9,   API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST,        API_DMA | API_HIGH_VOL),
+       API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT,         API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE,      API_CACHE),
+       API_ENTRY(CX2341X_ENC_PAUSE_ENCODER,            API_RESULT),
+       API_ENTRY(CX2341X_ENC_REFRESH_INPUT,            API_NO_WAIT_MB | API_HIGH_VOL),
+       API_ENTRY(CX2341X_ENC_SET_COPYRIGHT,            API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION,   API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES,      API_CACHE),
+       API_ENTRY(CX2341X_ENC_SET_PLACEHOLDER,          API_CACHE),
+       API_ENTRY(CX2341X_ENC_MUTE_VIDEO,               API_RESULT),
+       API_ENTRY(CX2341X_ENC_MUTE_AUDIO,               API_RESULT),
+       API_ENTRY(CX2341X_ENC_SET_VERT_CROP_LINE,       API_FAST_RESULT),
+       API_ENTRY(CX2341X_ENC_MISC,                     API_FAST_RESULT),
+       /* Obsolete PULLDOWN API command */
+       API_ENTRY(0xb1,                                 API_CACHE),
+
+       /* MPEG decoder API */
+       API_ENTRY(CX2341X_DEC_PING_FW,                  API_FAST_RESULT),
+       API_ENTRY(CX2341X_DEC_START_PLAYBACK,           API_RESULT | API_NO_POLL),
+       API_ENTRY(CX2341X_DEC_STOP_PLAYBACK,            API_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED,       API_RESULT),
+       API_ENTRY(CX2341X_DEC_STEP_VIDEO,               API_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE,       API_CACHE),
+       API_ENTRY(CX2341X_DEC_GET_XFER_INFO,            API_FAST_RESULT),
+       API_ENTRY(CX2341X_DEC_GET_DMA_STATUS,           API_FAST_RESULT),
+       API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST,      API_DMA | API_HIGH_VOL),
+       API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK,           API_RESULT),
+       API_ENTRY(CX2341X_DEC_HALT_FW,                  API_FAST_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_STANDARD,             API_CACHE),
+       API_ENTRY(CX2341X_DEC_GET_VERSION,              API_FAST_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_STREAM_INPUT,         API_CACHE),
+       API_ENTRY(CX2341X_DEC_GET_TIMING_INFO,          API_RESULT /*| API_NO_WAIT_RES*/),
+       API_ENTRY(CX2341X_DEC_SET_AUDIO_MODE,           API_CACHE),
+       API_ENTRY(CX2341X_DEC_SET_EVENT_NOTIFICATION,   API_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_DISPLAY_BUFFERS,      API_CACHE),
+       API_ENTRY(CX2341X_DEC_EXTRACT_VBI,              API_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_DECODER_SOURCE,       API_FAST_RESULT),
+       API_ENTRY(CX2341X_DEC_SET_PREBUFFERING,         API_CACHE),
+
+       /* OSD API */
+       API_ENTRY(CX2341X_OSD_GET_FRAMEBUFFER,          API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_GET_PIXEL_FORMAT,         API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_PIXEL_FORMAT,         API_CACHE),
+       API_ENTRY(CX2341X_OSD_GET_STATE,                API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_STATE,                API_CACHE),
+       API_ENTRY(CX2341X_OSD_GET_OSD_COORDS,           API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_OSD_COORDS,           API_CACHE),
+       API_ENTRY(CX2341X_OSD_GET_SCREEN_COORDS,        API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_SCREEN_COORDS,        API_CACHE),
+       API_ENTRY(CX2341X_OSD_GET_GLOBAL_ALPHA,         API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_GLOBAL_ALPHA,         API_CACHE),
+       API_ENTRY(CX2341X_OSD_SET_BLEND_COORDS,         API_CACHE),
+       API_ENTRY(CX2341X_OSD_GET_FLICKER_STATE,        API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_FLICKER_STATE,        API_CACHE),
+       API_ENTRY(CX2341X_OSD_BLT_COPY,                 API_RESULT),
+       API_ENTRY(CX2341X_OSD_BLT_FILL,                 API_RESULT),
+       API_ENTRY(CX2341X_OSD_BLT_TEXT,                 API_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_FRAMEBUFFER_WINDOW,   API_CACHE),
+       API_ENTRY(CX2341X_OSD_SET_CHROMA_KEY,           API_CACHE),
+       API_ENTRY(CX2341X_OSD_GET_ALPHA_CONTENT_INDEX,  API_FAST_RESULT),
+       API_ENTRY(CX2341X_OSD_SET_ALPHA_CONTENT_INDEX,  API_CACHE)
+};
+
+static int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb)
+{
+       u32 flags = readl(&mbdata->mbox[mb].flags);
+       int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE);
+
+       /* if the mailbox is free, then try to claim it */
+       if (is_free && !test_and_set_bit(mb, &mbdata->busy)) {
+               write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags);
+               return 1;
+       }
+       return 0;
+}
+
+/* Try to find a free mailbox. Note mailbox 0 is reserved for DMA and so is not
+   attempted here. */
+static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int flags)
+{
+       unsigned long then = jiffies;
+       int i, mb;
+       int max_mbox = mbdata->max_mbox;
+       int retries = 100;
+
+       /* All slow commands use the same mailbox, serializing them and also
+          leaving the other mailbox free for simple fast commands. */
+       if ((flags & API_FAST_RESULT) == API_RESULT)
+               max_mbox = 1;
+
+       /* find free non-DMA mailbox */
+       for (i = 0; i < retries; i++) {
+               for (mb = 1; mb <= max_mbox; mb++)
+                       if (try_mailbox(itv, mbdata, mb))
+                               return mb;
+
+               /* Sleep before a retry, if not atomic */
+               if (!(flags & API_NO_WAIT_MB)) {
+                       if (time_after(jiffies,
+                                      then + msecs_to_jiffies(10*retries)))
+                              break;
+                       ivtv_msleep_timeout(10, 0);
+               }
+       }
+       return -ENODEV;
+}
+
+static void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[])
+{
+       int i;
+
+       write_sync(cmd, &mbox->cmd);
+       write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout);
+
+       for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
+               write_sync(data[i], &mbox->data[i]);
+
+       write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags);
+}
+
+static void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata)
+{
+       int i;
+
+       for (i = 0; i <= mbdata->max_mbox; i++) {
+               IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n",
+                       i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags));
+               write_sync(0, &mbdata->mbox[i].flags);
+               clear_bit(i, &mbdata->busy);
+       }
+}
+
+static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+{
+       struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox;
+       volatile struct ivtv_mailbox __iomem *mbox;
+       int api_timeout = msecs_to_jiffies(1000);
+       int flags, mb, i;
+       unsigned long then;
+
+       /* sanity checks */
+       if (NULL == mbdata) {
+               IVTV_ERR("No mailbox allocated\n");
+               return -ENODEV;
+       }
+       if (args < 0 || args > CX2341X_MBOX_MAX_DATA ||
+           cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) {
+               IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args);
+               return -EINVAL;
+       }
+
+       if (api_info[cmd].flags & API_HIGH_VOL) {
+           IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name);
+       }
+       else {
+           IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name);
+       }
+
+       /* clear possibly uninitialized part of data array */
+       for (i = args; i < CX2341X_MBOX_MAX_DATA; i++)
+               data[i] = 0;
+
+       /* If this command was issued within the last 30 minutes and with identical
+          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 &&
+           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;
+       }
+
+       flags = api_info[cmd].flags;
+
+       if (flags & API_DMA) {
+               for (i = 0; i < 100; i++) {
+                       mb = i % (mbdata->max_mbox + 1);
+                       if (try_mailbox(itv, mbdata, mb)) {
+                               write_mailbox(&mbdata->mbox[mb], cmd, args, data);
+                               clear_bit(mb, &mbdata->busy);
+                               return 0;
+                       }
+                       IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n",
+                                       api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags));
+               }
+               IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name);
+               clear_all_mailboxes(itv, mbdata);
+               return -EBUSY;
+       }
+
+       if ((flags & API_FAST_RESULT) == API_FAST_RESULT)
+               api_timeout = msecs_to_jiffies(100);
+
+       mb = get_mailbox(itv, mbdata, flags);
+       if (mb < 0) {
+               IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name);
+               clear_all_mailboxes(itv, mbdata);
+               return -EBUSY;
+       }
+       mbox = &mbdata->mbox[mb];
+       write_mailbox(mbox, cmd, args, data);
+       if (flags & API_CACHE) {
+               memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data));
+               itv->api_cache[cmd].last_jiffies = jiffies;
+       }
+       if ((flags & API_RESULT) == 0) {
+               clear_bit(mb, &mbdata->busy);
+               return 0;
+       }
+
+       /* Get results */
+       then = jiffies;
+
+       if (!(flags & API_NO_POLL)) {
+               /* First try to poll, then switch to delays */
+               for (i = 0; i < 100; i++) {
+                       if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)
+                               break;
+               }
+       }
+       while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
+               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);
+                       clear_bit(mb, &mbdata->busy);
+                       return -EIO;
+               }
+               if (flags & API_NO_WAIT_RES)
+                       mdelay(1);
+               else
+                       ivtv_msleep_timeout(1, 0);
+       }
+       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));
+
+       for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
+               data[i] = readl(&mbox->data[i]);
+       write_sync(0, &mbox->flags);
+       clear_bit(mb, &mbdata->busy);
+       return 0;
+}
+
+int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[])
+{
+       int res = ivtv_api_call(itv, cmd, args, data);
+
+       /* Allow a single retry, probably already too late though.
+          If there is no free mailbox then that is usually an indication
+          of a more serious problem. */
+       return (res == -EBUSY) ? ivtv_api_call(itv, cmd, args, data) : res;
+}
+
+int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       return ivtv_api(priv, cmd, in, data);
+}
+
+int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...)
+{
+       va_list ap;
+       int i;
+
+       va_start(ap, args);
+       for (i = 0; i < args; i++) {
+               data[i] = va_arg(ap, u32);
+       }
+       va_end(ap);
+       return ivtv_api(itv, cmd, args, data);
+}
+
+int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list ap;
+       int i;
+
+       va_start(ap, args);
+       for (i = 0; i < args; i++) {
+               data[i] = va_arg(ap, u32);
+       }
+       va_end(ap);
+       return ivtv_api(itv, cmd, args, data);
+}
+
+/* This one is for stuff that can't sleep.. irq handlers, etc.. */
+void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
+                      int argc, u32 data[])
+{
+       volatile u32 __iomem *p = mbdata->mbox[mb].data;
+       int i;
+       for (i = 0; i < argc; i++, p++)
+               data[i] = readl(p);
+}
+
+/* Wipe api cache */
+void ivtv_mailbox_cache_invalidate(struct ivtv *itv)
+{
+       int i;
+       for (i = 0; i < 256; i++)
+               itv->api_cache[i].last_jiffies = 0;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-mailbox.h b/drivers/media/pci/ivtv/ivtv-mailbox.h
new file mode 100644 (file)
index 0000000..2c834d2
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+    mailbox functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_MAILBOX_H
+#define IVTV_MAILBOX_H
+
+#define IVTV_MBOX_DMA_END         8
+#define IVTV_MBOX_DMA             9
+
+void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
+                      int argc, u32 data[]);
+int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]);
+int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...);
+int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...);
+int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]);
+void ivtv_mailbox_cache_invalidate(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-queue.c b/drivers/media/pci/ivtv/ivtv-queue.c
new file mode 100644 (file)
index 0000000..7fde36e
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+    buffer queues.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-queue.h"
+
+int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes)
+{
+       if (s->buf_size - buf->bytesused < copybytes)
+               copybytes = s->buf_size - buf->bytesused;
+       if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) {
+               return -EFAULT;
+       }
+       buf->bytesused += copybytes;
+       return copybytes;
+}
+
+void ivtv_buf_swap(struct ivtv_buffer *buf)
+{
+       int i;
+
+       for (i = 0; i < buf->bytesused; i += 4)
+               swab32s((u32 *)(buf->buf + i));
+}
+
+void ivtv_queue_init(struct ivtv_queue *q)
+{
+       INIT_LIST_HEAD(&q->list);
+       q->buffers = 0;
+       q->length = 0;
+       q->bytesused = 0;
+}
+
+void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
+{
+       unsigned long flags;
+
+       /* clear the buffer if it is going to be enqueued to the free queue */
+       if (q == &s->q_free) {
+               buf->bytesused = 0;
+               buf->readpos = 0;
+               buf->b_flags = 0;
+               buf->dma_xfer_cnt = 0;
+       }
+       spin_lock_irqsave(&s->qlock, flags);
+       list_add_tail(&buf->list, &q->list);
+       q->buffers++;
+       q->length += s->buf_size;
+       q->bytesused += buf->bytesused - buf->readpos;
+       spin_unlock_irqrestore(&s->qlock, flags);
+}
+
+struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
+{
+       struct ivtv_buffer *buf = NULL;
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->qlock, flags);
+       if (!list_empty(&q->list)) {
+               buf = list_entry(q->list.next, struct ivtv_buffer, list);
+               list_del_init(q->list.next);
+               q->buffers--;
+               q->length -= s->buf_size;
+               q->bytesused -= buf->bytesused - buf->readpos;
+       }
+       spin_unlock_irqrestore(&s->qlock, flags);
+       return buf;
+}
+
+static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
+               struct ivtv_queue *to, int clear)
+{
+       struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list);
+
+       list_move_tail(from->list.next, &to->list);
+       from->buffers--;
+       from->length -= s->buf_size;
+       from->bytesused -= buf->bytesused - buf->readpos;
+       /* special handling for q_free */
+       if (clear)
+               buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
+       to->buffers++;
+       to->length += s->buf_size;
+       to->bytesused += buf->bytesused - buf->readpos;
+}
+
+/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
+   If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
+   If 'steal' != NULL, then buffers may also taken from that queue if
+   needed, but only if 'from' is the free queue.
+
+   The buffer is automatically cleared if it goes to the free queue. It is
+   also cleared if buffers need to be taken from the 'steal' queue and
+   the 'from' queue is the free queue.
+
+   When 'from' is q_free, then needed_bytes is compared to the total
+   available buffer length, otherwise needed_bytes is compared to the
+   bytesused value. For the 'steal' queue the total available buffer
+   length is always used.
+
+   -ENOMEM is returned if the buffers could not be obtained, 0 if all
+   buffers where obtained from the 'from' list and if non-zero then
+   the number of stolen buffers is returned. */
+int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
+                   struct ivtv_queue *to, int needed_bytes)
+{
+       unsigned long flags;
+       int rc = 0;
+       int from_free = from == &s->q_free;
+       int to_free = to == &s->q_free;
+       int bytes_available, bytes_steal;
+
+       spin_lock_irqsave(&s->qlock, flags);
+       if (needed_bytes == 0) {
+               from_free = 1;
+               needed_bytes = from->length;
+       }
+
+       bytes_available = from_free ? from->length : from->bytesused;
+       bytes_steal = (from_free && steal) ? steal->length : 0;
+
+       if (bytes_available + bytes_steal < needed_bytes) {
+               spin_unlock_irqrestore(&s->qlock, flags);
+               return -ENOMEM;
+       }
+       while (bytes_available < needed_bytes) {
+               struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
+               u16 dma_xfer_cnt = buf->dma_xfer_cnt;
+
+               /* move buffers from the tail of the 'steal' queue to the tail of the
+                  'from' queue. Always copy all the buffers with the same dma_xfer_cnt
+                  value, this ensures that you do not end up with partial frame data
+                  if one frame is stored in multiple buffers. */
+               while (dma_xfer_cnt == buf->dma_xfer_cnt) {
+                       list_move_tail(steal->list.prev, &from->list);
+                       rc++;
+                       steal->buffers--;
+                       steal->length -= s->buf_size;
+                       steal->bytesused -= buf->bytesused - buf->readpos;
+                       buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
+                       from->buffers++;
+                       from->length += s->buf_size;
+                       bytes_available += s->buf_size;
+                       if (list_empty(&steal->list))
+                               break;
+                       buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
+               }
+       }
+       if (from_free) {
+               u32 old_length = to->length;
+
+               while (to->length - old_length < needed_bytes) {
+                       ivtv_queue_move_buf(s, from, to, 1);
+               }
+       }
+       else {
+               u32 old_bytesused = to->bytesused;
+
+               while (to->bytesused - old_bytesused < needed_bytes) {
+                       ivtv_queue_move_buf(s, from, to, to_free);
+               }
+       }
+       spin_unlock_irqrestore(&s->qlock, flags);
+       return rc;
+}
+
+void ivtv_flush_queues(struct ivtv_stream *s)
+{
+       ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
+       ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+       ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
+       ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
+}
+
+int ivtv_stream_alloc(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+       int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers;
+       int i;
+
+       if (s->buffers == 0)
+               return 0;
+
+       IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n",
+               s->dma != PCI_DMA_NONE ? "DMA " : "",
+               s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
+
+       s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
+       if (s->sg_pending == NULL) {
+               IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
+               return -ENOMEM;
+       }
+       s->sg_pending_size = 0;
+
+       s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
+       if (s->sg_processing == NULL) {
+               IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
+               kfree(s->sg_pending);
+               s->sg_pending = NULL;
+               return -ENOMEM;
+       }
+       s->sg_processing_size = 0;
+
+       s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element),
+                                       GFP_KERNEL|__GFP_NOWARN);
+       if (s->sg_dma == NULL) {
+               IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
+               kfree(s->sg_pending);
+               s->sg_pending = NULL;
+               kfree(s->sg_processing);
+               s->sg_processing = NULL;
+               return -ENOMEM;
+       }
+       if (ivtv_might_use_dma(s)) {
+               s->sg_handle = pci_map_single(itv->pdev, s->sg_dma,
+                               sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+               ivtv_stream_sync_for_cpu(s);
+       }
+
+       /* allocate stream buffers. Initially all buffers are in q_free. */
+       for (i = 0; i < s->buffers; i++) {
+               struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer),
+                                               GFP_KERNEL|__GFP_NOWARN);
+
+               if (buf == NULL)
+                       break;
+               buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN);
+               if (buf->buf == NULL) {
+                       kfree(buf);
+                       break;
+               }
+               INIT_LIST_HEAD(&buf->list);
+               if (ivtv_might_use_dma(s)) {
+                       buf->dma_handle = pci_map_single(s->itv->pdev,
+                               buf->buf, s->buf_size + 256, s->dma);
+                       ivtv_buf_sync_for_cpu(s, buf);
+               }
+               ivtv_enqueue(s, buf, &s->q_free);
+       }
+       if (i == s->buffers)
+               return 0;
+       IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name);
+       ivtv_stream_free(s);
+       return -ENOMEM;
+}
+
+void ivtv_stream_free(struct ivtv_stream *s)
+{
+       struct ivtv_buffer *buf;
+
+       /* move all buffers to q_free */
+       ivtv_flush_queues(s);
+
+       /* empty q_free */
+       while ((buf = ivtv_dequeue(s, &s->q_free))) {
+               if (ivtv_might_use_dma(s))
+                       pci_unmap_single(s->itv->pdev, buf->dma_handle,
+                               s->buf_size + 256, s->dma);
+               kfree(buf->buf);
+               kfree(buf);
+       }
+
+       /* Free SG Array/Lists */
+       if (s->sg_dma != NULL) {
+               if (s->sg_handle != IVTV_DMA_UNMAPPED) {
+                       pci_unmap_single(s->itv->pdev, s->sg_handle,
+                                sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+                       s->sg_handle = IVTV_DMA_UNMAPPED;
+               }
+               kfree(s->sg_pending);
+               kfree(s->sg_processing);
+               kfree(s->sg_dma);
+               s->sg_pending = NULL;
+               s->sg_processing = NULL;
+               s->sg_dma = NULL;
+               s->sg_pending_size = 0;
+               s->sg_processing_size = 0;
+       }
+}
diff --git a/drivers/media/pci/ivtv/ivtv-queue.h b/drivers/media/pci/ivtv/ivtv-queue.h
new file mode 100644 (file)
index 0000000..9123383
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+    buffer queues.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_QUEUE_H
+#define IVTV_QUEUE_H
+
+#define IVTV_DMA_UNMAPPED      ((u32) -1)
+#define SLICED_VBI_PIO 0
+
+/* ivtv_buffer utility functions */
+
+static inline int ivtv_might_use_pio(struct ivtv_stream *s)
+{
+       return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
+}
+
+static inline int ivtv_use_pio(struct ivtv_stream *s)
+{
+       struct ivtv *itv = s->itv;
+
+       return s->dma == PCI_DMA_NONE ||
+           (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+}
+
+static inline int ivtv_might_use_dma(struct ivtv_stream *s)
+{
+       return s->dma != PCI_DMA_NONE;
+}
+
+static inline int ivtv_use_dma(struct ivtv_stream *s)
+{
+       return !ivtv_use_pio(s);
+}
+
+static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
+{
+       if (ivtv_use_dma(s))
+               pci_dma_sync_single_for_cpu(s->itv->pdev, buf->dma_handle,
+                               s->buf_size + 256, s->dma);
+}
+
+static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
+{
+       if (ivtv_use_dma(s))
+               pci_dma_sync_single_for_device(s->itv->pdev, buf->dma_handle,
+                               s->buf_size + 256, s->dma);
+}
+
+int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes);
+void ivtv_buf_swap(struct ivtv_buffer *buf);
+
+/* ivtv_queue utility functions */
+void ivtv_queue_init(struct ivtv_queue *q);
+void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q);
+struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q);
+int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
+                   struct ivtv_queue *to, int needed_bytes);
+void ivtv_flush_queues(struct ivtv_stream *s);
+
+/* ivtv_stream utility functions */
+int ivtv_stream_alloc(struct ivtv_stream *s);
+void ivtv_stream_free(struct ivtv_stream *s);
+
+static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
+{
+       if (ivtv_use_dma(s))
+               pci_dma_sync_single_for_cpu(s->itv->pdev, s->sg_handle,
+                       sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+}
+
+static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
+{
+       if (ivtv_use_dma(s))
+               pci_dma_sync_single_for_device(s->itv->pdev, s->sg_handle,
+                       sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+}
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-routing.c b/drivers/media/pci/ivtv/ivtv-routing.c
new file mode 100644 (file)
index 0000000..8898c56
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+    Audio/video-routing-related ivtv functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-i2c.h"
+#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "ivtv-routing.h"
+
+#include <media/msp3400.h>
+#include <media/m52790.h>
+#include <media/upd64031a.h>
+#include <media/upd64083.h>
+
+/* Selects the audio input and output according to the current
+   settings. */
+void ivtv_audio_set_io(struct ivtv *itv)
+{
+       const struct ivtv_card_audio_input *in;
+       u32 input, output = 0;
+
+       /* Determine which input to use */
+       if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
+               in = &itv->card->radio_input;
+       else
+               in = &itv->card->audio_inputs[itv->audio_input];
+
+       /* handle muxer chips */
+       input = in->muxer_input;
+       if (itv->card->hw_muxer & IVTV_HW_M52790)
+               output = M52790_OUT_STEREO;
+       v4l2_subdev_call(itv->sd_muxer, audio, s_routing,
+                       input, output, 0);
+
+       input = in->audio_input;
+       output = 0;
+       if (itv->card->hw_audio & IVTV_HW_MSP34XX)
+               output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+       ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing,
+                       input, output, 0);
+}
+
+/* Selects the video input and output according to the current
+   settings. */
+void ivtv_video_set_io(struct ivtv *itv)
+{
+       int inp = itv->active_input;
+       u32 input;
+       u32 type;
+
+       v4l2_subdev_call(itv->sd_video, video, s_routing,
+               itv->card->video_inputs[inp].video_input, 0, 0);
+
+       type = itv->card->video_inputs[inp].video_type;
+
+       if (type == IVTV_CARD_INPUT_VID_TUNER) {
+               input = 0;  /* Tuner */
+       } else if (type < IVTV_CARD_INPUT_COMPOSITE1) {
+               input = 2;  /* S-Video */
+       } else {
+               input = 1;  /* Composite */
+       }
+
+       if (itv->card->hw_video & IVTV_HW_GPIO)
+               ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing,
+                               input, 0, 0);
+
+       if (itv->card->hw_video & IVTV_HW_UPD64031A) {
+               if (type == IVTV_CARD_INPUT_VID_TUNER ||
+                   type >= IVTV_CARD_INPUT_COMPOSITE1) {
+                       /* Composite: GR on, connect to 3DYCS */
+                       input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE;
+               } else {
+                       /* S-Video: GR bypassed, turn it off */
+                       input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE;
+               }
+               input |= itv->card->gr_config;
+
+               ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing,
+                               input, 0, 0);
+       }
+
+       if (itv->card->hw_video & IVTV_HW_UPD6408X) {
+               input = UPD64083_YCS_MODE;
+               if (type > IVTV_CARD_INPUT_VID_TUNER &&
+                   type < IVTV_CARD_INPUT_COMPOSITE1) {
+                       /* S-Video uses YCNR mode and internal Y-ADC, the
+                          upd64031a is not used. */
+                       input |= UPD64083_YCNR_MODE;
+               }
+               else if (itv->card->hw_video & IVTV_HW_UPD64031A) {
+                       /* Use upd64031a output for tuner and
+                          composite(CX23416GYC only) inputs */
+                       if (type == IVTV_CARD_INPUT_VID_TUNER ||
+                           itv->card->type == IVTV_CARD_CX23416GYC) {
+                               input |= UPD64083_EXT_Y_ADC;
+                       }
+               }
+               ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing,
+                               input, 0, 0);
+       }
+}
diff --git a/drivers/media/pci/ivtv/ivtv-routing.h b/drivers/media/pci/ivtv/ivtv-routing.h
new file mode 100644 (file)
index 0000000..c72a973
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+    Audio/video-routing-related ivtv functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_ROUTING_H
+#define IVTV_ROUTING_H
+
+void ivtv_audio_set_io(struct ivtv *itv);
+void ivtv_video_set_io(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c
new file mode 100644 (file)
index 0000000..f08ec17
--- /dev/null
@@ -0,0 +1,1014 @@
+/*
+    init/start/stop/exit stream functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    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
+ */
+
+/* License: GPL
+ * Author: Kevin Thayer <nufan_wfk at yahoo dot com>
+ *
+ * This file will hold API related functions, both internal (firmware api)
+ * and external (v4l2, etc)
+ *
+ * -----
+ * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
+ *                      and Takeru KOMORIYA<komoriya@paken.org>
+ *
+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
+ *                using information provided by Jiun-Kuei Jung @ AVerMedia.
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-fileops.h"
+#include "ivtv-queue.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-irq.h"
+#include "ivtv-yuv.h"
+#include "ivtv-cards.h"
+#include "ivtv-streams.h"
+#include "ivtv-firmware.h"
+#include <media/v4l2-event.h>
+
+static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
+       .owner = THIS_MODULE,
+       .read = ivtv_v4l2_read,
+       .write = ivtv_v4l2_write,
+       .open = ivtv_v4l2_open,
+       .unlocked_ioctl = video_ioctl2,
+       .release = ivtv_v4l2_close,
+       .poll = ivtv_v4l2_enc_poll,
+};
+
+static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
+       .owner = THIS_MODULE,
+       .read = ivtv_v4l2_read,
+       .write = ivtv_v4l2_write,
+       .open = ivtv_v4l2_open,
+       .unlocked_ioctl = video_ioctl2,
+       .release = ivtv_v4l2_close,
+       .poll = ivtv_v4l2_dec_poll,
+};
+
+#define IVTV_V4L2_DEC_MPG_OFFSET  16   /* offset from 0 to register decoder mpg v4l2 minors on */
+#define IVTV_V4L2_ENC_PCM_OFFSET  24   /* offset from 0 to register pcm v4l2 minors on */
+#define IVTV_V4L2_ENC_YUV_OFFSET  32   /* offset from 0 to register yuv v4l2 minors on */
+#define IVTV_V4L2_DEC_YUV_OFFSET  48   /* offset from 0 to register decoder yuv v4l2 minors on */
+#define IVTV_V4L2_DEC_VBI_OFFSET   8   /* offset from 0 to register decoder vbi input v4l2 minors on */
+#define IVTV_V4L2_DEC_VOUT_OFFSET 16   /* offset from 0 to register vbi output v4l2 minors on */
+
+static struct {
+       const char *name;
+       int vfl_type;
+       int num_offset;
+       int dma, pio;
+       enum v4l2_buf_type buf_type;
+       u32 v4l2_caps;
+       const struct v4l2_file_operations *fops;
+} ivtv_stream_info[] = {
+       {       /* IVTV_ENC_STREAM_TYPE_MPG */
+               "encoder MPG",
+               VFL_TYPE_GRABBER, 0,
+               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
+                       V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_enc_fops
+       },
+       {       /* IVTV_ENC_STREAM_TYPE_YUV */
+               "encoder YUV",
+               VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET,
+               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
+                       V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_enc_fops
+       },
+       {       /* IVTV_ENC_STREAM_TYPE_VBI */
+               "encoder VBI",
+               VFL_TYPE_VBI, 0,
+               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE,
+               V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER |
+                       V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_enc_fops
+       },
+       {       /* IVTV_ENC_STREAM_TYPE_PCM */
+               "encoder PCM",
+               VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET,
+               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE,
+               V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_enc_fops
+       },
+       {       /* IVTV_ENC_STREAM_TYPE_RAD */
+               "encoder radio",
+               VFL_TYPE_RADIO, 0,
+               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE,
+               V4L2_CAP_RADIO | V4L2_CAP_TUNER,
+               &ivtv_v4l2_enc_fops
+       },
+       {       /* IVTV_DEC_STREAM_TYPE_MPG */
+               "decoder MPG",
+               VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
+               PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_dec_fops
+       },
+       {       /* IVTV_DEC_STREAM_TYPE_VBI */
+               "decoder VBI",
+               VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET,
+               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE,
+               V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_enc_fops
+       },
+       {       /* IVTV_DEC_STREAM_TYPE_VOUT */
+               "decoder VOUT",
+               VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET,
+               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT,
+               V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_dec_fops
+       },
+       {       /* IVTV_DEC_STREAM_TYPE_YUV */
+               "decoder YUV",
+               VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET,
+               PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+               &ivtv_v4l2_dec_fops
+       }
+};
+
+static void ivtv_stream_init(struct ivtv *itv, int type)
+{
+       struct ivtv_stream *s = &itv->streams[type];
+       struct video_device *vdev = s->vdev;
+
+       /* we need to keep vdev, so restore it afterwards */
+       memset(s, 0, sizeof(*s));
+       s->vdev = vdev;
+
+       /* initialize ivtv_stream fields */
+       s->itv = itv;
+       s->type = type;
+       s->name = ivtv_stream_info[type].name;
+       s->caps = ivtv_stream_info[type].v4l2_caps;
+
+       if (ivtv_stream_info[type].pio)
+               s->dma = PCI_DMA_NONE;
+       else
+               s->dma = ivtv_stream_info[type].dma;
+       s->buf_size = itv->stream_buf_size[type];
+       if (s->buf_size)
+               s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
+       spin_lock_init(&s->qlock);
+       init_waitqueue_head(&s->waitq);
+       s->sg_handle = IVTV_DMA_UNMAPPED;
+       ivtv_queue_init(&s->q_free);
+       ivtv_queue_init(&s->q_full);
+       ivtv_queue_init(&s->q_dma);
+       ivtv_queue_init(&s->q_predma);
+       ivtv_queue_init(&s->q_io);
+}
+
+static int ivtv_prep_dev(struct ivtv *itv, int type)
+{
+       struct ivtv_stream *s = &itv->streams[type];
+       int num_offset = ivtv_stream_info[type].num_offset;
+       int num = itv->instance + ivtv_first_minor + num_offset;
+
+       /* These four fields are always initialized. If vdev == NULL, then
+          this stream is not in use. In that case no other fields but these
+          four can be used. */
+       s->vdev = NULL;
+       s->itv = itv;
+       s->type = type;
+       s->name = ivtv_stream_info[type].name;
+
+       /* Check whether the radio is supported */
+       if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO))
+               return 0;
+       if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return 0;
+
+       /* User explicitly selected 0 buffers for these streams, so don't
+          create them. */
+       if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
+           itv->options.kilobytes[type] == 0) {
+               IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
+               return 0;
+       }
+
+       ivtv_stream_init(itv, type);
+
+       /* allocate and initialize the v4l2 video device structure */
+       s->vdev = video_device_alloc();
+       if (s->vdev == NULL) {
+               IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name);
+               return -ENOMEM;
+       }
+
+       snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s",
+                       itv->v4l2_dev.name, s->name);
+
+       s->vdev->num = num;
+       s->vdev->v4l2_dev = &itv->v4l2_dev;
+       s->vdev->fops = ivtv_stream_info[type].fops;
+       s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
+       s->vdev->release = video_device_release;
+       s->vdev->tvnorms = V4L2_STD_ALL;
+       s->vdev->lock = &itv->serialize_lock;
+       set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
+       ivtv_set_funcs(s->vdev);
+       return 0;
+}
+
+/* Initialize v4l2 variables and prepare v4l2 devices */
+int ivtv_streams_setup(struct ivtv *itv)
+{
+       int type;
+
+       /* Setup V4L2 Devices */
+       for (type = 0; type < IVTV_MAX_STREAMS; type++) {
+               /* Prepare device */
+               if (ivtv_prep_dev(itv, type))
+                       break;
+
+               if (itv->streams[type].vdev == NULL)
+                       continue;
+
+               /* Allocate Stream */
+               if (ivtv_stream_alloc(&itv->streams[type]))
+                       break;
+       }
+       if (type == IVTV_MAX_STREAMS)
+               return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       ivtv_streams_cleanup(itv, 0);
+       return -ENOMEM;
+}
+
+static int ivtv_reg_dev(struct ivtv *itv, int type)
+{
+       struct ivtv_stream *s = &itv->streams[type];
+       int vfl_type = ivtv_stream_info[type].vfl_type;
+       const char *name;
+       int num;
+
+       if (s->vdev == NULL)
+               return 0;
+
+       num = s->vdev->num;
+       /* card number + user defined offset + device offset */
+       if (type != IVTV_ENC_STREAM_TYPE_MPG) {
+               struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
+
+               if (s_mpg->vdev)
+                       num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset;
+       }
+       video_set_drvdata(s->vdev, s);
+
+       /* Register device. First try the desired minor, then any free one. */
+       if (video_register_device_no_warn(s->vdev, vfl_type, num)) {
+               IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
+                               s->name, num);
+               video_device_release(s->vdev);
+               s->vdev = NULL;
+               return -ENOMEM;
+       }
+       name = video_device_node_name(s->vdev);
+
+       switch (vfl_type) {
+       case VFL_TYPE_GRABBER:
+               IVTV_INFO("Registered device %s for %s (%d kB)\n",
+                       name, s->name, itv->options.kilobytes[type]);
+               break;
+       case VFL_TYPE_RADIO:
+               IVTV_INFO("Registered device %s for %s\n",
+                       name, s->name);
+               break;
+       case VFL_TYPE_VBI:
+               if (itv->options.kilobytes[type])
+                       IVTV_INFO("Registered device %s for %s (%d kB)\n",
+                               name, s->name, itv->options.kilobytes[type]);
+               else
+                       IVTV_INFO("Registered device %s for %s\n",
+                               name, s->name);
+               break;
+       }
+       return 0;
+}
+
+/* Register v4l2 devices */
+int ivtv_streams_register(struct ivtv *itv)
+{
+       int type;
+       int err = 0;
+
+       /* Register V4L2 devices */
+       for (type = 0; type < IVTV_MAX_STREAMS; type++)
+               err |= ivtv_reg_dev(itv, type);
+
+       if (err == 0)
+               return 0;
+
+       /* One or more streams could not be initialized. Clean 'em all up. */
+       ivtv_streams_cleanup(itv, 1);
+       return -ENOMEM;
+}
+
+/* Unregister v4l2 devices */
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
+{
+       int type;
+
+       /* Teardown all streams */
+       for (type = 0; type < IVTV_MAX_STREAMS; type++) {
+               struct video_device *vdev = itv->streams[type].vdev;
+
+               itv->streams[type].vdev = NULL;
+               if (vdev == NULL)
+                       continue;
+
+               ivtv_stream_free(&itv->streams[type]);
+               /* Unregister or release device */
+               if (unregister)
+                       video_unregister_device(vdev);
+               else
+                       video_device_release(vdev);
+       }
+}
+
+static void ivtv_vbi_setup(struct ivtv *itv)
+{
+       int raw = ivtv_raw_vbi(itv);
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       int lines;
+       int i;
+
+       /* Reset VBI */
+       ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
+
+       /* setup VBI registers */
+       if (raw)
+               v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi);
+       else
+               v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced);
+
+       /* determine number of lines and total number of VBI bytes.
+          A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
+          The '- 1' byte is probably an unused U or V byte. Or something...
+          A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
+          header, 42 data bytes + checksum (to be confirmed) */
+       if (raw) {
+               lines = itv->vbi.count * 2;
+       } else {
+               lines = itv->is_60hz ? 24 : 38;
+               if (itv->is_60hz && (itv->hw_flags & IVTV_HW_CX25840))
+                       lines += 2;
+       }
+
+       itv->vbi.enc_size = lines * (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
+
+       /* Note: sliced vs raw flag doesn't seem to have any effect
+          TODO: check mode (0x02) value with older ivtv versions. */
+       data[0] = raw | 0x02 | (0xbd << 8);
+
+       /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
+       data[1] = 1;
+       /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
+       data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
+       /* The start/stop codes determine which VBI lines end up in the raw VBI data area.
+          The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
+          is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
+          code. These values for raw VBI are obtained from a driver disassembly. The sliced
+          start/stop codes was deduced from this, but they do not appear in the driver.
+          Other code pairs that I found are: 0x250E6249/0x13545454 and 0x25256262/0x38137F54.
+          However, I have no idea what these values are for. */
+       if (itv->hw_flags & IVTV_HW_CX25840) {
+               /* Setup VBI for the cx25840 digitizer */
+               if (raw) {
+                       data[3] = 0x20602060;
+                       data[4] = 0x30703070;
+               } else {
+                       data[3] = 0xB0F0B0F0;
+                       data[4] = 0xA0E0A0E0;
+               }
+               /* Lines per frame */
+               data[5] = lines;
+               /* bytes per line */
+               data[6] = (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
+       } else {
+               /* Setup VBI for the saa7115 digitizer */
+               if (raw) {
+                       data[3] = 0x25256262;
+                       data[4] = 0x387F7F7F;
+               } else {
+                       data[3] = 0xABABECEC;
+                       data[4] = 0xB6F1F1F1;
+               }
+               /* Lines per frame */
+               data[5] = lines;
+               /* bytes per line */
+               data[6] = itv->vbi.enc_size / lines;
+       }
+
+       IVTV_DEBUG_INFO(
+               "Setup VBI API header 0x%08x pkts %d buffs %d ln %d sz %d\n",
+                       data[0], data[1], data[2], data[5], data[6]);
+
+       ivtv_api(itv, CX2341X_ENC_SET_VBI_CONFIG, 7, data);
+
+       /* returns the VBI encoder memory area. */
+       itv->vbi.enc_start = data[2];
+       itv->vbi.fpi = data[0];
+       if (!itv->vbi.fpi)
+               itv->vbi.fpi = 1;
+
+       IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n",
+               itv->vbi.enc_start, data[1], itv->vbi.fpi);
+
+       /* select VBI lines.
+          Note that the sliced argument seems to have no effect. */
+       for (i = 2; i <= 24; i++) {
+               int valid;
+
+               if (itv->is_60hz) {
+                       valid = i >= 10 && i < 22;
+               } else {
+                       valid = i >= 6 && i < 24;
+               }
+               ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, i - 1,
+                               valid, 0 , 0, 0);
+               ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, (i - 1) | 0x80000000,
+                               valid, 0, 0, 0);
+       }
+
+       /* Remaining VBI questions:
+          - Is it possible to select particular VBI lines only for inclusion in the MPEG
+          stream? Currently you can only get the first X lines.
+          - Is mixed raw and sliced VBI possible?
+          - What's the meaning of the raw/sliced flag?
+          - What's the meaning of params 2, 3 & 4 of the Select VBI command? */
+}
+
+int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv *itv = s->itv;
+       int captype = 0, subtype = 0;
+       int enable_passthrough = 0;
+
+       if (s->vdev == NULL)
+               return -EINVAL;
+
+       IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
+       switch (s->type) {
+       case IVTV_ENC_STREAM_TYPE_MPG:
+               captype = 0;
+               subtype = 3;
+
+               /* Stop Passthrough */
+               if (itv->output_mode == OUT_PASSTHROUGH) {
+                       ivtv_passthrough_mode(itv, 0);
+                       enable_passthrough = 1;
+               }
+               itv->mpg_data_received = itv->vbi_data_inserted = 0;
+               itv->dualwatch_jiffies = jiffies;
+               itv->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
+               itv->search_pack_header = 0;
+               break;
+
+       case IVTV_ENC_STREAM_TYPE_YUV:
+               if (itv->output_mode == OUT_PASSTHROUGH) {
+                       captype = 2;
+                       subtype = 11;   /* video+audio+decoder */
+                       break;
+               }
+               captype = 1;
+               subtype = 1;
+               break;
+       case IVTV_ENC_STREAM_TYPE_PCM:
+               captype = 1;
+               subtype = 2;
+               break;
+       case IVTV_ENC_STREAM_TYPE_VBI:
+               captype = 1;
+               subtype = 4;
+
+               itv->vbi.frame = 0;
+               itv->vbi.inserted_frame = 0;
+               memset(itv->vbi.sliced_mpeg_size,
+                       0, sizeof(itv->vbi.sliced_mpeg_size));
+               break;
+       default:
+               return -EINVAL;
+       }
+       s->subtype = subtype;
+       s->buffers_stolen = 0;
+
+       /* Clear Streamoff flags in case left from last capture */
+       clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+
+       if (atomic_read(&itv->capturing) == 0) {
+               int digitizer;
+
+               /* Always use frame based mode. Experiments have demonstrated that byte
+                  stream based mode results in dropped frames and corruption. Not often,
+                  but occasionally. Many thanks go to Leonard Orb who spent a lot of
+                  effort and time trying to trace the cause of the drop outs. */
+               /* 1 frame per DMA */
+               /*ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 128, 0); */
+               ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 1, 1);
+
+               /* Stuff from Windows, we don't know what it is */
+               ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, 0);
+               /* According to the docs, this should be correct. However, this is
+                  untested. I don't dare enable this without having tested it.
+                  Only very few old cards actually have this hardware combination.
+               ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1,
+                       ((itv->hw_flags & IVTV_HW_SAA7114) && itv->is_60hz) ? 10001 : 0);
+               */
+               ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 3, !itv->has_cx23415);
+               ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 8, 0);
+               ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 4, 1);
+               ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
+
+               /* assign placeholder */
+               ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12,
+                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+               if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
+                   digitizer = 0xF1;
+               else if (itv->card->hw_all & IVTV_HW_SAA7114)
+                   digitizer = 0xEF;
+               else /* cx25840 */
+                   digitizer = 0x140;
+
+               ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer);
+
+               /* Setup VBI */
+               if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) {
+                       ivtv_vbi_setup(itv);
+               }
+
+               /* assign program index info. Mask 7: select I/P/B, Num_req: 400 max */
+               ivtv_vapi_result(itv, data, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, 7, 400);
+               itv->pgm_info_offset = data[0];
+               itv->pgm_info_num = data[1];
+               itv->pgm_info_write_idx = 0;
+               itv->pgm_info_read_idx = 0;
+
+               IVTV_DEBUG_INFO("PGM Index at 0x%08x with %d elements\n",
+                               itv->pgm_info_offset, itv->pgm_info_num);
+
+               /* Setup API for Stream */
+               cx2341x_handler_setup(&itv->cxhdl);
+
+               /* mute if capturing radio */
+               if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
+                       ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+                               1 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+       }
+
+       /* Vsync Setup */
+       if (itv->has_cx23415 && !test_and_set_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
+               /* event notification (on) */
+               ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_ENC_VIM_RST, -1);
+               ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
+       }
+
+       if (atomic_read(&itv->capturing) == 0) {
+               /* Clear all Pending Interrupts */
+               ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
+
+               clear_bit(IVTV_F_I_EOS, &itv->i_flags);
+
+               cx2341x_handler_set_busy(&itv->cxhdl, 1);
+
+               /* Initialize Digitizer for Capture */
+               /* Avoid tinny audio problem - ensure audio clocks are going */
+               v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
+               /* Avoid unpredictable PCI bus hang - disable video clocks */
+               v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
+               ivtv_msleep_timeout(300, 0);
+               ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
+               v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
+       }
+
+       /* begin_capture */
+       if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype))
+       {
+               IVTV_DEBUG_WARN( "Error starting capture!\n");
+               return -EINVAL;
+       }
+
+       /* Start Passthrough */
+       if (enable_passthrough) {
+               ivtv_passthrough_mode(itv, 1);
+       }
+
+       if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
+               ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
+       else
+               ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
+
+       /* you're live! sit back and await interrupts :) */
+       atomic_inc(&itv->capturing);
+       return 0;
+}
+
+static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       struct ivtv *itv = s->itv;
+       int datatype;
+       u16 width;
+       u16 height;
+
+       if (s->vdev == NULL)
+               return -EINVAL;
+
+       IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
+
+       width = itv->cxhdl.width;
+       height = itv->cxhdl.height;
+
+       /* set audio mode to left/stereo  for dual/stereo mode. */
+       ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
+
+       /* set number of internal decoder buffers */
+       ivtv_vapi(itv, CX2341X_DEC_SET_DISPLAY_BUFFERS, 1, 0);
+
+       /* prebuffering */
+       ivtv_vapi(itv, CX2341X_DEC_SET_PREBUFFERING, 1, 1);
+
+       /* extract from user packets */
+       ivtv_vapi_result(itv, data, CX2341X_DEC_EXTRACT_VBI, 1, 1);
+       itv->vbi.dec_start = data[0];
+
+       IVTV_DEBUG_INFO("Decoder VBI RE-Insert start 0x%08x size 0x%08x\n",
+               itv->vbi.dec_start, data[1]);
+
+       /* set decoder source settings */
+       /* Data type: 0 = mpeg from host,
+          1 = yuv from encoder,
+          2 = yuv_from_host */
+       switch (s->type) {
+       case IVTV_DEC_STREAM_TYPE_YUV:
+               if (itv->output_mode == OUT_PASSTHROUGH) {
+                       datatype = 1;
+               } else {
+                       /* Fake size to avoid switching video standard */
+                       datatype = 2;
+                       width = 720;
+                       height = itv->is_out_50hz ? 576 : 480;
+               }
+               IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
+               break;
+       case IVTV_DEC_STREAM_TYPE_MPG:
+       default:
+               datatype = 0;
+               break;
+       }
+       if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
+                       width, height, itv->cxhdl.audio_properties)) {
+               IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
+       }
+
+       /* Decoder sometimes dies here, so wait a moment */
+       ivtv_msleep_timeout(10, 0);
+
+       /* Known failure point for firmware, so check */
+       return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream");
+}
+
+int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
+{
+       struct ivtv *itv = s->itv;
+       int rc;
+
+       if (s->vdev == NULL)
+               return -EINVAL;
+
+       if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
+               return 0;       /* already started */
+
+       IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset);
+
+       rc = ivtv_setup_v4l2_decode_stream(s);
+       if (rc < 0) {
+               clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+               return rc;
+       }
+
+       /* set dma size to 65536 bytes */
+       ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);
+
+       /* Clear Streamoff */
+       clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+
+       /* Zero out decoder counters */
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[0]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[1]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[2]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[3]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]);
+       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[3]);
+
+       /* turn on notification of dual/stereo mode change */
+       ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
+
+       /* start playback */
+       ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
+
+       /* Let things settle before we actually start */
+       ivtv_msleep_timeout(10, 0);
+
+       /* Clear the following Interrupt mask bits for decoding */
+       ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
+       IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
+
+       /* you're live! sit back and await interrupts :) */
+       atomic_inc(&itv->decoding);
+       return 0;
+}
+
+void ivtv_stop_all_captures(struct ivtv *itv)
+{
+       int i;
+
+       for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
+               struct ivtv_stream *s = &itv->streams[i];
+
+               if (s->vdev == NULL)
+                       continue;
+               if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+                       ivtv_stop_v4l2_encode_stream(s, 0);
+               }
+       }
+}
+
+int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
+{
+       struct ivtv *itv = s->itv;
+       DECLARE_WAITQUEUE(wait, current);
+       int cap_type;
+       int stopmode;
+
+       if (s->vdev == NULL)
+               return -EINVAL;
+
+       /* This function assumes that you are allowed to stop the capture
+          and that we are actually capturing */
+
+       IVTV_DEBUG_INFO("Stop Capture\n");
+
+       if (s->type == IVTV_DEC_STREAM_TYPE_VOUT)
+               return 0;
+       if (atomic_read(&itv->capturing) == 0)
+               return 0;
+
+       switch (s->type) {
+       case IVTV_ENC_STREAM_TYPE_YUV:
+               cap_type = 1;
+               break;
+       case IVTV_ENC_STREAM_TYPE_PCM:
+               cap_type = 1;
+               break;
+       case IVTV_ENC_STREAM_TYPE_VBI:
+               cap_type = 1;
+               break;
+       case IVTV_ENC_STREAM_TYPE_MPG:
+       default:
+               cap_type = 0;
+               break;
+       }
+
+       /* Stop Capture Mode */
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
+               stopmode = 0;
+       } else {
+               stopmode = 1;
+       }
+
+       /* end_capture */
+       /* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
+       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);
+
+       if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
+               if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
+                       /* only run these if we're shutting down the last cap */
+                       unsigned long duration;
+                       unsigned long then = jiffies;
+
+                       add_wait_queue(&itv->eos_waitq, &wait);
+
+                       set_current_state(TASK_INTERRUPTIBLE);
+
+                       /* wait 2s for EOS interrupt */
+                       while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
+                               time_before(jiffies,
+                                           then + msecs_to_jiffies(2000))) {
+                               schedule_timeout(msecs_to_jiffies(10));
+                       }
+
+                       /* To convert jiffies to ms, we must multiply by 1000
+                        * and divide by HZ.  To avoid runtime division, we
+                        * convert this to multiplication by 1000/HZ.
+                        * Since integer division truncates, we get the best
+                        * accuracy if we do a rounding calculation of the constant.
+                        * Think of the case where HZ is 1024.
+                        */
+                       duration = ((1000 + HZ / 2) / HZ) * (jiffies - then);
+
+                       if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) {
+                               IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
+                               IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
+                       } else {
+                               IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
+                       }
+                       set_current_state(TASK_RUNNING);
+                       remove_wait_queue(&itv->eos_waitq, &wait);
+                       set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+               }
+
+               /* Handle any pending interrupts */
+               ivtv_msleep_timeout(100, 0);
+       }
+
+       atomic_dec(&itv->capturing);
+
+       /* Clear capture and no-read bits */
+       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+
+       if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
+               ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
+
+       if (atomic_read(&itv->capturing) > 0) {
+               return 0;
+       }
+
+       cx2341x_handler_set_busy(&itv->cxhdl, 0);
+
+       /* Set the following Interrupt mask bits for capture */
+       ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
+       del_timer(&itv->dma_timer);
+
+       /* event notification (off) */
+       if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
+               /* type: 0 = refresh */
+               /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
+               ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
+               ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
+       }
+
+       /* Raw-passthrough is implied on start. Make sure it's stopped so
+          the encoder will re-initialize when next started */
+       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7);
+
+       wake_up(&s->waitq);
+
+       return 0;
+}
+
+int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
+{
+       static const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS,
+       };
+       struct ivtv *itv = s->itv;
+
+       if (s->vdev == NULL)
+               return -EINVAL;
+
+       if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
+               return -EINVAL;
+
+       if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
+               return 0;
+
+       IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
+
+       /* Stop Decoder */
+       if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) {
+               u32 tmp = 0;
+
+               /* Wait until the decoder is no longer running */
+               if (pts) {
+                       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3,
+                               0, (u32)(pts & 0xffffffff), (u32)(pts >> 32));
+               }
+               while (1) {
+                       u32 data[CX2341X_MBOX_MAX_DATA];
+                       ivtv_vapi_result(itv, data, CX2341X_DEC_GET_XFER_INFO, 0);
+                       if (s->q_full.buffers + s->q_dma.buffers == 0) {
+                               if (tmp == data[3])
+                                       break;
+                               tmp = data[3];
+                       }
+                       if (ivtv_msleep_timeout(100, 1))
+                               break;
+               }
+       }
+       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0);
+
+       /* turn off notification of dual/stereo mode change */
+       ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
+
+       ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
+       del_timer(&itv->dma_timer);
+
+       clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+       ivtv_flush_queues(s);
+
+       /* decoder needs time to settle */
+       ivtv_msleep_timeout(40, 0);
+
+       /* decrement decoding */
+       atomic_dec(&itv->decoding);
+
+       set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
+       wake_up(&itv->event_waitq);
+       v4l2_event_queue(s->vdev, &ev);
+
+       /* wake up wait queues */
+       wake_up(&s->waitq);
+
+       return 0;
+}
+
+int ivtv_passthrough_mode(struct ivtv *itv, int enable)
+{
+       struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV];
+       struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
+
+       if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL)
+               return -EINVAL;
+
+       IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");
+
+       /* Prevent others from starting/stopping streams while we
+          initiate/terminate passthrough mode */
+       if (enable) {
+               if (itv->output_mode == OUT_PASSTHROUGH) {
+                       return 0;
+               }
+               if (ivtv_set_output_mode(itv, OUT_PASSTHROUGH) != OUT_PASSTHROUGH)
+                       return -EBUSY;
+
+               /* Fully initialize stream, and then unflag init */
+               set_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
+               set_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
+
+               /* Setup YUV Decoder */
+               ivtv_setup_v4l2_decode_stream(dec_stream);
+
+               /* Start Decoder */
+               ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1);
+               atomic_inc(&itv->decoding);
+
+               /* Setup capture if not already done */
+               if (atomic_read(&itv->capturing) == 0) {
+                       cx2341x_handler_setup(&itv->cxhdl);
+                       cx2341x_handler_set_busy(&itv->cxhdl, 1);
+               }
+
+               /* Start Passthrough Mode */
+               ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, 2, 11);
+               atomic_inc(&itv->capturing);
+               return 0;
+       }
+
+       if (itv->output_mode != OUT_PASSTHROUGH)
+               return 0;
+
+       /* Stop Passthrough Mode */
+       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 11);
+       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, 1, 0, 0);
+
+       atomic_dec(&itv->capturing);
+       atomic_dec(&itv->decoding);
+       clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
+       clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
+       itv->output_mode = OUT_NONE;
+       if (atomic_read(&itv->capturing) == 0)
+               cx2341x_handler_set_busy(&itv->cxhdl, 0);
+
+       return 0;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-streams.h b/drivers/media/pci/ivtv/ivtv-streams.h
new file mode 100644 (file)
index 0000000..a653a51
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+    init/start/stop/exit stream functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_STREAMS_H
+#define IVTV_STREAMS_H
+
+int ivtv_streams_setup(struct ivtv *itv);
+int ivtv_streams_register(struct ivtv *itv);
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
+
+/* Capture related */
+int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
+int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end);
+int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset);
+int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts);
+
+void ivtv_stop_all_captures(struct ivtv *itv);
+int ivtv_passthrough_mode(struct ivtv *itv, int enable);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c
new file mode 100644 (file)
index 0000000..7338cb2
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+    User DMA
+
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-udma.h"
+
+void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size)
+{
+       dma_page->uaddr = first & PAGE_MASK;
+       dma_page->offset = first & ~PAGE_MASK;
+       dma_page->tail = 1 + ((first+size-1) & ~PAGE_MASK);
+       dma_page->first = (first & PAGE_MASK) >> PAGE_SHIFT;
+       dma_page->last = ((first+size-1) & PAGE_MASK) >> PAGE_SHIFT;
+       dma_page->page_count = dma_page->last - dma_page->first + 1;
+       if (dma_page->page_count == 1) dma_page->tail -= dma_page->offset;
+}
+
+int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset)
+{
+       int i, offset;
+       unsigned long flags;
+
+       if (map_offset < 0)
+               return map_offset;
+
+       offset = dma_page->offset;
+
+       /* Fill SG Array with new values */
+       for (i = 0; i < dma_page->page_count; i++) {
+               unsigned int len = (i == dma_page->page_count - 1) ?
+                       dma_page->tail : PAGE_SIZE - offset;
+
+               if (PageHighMem(dma->map[map_offset])) {
+                       void *src;
+
+                       if (dma->bouncemap[map_offset] == NULL)
+                               dma->bouncemap[map_offset] = alloc_page(GFP_KERNEL);
+                       if (dma->bouncemap[map_offset] == NULL)
+                               return -1;
+                       local_irq_save(flags);
+                       src = kmap_atomic(dma->map[map_offset]) + offset;
+                       memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
+                       kunmap_atomic(src);
+                       local_irq_restore(flags);
+                       sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset);
+               }
+               else {
+                       sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset);
+               }
+               offset = 0;
+               map_offset++;
+       }
+       return map_offset;
+}
+
+void ivtv_udma_fill_sg_array (struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split) {
+       int i;
+       struct scatterlist *sg;
+
+       for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) {
+               dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg));
+               dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg));
+               dma->SGarray[i].dst = cpu_to_le32(buffer_offset);
+               buffer_offset += sg_dma_len(sg);
+
+               split -= sg_dma_len(sg);
+               if (split == 0)
+                       buffer_offset = buffer_offset_2;
+       }
+}
+
+/* User DMA Buffers */
+void ivtv_udma_alloc(struct ivtv *itv)
+{
+       if (itv->udma.SG_handle == 0) {
+               /* Map DMA Page Array Buffer */
+               itv->udma.SG_handle = pci_map_single(itv->pdev, itv->udma.SGarray,
+                          sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
+               ivtv_udma_sync_for_cpu(itv);
+       }
+}
+
+int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
+                      void __user *userbuf, int size_in_bytes)
+{
+       struct ivtv_dma_page_info user_dma;
+       struct ivtv_user_dma *dma = &itv->udma;
+       int i, err;
+
+       IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr);
+
+       /* Still in USE */
+       if (dma->SG_length || dma->page_count) {
+               IVTV_DEBUG_WARN("ivtv_udma_setup: SG_length %d page_count %d still full?\n",
+                          dma->SG_length, dma->page_count);
+               return -EBUSY;
+       }
+
+       ivtv_udma_get_page_info(&user_dma, (unsigned long)userbuf, size_in_bytes);
+
+       if (user_dma.page_count <= 0) {
+               IVTV_DEBUG_WARN("ivtv_udma_setup: Error %d page_count from %d bytes %d offset\n",
+                          user_dma.page_count, size_in_bytes, user_dma.offset);
+               return -EINVAL;
+       }
+
+       /* Get user pages for DMA Xfer */
+       down_read(&current->mm->mmap_sem);
+       err = get_user_pages(current, current->mm,
+                       user_dma.uaddr, user_dma.page_count, 0, 1, dma->map, NULL);
+       up_read(&current->mm->mmap_sem);
+
+       if (user_dma.page_count != err) {
+               IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
+                          err, user_dma.page_count);
+               if (err >= 0) {
+                       for (i = 0; i < err; i++)
+                               put_page(dma->map[i]);
+                       return -EINVAL;
+               }
+               return err;
+       }
+
+       dma->page_count = user_dma.page_count;
+
+       /* Fill SG List with new values */
+       if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {
+               for (i = 0; i < dma->page_count; i++) {
+                       put_page(dma->map[i]);
+               }
+               dma->page_count = 0;
+               return -ENOMEM;
+       }
+
+       /* Map SG List */
+       dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+
+       /* Fill SG Array with new values */
+       ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);
+
+       /* Tag SG Array with Interrupt Bit */
+       dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
+
+       ivtv_udma_sync_for_device(itv);
+       return dma->page_count;
+}
+
+void ivtv_udma_unmap(struct ivtv *itv)
+{
+       struct ivtv_user_dma *dma = &itv->udma;
+       int i;
+
+       IVTV_DEBUG_INFO("ivtv_unmap_user_dma\n");
+
+       /* Nothing to free */
+       if (dma->page_count == 0)
+               return;
+
+       /* Unmap Scatterlist */
+       if (dma->SG_length) {
+               pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+               dma->SG_length = 0;
+       }
+       /* sync DMA */
+       ivtv_udma_sync_for_cpu(itv);
+
+       /* Release User Pages */
+       for (i = 0; i < dma->page_count; i++) {
+               put_page(dma->map[i]);
+       }
+       dma->page_count = 0;
+}
+
+void ivtv_udma_free(struct ivtv *itv)
+{
+       int i;
+
+       /* Unmap SG Array */
+       if (itv->udma.SG_handle) {
+               pci_unmap_single(itv->pdev, itv->udma.SG_handle,
+                        sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
+       }
+
+       /* Unmap Scatterlist */
+       if (itv->udma.SG_length) {
+               pci_unmap_sg(itv->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE);
+       }
+
+       for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) {
+               if (itv->udma.bouncemap[i])
+                       __free_page(itv->udma.bouncemap[i]);
+       }
+}
+
+void ivtv_udma_start(struct ivtv *itv)
+{
+       IVTV_DEBUG_DMA("start UDMA\n");
+       write_reg(itv->udma.SG_handle, IVTV_REG_DECDMAADDR);
+       write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+       set_bit(IVTV_F_I_DMA, &itv->i_flags);
+       set_bit(IVTV_F_I_UDMA, &itv->i_flags);
+       clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags);
+}
+
+void ivtv_udma_prepare(struct ivtv *itv)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&itv->dma_reg_lock, flags);
+       if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
+               ivtv_udma_start(itv);
+       else
+               set_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags);
+       spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-udma.h b/drivers/media/pci/ivtv/ivtv-udma.h
new file mode 100644 (file)
index 0000000..ee3c9ef
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2006-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_UDMA_H
+#define IVTV_UDMA_H
+
+/* User DMA functions */
+void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size);
+int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset);
+void ivtv_udma_fill_sg_array(struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split);
+int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
+                      void __user *userbuf, int size_in_bytes);
+void ivtv_udma_unmap(struct ivtv *itv);
+void ivtv_udma_free(struct ivtv *itv);
+void ivtv_udma_alloc(struct ivtv *itv);
+void ivtv_udma_prepare(struct ivtv *itv);
+void ivtv_udma_start(struct ivtv *itv);
+
+static inline void ivtv_udma_sync_for_device(struct ivtv *itv)
+{
+       pci_dma_sync_single_for_device(itv->pdev, itv->udma.SG_handle,
+               sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
+}
+
+static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv)
+{
+       pci_dma_sync_single_for_cpu(itv->pdev, itv->udma.SG_handle,
+               sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
+}
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c
new file mode 100644 (file)
index 0000000..293db80
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+    Vertical Blank Interval support functions
+    Copyright (C) 2004-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-i2c.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-queue.h"
+#include "ivtv-cards.h"
+#include "ivtv-vbi.h"
+
+static void ivtv_set_vps(struct ivtv *itv, int enabled)
+{
+       struct v4l2_sliced_vbi_data data;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return;
+       data.id = V4L2_SLICED_VPS;
+       data.field = 0;
+       data.line = enabled ? 16 : 0;
+       data.data[2] = itv->vbi.vps_payload.data[0];
+       data.data[8] = itv->vbi.vps_payload.data[1];
+       data.data[9] = itv->vbi.vps_payload.data[2];
+       data.data[10] = itv->vbi.vps_payload.data[3];
+       data.data[11] = itv->vbi.vps_payload.data[4];
+       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+}
+
+static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
+{
+       struct v4l2_sliced_vbi_data data;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return;
+       data.id = V4L2_SLICED_CAPTION_525;
+       data.field = 0;
+       data.line = (mode & 1) ? 21 : 0;
+       data.data[0] = cc->odd[0];
+       data.data[1] = cc->odd[1];
+       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+       data.field = 1;
+       data.line = (mode & 2) ? 21 : 0;
+       data.data[0] = cc->even[0];
+       data.data[1] = cc->even[1];
+       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+}
+
+static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
+{
+       struct v4l2_sliced_vbi_data data;
+
+       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+               return;
+       /* When using a 50 Hz system, always turn on the
+          wide screen signal with 4x3 ratio as the default.
+          Turning this signal on and off can confuse certain
+          TVs. As far as I can tell there is no reason not to
+          transmit this signal. */
+       if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
+               enabled = 1;
+               mode = 0x08;  /* 4x3 full format */
+       }
+       data.id = V4L2_SLICED_WSS_625;
+       data.field = 0;
+       data.line = enabled ? 23 : 0;
+       data.data[0] = mode & 0xff;
+       data.data[1] = (mode >> 8) & 0xff;
+       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+}
+
+static int odd_parity(u8 c)
+{
+       c ^= (c >> 4);
+       c ^= (c >> 2);
+       c ^= (c >> 1);
+
+       return c & 1;
+}
+
+static void ivtv_write_vbi_line(struct ivtv *itv,
+                               const struct v4l2_sliced_vbi_data *d,
+                               struct vbi_cc *cc, int *found_cc)
+{
+       struct vbi_info *vi = &itv->vbi;
+
+       if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
+               if (d->field) {
+                       cc->even[0] = d->data[0];
+                       cc->even[1] = d->data[1];
+               } else {
+                       cc->odd[0] = d->data[0];
+                       cc->odd[1] = d->data[1];
+               }
+               *found_cc = 1;
+       } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
+               struct vbi_vps vps;
+
+               vps.data[0] = d->data[2];
+               vps.data[1] = d->data[8];
+               vps.data[2] = d->data[9];
+               vps.data[3] = d->data[10];
+               vps.data[4] = d->data[11];
+               if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
+                       vi->vps_payload = vps;
+                       set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
+               }
+       } else if (d->id == V4L2_SLICED_WSS_625 &&
+                  d->line == 23 && d->field == 0) {
+               int wss = d->data[0] | d->data[1] << 8;
+
+               if (vi->wss_payload != wss) {
+                       vi->wss_payload = wss;
+                       set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
+               }
+       }
+}
+
+static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
+{
+       struct vbi_info *vi = &itv->vbi;
+
+       if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
+               memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
+                      sizeof(struct vbi_cc));
+               vi->cc_payload_idx++;
+               set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+       }
+}
+
+static void ivtv_write_vbi(struct ivtv *itv,
+                          const struct v4l2_sliced_vbi_data *sliced,
+                          size_t cnt)
+{
+       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+       int found_cc = 0;
+       size_t i;
+
+       for (i = 0; i < cnt; i++)
+               ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
+
+       if (found_cc)
+               ivtv_write_vbi_cc_lines(itv, &cc);
+}
+
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+                        const struct v4l2_sliced_vbi_data __user *sliced,
+                        size_t cnt)
+{
+       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+       int found_cc = 0;
+       size_t i;
+       struct v4l2_sliced_vbi_data d;
+       ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
+
+       for (i = 0; i < cnt; i++) {
+               if (copy_from_user(&d, sliced + i,
+                                  sizeof(struct v4l2_sliced_vbi_data))) {
+                       ret = -EFAULT;
+                       break;
+               }
+               ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
+       }
+
+       if (found_cc)
+               ivtv_write_vbi_cc_lines(itv, &cc);
+
+       return ret;
+}
+
+static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
+{
+       int line = 0;
+       int i;
+       u32 linemask[2] = { 0, 0 };
+       unsigned short size;
+       static const u8 mpeg_hdr_data[] = {
+               0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
+               0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
+               0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
+               0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
+       };
+       const int sd = sizeof(mpeg_hdr_data);   /* start of vbi data */
+       int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
+       u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
+
+       for (i = 0; i < lines; i++) {
+               int f, l;
+
+               if (itv->vbi.sliced_data[i].id == 0)
+                       continue;
+
+               l = itv->vbi.sliced_data[i].line - 6;
+               f = itv->vbi.sliced_data[i].field;
+               if (f)
+                       l += 18;
+               if (l < 32)
+                       linemask[0] |= (1 << l);
+               else
+                       linemask[1] |= (1 << (l - 32));
+               dst[sd + 12 + line * 43] =
+                       ivtv_service2vbi(itv->vbi.sliced_data[i].id);
+               memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
+               line++;
+       }
+       memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
+       if (line == 36) {
+               /* All lines are used, so there is no space for the linemask
+                  (the max size of the VBI data is 36 * 43 + 4 bytes).
+                  So in this case we use the magic number 'ITV0'. */
+               memcpy(dst + sd, "ITV0", 4);
+               memcpy(dst + sd + 4, dst + sd + 12, line * 43);
+               size = 4 + ((43 * line + 3) & ~3);
+       } else {
+               memcpy(dst + sd, "itv0", 4);
+               cpu_to_le32s(&linemask[0]);
+               cpu_to_le32s(&linemask[1]);
+               memcpy(dst + sd + 4, &linemask[0], 8);
+               size = 12 + ((43 * line + 3) & ~3);
+       }
+       dst[4+16] = (size + 10) >> 8;
+       dst[5+16] = (size + 10) & 0xff;
+       dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
+       dst[10+16] = (pts_stamp >> 22) & 0xff;
+       dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
+       dst[12+16] = (pts_stamp >> 7) & 0xff;
+       dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
+       itv->vbi.sliced_mpeg_size[idx] = sd + size;
+}
+
+static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
+{
+       u32 linemask[2];
+       int i, l, id2;
+       int line = 0;
+
+       if (!memcmp(p, "itv0", 4)) {
+               memcpy(linemask, p + 4, 8);
+               p += 12;
+       } else if (!memcmp(p, "ITV0", 4)) {
+               linemask[0] = 0xffffffff;
+               linemask[1] = 0xf;
+               p += 4;
+       } else {
+               /* unknown VBI data, convert to empty VBI frame */
+               linemask[0] = linemask[1] = 0;
+       }
+       for (i = 0; i < 36; i++) {
+               int err = 0;
+
+               if (i < 32 && !(linemask[0] & (1 << i)))
+                       continue;
+               if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
+                       continue;
+               id2 = *p & 0xf;
+               switch (id2) {
+               case IVTV_SLICED_TYPE_TELETEXT_B:
+                       id2 = V4L2_SLICED_TELETEXT_B;
+                       break;
+               case IVTV_SLICED_TYPE_CAPTION_525:
+                       id2 = V4L2_SLICED_CAPTION_525;
+                       err = !odd_parity(p[1]) || !odd_parity(p[2]);
+                       break;
+               case IVTV_SLICED_TYPE_VPS:
+                       id2 = V4L2_SLICED_VPS;
+                       break;
+               case IVTV_SLICED_TYPE_WSS_625:
+                       id2 = V4L2_SLICED_WSS_625;
+                       break;
+               default:
+                       id2 = 0;
+                       break;
+               }
+               if (err == 0) {
+                       l = (i < 18) ? i + 6 : i - 18 + 6;
+                       itv->vbi.sliced_dec_data[line].line = l;
+                       itv->vbi.sliced_dec_data[line].field = i >= 18;
+                       itv->vbi.sliced_dec_data[line].id = id2;
+                       memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
+                       line++;
+               }
+               p += 43;
+       }
+       while (line < 36) {
+               itv->vbi.sliced_dec_data[line].id = 0;
+               itv->vbi.sliced_dec_data[line].line = 0;
+               itv->vbi.sliced_dec_data[line].field = 0;
+               line++;
+       }
+       return line * sizeof(itv->vbi.sliced_dec_data[0]);
+}
+
+/* Compress raw VBI format, removes leading SAV codes and surplus space after the
+   field.
+   Returns new compressed size. */
+static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
+{
+       u32 line_size = itv->vbi.raw_decoder_line_size;
+       u32 lines = itv->vbi.count;
+       u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
+       u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
+       u8 *q = buf;
+       u8 *p;
+       int i;
+
+       for (i = 0; i < lines; i++) {
+               p = buf + i * line_size;
+
+               /* Look for SAV code */
+               if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
+                       break;
+               }
+               memcpy(q, p + 4, line_size - 4);
+               q += line_size - 4;
+       }
+       return lines * (line_size - 4);
+}
+
+
+/* Compressed VBI format, all found sliced blocks put next to one another
+   Returns new compressed size */
+static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
+{
+       u32 line_size = itv->vbi.sliced_decoder_line_size;
+       struct v4l2_decode_vbi_line vbi;
+       int i;
+       unsigned lines = 0;
+
+       /* find the first valid line */
+       for (i = 0; i < size; i++, buf++) {
+               if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
+                       break;
+       }
+
+       size -= i;
+       if (size < line_size) {
+               return line;
+       }
+       for (i = 0; i < size / line_size; i++) {
+               u8 *p = buf + i * line_size;
+
+               /* Look for SAV code  */
+               if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
+                       continue;
+               }
+               vbi.p = p + 4;
+               v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
+               if (vbi.type && !(lines & (1 << vbi.line))) {
+                       lines |= 1 << vbi.line;
+                       itv->vbi.sliced_data[line].id = vbi.type;
+                       itv->vbi.sliced_data[line].field = vbi.is_second_field;
+                       itv->vbi.sliced_data[line].line = vbi.line;
+                       memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
+                       line++;
+               }
+       }
+       return line;
+}
+
+void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
+                          u64 pts_stamp, int streamtype)
+{
+       u8 *p = (u8 *) buf->buf;
+       u32 size = buf->bytesused;
+       int y;
+
+       /* Raw VBI data */
+       if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
+               u8 type;
+
+               ivtv_buf_swap(buf);
+
+               type = p[3];
+
+               size = buf->bytesused = compress_raw_buf(itv, p, size);
+
+               /* second field of the frame? */
+               if (type == itv->vbi.raw_decoder_sav_even_field) {
+                       /* Dirty hack needed for backwards
+                          compatibility of old VBI software. */
+                       p += size - 4;
+                       memcpy(p, &itv->vbi.frame, 4);
+                       itv->vbi.frame++;
+               }
+               return;
+       }
+
+       /* Sliced VBI data with data insertion */
+       if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
+               int lines;
+
+               ivtv_buf_swap(buf);
+
+               /* first field */
+               lines = compress_sliced_buf(itv, 0, p, size / 2,
+                       itv->vbi.sliced_decoder_sav_odd_field);
+               /* second field */
+               /* experimentation shows that the second half does not always begin
+                  at the exact address. So start a bit earlier (hence 32). */
+               lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
+                       itv->vbi.sliced_decoder_sav_even_field);
+               /* always return at least one empty line */
+               if (lines == 0) {
+                       itv->vbi.sliced_data[0].id = 0;
+                       itv->vbi.sliced_data[0].line = 0;
+                       itv->vbi.sliced_data[0].field = 0;
+                       lines = 1;
+               }
+               buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
+               memcpy(p, &itv->vbi.sliced_data[0], size);
+
+               if (itv->vbi.insert_mpeg) {
+                       copy_vbi_data(itv, lines, pts_stamp);
+               }
+               itv->vbi.frame++;
+               return;
+       }
+
+       /* Sliced VBI re-inserted from an MPEG stream */
+       if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
+               /* If the size is not 4-byte aligned, then the starting address
+                  for the swapping is also shifted. After swapping the data the
+                  real start address of the VBI data is exactly 4 bytes after the
+                  original start. It's a bit fiddly but it works like a charm.
+                  Non-4-byte alignment happens when an lseek is done on the input
+                  mpeg file to a non-4-byte aligned position. So on arrival here
+                  the VBI data is also non-4-byte aligned. */
+               int offset = size & 3;
+               int cnt;
+
+               if (offset) {
+                       p += 4 - offset;
+               }
+               /* Swap Buffer */
+               for (y = 0; y < size; y += 4) {
+                      swab32s((u32 *)(p + y));
+               }
+
+               cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
+               memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
+               buf->bytesused = cnt;
+
+               ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
+                              cnt / sizeof(itv->vbi.sliced_dec_data[0]));
+               return;
+       }
+}
+
+void ivtv_disable_cc(struct ivtv *itv)
+{
+       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+
+       clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+       ivtv_set_cc(itv, 0, &cc);
+       itv->vbi.cc_payload_idx = 0;
+}
+
+
+void ivtv_vbi_work_handler(struct ivtv *itv)
+{
+       struct vbi_info *vi = &itv->vbi;
+       struct v4l2_sliced_vbi_data data;
+       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+
+       /* Lock */
+       if (itv->output_mode == OUT_PASSTHROUGH) {
+               if (itv->is_50hz) {
+                       data.id = V4L2_SLICED_WSS_625;
+                       data.field = 0;
+
+                       if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
+                               ivtv_set_wss(itv, 1, data.data[0] & 0xf);
+                               vi->wss_missing_cnt = 0;
+                       } else if (vi->wss_missing_cnt == 4) {
+                               ivtv_set_wss(itv, 1, 0x8);  /* 4x3 full format */
+                       } else {
+                               vi->wss_missing_cnt++;
+                       }
+               }
+               else {
+                       int mode = 0;
+
+                       data.id = V4L2_SLICED_CAPTION_525;
+                       data.field = 0;
+                       if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
+                               mode |= 1;
+                               cc.odd[0] = data.data[0];
+                               cc.odd[1] = data.data[1];
+                       }
+                       data.field = 1;
+                       if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
+                               mode |= 2;
+                               cc.even[0] = data.data[0];
+                               cc.even[1] = data.data[1];
+                       }
+                       if (mode) {
+                               vi->cc_missing_cnt = 0;
+                               ivtv_set_cc(itv, mode, &cc);
+                       } else if (vi->cc_missing_cnt == 4) {
+                               ivtv_set_cc(itv, 0, &cc);
+                       } else {
+                               vi->cc_missing_cnt++;
+                       }
+               }
+               return;
+       }
+
+       if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
+               ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
+       }
+
+       if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
+               if (vi->cc_payload_idx == 0) {
+                       clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+                       ivtv_set_cc(itv, 3, &cc);
+               }
+               while (vi->cc_payload_idx) {
+                       cc = vi->cc_payload[0];
+
+                       memcpy(vi->cc_payload, vi->cc_payload + 1,
+                                       sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
+                       vi->cc_payload_idx--;
+                       if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
+                               continue;
+
+                       ivtv_set_cc(itv, 3, &cc);
+                       break;
+               }
+       }
+
+       if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
+               ivtv_set_vps(itv, 1);
+       }
+}
diff --git a/drivers/media/pci/ivtv/ivtv-vbi.h b/drivers/media/pci/ivtv/ivtv-vbi.h
new file mode 100644 (file)
index 0000000..166dd0b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+    Vertical Blank Interval support functions
+    Copyright (C) 2004-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_VBI_H
+#define IVTV_VBI_H
+
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+                        const struct v4l2_sliced_vbi_data __user *sliced,
+                        size_t count);
+void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
+                          u64 pts_stamp, int streamtype);
+int ivtv_used_line(struct ivtv *itv, int line, int field);
+void ivtv_disable_cc(struct ivtv *itv);
+void ivtv_set_vbi(unsigned long arg);
+void ivtv_vbi_work_handler(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-version.h b/drivers/media/pci/ivtv/ivtv-version.h
new file mode 100644 (file)
index 0000000..a20f346
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+    ivtv driver version information
+    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_VERSION_H
+#define IVTV_VERSION_H
+
+#define IVTV_DRIVER_NAME "ivtv"
+#define IVTV_VERSION "1.4.3"
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c
new file mode 100644 (file)
index 0000000..2ad65eb
--- /dev/null
@@ -0,0 +1,1296 @@
+/*
+    yuv support
+
+    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    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 "ivtv-driver.h"
+#include "ivtv-udma.h"
+#include "ivtv-yuv.h"
+
+/* YUV buffer offsets */
+const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
+       0x001a8600,
+       0x00240400,
+       0x002d8200,
+       0x00370000,
+       0x00029000,
+       0x000C0E00,
+       0x006B0400,
+       0x00748200
+};
+
+static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
+                                 struct ivtv_dma_frame *args)
+{
+       struct ivtv_dma_page_info y_dma;
+       struct ivtv_dma_page_info uv_dma;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       u8 frame = yi->draw_frame;
+       struct yuv_frame_info *f = &yi->new_frame_info[frame];
+       int i;
+       int y_pages, uv_pages;
+       unsigned long y_buffer_offset, uv_buffer_offset;
+       int y_decode_height, uv_decode_height, y_size;
+
+       y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
+       uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
+
+       y_decode_height = uv_decode_height = f->src_h + f->src_y;
+
+       if (f->offset_y)
+               y_buffer_offset += 720 * 16;
+
+       if (y_decode_height & 15)
+               y_decode_height = (y_decode_height + 16) & ~15;
+
+       if (uv_decode_height & 31)
+               uv_decode_height = (uv_decode_height + 32) & ~31;
+
+       y_size = 720 * y_decode_height;
+
+       /* Still in USE */
+       if (dma->SG_length || dma->page_count) {
+               IVTV_DEBUG_WARN
+                   ("prep_user_dma: SG_length %d page_count %d still full?\n",
+                    dma->SG_length, dma->page_count);
+               return -EBUSY;
+       }
+
+       ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
+       ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
+
+       /* Get user pages for DMA Xfer */
+       down_read(&current->mm->mmap_sem);
+       y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
+       uv_pages = 0; /* silence gcc. value is set and consumed only if: */
+       if (y_pages == y_dma.page_count) {
+               uv_pages = get_user_pages(current, current->mm,
+                                         uv_dma.uaddr, uv_dma.page_count, 0, 1,
+                                         &dma->map[y_pages], NULL);
+       }
+       up_read(&current->mm->mmap_sem);
+
+       if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
+               int rc = -EFAULT;
+
+               if (y_pages == y_dma.page_count) {
+                       IVTV_DEBUG_WARN
+                               ("failed to map uv user pages, returned %d "
+                                "expecting %d\n", uv_pages, uv_dma.page_count);
+
+                       if (uv_pages >= 0) {
+                               for (i = 0; i < uv_pages; i++)
+                                       put_page(dma->map[y_pages + i]);
+                               rc = -EFAULT;
+                       } else {
+                               rc = uv_pages;
+                       }
+               } else {
+                       IVTV_DEBUG_WARN
+                               ("failed to map y user pages, returned %d "
+                                "expecting %d\n", y_pages, y_dma.page_count);
+               }
+               if (y_pages >= 0) {
+                       for (i = 0; i < y_pages; i++)
+                               put_page(dma->map[i]);
+                       /*
+                        * Inherit the -EFAULT from rc's
+                        * initialization, but allow it to be
+                        * overriden by uv_pages above if it was an
+                        * actual errno.
+                        */
+               } else {
+                       rc = y_pages;
+               }
+               return rc;
+       }
+
+       dma->page_count = y_pages + uv_pages;
+
+       /* Fill & map SG List */
+       if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
+               IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
+               for (i = 0; i < dma->page_count; i++) {
+                       put_page(dma->map[i]);
+               }
+               dma->page_count = 0;
+               return -ENOMEM;
+       }
+       dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+
+       /* Fill SG Array with new values */
+       ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
+
+       /* If we've offset the y plane, ensure top area is blanked */
+       if (f->offset_y && yi->blanking_dmaptr) {
+               dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
+               dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
+               dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
+               dma->SG_length++;
+       }
+
+       /* Tag SG Array with Interrupt Bit */
+       dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
+
+       ivtv_udma_sync_for_device(itv);
+       return 0;
+}
+
+/* We rely on a table held in the firmware - Quick check. */
+int ivtv_yuv_filter_check(struct ivtv *itv)
+{
+       int i, y, uv;
+
+       for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
+               if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
+                   (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
+                       IVTV_WARN ("YUV filter table not found in firmware.\n");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
+{
+       u32 i, line;
+
+       /* If any filter is -1, then don't update it */
+       if (h_filter > -1) {
+               if (h_filter > 4)
+                       h_filter = 4;
+               i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
+               for (line = 0; line < 16; line++) {
+                       write_reg(read_dec(i), 0x02804);
+                       write_reg(read_dec(i), 0x0281c);
+                       i += 4;
+                       write_reg(read_dec(i), 0x02808);
+                       write_reg(read_dec(i), 0x02820);
+                       i += 4;
+                       write_reg(read_dec(i), 0x0280c);
+                       write_reg(read_dec(i), 0x02824);
+                       i += 4;
+                       write_reg(read_dec(i), 0x02810);
+                       write_reg(read_dec(i), 0x02828);
+                       i += 4;
+                       write_reg(read_dec(i), 0x02814);
+                       write_reg(read_dec(i), 0x0282c);
+                       i += 8;
+                       write_reg(0, 0x02818);
+                       write_reg(0, 0x02830);
+               }
+               IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
+       }
+
+       if (v_filter_1 > -1) {
+               if (v_filter_1 > 4)
+                       v_filter_1 = 4;
+               i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
+               for (line = 0; line < 16; line++) {
+                       write_reg(read_dec(i), 0x02900);
+                       i += 4;
+                       write_reg(read_dec(i), 0x02904);
+                       i += 8;
+                       write_reg(0, 0x02908);
+               }
+               IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
+       }
+
+       if (v_filter_2 > -1) {
+               if (v_filter_2 > 4)
+                       v_filter_2 = 4;
+               i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
+               for (line = 0; line < 16; line++) {
+                       write_reg(read_dec(i), 0x0290c);
+                       i += 4;
+                       write_reg(read_dec(i), 0x02910);
+                       i += 8;
+                       write_reg(0, 0x02914);
+               }
+               IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
+       }
+}
+
+static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       u32 reg_2834, reg_2838, reg_283c;
+       u32 reg_2844, reg_2854, reg_285c;
+       u32 reg_2864, reg_2874, reg_2890;
+       u32 reg_2870, reg_2870_base, reg_2870_offset;
+       int x_cutoff;
+       int h_filter;
+       u32 master_width;
+
+       IVTV_DEBUG_WARN
+           ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
+            f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
+
+       /* How wide is the src image */
+       x_cutoff = f->src_w + f->src_x;
+
+       /* Set the display width */
+       reg_2834 = f->dst_w;
+       reg_2838 = reg_2834;
+
+       /* Set the display position */
+       reg_2890 = f->dst_x;
+
+       /* Index into the image horizontally */
+       reg_2870 = 0;
+
+       /* 2870 is normally fudged to align video coords with osd coords.
+          If running full screen, it causes an unwanted left shift
+          Remove the fudge if we almost fill the screen.
+          Gradually adjust the offset to avoid the video 'snapping'
+          left/right if it gets dragged through this region.
+          Only do this if osd is full width. */
+       if (f->vis_w == 720) {
+               if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
+                       reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
+               else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
+                       reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
+
+               if (f->dst_w >= f->src_w)
+                       reg_2870 = reg_2870 << 16 | reg_2870;
+               else
+                       reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
+       }
+
+       if (f->dst_w < f->src_w)
+               reg_2870 = 0x000d000e - reg_2870;
+       else
+               reg_2870 = 0x0012000e - reg_2870;
+
+       /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
+       reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
+
+       if (f->dst_w >= f->src_w) {
+               x_cutoff &= ~1;
+               master_width = (f->src_w * 0x00200000) / (f->dst_w);
+               if (master_width * f->dst_w != f->src_w * 0x00200000)
+                       master_width++;
+               reg_2834 = (reg_2834 << 16) | x_cutoff;
+               reg_2838 = (reg_2838 << 16) | x_cutoff;
+               reg_283c = master_width >> 2;
+               reg_2844 = master_width >> 2;
+               reg_2854 = master_width;
+               reg_285c = master_width >> 1;
+               reg_2864 = master_width >> 1;
+
+               /* We also need to factor in the scaling
+                  (src_w - dst_w) / (src_w / 4) */
+               if (f->dst_w > f->src_w)
+                       reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
+               else
+                       reg_2870_base = 0;
+
+               reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
+               reg_2874 = 0;
+       } else if (f->dst_w < f->src_w / 2) {
+               master_width = (f->src_w * 0x00080000) / f->dst_w;
+               if (master_width * f->dst_w != f->src_w * 0x00080000)
+                       master_width++;
+               reg_2834 = (reg_2834 << 16) | x_cutoff;
+               reg_2838 = (reg_2838 << 16) | x_cutoff;
+               reg_283c = master_width >> 2;
+               reg_2844 = master_width >> 1;
+               reg_2854 = master_width;
+               reg_285c = master_width >> 1;
+               reg_2864 = master_width >> 1;
+               reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
+               reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
+               reg_2874 = 0x00000012;
+       } else {
+               master_width = (f->src_w * 0x00100000) / f->dst_w;
+               if (master_width * f->dst_w != f->src_w * 0x00100000)
+                       master_width++;
+               reg_2834 = (reg_2834 << 16) | x_cutoff;
+               reg_2838 = (reg_2838 << 16) | x_cutoff;
+               reg_283c = master_width >> 2;
+               reg_2844 = master_width >> 1;
+               reg_2854 = master_width;
+               reg_285c = master_width >> 1;
+               reg_2864 = master_width >> 1;
+               reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
+               reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
+               reg_2874 = 0x00000001;
+       }
+
+       /* Select the horizontal filter */
+       if (f->src_w == f->dst_w) {
+               /* An exact size match uses filter 0 */
+               h_filter = 0;
+       } else {
+               /* Figure out which filter to use */
+               h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
+               h_filter = (h_filter >> 1) + (h_filter & 1);
+               /* Only an exact size match can use filter 0 */
+               h_filter += !h_filter;
+       }
+
+       write_reg(reg_2834, 0x02834);
+       write_reg(reg_2838, 0x02838);
+       IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
+                      yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
+
+       write_reg(reg_283c, 0x0283c);
+       write_reg(reg_2844, 0x02844);
+
+       IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
+                      yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
+
+       write_reg(0x00080514, 0x02840);
+       write_reg(0x00100514, 0x02848);
+       IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
+                      yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
+
+       write_reg(reg_2854, 0x02854);
+       IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
+                      yi->reg_2854, reg_2854);
+
+       write_reg(reg_285c, 0x0285c);
+       write_reg(reg_2864, 0x02864);
+       IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
+                      yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
+
+       write_reg(reg_2874, 0x02874);
+       IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
+                      yi->reg_2874, reg_2874);
+
+       write_reg(reg_2870, 0x02870);
+       IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
+                      yi->reg_2870, reg_2870);
+
+       write_reg(reg_2890, 0x02890);
+       IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
+                      yi->reg_2890, reg_2890);
+
+       /* Only update the filter if we really need to */
+       if (h_filter != yi->h_filter) {
+               ivtv_yuv_filter(itv, h_filter, -1, -1);
+               yi->h_filter = h_filter;
+       }
+}
+
+static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       u32 master_height;
+       u32 reg_2918, reg_291c, reg_2920, reg_2928;
+       u32 reg_2930, reg_2934, reg_293c;
+       u32 reg_2940, reg_2944, reg_294c;
+       u32 reg_2950, reg_2954, reg_2958, reg_295c;
+       u32 reg_2960, reg_2964, reg_2968, reg_296c;
+       u32 reg_289c;
+       u32 src_major_y, src_minor_y;
+       u32 src_major_uv, src_minor_uv;
+       u32 reg_2964_base, reg_2968_base;
+       int v_filter_1, v_filter_2;
+
+       IVTV_DEBUG_WARN
+           ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
+            f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
+
+       /* What scaling mode is being used... */
+       IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
+                      f->interlaced_y ? "Interlaced" : "Progressive");
+
+       IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
+                      f->interlaced_uv ? "Interlaced" : "Progressive");
+
+       /* What is the source video being treated as... */
+       IVTV_DEBUG_WARN("Source video: %s\n",
+                       f->interlaced ? "Interlaced" : "Progressive");
+
+       /* We offset into the image using two different index methods, so split
+          the y source coord into two parts. */
+       if (f->src_y < 8) {
+               src_minor_uv = f->src_y;
+               src_major_uv = 0;
+       } else {
+               src_minor_uv = 8;
+               src_major_uv = f->src_y - 8;
+       }
+
+       src_minor_y = src_minor_uv;
+       src_major_y = src_major_uv;
+
+       if (f->offset_y)
+               src_minor_y += 16;
+
+       if (f->interlaced_y)
+               reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
+       else
+               reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
+
+       if (f->interlaced_uv)
+               reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
+       else
+               reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
+
+       reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
+       reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
+
+       if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
+               master_height = (f->src_h * 0x00400000) / f->dst_h;
+               if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
+                       master_height++;
+               reg_2920 = master_height >> 2;
+               reg_2928 = master_height >> 3;
+               reg_2930 = master_height;
+               reg_2940 = master_height >> 1;
+               reg_2964_base >>= 3;
+               reg_2968_base >>= 3;
+               reg_296c = 0x00000000;
+       } else if (f->dst_h >= f->src_h) {
+               master_height = (f->src_h * 0x00400000) / f->dst_h;
+               master_height = (master_height >> 1) + (master_height & 1);
+               reg_2920 = master_height >> 2;
+               reg_2928 = master_height >> 2;
+               reg_2930 = master_height;
+               reg_2940 = master_height >> 1;
+               reg_296c = 0x00000000;
+               if (f->interlaced_y) {
+                       reg_2964_base >>= 3;
+               } else {
+                       reg_296c++;
+                       reg_2964_base >>= 2;
+               }
+               if (f->interlaced_uv)
+                       reg_2928 >>= 1;
+               reg_2968_base >>= 3;
+       } else if (f->dst_h >= f->src_h / 2) {
+               master_height = (f->src_h * 0x00200000) / f->dst_h;
+               master_height = (master_height >> 1) + (master_height & 1);
+               reg_2920 = master_height >> 2;
+               reg_2928 = master_height >> 2;
+               reg_2930 = master_height;
+               reg_2940 = master_height;
+               reg_296c = 0x00000101;
+               if (f->interlaced_y) {
+                       reg_2964_base >>= 2;
+               } else {
+                       reg_296c++;
+                       reg_2964_base >>= 1;
+               }
+               if (f->interlaced_uv)
+                       reg_2928 >>= 1;
+               reg_2968_base >>= 2;
+       } else {
+               master_height = (f->src_h * 0x00100000) / f->dst_h;
+               master_height = (master_height >> 1) + (master_height & 1);
+               reg_2920 = master_height >> 2;
+               reg_2928 = master_height >> 2;
+               reg_2930 = master_height;
+               reg_2940 = master_height;
+               reg_2964_base >>= 1;
+               reg_2968_base >>= 2;
+               reg_296c = 0x00000102;
+       }
+
+       /* FIXME These registers change depending on scaled / unscaled output
+          We really need to work out what they should be */
+       if (f->src_h == f->dst_h) {
+               reg_2934 = 0x00020000;
+               reg_293c = 0x00100000;
+               reg_2944 = 0x00040000;
+               reg_294c = 0x000b0000;
+       } else {
+               reg_2934 = 0x00000FF0;
+               reg_293c = 0x00000FF0;
+               reg_2944 = 0x00000FF0;
+               reg_294c = 0x00000FF0;
+       }
+
+       /* The first line to be displayed */
+       reg_2950 = 0x00010000 + src_major_y;
+       if (f->interlaced_y)
+               reg_2950 += 0x00010000;
+       reg_2954 = reg_2950 + 1;
+
+       reg_2958 = 0x00010000 + (src_major_y >> 1);
+       if (f->interlaced_uv)
+               reg_2958 += 0x00010000;
+       reg_295c = reg_2958 + 1;
+
+       if (yi->decode_height == 480)
+               reg_289c = 0x011e0017;
+       else
+               reg_289c = 0x01500017;
+
+       if (f->dst_y < 0)
+               reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
+       else
+               reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
+
+       /* How much of the source to decode.
+          Take into account the source offset */
+       reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
+               (((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
+
+       /* Calculate correct value for register 2964 */
+       if (f->src_h == f->dst_h) {
+               reg_2964 = 1;
+       } else {
+               reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
+               reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
+       }
+       reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
+       reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
+
+       /* Okay, we've wasted time working out the correct value,
+          but if we use it, it fouls the the window alignment.
+          Fudge it to what we want... */
+       reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
+       reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
+
+       /* Deviate further from what it should be. I find the flicker headache
+          inducing so try to reduce it slightly. Leave 2968 as-is otherwise
+          colours foul. */
+       if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
+               reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
+
+       if (!f->interlaced_y)
+               reg_2964 -= 0x00010001;
+       if (!f->interlaced_uv)
+               reg_2968 -= 0x00010001;
+
+       reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
+       reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
+
+       /* Select the vertical filter */
+       if (f->src_h == f->dst_h) {
+               /* An exact size match uses filter 0/1 */
+               v_filter_1 = 0;
+               v_filter_2 = 1;
+       } else {
+               /* Figure out which filter to use */
+               v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
+               v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
+               /* Only an exact size match can use filter 0 */
+               v_filter_1 += !v_filter_1;
+               v_filter_2 = v_filter_1;
+       }
+
+       write_reg(reg_2934, 0x02934);
+       write_reg(reg_293c, 0x0293c);
+       IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
+                      yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
+       write_reg(reg_2944, 0x02944);
+       write_reg(reg_294c, 0x0294c);
+       IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
+                      yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
+
+       /* Ensure 2970 is 0 (does it ever change ?) */
+/*     write_reg(0,0x02970); */
+/*     IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
+
+       write_reg(reg_2930, 0x02938);
+       write_reg(reg_2930, 0x02930);
+       IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
+                      yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
+
+       write_reg(reg_2928, 0x02928);
+       write_reg(reg_2928 + 0x514, 0x0292C);
+       IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
+                      yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
+
+       write_reg(reg_2920, 0x02920);
+       write_reg(reg_2920 + 0x514, 0x02924);
+       IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
+                      yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
+
+       write_reg(reg_2918, 0x02918);
+       write_reg(reg_291c, 0x0291C);
+       IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
+                      yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
+
+       write_reg(reg_296c, 0x0296c);
+       IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
+                      yi->reg_296c, reg_296c);
+
+       write_reg(reg_2940, 0x02948);
+       write_reg(reg_2940, 0x02940);
+       IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
+                      yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
+
+       write_reg(reg_2950, 0x02950);
+       write_reg(reg_2954, 0x02954);
+       IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
+                      yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
+
+       write_reg(reg_2958, 0x02958);
+       write_reg(reg_295c, 0x0295C);
+       IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
+                      yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
+
+       write_reg(reg_2960, 0x02960);
+       IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
+                      yi->reg_2960, reg_2960);
+
+       write_reg(reg_2964, 0x02964);
+       write_reg(reg_2968, 0x02968);
+       IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
+                      yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
+
+       write_reg(reg_289c, 0x0289c);
+       IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
+                      yi->reg_289c, reg_289c);
+
+       /* Only update filter 1 if we really need to */
+       if (v_filter_1 != yi->v_filter_1) {
+               ivtv_yuv_filter(itv, -1, v_filter_1, -1);
+               yi->v_filter_1 = v_filter_1;
+       }
+
+       /* Only update filter 2 if we really need to */
+       if (v_filter_2 != yi->v_filter_2) {
+               ivtv_yuv_filter(itv, -1, -1, v_filter_2);
+               yi->v_filter_2 = v_filter_2;
+       }
+}
+
+/* Modify the supplied coordinate information to fit the visible osd area */
+static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
+{
+       struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
+       int osd_crop;
+       u32 osd_scale;
+       u32 yuv_update = 0;
+
+       /* Sorry, but no negative coords for src */
+       if (f->src_x < 0)
+               f->src_x = 0;
+       if (f->src_y < 0)
+               f->src_y = 0;
+
+       /* Can only reduce width down to 1/4 original size */
+       if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
+               f->src_x += osd_crop / 2;
+               f->src_w = (f->src_w - osd_crop) & ~3;
+               f->dst_w = f->src_w / 4;
+               f->dst_w += f->dst_w & 1;
+       }
+
+       /* Can only reduce height down to 1/4 original size */
+       if (f->src_h / f->dst_h >= 2) {
+               /* Overflow may be because we're running progressive,
+                  so force mode switch */
+               f->interlaced_y = 1;
+               /* Make sure we're still within limits for interlace */
+               if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
+                       /* If we reach here we'll have to force the height. */
+                       f->src_y += osd_crop / 2;
+                       f->src_h = (f->src_h - osd_crop) & ~3;
+                       f->dst_h = f->src_h / 4;
+                       f->dst_h += f->dst_h & 1;
+               }
+       }
+
+       /* If there's nothing to safe to display, we may as well stop now */
+       if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
+           (int)f->src_w <= 2 || (int)f->src_h <= 2) {
+               return IVTV_YUV_UPDATE_INVALID;
+       }
+
+       /* Ensure video remains inside OSD area */
+       osd_scale = (f->src_h << 16) / f->dst_h;
+
+       if ((osd_crop = f->pan_y - f->dst_y) > 0) {
+               /* Falls off the upper edge - crop */
+               f->src_y += (osd_scale * osd_crop) >> 16;
+               f->src_h -= (osd_scale * osd_crop) >> 16;
+               f->dst_h -= osd_crop;
+               f->dst_y = 0;
+       } else {
+               f->dst_y -= f->pan_y;
+       }
+
+       if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
+               /* Falls off the lower edge - crop */
+               f->dst_h -= osd_crop;
+               f->src_h -= (osd_scale * osd_crop) >> 16;
+       }
+
+       osd_scale = (f->src_w << 16) / f->dst_w;
+
+       if ((osd_crop = f->pan_x - f->dst_x) > 0) {
+               /* Fall off the left edge - crop */
+               f->src_x += (osd_scale * osd_crop) >> 16;
+               f->src_w -= (osd_scale * osd_crop) >> 16;
+               f->dst_w -= osd_crop;
+               f->dst_x = 0;
+       } else {
+               f->dst_x -= f->pan_x;
+       }
+
+       if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
+               /* Falls off the right edge - crop */
+               f->dst_w -= osd_crop;
+               f->src_w -= (osd_scale * osd_crop) >> 16;
+       }
+
+       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. */
+       f->dst_w &= ~1;
+       f->dst_x &= ~1;
+
+       f->src_w += f->src_x & 1;
+       f->src_x &= ~1;
+
+       f->src_w &= ~1;
+       f->dst_w &= ~1;
+
+       f->dst_h &= ~1;
+       f->dst_y &= ~1;
+
+       f->src_h += f->src_y & 1;
+       f->src_y &= ~1;
+
+       f->src_h &= ~1;
+       f->dst_h &= ~1;
+
+       /* Due to rounding, we may have reduced the output size to <1/4 of
+          the source. Check again, but this time just resize. Don't change
+          source coordinates */
+       if (f->dst_w < f->src_w / 4) {
+               f->src_w &= ~3;
+               f->dst_w = f->src_w / 4;
+               f->dst_w += f->dst_w & 1;
+       }
+       if (f->dst_h < f->src_h / 4) {
+               f->src_h &= ~3;
+               f->dst_h = f->src_h / 4;
+               f->dst_h += f->dst_h & 1;
+       }
+
+       /* Check again. If there's nothing to safe to display, stop now */
+       if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
+           (int)f->src_w <= 2 || (int)f->src_h <= 2) {
+               return IVTV_YUV_UPDATE_INVALID;
+       }
+
+       /* Both x offset & width are linked, so they have to be done together */
+       if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
+           (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
+           (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
+               yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
+       }
+
+       if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
+           (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
+           (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
+           (of->lace_mode != f->lace_mode) ||
+           (of->interlaced_y != f->interlaced_y) ||
+           (of->interlaced_uv != f->interlaced_uv)) {
+               yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
+       }
+
+       return yuv_update;
+}
+
+/* Update the scaling register to the requested value */
+void ivtv_yuv_work_handler(struct ivtv *itv)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       struct yuv_frame_info f;
+       int frame = yi->update_frame;
+       u32 yuv_update;
+
+       IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
+       f = yi->new_frame_info[frame];
+
+       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)))
+               return;
+
+       if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
+               write_reg(0x01008080, 0x2898);
+       } else if (yuv_update) {
+               write_reg(0x00108080, 0x2898);
+
+               if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
+                       ivtv_yuv_handle_horizontal(itv, &f);
+
+               if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
+                       ivtv_yuv_handle_vertical(itv, &f);
+       }
+       yi->old_frame_info = f;
+}
+
+static void ivtv_yuv_init(struct ivtv *itv)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+
+       IVTV_DEBUG_YUV("ivtv_yuv_init\n");
+
+       /* Take a snapshot of the current register settings */
+       yi->reg_2834 = read_reg(0x02834);
+       yi->reg_2838 = read_reg(0x02838);
+       yi->reg_283c = read_reg(0x0283c);
+       yi->reg_2840 = read_reg(0x02840);
+       yi->reg_2844 = read_reg(0x02844);
+       yi->reg_2848 = read_reg(0x02848);
+       yi->reg_2854 = read_reg(0x02854);
+       yi->reg_285c = read_reg(0x0285c);
+       yi->reg_2864 = read_reg(0x02864);
+       yi->reg_2870 = read_reg(0x02870);
+       yi->reg_2874 = read_reg(0x02874);
+       yi->reg_2898 = read_reg(0x02898);
+       yi->reg_2890 = read_reg(0x02890);
+
+       yi->reg_289c = read_reg(0x0289c);
+       yi->reg_2918 = read_reg(0x02918);
+       yi->reg_291c = read_reg(0x0291c);
+       yi->reg_2920 = read_reg(0x02920);
+       yi->reg_2924 = read_reg(0x02924);
+       yi->reg_2928 = read_reg(0x02928);
+       yi->reg_292c = read_reg(0x0292c);
+       yi->reg_2930 = read_reg(0x02930);
+       yi->reg_2934 = read_reg(0x02934);
+       yi->reg_2938 = read_reg(0x02938);
+       yi->reg_293c = read_reg(0x0293c);
+       yi->reg_2940 = read_reg(0x02940);
+       yi->reg_2944 = read_reg(0x02944);
+       yi->reg_2948 = read_reg(0x02948);
+       yi->reg_294c = read_reg(0x0294c);
+       yi->reg_2950 = read_reg(0x02950);
+       yi->reg_2954 = read_reg(0x02954);
+       yi->reg_2958 = read_reg(0x02958);
+       yi->reg_295c = read_reg(0x0295c);
+       yi->reg_2960 = read_reg(0x02960);
+       yi->reg_2964 = read_reg(0x02964);
+       yi->reg_2968 = read_reg(0x02968);
+       yi->reg_296c = read_reg(0x0296c);
+       yi->reg_2970 = read_reg(0x02970);
+
+       yi->v_filter_1 = -1;
+       yi->v_filter_2 = -1;
+       yi->h_filter = -1;
+
+       /* Set some valid size info */
+       yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
+       yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
+
+       /* Bit 2 of reg 2878 indicates current decoder output format
+          0 : NTSC    1 : PAL */
+       if (read_reg(0x2878) & 4)
+               yi->decode_height = 576;
+       else
+               yi->decode_height = 480;
+
+       if (!itv->osd_info) {
+               yi->osd_vis_w = 720 - yi->osd_x_offset;
+               yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+       } else {
+               /* If no visible size set, assume full size */
+               if (!yi->osd_vis_w)
+                       yi->osd_vis_w = 720 - yi->osd_x_offset;
+
+               if (!yi->osd_vis_h) {
+                       yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+               } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
+                       /* If output video standard has changed, requested height may
+                          not be legal */
+                       IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
+                                       yi->osd_vis_h + yi->osd_y_offset,
+                                       yi->decode_height);
+                       yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+               }
+       }
+
+       /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
+       yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
+       if (yi->blanking_ptr) {
+               yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
+       } else {
+               yi->blanking_dmaptr = 0;
+               IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
+       }
+
+       /* Enable YUV decoder output */
+       write_reg_sync(0x01, IVTV_REG_VDM);
+
+       set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
+       atomic_set(&yi->next_dma_frame, 0);
+}
+
+/* Get next available yuv buffer on PVR350 */
+static void ivtv_yuv_next_free(struct ivtv *itv)
+{
+       int draw, display;
+       struct yuv_playback_info *yi = &itv->yuv_info;
+
+       if (atomic_read(&yi->next_dma_frame) == -1)
+               ivtv_yuv_init(itv);
+
+       draw = atomic_read(&yi->next_fill_frame);
+       display = atomic_read(&yi->next_dma_frame);
+
+       if (display > draw)
+               display -= IVTV_YUV_BUFFERS;
+
+       if (draw - display >= yi->max_frames_buffered)
+               draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
+       else
+               yi->new_frame_info[draw].update = 0;
+
+       yi->draw_frame = draw;
+}
+
+/* Set up frame according to ivtv_dma_frame parameters */
+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;
+       u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
+       struct yuv_frame_info *nf = &yi->new_frame_info[frame];
+       struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
+       int lace_threshold = yi->lace_threshold;
+
+       /* Preserve old update flag in case we're overwriting a queued frame */
+       int update = nf->update;
+
+       /* Take a snapshot of the yuv coordinate information */
+       nf->src_x = args->src.left;
+       nf->src_y = args->src.top;
+       nf->src_w = args->src.width;
+       nf->src_h = args->src.height;
+       nf->dst_x = args->dst.left;
+       nf->dst_y = args->dst.top;
+       nf->dst_w = args->dst.width;
+       nf->dst_h = args->dst.height;
+       nf->tru_x = args->dst.left;
+       nf->tru_w = args->src_width;
+       nf->tru_h = args->src_height;
+
+       /* Are we going to offset the Y plane */
+       nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
+
+       nf->update = 0;
+       nf->interlaced_y = 0;
+       nf->interlaced_uv = 0;
+       nf->delay = 0;
+       nf->sync_field = 0;
+       nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
+
+       if (lace_threshold < 0)
+               lace_threshold = yi->decode_height - 1;
+
+       /* Work out the lace settings */
+       switch (nf->lace_mode) {
+       case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
+               nf->interlaced = 0;
+               if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
+                       nf->interlaced_y = 0;
+               else
+                       nf->interlaced_y = 1;
+
+               if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
+                       nf->interlaced_uv = 0;
+               else
+                       nf->interlaced_uv = 1;
+               break;
+
+       case IVTV_YUV_MODE_AUTO:
+               if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
+                       nf->interlaced = 0;
+                       if ((nf->tru_h < 512) ||
+                           (nf->tru_h > 576 && nf->tru_h < 1021) ||
+                           (nf->tru_w > 720 && nf->tru_h < 1021))
+                               nf->interlaced_y = 0;
+                       else
+                               nf->interlaced_y = 1;
+                       if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
+                               nf->interlaced_uv = 0;
+                       else
+                               nf->interlaced_uv = 1;
+               } else {
+                       nf->interlaced = 1;
+                       nf->interlaced_y = 1;
+                       nf->interlaced_uv = 1;
+               }
+               break;
+
+       case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
+       default:
+               nf->interlaced = 1;
+               nf->interlaced_y = 1;
+               nf->interlaced_uv = 1;
+               break;
+       }
+
+       if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
+               yi->old_frame_info_args = *nf;
+               nf->update = 1;
+               IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
+       }
+
+       nf->update |= update;
+       nf->sync_field = yi->lace_sync_field;
+       nf->delay = nf->sync_field != of->sync_field;
+}
+
+/* Frame is complete & ready for display */
+void ivtv_yuv_frame_complete(struct ivtv *itv)
+{
+       atomic_set(&itv->yuv_info.next_fill_frame,
+                       (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
+}
+
+static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+{
+       DEFINE_WAIT(wait);
+       int rc = 0;
+       int got_sig = 0;
+       /* DMA the frame */
+       mutex_lock(&itv->udma.lock);
+
+       if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
+               mutex_unlock(&itv->udma.lock);
+               return rc;
+       }
+
+       ivtv_udma_prepare(itv);
+       prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+       /* if no UDMA is pending and no UDMA is in progress, then the DMA
+          is finished */
+       while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
+              test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+               /* don't interrupt if the DMA is in progress but break off
+                  a still pending DMA. */
+               got_sig = signal_pending(current);
+               if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
+                       break;
+               got_sig = 0;
+               schedule();
+       }
+       finish_wait(&itv->dma_waitq, &wait);
+
+       /* Unmap Last DMA Xfer */
+       ivtv_udma_unmap(itv);
+
+       if (got_sig) {
+               IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
+               mutex_unlock(&itv->udma.lock);
+               return -EINTR;
+       }
+
+       ivtv_yuv_frame_complete(itv);
+
+       mutex_unlock(&itv->udma.lock);
+       return rc;
+}
+
+/* Setup frame according to V4L2 parameters */
+void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       struct ivtv_dma_frame dma_args;
+
+       ivtv_yuv_next_free(itv);
+
+       /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
+       dma_args.y_source = NULL;
+       dma_args.uv_source = NULL;
+       dma_args.src.left = 0;
+       dma_args.src.top = 0;
+       dma_args.src.width = yi->v4l2_src_w;
+       dma_args.src.height = yi->v4l2_src_h;
+       dma_args.dst = yi->main_rect;
+       dma_args.src_width = yi->v4l2_src_w;
+       dma_args.src_height = yi->v4l2_src_h;
+
+       /* ... and use the same setup routine as ivtv_yuv_prep_frame */
+       ivtv_yuv_setup_frame(itv, &dma_args);
+
+       if (!itv->dma_data_req_offset)
+               itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
+}
+
+/* Attempt to dma a frame from a user buffer */
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       struct ivtv_dma_frame dma_args;
+       int res;
+
+       ivtv_yuv_setup_stream_frame(itv);
+
+       /* We only need to supply source addresses for this */
+       dma_args.y_source = src;
+       dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
+       /* Wait for frame DMA. Note that serialize_lock is locked,
+          so to allow other processes to access the driver while
+          we are waiting unlock first and later lock again. */
+       mutex_unlock(&itv->serialize_lock);
+       res = ivtv_yuv_udma_frame(itv, &dma_args);
+       mutex_lock(&itv->serialize_lock);
+       return res;
+}
+
+/* IVTV_IOC_DMA_FRAME ioctl handler */
+int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+{
+       int res;
+
+/*     IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
+       ivtv_yuv_next_free(itv);
+       ivtv_yuv_setup_frame(itv, args);
+       /* Wait for frame DMA. Note that serialize_lock is locked,
+          so to allow other processes to access the driver while
+          we are waiting unlock first and later lock again. */
+       mutex_unlock(&itv->serialize_lock);
+       res = ivtv_yuv_udma_frame(itv, args);
+       mutex_lock(&itv->serialize_lock);
+       return res;
+}
+
+void ivtv_yuv_close(struct ivtv *itv)
+{
+       struct yuv_playback_info *yi = &itv->yuv_info;
+       int h_filter, v_filter_1, v_filter_2;
+
+       IVTV_DEBUG_YUV("ivtv_yuv_close\n");
+       mutex_unlock(&itv->serialize_lock);
+       ivtv_waitq(&itv->vsync_waitq);
+       mutex_lock(&itv->serialize_lock);
+
+       yi->running = 0;
+       atomic_set(&yi->next_dma_frame, -1);
+       atomic_set(&yi->next_fill_frame, 0);
+
+       /* Reset registers we have changed so mpeg playback works */
+
+       /* If we fully restore this register, the display may remain active.
+          Restore, but set one bit to blank the video. Firmware will always
+          clear this bit when needed, so not a problem. */
+       write_reg(yi->reg_2898 | 0x01000000, 0x2898);
+
+       write_reg(yi->reg_2834, 0x02834);
+       write_reg(yi->reg_2838, 0x02838);
+       write_reg(yi->reg_283c, 0x0283c);
+       write_reg(yi->reg_2840, 0x02840);
+       write_reg(yi->reg_2844, 0x02844);
+       write_reg(yi->reg_2848, 0x02848);
+       write_reg(yi->reg_2854, 0x02854);
+       write_reg(yi->reg_285c, 0x0285c);
+       write_reg(yi->reg_2864, 0x02864);
+       write_reg(yi->reg_2870, 0x02870);
+       write_reg(yi->reg_2874, 0x02874);
+       write_reg(yi->reg_2890, 0x02890);
+       write_reg(yi->reg_289c, 0x0289c);
+
+       write_reg(yi->reg_2918, 0x02918);
+       write_reg(yi->reg_291c, 0x0291c);
+       write_reg(yi->reg_2920, 0x02920);
+       write_reg(yi->reg_2924, 0x02924);
+       write_reg(yi->reg_2928, 0x02928);
+       write_reg(yi->reg_292c, 0x0292c);
+       write_reg(yi->reg_2930, 0x02930);
+       write_reg(yi->reg_2934, 0x02934);
+       write_reg(yi->reg_2938, 0x02938);
+       write_reg(yi->reg_293c, 0x0293c);
+       write_reg(yi->reg_2940, 0x02940);
+       write_reg(yi->reg_2944, 0x02944);
+       write_reg(yi->reg_2948, 0x02948);
+       write_reg(yi->reg_294c, 0x0294c);
+       write_reg(yi->reg_2950, 0x02950);
+       write_reg(yi->reg_2954, 0x02954);
+       write_reg(yi->reg_2958, 0x02958);
+       write_reg(yi->reg_295c, 0x0295c);
+       write_reg(yi->reg_2960, 0x02960);
+       write_reg(yi->reg_2964, 0x02964);
+       write_reg(yi->reg_2968, 0x02968);
+       write_reg(yi->reg_296c, 0x0296c);
+       write_reg(yi->reg_2970, 0x02970);
+
+       /* Prepare to restore filters */
+
+       /* First the horizontal filter */
+       if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
+               /* An exact size match uses filter 0 */
+               h_filter = 0;
+       } else {
+               /* Figure out which filter to use */
+               h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
+               h_filter = (h_filter >> 1) + (h_filter & 1);
+               /* Only an exact size match can use filter 0. */
+               h_filter += !h_filter;
+       }
+
+       /* Now the vertical filter */
+       if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
+               /* An exact size match uses filter 0/1 */
+               v_filter_1 = 0;
+               v_filter_2 = 1;
+       } else {
+               /* Figure out which filter to use */
+               v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
+               v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
+               /* Only an exact size match can use filter 0 */
+               v_filter_1 += !v_filter_1;
+               v_filter_2 = v_filter_1;
+       }
+
+       /* Now restore the filters */
+       ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
+
+       /* and clear a few registers */
+       write_reg(0, 0x02814);
+       write_reg(0, 0x0282c);
+       write_reg(0, 0x02904);
+       write_reg(0, 0x02910);
+
+       /* Release the blanking buffer */
+       if (yi->blanking_ptr) {
+               kfree(yi->blanking_ptr);
+               yi->blanking_ptr = NULL;
+               pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
+       }
+
+       /* Invalidate the old dimension information */
+       yi->old_frame_info.src_w = 0;
+       yi->old_frame_info.src_h = 0;
+       yi->old_frame_info_args.src_w = 0;
+       yi->old_frame_info_args.src_h = 0;
+
+       /* All done. */
+       clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.h b/drivers/media/pci/ivtv/ivtv-yuv.h
new file mode 100644 (file)
index 0000000..ca5173f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    yuv support
+
+    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_YUV_H
+#define IVTV_YUV_H
+
+#define IVTV_YUV_BUFFER_UV_OFFSET 0x65400      /* Offset to UV Buffer */
+
+/* Offset to filter table in firmware */
+#define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8
+#define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358
+
+#define IVTV_YUV_UPDATE_HORIZONTAL  0x01
+#define IVTV_YUV_UPDATE_VERTICAL    0x02
+#define IVTV_YUV_UPDATE_INVALID     0x04
+
+extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
+
+int ivtv_yuv_filter_check(struct ivtv *itv);
+void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src);
+void ivtv_yuv_frame_complete(struct ivtv *itv);
+int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
+void ivtv_yuv_close(struct ivtv *itv);
+void ivtv_yuv_work_handler(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
new file mode 100644 (file)
index 0000000..05b94aa
--- /dev/null
@@ -0,0 +1,1317 @@
+/*
+    On Screen Display cx23415 Framebuffer driver
+
+    This module presents the cx23415 OSD (onscreen display) framebuffer memory
+    as a standard Linux /dev/fb style framebuffer device. The framebuffer has
+    support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
+    mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
+    local alpha. The colorspace is selectable between rgb & yuv.
+    Depending on the TV standard configured in the ivtv module at load time,
+    the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
+    Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
+    or 59.94 (NTSC)
+
+    Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
+
+    Derived from drivers/video/vesafb.c
+    Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+
+    2.6 kernel port:
+    Copyright (C) 2004 Matthias Badaire
+
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+
+    Copyright (C) 2006  Ian Armstrong <ian@iarmst.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/ivtvfb.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-i2c.h"
+#include "ivtv-udma.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-firmware.h"
+
+/* card parameters */
+static int ivtvfb_card_id = -1;
+static int ivtvfb_debug = 0;
+static bool osd_laced;
+static int osd_depth;
+static int osd_upper;
+static int osd_left;
+static int osd_yres;
+static int osd_xres;
+
+module_param(ivtvfb_card_id, int, 0444);
+module_param_named(debug,ivtvfb_debug, int, 0644);
+module_param(osd_laced, bool, 0444);
+module_param(osd_depth, int, 0444);
+module_param(osd_upper, int, 0444);
+module_param(osd_left, int, 0444);
+module_param(osd_yres, int, 0444);
+module_param(osd_xres, int, 0444);
+
+MODULE_PARM_DESC(ivtvfb_card_id,
+                "Only use framebuffer of the specified ivtv card (0-31)\n"
+                "\t\t\tdefault -1: initialize all available framebuffers");
+
+MODULE_PARM_DESC(debug,
+                "Debug level (bitmask). Default: errors only\n"
+                "\t\t\t(debug = 3 gives full debugging)");
+
+/* Why upper, left, xres, yres, depth, laced ? To match terminology used
+   by fbset.
+   Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
+
+MODULE_PARM_DESC(osd_laced,
+                "Interlaced mode\n"
+                "\t\t\t0=off\n"
+                "\t\t\t1=on\n"
+                "\t\t\tdefault off");
+
+MODULE_PARM_DESC(osd_depth,
+                "Bits per pixel - 8, 16, 32\n"
+                "\t\t\tdefault 8");
+
+MODULE_PARM_DESC(osd_upper,
+                "Vertical start position\n"
+                "\t\t\tdefault 0 (Centered)");
+
+MODULE_PARM_DESC(osd_left,
+                "Horizontal start position\n"
+                "\t\t\tdefault 0 (Centered)");
+
+MODULE_PARM_DESC(osd_yres,
+                "Display height\n"
+                "\t\t\tdefault 480 (PAL)\n"
+                "\t\t\t        400 (NTSC)");
+
+MODULE_PARM_DESC(osd_xres,
+                "Display width\n"
+                "\t\t\tdefault 640");
+
+MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
+MODULE_LICENSE("GPL");
+
+/* --------------------------------------------------------------------- */
+
+#define IVTVFB_DBGFLG_WARN  (1 << 0)
+#define IVTVFB_DBGFLG_INFO  (1 << 1)
+
+#define IVTVFB_DEBUG(x, type, fmt, args...) \
+       do { \
+               if ((x) & ivtvfb_debug) \
+                       printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
+       } while (0)
+#define IVTVFB_DEBUG_WARN(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
+#define IVTVFB_DEBUG_INFO(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
+
+/* Standard kernel messages */
+#define IVTVFB_ERR(fmt, args...)   printk(KERN_ERR  "ivtvfb%d: " fmt, itv->instance , ## args)
+#define IVTVFB_WARN(fmt, args...)  printk(KERN_WARNING  "ivtvfb%d: " fmt, itv->instance , ## args)
+#define IVTVFB_INFO(fmt, args...)  printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
+
+/* --------------------------------------------------------------------- */
+
+#define IVTV_OSD_MAX_WIDTH  720
+#define IVTV_OSD_MAX_HEIGHT 576
+
+#define IVTV_OSD_BPP_8      0x00
+#define IVTV_OSD_BPP_16_444 0x03
+#define IVTV_OSD_BPP_16_555 0x02
+#define IVTV_OSD_BPP_16_565 0x01
+#define IVTV_OSD_BPP_32     0x04
+
+struct osd_info {
+       /* Physical base address */
+       unsigned long video_pbase;
+       /* Relative base address (relative to start of decoder memory) */
+       u32 video_rbase;
+       /* Mapped base address */
+       volatile char __iomem *video_vbase;
+       /* Buffer size */
+       u32 video_buffer_size;
+
+#ifdef CONFIG_MTRR
+       /* video_base rounded down as required by hardware MTRRs */
+       unsigned long fb_start_aligned_physaddr;
+       /* video_base rounded up as required by hardware MTRRs */
+       unsigned long fb_end_aligned_physaddr;
+#endif
+
+       /* Store the buffer offset */
+       int set_osd_coords_x;
+       int set_osd_coords_y;
+
+       /* Current dimensions (NOT VISIBLE SIZE!) */
+       int display_width;
+       int display_height;
+       int display_byte_stride;
+
+       /* Current bits per pixel */
+       int bits_per_pixel;
+       int bytes_per_pixel;
+
+       /* Frame buffer stuff */
+       struct fb_info ivtvfb_info;
+       struct fb_var_screeninfo ivtvfb_defined;
+       struct fb_fix_screeninfo ivtvfb_fix;
+
+       /* Used for a warm start */
+       struct fb_var_screeninfo fbvar_cur;
+       int blank_cur;
+       u32 palette_cur[256];
+       u32 pan_cur;
+};
+
+struct ivtv_osd_coords {
+       unsigned long offset;
+       unsigned long max_offset;
+       int pixel_stride;
+       int lines;
+       int x;
+       int y;
+};
+
+/* --------------------------------------------------------------------- */
+
+/* ivtv API calls for framebuffer related support */
+
+static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
+                                      u32 *fblength)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       int rc;
+
+       ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
+       rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
+       *fbbase = data[0];
+       *fblength = data[1];
+       return rc;
+}
+
+static int ivtvfb_get_osd_coords(struct ivtv *itv,
+                                     struct ivtv_osd_coords *osd)
+{
+       struct osd_info *oi = itv->osd_info;
+       u32 data[CX2341X_MBOX_MAX_DATA];
+
+       ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
+
+       osd->offset = data[0] - oi->video_rbase;
+       osd->max_offset = oi->display_width * oi->display_height * 4;
+       osd->pixel_stride = data[1];
+       osd->lines = data[2];
+       osd->x = data[3];
+       osd->y = data[4];
+       return 0;
+}
+
+static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
+{
+       struct osd_info *oi = itv->osd_info;
+
+       oi->display_width = osd->pixel_stride;
+       oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
+       oi->set_osd_coords_x += osd->x;
+       oi->set_osd_coords_y = osd->y;
+
+       return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
+                       osd->offset + oi->video_rbase,
+                       osd->pixel_stride,
+                       osd->lines, osd->x, osd->y);
+}
+
+static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
+{
+       int osd_height_limit = itv->is_out_50hz ? 576 : 480;
+
+       /* Only fail if resolution too high, otherwise fudge the start coords. */
+       if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
+               return -EINVAL;
+
+       /* Ensure we don't exceed display limits */
+       if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
+               IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
+                       ivtv_window->top, ivtv_window->height);
+               ivtv_window->top = osd_height_limit - ivtv_window->height;
+       }
+
+       if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
+               IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
+                       ivtv_window->left, ivtv_window->width);
+               ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
+       }
+
+       /* Set the OSD origin */
+       write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
+
+       /* How much to display */
+       write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
+
+       /* Pass this info back the yuv handler */
+       itv->yuv_info.osd_vis_w = ivtv_window->width;
+       itv->yuv_info.osd_vis_h = ivtv_window->height;
+       itv->yuv_info.osd_x_offset = ivtv_window->left;
+       itv->yuv_info.osd_y_offset = ivtv_window->top;
+
+       return 0;
+}
+
+static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
+                                 unsigned long ivtv_dest_addr, void __user *userbuf,
+                                 int size_in_bytes)
+{
+       DEFINE_WAIT(wait);
+       int got_sig = 0;
+
+       mutex_lock(&itv->udma.lock);
+       /* Map User DMA */
+       if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
+               mutex_unlock(&itv->udma.lock);
+               IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
+                              "Error with get_user_pages: %d bytes, %d pages returned\n",
+                              size_in_bytes, itv->udma.page_count);
+
+               /* get_user_pages must have failed completely */
+               return -EIO;
+       }
+
+       IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
+                      size_in_bytes, itv->udma.page_count);
+
+       ivtv_udma_prepare(itv);
+       prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+       /* if no UDMA is pending and no UDMA is in progress, then the DMA
+          is finished */
+       while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
+              test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+               /* don't interrupt if the DMA is in progress but break off
+                  a still pending DMA. */
+               got_sig = signal_pending(current);
+               if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
+                       break;
+               got_sig = 0;
+               schedule();
+       }
+       finish_wait(&itv->dma_waitq, &wait);
+
+       /* Unmap Last DMA Xfer */
+       ivtv_udma_unmap(itv);
+       mutex_unlock(&itv->udma.lock);
+       if (got_sig) {
+               IVTV_DEBUG_INFO("User stopped OSD\n");
+               return -EINTR;
+       }
+
+       return 0;
+}
+
+static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
+                             unsigned long dest_offset, int count)
+{
+       DEFINE_WAIT(wait);
+       struct osd_info *oi = itv->osd_info;
+
+       /* Nothing to do */
+       if (count == 0) {
+               IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
+               return -EINVAL;
+       }
+
+       /* Check Total FB Size */
+       if ((dest_offset + count) > oi->video_buffer_size) {
+               IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
+                       dest_offset + count, oi->video_buffer_size);
+               return -E2BIG;
+       }
+
+       /* Not fatal, but will have undesirable results */
+       if ((unsigned long)source & 3)
+               IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
+                       (unsigned long)source);
+
+       if (dest_offset & 3)
+               IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
+
+       if (count & 3)
+               IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
+
+       /* Check Source */
+       if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
+               IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
+                       (unsigned long)source);
+
+               IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
+                       dest_offset, (unsigned long)source,
+                       count);
+               return -EINVAL;
+       }
+
+       /* OSD Address to send DMA to */
+       dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
+
+       /* Fill Buffers */
+       return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
+}
+
+static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
+                                               size_t count, loff_t *ppos)
+{
+       unsigned long p = *ppos;
+       void *dst;
+       int err = 0;
+       int dma_err;
+       unsigned long total_size;
+       struct ivtv *itv = (struct ivtv *) info->par;
+       unsigned long dma_offset =
+                       IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
+       unsigned long dma_size;
+       u16 lead = 0, tail = 0;
+
+       if (info->state != FBINFO_STATE_RUNNING)
+               return -EPERM;
+
+       total_size = info->screen_size;
+
+       if (total_size == 0)
+               total_size = info->fix.smem_len;
+
+       if (p > total_size)
+               return -EFBIG;
+
+       if (count > total_size) {
+               err = -EFBIG;
+               count = total_size;
+       }
+
+       if (count + p > total_size) {
+               if (!err)
+                       err = -ENOSPC;
+               count = total_size - p;
+       }
+
+       dst = (void __force *) (info->screen_base + p);
+
+       if (info->fbops->fb_sync)
+               info->fbops->fb_sync(info);
+
+       /* If transfer size > threshold and both src/dst
+       addresses are aligned, use DMA */
+       if (count >= 4096 &&
+           ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
+               /* Odd address = can't DMA. Align */
+               if ((unsigned long)dst & 3) {
+                       lead = 4 - ((unsigned long)dst & 3);
+                       if (copy_from_user(dst, buf, lead))
+                               return -EFAULT;
+                       buf += lead;
+                       dst += lead;
+               }
+               /* DMA resolution is 32 bits */
+               if ((count - lead) & 3)
+                       tail = (count - lead) & 3;
+               /* DMA the data */
+               dma_size = count - lead - tail;
+               dma_err = ivtvfb_prep_dec_dma_to_device(itv,
+                      p + lead + dma_offset, (void __user *)buf, dma_size);
+               if (dma_err)
+                       return dma_err;
+               dst += dma_size;
+               buf += dma_size;
+               /* Copy any leftover data */
+               if (tail && copy_from_user(dst, buf, tail))
+                       return -EFAULT;
+       } else if (copy_from_user(dst, buf, count)) {
+               return -EFAULT;
+       }
+
+       if  (!err)
+               *ppos += count;
+
+       return (err) ? err : count;
+}
+
+static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+       DEFINE_WAIT(wait);
+       struct ivtv *itv = (struct ivtv *)info->par;
+       int rc = 0;
+
+       switch (cmd) {
+               case FBIOGET_VBLANK: {
+                       struct fb_vblank vblank;
+                       u32 trace;
+
+                       memset(&vblank, 0, sizeof(struct fb_vblank));
+
+                       vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
+                                       FB_VBLANK_HAVE_VSYNC;
+                       trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
+                       if (itv->is_out_50hz && trace > 312)
+                               trace -= 312;
+                       else if (itv->is_out_60hz && trace > 262)
+                               trace -= 262;
+                       if (trace == 1)
+                               vblank.flags |= FB_VBLANK_VSYNCING;
+                       vblank.count = itv->last_vsync_field;
+                       vblank.vcount = trace;
+                       vblank.hcount = 0;
+                       if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
+                               return -EFAULT;
+                       return 0;
+               }
+
+               case FBIO_WAITFORVSYNC:
+                       prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
+                       if (!schedule_timeout(msecs_to_jiffies(50)))
+                               rc = -ETIMEDOUT;
+                       finish_wait(&itv->vsync_waitq, &wait);
+                       return rc;
+
+               case IVTVFB_IOC_DMA_FRAME: {
+                       struct ivtvfb_dma_frame args;
+
+                       IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
+                       if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
+                               return -EFAULT;
+
+                       return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
+               }
+
+               default:
+                       IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
+                       return -EINVAL;
+       }
+       return 0;
+}
+
+/* Framebuffer device handling */
+
+static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
+{
+       struct osd_info *oi = itv->osd_info;
+       struct ivtv_osd_coords ivtv_osd;
+       struct v4l2_rect ivtv_window;
+       int osd_mode = -1;
+
+       IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
+
+       /* Select color space */
+       if (var->nonstd) /* YUV */
+               write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
+       else /* RGB  */
+               write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
+
+       /* Set the color mode */
+       switch (var->bits_per_pixel) {
+               case 8:
+                       osd_mode = IVTV_OSD_BPP_8;
+                       break;
+               case 32:
+                       osd_mode = IVTV_OSD_BPP_32;
+                       break;
+               case 16:
+                       switch (var->green.length) {
+                       case 4:
+                               osd_mode = IVTV_OSD_BPP_16_444;
+                               break;
+                       case 5:
+                               osd_mode = IVTV_OSD_BPP_16_555;
+                               break;
+                       case 6:
+                               osd_mode = IVTV_OSD_BPP_16_565;
+                               break;
+                       default:
+                               IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
+                       }
+                       break;
+               default:
+                       IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
+       }
+
+       /* Set video mode. Although rare, the display can become scrambled even
+          if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
+       if (osd_mode != -1) {
+               ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
+               ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
+       }
+
+       oi->bits_per_pixel = var->bits_per_pixel;
+       oi->bytes_per_pixel = var->bits_per_pixel / 8;
+
+       /* Set the flicker filter */
+       switch (var->vmode & FB_VMODE_MASK) {
+               case FB_VMODE_NONINTERLACED: /* Filter on */
+                       ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
+                       break;
+               case FB_VMODE_INTERLACED: /* Filter off */
+                       ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
+                       break;
+               default:
+                       IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
+       }
+
+       /* Read the current osd info */
+       ivtvfb_get_osd_coords(itv, &ivtv_osd);
+
+       /* Now set the OSD to the size we want */
+       ivtv_osd.pixel_stride = var->xres_virtual;
+       ivtv_osd.lines = var->yres_virtual;
+       ivtv_osd.x = 0;
+       ivtv_osd.y = 0;
+       ivtvfb_set_osd_coords(itv, &ivtv_osd);
+
+       /* Can't seem to find the right API combo for this.
+          Use another function which does what we need through direct register access. */
+       ivtv_window.width = var->xres;
+       ivtv_window.height = var->yres;
+
+       /* Minimum margin cannot be 0, as X won't allow such a mode */
+       if (!var->upper_margin)
+               var->upper_margin++;
+       if (!var->left_margin)
+               var->left_margin++;
+       ivtv_window.top = var->upper_margin - 1;
+       ivtv_window.left = var->left_margin - 1;
+
+       ivtvfb_set_display_window(itv, &ivtv_window);
+
+       /* Pass screen size back to yuv handler */
+       itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
+       itv->yuv_info.osd_full_h = ivtv_osd.lines;
+
+       /* Force update of yuv registers */
+       itv->yuv_info.yuv_forced_update = 1;
+
+       /* Keep a copy of these settings */
+       memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
+
+       IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
+                     var->xres, var->yres,
+                     var->xres_virtual, var->yres_virtual,
+                     var->bits_per_pixel);
+
+       IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
+                     var->left_margin, var->upper_margin);
+
+       IVTVFB_DEBUG_INFO("Display filter: %s\n",
+                       (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
+       IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
+
+       return 0;
+}
+
+static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
+{
+       struct osd_info *oi = itv->osd_info;
+
+       IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
+       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+       strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
+       fix->smem_start = oi->video_pbase;
+       fix->smem_len = oi->video_buffer_size;
+       fix->type = FB_TYPE_PACKED_PIXELS;
+       fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+       fix->xpanstep = 1;
+       fix->ypanstep = 1;
+       fix->ywrapstep = 0;
+       fix->line_length = oi->display_byte_stride;
+       fix->accel = FB_ACCEL_NONE;
+       return 0;
+}
+
+/* Check the requested display mode, returning -EINVAL if we can't
+   handle it. */
+
+static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
+{
+       struct osd_info *oi = itv->osd_info;
+       int osd_height_limit;
+       u32 pixclock, hlimit, vlimit;
+
+       IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
+
+       /* Set base references for mode calcs. */
+       if (itv->is_out_50hz) {
+               pixclock = 84316;
+               hlimit = 776;
+               vlimit = 591;
+               osd_height_limit = 576;
+       }
+       else {
+               pixclock = 83926;
+               hlimit = 776;
+               vlimit = 495;
+               osd_height_limit = 480;
+       }
+
+       if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
+               var->transp.offset = 24;
+               var->transp.length = 8;
+               var->red.offset = 16;
+               var->red.length = 8;
+               var->green.offset = 8;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+       }
+       else if (var->bits_per_pixel == 16) {
+               /* To find out the true mode, check green length */
+               switch (var->green.length) {
+                       case 4:
+                               var->red.offset = 8;
+                               var->red.length = 4;
+                               var->green.offset = 4;
+                               var->green.length = 4;
+                               var->blue.offset = 0;
+                               var->blue.length = 4;
+                               var->transp.offset = 12;
+                               var->transp.length = 1;
+                               break;
+                       case 5:
+                               var->red.offset = 10;
+                               var->red.length = 5;
+                               var->green.offset = 5;
+                               var->green.length = 5;
+                               var->blue.offset = 0;
+                               var->blue.length = 5;
+                               var->transp.offset = 15;
+                               var->transp.length = 1;
+                               break;
+                       default:
+                               var->red.offset = 11;
+                               var->red.length = 5;
+                               var->green.offset = 5;
+                               var->green.length = 6;
+                               var->blue.offset = 0;
+                               var->blue.length = 5;
+                               var->transp.offset = 0;
+                               var->transp.length = 0;
+                               break;
+               }
+       }
+       else {
+               IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
+               return -EINVAL;
+       }
+
+       /* Check the resolution */
+       if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
+               IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
+                               var->xres, var->yres);
+               return -EINVAL;
+       }
+
+       /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
+       if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
+           var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
+           var->xres_virtual < var->xres ||
+           var->yres_virtual < var->yres) {
+               IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
+                       var->xres_virtual, var->yres_virtual);
+               return -EINVAL;
+       }
+
+       /* Some extra checks if in 8 bit mode */
+       if (var->bits_per_pixel == 8) {
+               /* Width must be a multiple of 4 */
+               if (var->xres & 3) {
+                       IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
+                       return -EINVAL;
+               }
+               if (var->xres_virtual & 3) {
+                       IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
+                       return -EINVAL;
+               }
+       }
+       else if (var->bits_per_pixel == 16) {
+               /* Width must be a multiple of 2 */
+               if (var->xres & 1) {
+                       IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
+                       return -EINVAL;
+               }
+               if (var->xres_virtual & 1) {
+                       IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
+                       return -EINVAL;
+               }
+       }
+
+       /* Now check the offsets */
+       if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
+               IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
+                       var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
+               return -EINVAL;
+       }
+
+       /* Check pixel format */
+       if (var->nonstd > 1) {
+               IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
+               return -EINVAL;
+       }
+
+       /* Check video mode */
+       if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
+               ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
+               IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
+               return -EINVAL;
+       }
+
+       /* Check the left & upper margins
+          If the margins are too large, just center the screen
+          (enforcing margins causes too many problems) */
+
+       if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
+               var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
+
+       if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
+               var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
+                       var->yres) / 2);
+
+       /* Maintain overall 'size' for a constant refresh rate */
+       var->right_margin = hlimit - var->left_margin - var->xres;
+       var->lower_margin = vlimit - var->upper_margin - var->yres;
+
+       /* Fixed sync times */
+       var->hsync_len = 24;
+       var->vsync_len = 2;
+
+       /* Non-interlaced / interlaced mode is used to switch the OSD filter
+          on or off. Adjust the clock timings to maintain a constant
+          vertical refresh rate. */
+       if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+               var->pixclock = pixclock / 2;
+       else
+               var->pixclock = pixclock;
+
+       itv->osd_rect.width = var->xres;
+       itv->osd_rect.height = var->yres;
+
+       IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
+                     var->xres, var->yres,
+                     var->xres_virtual, var->yres_virtual,
+                     var->bits_per_pixel);
+
+       IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
+                     var->left_margin, var->upper_margin);
+
+       IVTVFB_DEBUG_INFO("Display filter: %s\n",
+                       (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
+       IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
+       return 0;
+}
+
+static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       struct ivtv *itv = (struct ivtv *) info->par;
+       IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
+       return _ivtvfb_check_var(var, itv);
+}
+
+static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       u32 osd_pan_index;
+       struct ivtv *itv = (struct ivtv *) info->par;
+
+       if (var->yoffset + info->var.yres > info->var.yres_virtual ||
+           var->xoffset + info->var.xres > info->var.xres_virtual)
+               return -EINVAL;
+
+       osd_pan_index = var->yoffset * info->fix.line_length
+                     + var->xoffset * info->var.bits_per_pixel / 8;
+       write_reg(osd_pan_index, 0x02A0C);
+
+       /* Pass this info back the yuv handler */
+       itv->yuv_info.osd_x_pan = var->xoffset;
+       itv->yuv_info.osd_y_pan = var->yoffset;
+       /* Force update of yuv registers */
+       itv->yuv_info.yuv_forced_update = 1;
+       /* Remember this value */
+       itv->osd_info->pan_cur = osd_pan_index;
+       return 0;
+}
+
+static int ivtvfb_set_par(struct fb_info *info)
+{
+       int rc = 0;
+       struct ivtv *itv = (struct ivtv *) info->par;
+
+       IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
+
+       rc = ivtvfb_set_var(itv, &info->var);
+       ivtvfb_pan_display(&info->var, info);
+       ivtvfb_get_fix(itv, &info->fix);
+       ivtv_firmware_check(itv, "ivtvfb_set_par");
+       return rc;
+}
+
+static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                               unsigned blue, unsigned transp,
+                               struct fb_info *info)
+{
+       u32 color, *palette;
+       struct ivtv *itv = (struct ivtv *)info->par;
+
+       if (regno >= info->cmap.len)
+               return -EINVAL;
+
+       color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+       if (info->var.bits_per_pixel <= 8) {
+               write_reg(regno, 0x02a30);
+               write_reg(color, 0x02a34);
+               itv->osd_info->palette_cur[regno] = color;
+               return 0;
+       }
+       if (regno >= 16)
+               return -EINVAL;
+
+       palette = info->pseudo_palette;
+       if (info->var.bits_per_pixel == 16) {
+               switch (info->var.green.length) {
+                       case 4:
+                               color = ((red & 0xf000) >> 4) |
+                                       ((green & 0xf000) >> 8) |
+                                       ((blue & 0xf000) >> 12);
+                               break;
+                       case 5:
+                               color = ((red & 0xf800) >> 1) |
+                                       ((green & 0xf800) >> 6) |
+                                       ((blue & 0xf800) >> 11);
+                               break;
+                       case 6:
+                               color = (red & 0xf800 ) |
+                                       ((green & 0xfc00) >> 5) |
+                                       ((blue & 0xf800) >> 11);
+                               break;
+               }
+       }
+       palette[regno] = color;
+       return 0;
+}
+
+/* We don't really support blanking. All this does is enable or
+   disable the OSD. */
+static int ivtvfb_blank(int blank_mode, struct fb_info *info)
+{
+       struct ivtv *itv = (struct ivtv *)info->par;
+
+       IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
+       switch (blank_mode) {
+       case FB_BLANK_UNBLANK:
+               ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
+               break;
+       case FB_BLANK_NORMAL:
+       case FB_BLANK_HSYNC_SUSPEND:
+       case FB_BLANK_VSYNC_SUSPEND:
+               ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
+               break;
+       case FB_BLANK_POWERDOWN:
+               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
+               ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+               break;
+       }
+       itv->osd_info->blank_cur = blank_mode;
+       return 0;
+}
+
+static struct fb_ops ivtvfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_write       = ivtvfb_write,
+       .fb_check_var   = ivtvfb_check_var,
+       .fb_set_par     = ivtvfb_set_par,
+       .fb_setcolreg   = ivtvfb_setcolreg,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_cursor      = NULL,
+       .fb_ioctl       = ivtvfb_ioctl,
+       .fb_pan_display = ivtvfb_pan_display,
+       .fb_blank       = ivtvfb_blank,
+};
+
+/* Restore hardware after firmware restart */
+static void ivtvfb_restore(struct ivtv *itv)
+{
+       struct osd_info *oi = itv->osd_info;
+       int i;
+
+       ivtvfb_set_var(itv, &oi->fbvar_cur);
+       ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
+       for (i = 0; i < 256; i++) {
+               write_reg(i, 0x02a30);
+               write_reg(oi->palette_cur[i], 0x02a34);
+       }
+       write_reg(oi->pan_cur, 0x02a0c);
+}
+
+/* Initialization */
+
+
+/* Setup our initial video mode */
+static int ivtvfb_init_vidmode(struct ivtv *itv)
+{
+       struct osd_info *oi = itv->osd_info;
+       struct v4l2_rect start_window;
+       int max_height;
+
+       /* Color mode */
+
+       if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
+               osd_depth = 8;
+       oi->bits_per_pixel = osd_depth;
+       oi->bytes_per_pixel = oi->bits_per_pixel / 8;
+
+       /* Horizontal size & position */
+
+       if (osd_xres > 720)
+               osd_xres = 720;
+
+       /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
+       if (osd_depth == 8)
+               osd_xres &= ~3;
+       else if (osd_depth == 16)
+               osd_xres &= ~1;
+
+       start_window.width = osd_xres ? osd_xres : 640;
+
+       /* Check horizontal start (osd_left). */
+       if (osd_left && osd_left + start_window.width > 721) {
+               IVTVFB_ERR("Invalid osd_left - assuming default\n");
+               osd_left = 0;
+       }
+
+       /* Hardware coords start at 0, user coords start at 1. */
+       osd_left--;
+
+       start_window.left = osd_left >= 0 ?
+                osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
+
+       oi->display_byte_stride =
+                       start_window.width * oi->bytes_per_pixel;
+
+       /* Vertical size & position */
+
+       max_height = itv->is_out_50hz ? 576 : 480;
+
+       if (osd_yres > max_height)
+               osd_yres = max_height;
+
+       start_window.height = osd_yres ?
+               osd_yres : itv->is_out_50hz ? 480 : 400;
+
+       /* Check vertical start (osd_upper). */
+       if (osd_upper + start_window.height > max_height + 1) {
+               IVTVFB_ERR("Invalid osd_upper - assuming default\n");
+               osd_upper = 0;
+       }
+
+       /* Hardware coords start at 0, user coords start at 1. */
+       osd_upper--;
+
+       start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
+
+       oi->display_width = start_window.width;
+       oi->display_height = start_window.height;
+
+       /* Generate a valid fb_var_screeninfo */
+
+       oi->ivtvfb_defined.xres = oi->display_width;
+       oi->ivtvfb_defined.yres = oi->display_height;
+       oi->ivtvfb_defined.xres_virtual = oi->display_width;
+       oi->ivtvfb_defined.yres_virtual = oi->display_height;
+       oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
+       oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
+       oi->ivtvfb_defined.left_margin = start_window.left + 1;
+       oi->ivtvfb_defined.upper_margin = start_window.top + 1;
+       oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
+       oi->ivtvfb_defined.nonstd = 0;
+
+       /* We've filled in the most data, let the usual mode check
+          routine fill in the rest. */
+       _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
+
+       /* Generate valid fb_fix_screeninfo */
+
+       ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
+
+       /* Generate valid fb_info */
+
+       oi->ivtvfb_info.node = -1;
+       oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
+       oi->ivtvfb_info.fbops = &ivtvfb_ops;
+       oi->ivtvfb_info.par = itv;
+       oi->ivtvfb_info.var = oi->ivtvfb_defined;
+       oi->ivtvfb_info.fix = oi->ivtvfb_fix;
+       oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
+       oi->ivtvfb_info.fbops = &ivtvfb_ops;
+
+       /* Supply some monitor specs. Bogus values will do for now */
+       oi->ivtvfb_info.monspecs.hfmin = 8000;
+       oi->ivtvfb_info.monspecs.hfmax = 70000;
+       oi->ivtvfb_info.monspecs.vfmin = 10;
+       oi->ivtvfb_info.monspecs.vfmax = 100;
+
+       /* Allocate color map */
+       if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
+               IVTVFB_ERR("abort, unable to alloc cmap\n");
+               return -ENOMEM;
+       }
+
+       /* Allocate the pseudo palette */
+       oi->ivtvfb_info.pseudo_palette =
+               kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
+
+       if (!oi->ivtvfb_info.pseudo_palette) {
+               IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
+
+static int ivtvfb_init_io(struct ivtv *itv)
+{
+       struct osd_info *oi = itv->osd_info;
+
+       mutex_lock(&itv->serialize_lock);
+       if (ivtv_init_on_first_open(itv)) {
+               mutex_unlock(&itv->serialize_lock);
+               IVTVFB_ERR("Failed to initialize ivtv\n");
+               return -ENXIO;
+       }
+       mutex_unlock(&itv->serialize_lock);
+
+       if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
+                                       &oi->video_buffer_size) < 0) {
+               IVTVFB_ERR("Firmware failed to respond\n");
+               return -EIO;
+       }
+
+       /* The osd buffer size depends on the number of video buffers allocated
+          on the PVR350 itself. For now we'll hardcode the smallest osd buffer
+          size to prevent any overlap. */
+       oi->video_buffer_size = 1704960;
+
+       oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
+       oi->video_vbase = itv->dec_mem + oi->video_rbase;
+
+       if (!oi->video_vbase) {
+               IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
+                    oi->video_buffer_size, oi->video_pbase);
+               return -EIO;
+       }
+
+       IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+                       oi->video_pbase, oi->video_vbase,
+                       oi->video_buffer_size / 1024);
+
+#ifdef CONFIG_MTRR
+       {
+               /* Find the largest power of two that maps the whole buffer */
+               int size_shift = 31;
+
+               while (!(oi->video_buffer_size & (1 << size_shift))) {
+                       size_shift--;
+               }
+               size_shift++;
+               oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
+               oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
+               oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
+               oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
+               if (mtrr_add(oi->fb_start_aligned_physaddr,
+                       oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
+                            MTRR_TYPE_WRCOMB, 1) < 0) {
+                       IVTVFB_INFO("disabled mttr\n");
+                       oi->fb_start_aligned_physaddr = 0;
+                       oi->fb_end_aligned_physaddr = 0;
+               }
+       }
+#endif
+
+       /* Blank the entire osd. */
+       memset_io(oi->video_vbase, 0, oi->video_buffer_size);
+
+       return 0;
+}
+
+/* Release any memory we've grabbed & remove mtrr entry */
+static void ivtvfb_release_buffers (struct ivtv *itv)
+{
+       struct osd_info *oi = itv->osd_info;
+
+       /* Release cmap */
+       if (oi->ivtvfb_info.cmap.len)
+               fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
+
+       /* Release pseudo palette */
+       if (oi->ivtvfb_info.pseudo_palette)
+               kfree(oi->ivtvfb_info.pseudo_palette);
+
+#ifdef CONFIG_MTRR
+       if (oi->fb_end_aligned_physaddr) {
+               mtrr_del(-1, oi->fb_start_aligned_physaddr,
+                       oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
+       }
+#endif
+
+       kfree(oi);
+       itv->osd_info = NULL;
+}
+
+/* Initialize the specified card */
+
+static int ivtvfb_init_card(struct ivtv *itv)
+{
+       int rc;
+
+       if (itv->osd_info) {
+               IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
+               return -EBUSY;
+       }
+
+       itv->osd_info = kzalloc(sizeof(struct osd_info),
+                                       GFP_ATOMIC|__GFP_NOWARN);
+       if (itv->osd_info == NULL) {
+               IVTVFB_ERR("Failed to allocate memory for osd_info\n");
+               return -ENOMEM;
+       }
+
+       /* Find & setup the OSD buffer */
+       rc = ivtvfb_init_io(itv);
+       if (rc) {
+               ivtvfb_release_buffers(itv);
+               return rc;
+       }
+
+       /* Set the startup video mode information */
+       if ((rc = ivtvfb_init_vidmode(itv))) {
+               ivtvfb_release_buffers(itv);
+               return rc;
+       }
+
+       /* Register the framebuffer */
+       if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
+               ivtvfb_release_buffers(itv);
+               return -EINVAL;
+       }
+
+       itv->osd_video_pbase = itv->osd_info->video_pbase;
+
+       /* Set the card to the requested mode */
+       ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
+
+       /* Set color 0 to black */
+       write_reg(0, 0x02a30);
+       write_reg(0, 0x02a34);
+
+       /* Enable the osd */
+       ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
+
+       /* Enable restart */
+       itv->ivtvfb_restore = ivtvfb_restore;
+
+       /* Allocate DMA */
+       ivtv_udma_alloc(itv);
+       return 0;
+
+}
+
+static int __init ivtvfb_callback_init(struct device *dev, void *p)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+       struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
+
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+               if (ivtvfb_init_card(itv) == 0) {
+                       IVTVFB_INFO("Framebuffer registered on %s\n",
+                                       itv->v4l2_dev.name);
+                       (*(int *)p)++;
+               }
+       }
+       return 0;
+}
+
+static int ivtvfb_callback_cleanup(struct device *dev, void *p)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+       struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
+       struct osd_info *oi = itv->osd_info;
+
+       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+               if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
+                       IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
+                                      itv->instance);
+                       return 0;
+               }
+               IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
+               itv->ivtvfb_restore = NULL;
+               ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
+               ivtvfb_release_buffers(itv);
+               itv->osd_video_pbase = 0;
+       }
+       return 0;
+}
+
+static int __init ivtvfb_init(void)
+{
+       struct device_driver *drv;
+       int registered = 0;
+       int err;
+
+       if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
+               printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
+                    IVTV_MAX_CARDS - 1);
+               return -EINVAL;
+       }
+
+       drv = driver_find("ivtv", &pci_bus_type);
+       err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
+       (void)err;      /* suppress compiler warning */
+       if (!registered) {
+               printk(KERN_ERR "ivtvfb:  no cards found\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void ivtvfb_cleanup(void)
+{
+       struct device_driver *drv;
+       int err;
+
+       printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");
+
+       drv = driver_find("ivtv", &pci_bus_type);
+       err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
+       (void)err;      /* suppress compiler warning */
+}
+
+module_init(ivtvfb_init);
+module_exit(ivtvfb_cleanup);
diff --git a/drivers/media/pci/saa7134/Kconfig b/drivers/media/pci/saa7134/Kconfig
new file mode 100644 (file)
index 0000000..39fc018
--- /dev/null
@@ -0,0 +1,64 @@
+config VIDEO_SAA7134
+       tristate "Philips SAA7134 support"
+       depends on VIDEO_DEV && PCI && I2C
+       select VIDEOBUF_DMA_SG
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select CRC32
+       select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
+       ---help---
+         This is a video4linux driver for Philips SAA713x based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7134.
+
+config VIDEO_SAA7134_ALSA
+       tristate "Philips SAA7134 DMA audio support"
+       depends on VIDEO_SAA7134 && SND
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio in
+         Philips SAA713x based TV cards using ALSA
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7134-alsa.
+
+config VIDEO_SAA7134_RC
+       bool "Philips SAA7134 Remote Controller support"
+       depends on RC_CORE
+       depends on VIDEO_SAA7134
+       depends on !(RC_CORE=m && VIDEO_SAA7134=y)
+       default y
+       ---help---
+         Enables Remote Controller support on saa7134 driver.
+
+config VIDEO_SAA7134_DVB
+       tristate "DVB/ATSC Support for saa7134 based TV cards"
+       depends on VIDEO_SAA7134 && DVB_CORE
+       select VIDEOBUF_DVB
+       select DVB_PLL if !DVB_FE_CUSTOMISE
+       select DVB_MT352 if !DVB_FE_CUSTOMISE
+       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+       select DVB_NXT200X if !DVB_FE_CUSTOMISE
+       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+       select DVB_TDA826X if !DVB_FE_CUSTOMISE
+       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
+       select DVB_ISL6405 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+       select DVB_ZL10036 if !DVB_FE_CUSTOMISE
+       select DVB_MT312 if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_ZL10039 if !DVB_FE_CUSTOMISE
+       ---help---
+         This adds support for DVB cards based on the
+         Philips saa7134 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7134-dvb.
diff --git a/drivers/media/pci/saa7134/Makefile b/drivers/media/pci/saa7134/Makefile
new file mode 100644 (file)
index 0000000..aba5008
--- /dev/null
@@ -0,0 +1,16 @@
+
+saa7134-y :=   saa7134-cards.o saa7134-core.o saa7134-i2c.o
+saa7134-y +=   saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
+saa7134-y +=   saa7134-video.o
+saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
+
+obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o
+
+obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
+
+obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
+
+ccflags-y += -I$(srctree)/drivers/media/video
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
new file mode 100644 (file)
index 0000000..f147b05
--- /dev/null
@@ -0,0 +1,1012 @@
+ /*
+    saa6752hs - i2c-driver for the saa6752hs by Philips
+
+    Copyright (C) 2004 Andrew de Quincey
+
+    AC-3 support:
+
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License vs 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 Mvss Ave, Cambridge, MA 02139, USA.
+  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
+#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
+#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
+#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
+#define MPEG_PID_MAX ((1 << 14) - 1)
+
+
+MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+enum saa6752hs_videoformat {
+       SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
+       SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
+       SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
+       SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
+       SAA6752HS_VF_UNKNOWN,
+};
+
+struct saa6752hs_mpeg_params {
+       /* transport streams */
+       __u16                           ts_pid_pmt;
+       __u16                           ts_pid_audio;
+       __u16                           ts_pid_video;
+       __u16                           ts_pid_pcr;
+
+       /* audio */
+       enum v4l2_mpeg_audio_encoding    au_encoding;
+       enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
+       enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
+
+       /* video */
+       enum v4l2_mpeg_video_aspect     vi_aspect;
+       enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
+       __u32                           vi_bitrate;
+       __u32                           vi_bitrate_peak;
+};
+
+static const struct v4l2_format v4l2_format_table[] =
+{
+       [SAA6752HS_VF_D1] =
+               { .fmt = { .pix = { .width = 720, .height = 576 }}},
+       [SAA6752HS_VF_2_3_D1] =
+               { .fmt = { .pix = { .width = 480, .height = 576 }}},
+       [SAA6752HS_VF_1_2_D1] =
+               { .fmt = { .pix = { .width = 352, .height = 576 }}},
+       [SAA6752HS_VF_SIF] =
+               { .fmt = { .pix = { .width = 352, .height = 288 }}},
+       [SAA6752HS_VF_UNKNOWN] =
+               { .fmt = { .pix = { .width = 0, .height = 0}}},
+};
+
+struct saa6752hs_state {
+       struct v4l2_subdev            sd;
+       int                           chip;
+       u32                           revision;
+       int                           has_ac3;
+       struct saa6752hs_mpeg_params  params;
+       enum saa6752hs_videoformat    video_format;
+       v4l2_std_id                   standard;
+};
+
+enum saa6752hs_command {
+       SAA6752HS_COMMAND_RESET = 0,
+       SAA6752HS_COMMAND_STOP = 1,
+       SAA6752HS_COMMAND_START = 2,
+       SAA6752HS_COMMAND_PAUSE = 3,
+       SAA6752HS_COMMAND_RECONFIGURE = 4,
+       SAA6752HS_COMMAND_SLEEP = 5,
+       SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
+
+       SAA6752HS_COMMAND_MAX
+};
+
+static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct saa6752hs_state, sd);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static u8 PAT[] = {
+       0xc2, /* i2c register */
+       0x00, /* table number for encoder */
+
+       0x47, /* sync */
+       0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
+       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+       0x00, /* PSI pointer to start of table */
+
+       0x00, /* tid(0) */
+       0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
+
+       0x00, 0x01, /* transport_stream_id(1) */
+
+       0xc1, /* version_number(0), current_next_indicator(1) */
+
+       0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+       0x00, 0x01, /* program_number(1) */
+
+       0xe0, 0x00, /* PMT PID */
+
+       0x00, 0x00, 0x00, 0x00 /* CRC32 */
+};
+
+static u8 PMT[] = {
+       0xc2, /* i2c register */
+       0x01, /* table number for encoder */
+
+       0x47, /* sync */
+       0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
+       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+       0x00, /* PSI pointer to start of table */
+
+       0x02, /* tid(2) */
+       0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
+
+       0x00, 0x01, /* program_number(1) */
+
+       0xc1, /* version_number(0), current_next_indicator(1) */
+
+       0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+       0xe0, 0x00, /* PCR_PID */
+
+       0xf0, 0x00, /* program_info_length(0) */
+
+       0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+       0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
+
+       0x00, 0x00, 0x00, 0x00 /* CRC32 */
+};
+
+static u8 PMT_AC3[] = {
+       0xc2, /* i2c register */
+       0x01, /* table number for encoder(1) */
+       0x47, /* sync */
+
+       0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
+       0x10, /* PMT PID (0x0010) */
+       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+       0x00, /* PSI pointer to start of table */
+
+       0x02, /* TID (2) */
+       0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
+
+       0x00, 0x01, /* program_number(1) */
+
+       0xc1, /* version_number(0), current_next_indicator(1) */
+
+       0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+       0xe1, 0x04, /* PCR_PID (0x0104) */
+
+       0xf0, 0x00, /* program_info_length(0) */
+
+       0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+       0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
+       0x6a, /* AC3 */
+       0x01, /* Descriptor_length(1) */
+       0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
+
+       0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
+};
+
+static struct saa6752hs_mpeg_params param_defaults =
+{
+       .ts_pid_pmt      = 16,
+       .ts_pid_video    = 260,
+       .ts_pid_audio    = 256,
+       .ts_pid_pcr      = 259,
+
+       .vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
+       .vi_bitrate      = 4000,
+       .vi_bitrate_peak = 6000,
+       .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+
+       .au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+       .au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+       .au_ac3_bitrate  = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6752hs_chip_command(struct i2c_client *client,
+                                 enum saa6752hs_command command)
+{
+       unsigned char buf[3];
+       unsigned long timeout;
+       int status = 0;
+
+       /* execute the command */
+       switch(command) {
+       case SAA6752HS_COMMAND_RESET:
+               buf[0] = 0x00;
+               break;
+
+       case SAA6752HS_COMMAND_STOP:
+               buf[0] = 0x03;
+               break;
+
+       case SAA6752HS_COMMAND_START:
+               buf[0] = 0x02;
+               break;
+
+       case SAA6752HS_COMMAND_PAUSE:
+               buf[0] = 0x04;
+               break;
+
+       case SAA6752HS_COMMAND_RECONFIGURE:
+               buf[0] = 0x05;
+               break;
+
+       case SAA6752HS_COMMAND_SLEEP:
+               buf[0] = 0x06;
+               break;
+
+       case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
+               buf[0] = 0x07;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* set it and wait for it to be so */
+       i2c_master_send(client, buf, 1);
+       timeout = jiffies + HZ * 3;
+       for (;;) {
+               /* get the current status */
+               buf[0] = 0x10;
+               i2c_master_send(client, buf, 1);
+               i2c_master_recv(client, buf, 1);
+
+               if (!(buf[0] & 0x20))
+                       break;
+               if (time_after(jiffies,timeout)) {
+                       status = -ETIMEDOUT;
+                       break;
+               }
+
+               msleep(10);
+       }
+
+       /* delay a bit to let encoder settle */
+       msleep(50);
+
+       return status;
+}
+
+
+static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
+{
+       u8 buf[2];
+
+       buf[0] = reg;
+       buf[1] = val;
+       i2c_master_send(client, buf, 2);
+}
+
+static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
+{
+       u8 buf[3];
+
+       buf[0] = reg;
+       buf[1] = val >> 8;
+       buf[2] = val & 0xff;
+       i2c_master_send(client, buf, 3);
+}
+
+static int saa6752hs_set_bitrate(struct i2c_client *client,
+                                struct saa6752hs_state *h)
+{
+       struct saa6752hs_mpeg_params *params = &h->params;
+       int tot_bitrate;
+       int is_384k;
+
+       /* set the bitrate mode */
+       set_reg8(client, 0x71,
+               params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+
+       /* set the video bitrate */
+       if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+               /* set the target bitrate */
+               set_reg16(client, 0x80, params->vi_bitrate);
+
+               /* set the max bitrate */
+               set_reg16(client, 0x81, params->vi_bitrate_peak);
+               tot_bitrate = params->vi_bitrate_peak;
+       } else {
+               /* set the target bitrate (no max bitrate for CBR) */
+               set_reg16(client, 0x81, params->vi_bitrate);
+               tot_bitrate = params->vi_bitrate;
+       }
+
+       /* set the audio encoding */
+       set_reg8(client, 0x93,
+                       params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
+
+       /* set the audio bitrate */
+       if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
+               is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
+       else
+               is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
+       set_reg8(client, 0x94, is_384k);
+       tot_bitrate += is_384k ? 384 : 256;
+
+       /* Note: the total max bitrate is determined by adding the video and audio
+          bitrates together and also adding an extra 768kbit/s to stay on the
+          safe side. If more control should be required, then an extra MPEG control
+          should be added. */
+       tot_bitrate += 768;
+       if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
+               tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
+
+       /* set the total bitrate */
+       set_reg16(client, 0xb1, tot_bitrate);
+       return 0;
+}
+
+
+static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
+               struct v4l2_ext_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_PMT:
+               ctrl->value = params->ts_pid_pmt;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+               ctrl->value = params->ts_pid_audio;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+               ctrl->value = params->ts_pid_video;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_PCR:
+               ctrl->value = params->ts_pid_pcr;
+               break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               ctrl->value = params->au_encoding;
+               break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               ctrl->value = params->au_l2_bitrate;
+               break;
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               if (!has_ac3)
+                       return -EINVAL;
+               ctrl->value = params->au_ac3_bitrate;
+               break;
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               ctrl->value = params->vi_aspect;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               ctrl->value = params->vi_bitrate * 1000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               ctrl->value = params->vi_bitrate_peak * 1000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               ctrl->value = params->vi_bitrate_mode;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
+               struct v4l2_ext_control *ctrl, int set)
+{
+       int old = 0, new;
+
+       new = ctrl->value;
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+               if (set && new != old)
+                       return -ERANGE;
+               new = old;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_PMT:
+               old = params->ts_pid_pmt;
+               if (set && new > MPEG_PID_MAX)
+                       return -ERANGE;
+               if (new > MPEG_PID_MAX)
+                       new = MPEG_PID_MAX;
+               params->ts_pid_pmt = new;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+               old = params->ts_pid_audio;
+               if (set && new > MPEG_PID_MAX)
+                       return -ERANGE;
+               if (new > MPEG_PID_MAX)
+                       new = MPEG_PID_MAX;
+               params->ts_pid_audio = new;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+               old = params->ts_pid_video;
+               if (set && new > MPEG_PID_MAX)
+                       return -ERANGE;
+               if (new > MPEG_PID_MAX)
+                       new = MPEG_PID_MAX;
+               params->ts_pid_video = new;
+               break;
+       case V4L2_CID_MPEG_STREAM_PID_PCR:
+               old = params->ts_pid_pcr;
+               if (set && new > MPEG_PID_MAX)
+                       return -ERANGE;
+               if (new > MPEG_PID_MAX)
+                       new = MPEG_PID_MAX;
+               params->ts_pid_pcr = new;
+               break;
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               old = params->au_encoding;
+               if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
+                   (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
+                       return -ERANGE;
+               params->au_encoding = new;
+               break;
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               old = params->au_l2_bitrate;
+               if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
+                          new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
+                       return -ERANGE;
+               if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
+                       new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
+               else
+                       new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
+               params->au_l2_bitrate = new;
+               break;
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               if (!has_ac3)
+                       return -EINVAL;
+               old = params->au_ac3_bitrate;
+               if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
+                          new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
+                       return -ERANGE;
+               if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
+                       new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
+               else
+                       new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
+               params->au_ac3_bitrate = new;
+               break;
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
+               if (set && new != old)
+                       return -ERANGE;
+               new = old;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+               if (set && new != old)
+                       return -ERANGE;
+               new = old;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               old = params->vi_aspect;
+               if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
+                          new != V4L2_MPEG_VIDEO_ASPECT_4x3)
+                       return -ERANGE;
+               if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
+                       new = V4L2_MPEG_VIDEO_ASPECT_4x3;
+               params->vi_aspect = new;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               old = params->vi_bitrate * 1000;
+               new = 1000 * (new / 1000);
+               if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                       return -ERANGE;
+               if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                       new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+               params->vi_bitrate = new / 1000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               old = params->vi_bitrate_peak * 1000;
+               new = 1000 * (new / 1000);
+               if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                       return -ERANGE;
+               if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+                       new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+               params->vi_bitrate_peak = new / 1000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               old = params->vi_bitrate_mode;
+               params->vi_bitrate_mode = new;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ctrl->value = new;
+       return 0;
+}
+
+
+static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
+{
+       struct saa6752hs_state *h = to_state(sd);
+       struct saa6752hs_mpeg_params *params = &h->params;
+       int err;
+
+       switch (qctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+                               h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+                                       V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+                               1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+                               V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               if (!h->has_ac3)
+                       return -EINVAL;
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
+                               V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
+       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
+                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_VIDEO_ASPECT_4x3,
+                               V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
+                               V4L2_MPEG_VIDEO_ASPECT_4x3);
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
+               if (err == 0 &&
+                   params->vi_bitrate_mode ==
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+                               V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
+                               V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               return v4l2_ctrl_query_fill(qctrl,
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+                               V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
+       case V4L2_CID_MPEG_STREAM_PID_PMT:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
+       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
+       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
+       case V4L2_CID_MPEG_STREAM_PID_PCR:
+               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
+
+       default:
+               break;
+       }
+       return -EINVAL;
+}
+
+static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
+{
+       static const u32 mpeg_audio_encoding[] = {
+               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       static const u32 mpeg_audio_ac3_encoding[] = {
+               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+               V4L2_MPEG_AUDIO_ENCODING_AC3,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       static u32 mpeg_audio_l2_bitrate[] = {
+               V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+               V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       static u32 mpeg_audio_ac3_bitrate[] = {
+               V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+               V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
+               V4L2_CTRL_MENU_IDS_END
+       };
+       struct saa6752hs_state *h = to_state(sd);
+       struct v4l2_queryctrl qctrl;
+       int err;
+
+       qctrl.id = qmenu->id;
+       err = saa6752hs_queryctrl(sd, &qctrl);
+       if (err)
+               return err;
+       switch (qmenu->id) {
+       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+               return v4l2_ctrl_query_menu_valid_items(qmenu,
+                               mpeg_audio_l2_bitrate);
+       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+               if (!h->has_ac3)
+                       return -EINVAL;
+               return v4l2_ctrl_query_menu_valid_items(qmenu,
+                               mpeg_audio_ac3_bitrate);
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               return v4l2_ctrl_query_menu_valid_items(qmenu,
+                       h->has_ac3 ? mpeg_audio_ac3_encoding :
+                               mpeg_audio_encoding);
+       }
+       return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
+}
+
+static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
+{
+       unsigned char buf[9], buf2[4];
+       struct saa6752hs_state *h = to_state(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       unsigned size;
+       u32 crc;
+       unsigned char localPAT[256];
+       unsigned char localPMT[256];
+
+       /* Set video format - must be done first as it resets other settings */
+       set_reg8(client, 0x41, h->video_format);
+
+       /* Set number of lines in input signal */
+       set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
+
+       /* set bitrate */
+       saa6752hs_set_bitrate(client, h);
+
+       /* Set GOP structure {3, 13} */
+       set_reg16(client, 0x72, 0x030d);
+
+       /* Set minimum Q-scale {4} */
+       set_reg8(client, 0x82, 0x04);
+
+       /* Set maximum Q-scale {12} */
+       set_reg8(client, 0x83, 0x0c);
+
+       /* Set Output Protocol */
+       set_reg8(client, 0xd0, 0x81);
+
+       /* Set video output stream format {TS} */
+       set_reg8(client, 0xb0, 0x05);
+
+       /* Set leading null byte for TS */
+       set_reg16(client, 0xf6, leading_null_bytes);
+
+       /* compute PAT */
+       memcpy(localPAT, PAT, sizeof(PAT));
+       localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+       localPAT[18] = h->params.ts_pid_pmt & 0xff;
+       crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
+       localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+       localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+       localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+       localPAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+       /* compute PMT */
+       if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+               size = sizeof(PMT_AC3);
+               memcpy(localPMT, PMT_AC3, size);
+       } else {
+               size = sizeof(PMT);
+               memcpy(localPMT, PMT, size);
+       }
+       localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+       localPMT[4] = h->params.ts_pid_pmt & 0xff;
+       localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
+       localPMT[16] = h->params.ts_pid_pcr & 0xFF;
+       localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
+       localPMT[21] = h->params.ts_pid_video & 0xFF;
+       localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
+       localPMT[26] = h->params.ts_pid_audio & 0xFF;
+       crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
+       localPMT[size - 4] = (crc >> 24) & 0xFF;
+       localPMT[size - 3] = (crc >> 16) & 0xFF;
+       localPMT[size - 2] = (crc >> 8) & 0xFF;
+       localPMT[size - 1] = crc & 0xFF;
+
+       /* Set Audio PID */
+       set_reg16(client, 0xc1, h->params.ts_pid_audio);
+
+       /* Set Video PID */
+       set_reg16(client, 0xc0, h->params.ts_pid_video);
+
+       /* Set PCR PID */
+       set_reg16(client, 0xc4, h->params.ts_pid_pcr);
+
+       /* Send SI tables */
+       i2c_master_send(client, localPAT, sizeof(PAT));
+       i2c_master_send(client, localPMT, size);
+
+       /* mute then unmute audio. This removes buzzing artefacts */
+       set_reg8(client, 0xa4, 1);
+       set_reg8(client, 0xa4, 0);
+
+       /* start it going */
+       saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
+
+       /* readout current state */
+       buf[0] = 0xE1;
+       buf[1] = 0xA7;
+       buf[2] = 0xFE;
+       buf[3] = 0x82;
+       buf[4] = 0xB0;
+       i2c_master_send(client, buf, 5);
+       i2c_master_recv(client, buf2, 4);
+
+       /* change aspect ratio */
+       buf[0] = 0xE0;
+       buf[1] = 0xA7;
+       buf[2] = 0xFE;
+       buf[3] = 0x82;
+       buf[4] = 0xB0;
+       buf[5] = buf2[0];
+       switch (h->params.vi_aspect) {
+       case V4L2_MPEG_VIDEO_ASPECT_16x9:
+               buf[6] = buf2[1] | 0x40;
+               break;
+       case V4L2_MPEG_VIDEO_ASPECT_4x3:
+       default:
+               buf[6] = buf2[1] & 0xBF;
+               break;
+       }
+       buf[7] = buf2[2];
+       buf[8] = buf2[3];
+       i2c_master_send(client, buf, 9);
+
+       return 0;
+}
+
+static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
+{
+       struct saa6752hs_state *h = to_state(sd);
+       struct saa6752hs_mpeg_params params;
+       int i;
+
+       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       params = h->params;
+       for (i = 0; i < ctrls->count; i++) {
+               int err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, set);
+
+               if (err) {
+                       ctrls->error_idx = i;
+                       return err;
+               }
+       }
+       if (set)
+               h->params = params;
+       return 0;
+}
+
+static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+       return saa6752hs_do_ext_ctrls(sd, ctrls, 1);
+}
+
+static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+       return saa6752hs_do_ext_ctrls(sd, ctrls, 0);
+}
+
+static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
+{
+       struct saa6752hs_state *h = to_state(sd);
+       int i;
+
+       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       for (i = 0; i < ctrls->count; i++) {
+               int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i);
+
+               if (err) {
+                       ctrls->error_idx = i;
+                       return err;
+               }
+       }
+       return 0;
+}
+
+static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+       struct saa6752hs_state *h = to_state(sd);
+
+       if (h->video_format == SAA6752HS_VF_UNKNOWN)
+               h->video_format = SAA6752HS_VF_D1;
+       f->width = v4l2_format_table[h->video_format].fmt.pix.width;
+       f->height = v4l2_format_table[h->video_format].fmt.pix.height;
+       f->code = V4L2_MBUS_FMT_FIXED;
+       f->field = V4L2_FIELD_INTERLACED;
+       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       return 0;
+}
+
+static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+       struct saa6752hs_state *h = to_state(sd);
+       int dist_352, dist_480, dist_720;
+
+       if (f->code != V4L2_MBUS_FMT_FIXED)
+               return -EINVAL;
+
+       /*
+         FIXME: translate and round width/height into EMPRESS
+         subsample type:
+
+         type   |   PAL   |  NTSC
+         ---------------------------
+         SIF    | 352x288 | 352x240
+         1/2 D1 | 352x576 | 352x480
+         2/3 D1 | 480x576 | 480x480
+         D1     | 720x576 | 720x480
+       */
+
+       dist_352 = abs(f->width - 352);
+       dist_480 = abs(f->width - 480);
+       dist_720 = abs(f->width - 720);
+       if (dist_720 < dist_480) {
+               f->width = 720;
+               f->height = 576;
+               h->video_format = SAA6752HS_VF_D1;
+       } else if (dist_480 < dist_352) {
+               f->width = 480;
+               f->height = 576;
+               h->video_format = SAA6752HS_VF_2_3_D1;
+       } else {
+               f->width = 352;
+               if (abs(f->height - 576) <
+                   abs(f->height - 288)) {
+                       f->height = 576;
+                       h->video_format = SAA6752HS_VF_1_2_D1;
+               } else {
+                       f->height = 288;
+                       h->video_format = SAA6752HS_VF_SIF;
+               }
+       }
+       f->field = V4L2_FIELD_INTERLACED;
+       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+       return 0;
+}
+
+static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+       struct saa6752hs_state *h = to_state(sd);
+
+       h->standard = std;
+       return 0;
+}
+
+static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct saa6752hs_state *h = to_state(sd);
+
+       return v4l2_chip_ident_i2c_client(client,
+                       chip, h->chip, h->revision);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
+       .g_chip_ident = saa6752hs_g_chip_ident,
+       .init = saa6752hs_init,
+       .queryctrl = saa6752hs_queryctrl,
+       .querymenu = saa6752hs_querymenu,
+       .g_ext_ctrls = saa6752hs_g_ext_ctrls,
+       .s_ext_ctrls = saa6752hs_s_ext_ctrls,
+       .try_ext_ctrls = saa6752hs_try_ext_ctrls,
+       .s_std = saa6752hs_s_std,
+};
+
+static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
+       .s_mbus_fmt = saa6752hs_s_mbus_fmt,
+       .g_mbus_fmt = saa6752hs_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_ops saa6752hs_ops = {
+       .core = &saa6752hs_core_ops,
+       .video = &saa6752hs_video_ops,
+};
+
+static int saa6752hs_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
+       struct v4l2_subdev *sd;
+       u8 addr = 0x13;
+       u8 data[12];
+
+       v4l_info(client, "chip found @ 0x%x (%s)\n",
+                       client->addr << 1, client->adapter->name);
+       if (h == NULL)
+               return -ENOMEM;
+       sd = &h->sd;
+       v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops);
+
+       i2c_master_send(client, &addr, 1);
+       i2c_master_recv(client, data, sizeof(data));
+       h->chip = V4L2_IDENT_SAA6752HS;
+       h->revision = (data[8] << 8) | data[9];
+       h->has_ac3 = 0;
+       if (h->revision == 0x0206) {
+               h->chip = V4L2_IDENT_SAA6752HS_AC3;
+               h->has_ac3 = 1;
+               v4l_info(client, "support AC-3\n");
+       }
+       h->params = param_defaults;
+       h->standard = 0; /* Assume 625 input lines */
+       return 0;
+}
+
+static int saa6752hs_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+       v4l2_device_unregister_subdev(sd);
+       kfree(to_state(sd));
+       return 0;
+}
+
+static const struct i2c_device_id saa6752hs_id[] = {
+       { "saa6752hs", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
+
+static struct i2c_driver saa6752hs_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "saa6752hs",
+       },
+       .probe          = saa6752hs_probe,
+       .remove         = saa6752hs_remove,
+       .id_table       = saa6752hs_id,
+};
+
+module_i2c_driver(saa6752hs_driver);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
new file mode 100644 (file)
index 0000000..10460fd
--- /dev/null
@@ -0,0 +1,1209 @@
+/*
+ *   SAA713x ALSA support for V4L
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, version 2
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <linux/interrupt.h>
+
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
+
+/*
+ * Configuration macros
+ */
+
+/* defaults */
+#define MIXER_ADDR_UNSELECTED  -1
+#define MIXER_ADDR_TVTUNER     0
+#define MIXER_ADDR_LINE1       1
+#define MIXER_ADDR_LINE2       2
+#define MIXER_ADDR_LAST                2
+
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(index, int, NULL, 0444);
+module_param_array(enable, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
+MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s).");
+
+#define dprintk(fmt, arg...)    if (debug) \
+       printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg)
+
+
+
+/*
+ * Main chip structure
+ */
+
+typedef struct snd_card_saa7134 {
+       struct snd_card *card;
+       spinlock_t mixer_lock;
+       int mixer_volume[MIXER_ADDR_LAST+1][2];
+       int capture_source_addr;
+       int capture_source[2];
+       struct snd_kcontrol *capture_ctl[MIXER_ADDR_LAST+1];
+       struct pci_dev *pci;
+       struct saa7134_dev *dev;
+
+       unsigned long iobase;
+       s16 irq;
+       u16 mute_was_on;
+
+       spinlock_t lock;
+} snd_card_saa7134_t;
+
+
+/*
+ * PCM structure
+ */
+
+typedef struct snd_card_saa7134_pcm {
+       struct saa7134_dev *dev;
+
+       spinlock_t lock;
+
+       struct snd_pcm_substream *substream;
+} snd_card_saa7134_pcm_t;
+
+static struct snd_card *snd_saa7134_cards[SNDRV_CARDS];
+
+
+/*
+ * saa7134 DMA audio stop
+ *
+ *   Called when the capture device is released or the buffer overflows
+ *
+ *   - Copied verbatim from saa7134-oss's dsp_dma_stop.
+ *
+ */
+
+static void saa7134_dma_stop(struct saa7134_dev *dev)
+{
+       dev->dmasound.dma_blk     = -1;
+       dev->dmasound.dma_running = 0;
+       saa7134_set_dmabits(dev);
+}
+
+/*
+ * saa7134 DMA audio start
+ *
+ *   Called when preparing the capture device for use
+ *
+ *   - Copied verbatim from saa7134-oss's dsp_dma_start.
+ *
+ */
+
+static void saa7134_dma_start(struct saa7134_dev *dev)
+{
+       dev->dmasound.dma_blk     = 0;
+       dev->dmasound.dma_running = 1;
+       saa7134_set_dmabits(dev);
+}
+
+/*
+ * saa7134 audio DMA IRQ handler
+ *
+ *   Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt
+ *   Handles shifting between the 2 buffers, manages the read counters,
+ *  and notifies ALSA when periods elapse
+ *
+ *   - Mostly copied from saa7134-oss's saa7134_irq_oss_done.
+ *
+ */
+
+static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
+                                 unsigned long status)
+{
+       int next_blk, reg = 0;
+
+       spin_lock(&dev->slock);
+       if (UNSET == dev->dmasound.dma_blk) {
+               dprintk("irq: recording stopped\n");
+               goto done;
+       }
+       if (0 != (status & 0x0f000000))
+               dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
+       if (0 == (status & 0x10000000)) {
+               /* odd */
+               if (0 == (dev->dmasound.dma_blk & 0x01))
+                       reg = SAA7134_RS_BA1(6);
+       } else {
+               /* even */
+               if (1 == (dev->dmasound.dma_blk & 0x01))
+                       reg = SAA7134_RS_BA2(6);
+       }
+       if (0 == reg) {
+               dprintk("irq: field oops [%s]\n",
+                       (status & 0x10000000) ? "even" : "odd");
+               goto done;
+       }
+
+       if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
+               dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
+                       dev->dmasound.bufsize, dev->dmasound.blocks);
+               spin_unlock(&dev->slock);
+               snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+               return;
+       }
+
+       /* next block addr */
+       next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
+       saa_writel(reg,next_blk * dev->dmasound.blksize);
+       if (debug > 2)
+               dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
+                       (status & 0x10000000) ? "even" : "odd ", next_blk,
+                       next_blk * dev->dmasound.blksize, dev->dmasound.blocks, dev->dmasound.blksize, dev->dmasound.read_count);
+
+       /* update status & wake waiting readers */
+       dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
+       dev->dmasound.read_count += dev->dmasound.blksize;
+
+       dev->dmasound.recording_on = reg;
+
+       if (dev->dmasound.read_count >= snd_pcm_lib_period_bytes(dev->dmasound.substream)) {
+               spin_unlock(&dev->slock);
+               snd_pcm_period_elapsed(dev->dmasound.substream);
+               spin_lock(&dev->slock);
+       }
+
+ done:
+       spin_unlock(&dev->slock);
+
+}
+
+/*
+ * IRQ request handler
+ *
+ *   Runs along with saa7134's IRQ handler, discards anything that isn't
+ *   DMA sound
+ *
+ */
+
+static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id)
+{
+       struct saa7134_dmasound *dmasound = dev_id;
+       struct saa7134_dev *dev = dmasound->priv_data;
+
+       unsigned long report, status;
+       int loop, handled = 0;
+
+       for (loop = 0; loop < 10; loop++) {
+               report = saa_readl(SAA7134_IRQ_REPORT);
+               status = saa_readl(SAA7134_IRQ_STATUS);
+
+               if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
+                       handled = 1;
+                       saa_writel(SAA7134_IRQ_REPORT,
+                                  SAA7134_IRQ_REPORT_DONE_RA3);
+                       saa7134_irq_alsa_done(dev, status);
+               } else {
+                       goto out;
+               }
+       }
+
+       if (loop == 10) {
+               dprintk("error! looping IRQ!");
+       }
+
+out:
+       return IRQ_RETVAL(handled);
+}
+
+/*
+ * ALSA capture trigger
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called whenever a capture is started or stopped. Must be defined,
+ *   but there's nothing we want to do here
+ *
+ */
+
+static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream,
+                                         int cmd)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+       struct saa7134_dev *dev=pcm->dev;
+       int err = 0;
+
+       spin_lock(&dev->slock);
+       if (cmd == SNDRV_PCM_TRIGGER_START) {
+               /* start dma */
+               saa7134_dma_start(dev);
+       } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+               /* stop dma */
+               saa7134_dma_stop(dev);
+       } else {
+               err = -EINVAL;
+       }
+       spin_unlock(&dev->slock);
+
+       return err;
+}
+
+/*
+ * DMA buffer initialization
+ *
+ *   Uses V4L functions to initialize the DMA. Shouldn't be necessary in
+ *  ALSA, but I was unable to use ALSA's own DMA, and had to force the
+ *  usage of V4L's
+ *
+ *   - Copied verbatim from saa7134-oss.
+ *
+ */
+
+static int dsp_buffer_init(struct saa7134_dev *dev)
+{
+       int err;
+
+       BUG_ON(!dev->dmasound.bufsize);
+
+       videobuf_dma_init(&dev->dmasound.dma);
+       err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
+                                      (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
+       if (0 != err)
+               return err;
+       return 0;
+}
+
+/*
+ * DMA buffer release
+ *
+ *   Called after closing the device, during snd_card_saa7134_capture_close
+ *
+ */
+
+static int dsp_buffer_free(struct saa7134_dev *dev)
+{
+       BUG_ON(!dev->dmasound.blksize);
+
+       videobuf_dma_free(&dev->dmasound.dma);
+
+       dev->dmasound.blocks  = 0;
+       dev->dmasound.blksize = 0;
+       dev->dmasound.bufsize = 0;
+
+       return 0;
+}
+
+/*
+ * Setting the capture source and updating the ALSA controls
+ */
+static int snd_saa7134_capsrc_set(struct snd_kcontrol *kcontrol,
+                                 int left, int right, bool force_notify)
+{
+       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+       int change = 0, addr = kcontrol->private_value;
+       int active, old_addr;
+       u32 anabar, xbarin;
+       int analog_io, rate;
+       struct saa7134_dev *dev;
+
+       dev = chip->dev;
+
+       spin_lock_irq(&chip->mixer_lock);
+
+       active = left != 0 || right != 0;
+       old_addr = chip->capture_source_addr;
+
+       /* The active capture source cannot be deactivated */
+       if (active) {
+               change = old_addr != addr ||
+                        chip->capture_source[0] != left ||
+                        chip->capture_source[1] != right;
+
+               chip->capture_source[0] = left;
+               chip->capture_source[1] = right;
+               chip->capture_source_addr = addr;
+               dev->dmasound.input = addr;
+       }
+       spin_unlock_irq(&chip->mixer_lock);
+
+       if (change) {
+               switch (dev->pci->device) {
+
+               case PCI_DEVICE_ID_PHILIPS_SAA7134:
+                       switch (addr) {
+                       case MIXER_ADDR_TVTUNER:
+                               saa_andorb(SAA7134_AUDIO_FORMAT_CTRL,
+                                          0xc0, 0xc0);
+                               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,
+                                          0x03, 0x00);
+                               break;
+                       case MIXER_ADDR_LINE1:
+                       case MIXER_ADDR_LINE2:
+                               analog_io = (MIXER_ADDR_LINE1 == addr) ?
+                                            0x00 : 0x08;
+                               rate = (32000 == dev->dmasound.rate) ?
+                                       0x01 : 0x03;
+                               saa_andorb(SAA7134_ANALOG_IO_SELECT,
+                                          0x08, analog_io);
+                               saa_andorb(SAA7134_AUDIO_FORMAT_CTRL,
+                                          0xc0, 0x80);
+                               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,
+                                          0x03, rate);
+                               break;
+                       }
+
+                       break;
+               case PCI_DEVICE_ID_PHILIPS_SAA7133:
+               case PCI_DEVICE_ID_PHILIPS_SAA7135:
+                       xbarin = 0x03; /* adc */
+                       anabar = 0;
+                       switch (addr) {
+                       case MIXER_ADDR_TVTUNER:
+                               xbarin = 0; /* Demodulator */
+                               anabar = 2; /* DACs */
+                               break;
+                       case MIXER_ADDR_LINE1:
+                               anabar = 0;  /* aux1, aux1 */
+                               break;
+                       case MIXER_ADDR_LINE2:
+                               anabar = 9;  /* aux2, aux2 */
+                               break;
+                       }
+
+                       /* output xbar always main channel */
+                       saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1,
+                                      0xbbbb10);
+
+                       if (left || right) {
+                               /* We've got data, turn the input on */
+                               saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1,
+                                              xbarin);
+                               saa_writel(SAA7133_ANALOG_IO_SELECT, anabar);
+                       } else {
+                               saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1,
+                                              0);
+                               saa_writel(SAA7133_ANALOG_IO_SELECT, 0);
+                       }
+                       break;
+               }
+       }
+
+       if (change) {
+               if (force_notify)
+                       snd_ctl_notify(chip->card,
+                                      SNDRV_CTL_EVENT_MASK_VALUE,
+                                      &chip->capture_ctl[addr]->id);
+
+               if (old_addr != MIXER_ADDR_UNSELECTED && old_addr != addr)
+                       snd_ctl_notify(chip->card,
+                                      SNDRV_CTL_EVENT_MASK_VALUE,
+                                      &chip->capture_ctl[old_addr]->id);
+       }
+
+       return change;
+}
+
+/*
+ * ALSA PCM preparation
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called right after the capture device is opened, this function configures
+ *  the buffer using the previously defined functions, allocates the memory,
+ *  sets up the hardware registers, and then starts the DMA. When this function
+ *  returns, the audio should be flowing.
+ *
+ */
+
+static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int bswap, sign;
+       u32 fmt, control;
+       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+       struct saa7134_dev *dev;
+       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+
+       pcm->dev->dmasound.substream = substream;
+
+       dev = saa7134->dev;
+
+       if (snd_pcm_format_width(runtime->format) == 8)
+               fmt = 0x00;
+       else
+               fmt = 0x01;
+
+       if (snd_pcm_format_signed(runtime->format))
+               sign = 1;
+       else
+               sign = 0;
+
+       if (snd_pcm_format_big_endian(runtime->format))
+               bswap = 1;
+       else
+               bswap = 0;
+
+       switch (dev->pci->device) {
+         case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               if (1 == runtime->channels)
+                       fmt |= (1 << 3);
+               if (2 == runtime->channels)
+                       fmt |= (3 << 3);
+               if (sign)
+                       fmt |= 0x04;
+
+               fmt |= (MIXER_ADDR_TVTUNER == dev->dmasound.input) ? 0xc0 : 0x80;
+               saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff));
+               saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >>  8);
+               saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16);
+               saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+
+               break;
+         case PCI_DEVICE_ID_PHILIPS_SAA7133:
+         case PCI_DEVICE_ID_PHILIPS_SAA7135:
+               if (1 == runtime->channels)
+                       fmt |= (1 << 4);
+               if (2 == runtime->channels)
+                       fmt |= (2 << 4);
+               if (!sign)
+                       fmt |= 0x04;
+               saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1);
+               saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
+               break;
+       }
+
+       dprintk("rec_start: afmt=%d ch=%d  =>  fmt=0x%x swap=%c\n",
+               runtime->format, runtime->channels, fmt,
+               bswap ? 'b' : '-');
+       /* dma: setup channel 6 (= AUDIO) */
+       control = SAA7134_RS_CONTROL_BURST_16 |
+               SAA7134_RS_CONTROL_ME |
+               (dev->dmasound.pt.dma >> 12);
+       if (bswap)
+               control |= SAA7134_RS_CONTROL_BSWAP;
+
+       saa_writel(SAA7134_RS_BA1(6),0);
+       saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
+       saa_writel(SAA7134_RS_PITCH(6),0);
+       saa_writel(SAA7134_RS_CONTROL(6),control);
+
+       dev->dmasound.rate = runtime->rate;
+
+       /* Setup and update the card/ALSA controls */
+       snd_saa7134_capsrc_set(saa7134->capture_ctl[dev->dmasound.input], 1, 1,
+                              true);
+
+       return 0;
+
+}
+
+/*
+ * ALSA pointer fetching
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called whenever a period elapses, it must return the current hardware
+ *  position of the buffer.
+ *   Also resets the read counter used to prevent overruns
+ *
+ */
+
+static snd_pcm_uframes_t
+snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+       struct saa7134_dev *dev=pcm->dev;
+
+       if (dev->dmasound.read_count) {
+               dev->dmasound.read_count  -= snd_pcm_lib_period_bytes(substream);
+               dev->dmasound.read_offset += snd_pcm_lib_period_bytes(substream);
+               if (dev->dmasound.read_offset == dev->dmasound.bufsize)
+                       dev->dmasound.read_offset = 0;
+       }
+
+       return bytes_to_frames(runtime, dev->dmasound.read_offset);
+}
+
+/*
+ * ALSA hardware capabilities definition
+ *
+ *  Report only 32kHz for ALSA:
+ *
+ *  - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz
+ *    only
+ *  - SAA7134 for TV mode uses DemDec mode (32kHz)
+ *  - Radio works in 32kHz only
+ *  - When recording 48kHz from Line1/Line2, switching of capture source to TV
+ *    means
+ *    switching to 32kHz without any frequency translation
+ */
+
+static struct snd_pcm_hardware snd_card_saa7134_capture =
+{
+       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                SNDRV_PCM_INFO_MMAP_VALID),
+       .formats =              SNDRV_PCM_FMTBIT_S16_LE | \
+                               SNDRV_PCM_FMTBIT_S16_BE | \
+                               SNDRV_PCM_FMTBIT_S8 | \
+                               SNDRV_PCM_FMTBIT_U8 | \
+                               SNDRV_PCM_FMTBIT_U16_LE | \
+                               SNDRV_PCM_FMTBIT_U16_BE,
+       .rates =                SNDRV_PCM_RATE_32000,
+       .rate_min =             32000,
+       .rate_max =             32000,
+       .channels_min =         1,
+       .channels_max =         2,
+       .buffer_bytes_max =     (256*1024),
+       .period_bytes_min =     64,
+       .period_bytes_max =     (256*1024),
+       .periods_min =          4,
+       .periods_max =          1024,
+};
+
+static void snd_card_saa7134_runtime_free(struct snd_pcm_runtime *runtime)
+{
+       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+
+       kfree(pcm);
+}
+
+
+/*
+ * ALSA hardware params
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called on initialization, right before the PCM preparation
+ *
+ */
+
+static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+                                     struct snd_pcm_hw_params * hw_params)
+{
+       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+       struct saa7134_dev *dev;
+       unsigned int period_size, periods;
+       int err;
+
+       period_size = params_period_bytes(hw_params);
+       periods = params_periods(hw_params);
+
+       if (period_size < 0x100 || period_size > 0x10000)
+               return -EINVAL;
+       if (periods < 4)
+               return -EINVAL;
+       if (period_size * periods > 1024 * 1024)
+               return -EINVAL;
+
+       dev = saa7134->dev;
+
+       if (dev->dmasound.blocks == periods &&
+           dev->dmasound.blksize == period_size)
+               return 0;
+
+       /* release the old buffer */
+       if (substream->runtime->dma_area) {
+               saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+               videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+               dsp_buffer_free(dev);
+               substream->runtime->dma_area = NULL;
+       }
+       dev->dmasound.blocks  = periods;
+       dev->dmasound.blksize = period_size;
+       dev->dmasound.bufsize = period_size * periods;
+
+       err = dsp_buffer_init(dev);
+       if (0 != err) {
+               dev->dmasound.blocks  = 0;
+               dev->dmasound.blksize = 0;
+               dev->dmasound.bufsize = 0;
+               return err;
+       }
+
+       if (0 != (err = videobuf_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_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+               dsp_buffer_free(dev);
+               return err;
+       }
+       if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
+                                               dev->dmasound.dma.sglist,
+                                               dev->dmasound.dma.sglen,
+                                               0))) {
+               saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+               videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+               dsp_buffer_free(dev);
+               return err;
+       }
+
+       /* I should be able to use runtime->dma_addr in the control
+          byte, but it doesn't work. So I allocate the DMA using the
+          V4L functions, and force ALSA to use that as the DMA area */
+
+       substream->runtime->dma_area = dev->dmasound.dma.vaddr;
+       substream->runtime->dma_bytes = dev->dmasound.bufsize;
+       substream->runtime->dma_addr = 0;
+
+       return 0;
+
+}
+
+/*
+ * ALSA hardware release
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called after closing the device, but before snd_card_saa7134_capture_close
+ *   It stops the DMA audio and releases the buffers.
+ *
+ */
+
+static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
+{
+       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+       struct saa7134_dev *dev;
+
+       dev = saa7134->dev;
+
+       if (substream->runtime->dma_area) {
+               saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+               videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+               dsp_buffer_free(dev);
+               substream->runtime->dma_area = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * ALSA capture finish
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called after closing the device.
+ *
+ */
+
+static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream)
+{
+       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+       struct saa7134_dev *dev = saa7134->dev;
+
+       if (saa7134->mute_was_on) {
+               dev->ctl_mute = 1;
+               saa7134_tvaudio_setmute(dev);
+       }
+       return 0;
+}
+
+/*
+ * ALSA capture start
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called when opening the device. It creates and populates the PCM
+ *  structure
+ *
+ */
+
+static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       snd_card_saa7134_pcm_t *pcm;
+       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+       struct saa7134_dev *dev;
+       int amux, err;
+
+       if (!saa7134) {
+               printk(KERN_ERR "BUG: saa7134 can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+       dev = saa7134->dev;
+       mutex_lock(&dev->dmasound.lock);
+
+       dev->dmasound.read_count  = 0;
+       dev->dmasound.read_offset = 0;
+
+       amux = dev->input->amux;
+       if ((amux < 1) || (amux > 3))
+               amux = 1;
+       dev->dmasound.input  =  amux - 1;
+
+       mutex_unlock(&dev->dmasound.lock);
+
+       pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+       if (pcm == NULL)
+               return -ENOMEM;
+
+       pcm->dev=saa7134->dev;
+
+       spin_lock_init(&pcm->lock);
+
+       pcm->substream = substream;
+       runtime->private_data = pcm;
+       runtime->private_free = snd_card_saa7134_runtime_free;
+       runtime->hw = snd_card_saa7134_capture;
+
+       if (dev->ctl_mute != 0) {
+               saa7134->mute_was_on = 1;
+               dev->ctl_mute = 0;
+               saa7134_tvaudio_setmute(dev);
+       }
+
+       err = snd_pcm_hw_constraint_integer(runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               return err;
+
+       err = snd_pcm_hw_constraint_step(runtime, 0,
+                                               SNDRV_PCM_HW_PARAM_PERIODS, 2);
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+
+static struct page *snd_card_saa7134_page(struct snd_pcm_substream *substream,
+                                       unsigned long offset)
+{
+       void *pageptr = substream->runtime->dma_area + offset;
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * ALSA capture callbacks definition
+ */
+
+static struct snd_pcm_ops snd_card_saa7134_capture_ops = {
+       .open =                 snd_card_saa7134_capture_open,
+       .close =                snd_card_saa7134_capture_close,
+       .ioctl =                snd_pcm_lib_ioctl,
+       .hw_params =            snd_card_saa7134_hw_params,
+       .hw_free =              snd_card_saa7134_hw_free,
+       .prepare =              snd_card_saa7134_capture_prepare,
+       .trigger =              snd_card_saa7134_capture_trigger,
+       .pointer =              snd_card_saa7134_capture_pointer,
+       .page =                 snd_card_saa7134_page,
+};
+
+/*
+ * ALSA PCM setup
+ *
+ *   Called when initializing the board. Sets up the name and hooks up
+ *  the callbacks
+ *
+ */
+
+static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device)
+{
+       struct snd_pcm *pcm;
+       int err;
+
+       if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0)
+               return err;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops);
+       pcm->private_data = saa7134;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, "SAA7134 PCM");
+       return 0;
+}
+
+#define SAA713x_VOLUME(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_saa7134_volume_info, \
+  .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \
+  .private_value = addr }
+
+static int snd_saa7134_volume_info(struct snd_kcontrol * kcontrol,
+                                  struct snd_ctl_elem_info * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 20;
+       return 0;
+}
+
+static int snd_saa7134_volume_get(struct snd_kcontrol * kcontrol,
+                                 struct snd_ctl_elem_value * ucontrol)
+{
+       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+       int addr = kcontrol->private_value;
+
+       ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0];
+       ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1];
+       return 0;
+}
+
+static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
+                                 struct snd_ctl_elem_value * ucontrol)
+{
+       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+       struct saa7134_dev *dev = chip->dev;
+
+       int change, addr = kcontrol->private_value;
+       int left, right;
+
+       left = ucontrol->value.integer.value[0];
+       if (left < 0)
+               left = 0;
+       if (left > 20)
+               left = 20;
+       right = ucontrol->value.integer.value[1];
+       if (right < 0)
+               right = 0;
+       if (right > 20)
+               right = 20;
+       spin_lock_irq(&chip->mixer_lock);
+       change = 0;
+       if (chip->mixer_volume[addr][0] != left) {
+               change = 1;
+               right = left;
+       }
+       if (chip->mixer_volume[addr][1] != right) {
+               change = 1;
+               left = right;
+       }
+       if (change) {
+               switch (dev->pci->device) {
+                       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+                               switch (addr) {
+                                       case MIXER_ADDR_TVTUNER:
+                                               left = 20;
+                                               break;
+                                       case MIXER_ADDR_LINE1:
+                                               saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
+                                                          (left > 10) ? 0x00 : 0x10);
+                                               break;
+                                       case MIXER_ADDR_LINE2:
+                                               saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
+                                                          (left > 10) ? 0x00 : 0x20);
+                                               break;
+                               }
+                               break;
+                       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+                       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+                               switch (addr) {
+                                       case MIXER_ADDR_TVTUNER:
+                                               left = 20;
+                                               break;
+                                       case MIXER_ADDR_LINE1:
+                                               saa_andorb(0x0594,  0x10,
+                                                          (left > 10) ? 0x00 : 0x10);
+                                               break;
+                                       case MIXER_ADDR_LINE2:
+                                               saa_andorb(0x0594,  0x20,
+                                                          (left > 10) ? 0x00 : 0x20);
+                                               break;
+                               }
+                               break;
+               }
+               chip->mixer_volume[addr][0] = left;
+               chip->mixer_volume[addr][1] = right;
+       }
+       spin_unlock_irq(&chip->mixer_lock);
+       return change;
+}
+
+#define SAA713x_CAPSRC(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_saa7134_capsrc_info, \
+  .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \
+  .private_value = addr }
+
+static int snd_saa7134_capsrc_info(struct snd_kcontrol * kcontrol,
+                                  struct snd_ctl_elem_info * uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+       uinfo->count = 2;
+       uinfo->value.integer.min = 0;
+       uinfo->value.integer.max = 1;
+       return 0;
+}
+
+static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol,
+                                 struct snd_ctl_elem_value * ucontrol)
+{
+       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+       int addr = kcontrol->private_value;
+
+       spin_lock_irq(&chip->mixer_lock);
+       if (chip->capture_source_addr == addr) {
+               ucontrol->value.integer.value[0] = chip->capture_source[0];
+               ucontrol->value.integer.value[1] = chip->capture_source[1];
+       } else {
+               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.integer.value[1] = 0;
+       }
+       spin_unlock_irq(&chip->mixer_lock);
+
+       return 0;
+}
+
+static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol,
+                                 struct snd_ctl_elem_value * ucontrol)
+{
+       int left, right;
+       left = ucontrol->value.integer.value[0] & 1;
+       right = ucontrol->value.integer.value[1] & 1;
+
+       return snd_saa7134_capsrc_set(kcontrol, left, right, false);
+}
+
+static struct snd_kcontrol_new snd_saa7134_volume_controls[] = {
+SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER),
+SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1),
+SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2),
+};
+
+static struct snd_kcontrol_new snd_saa7134_capture_controls[] = {
+SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER),
+SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1),
+SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2),
+};
+
+/*
+ * ALSA mixer setup
+ *
+ *   Called when initializing the board. Sets up the name and hooks up
+ *  the callbacks
+ *
+ */
+
+static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
+{
+       struct snd_card *card = chip->card;
+       struct snd_kcontrol *kcontrol;
+       unsigned int idx;
+       int err, addr;
+
+       strcpy(card->mixername, "SAA7134 Mixer");
+
+       for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) {
+               kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx],
+                                       chip);
+               err = snd_ctl_add(card, kcontrol);
+               if (err < 0)
+                       return err;
+       }
+
+       for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_capture_controls); idx++) {
+               kcontrol = snd_ctl_new1(&snd_saa7134_capture_controls[idx],
+                                       chip);
+               addr = snd_saa7134_capture_controls[idx].private_value;
+               chip->capture_ctl[addr] = kcontrol;
+               err = snd_ctl_add(card, kcontrol);
+               if (err < 0)
+                       return err;
+       }
+
+       chip->capture_source_addr = MIXER_ADDR_UNSELECTED;
+       return 0;
+}
+
+static void snd_saa7134_free(struct snd_card * card)
+{
+       snd_card_saa7134_t *chip = card->private_data;
+
+       if (chip->dev->dmasound.priv_data == NULL)
+               return;
+
+       if (chip->irq >= 0)
+               free_irq(chip->irq, &chip->dev->dmasound);
+
+       chip->dev->dmasound.priv_data = NULL;
+
+}
+
+/*
+ * ALSA initialization
+ *
+ *   Called by the init routine, once for each saa7134 device present,
+ *  it creates the basic structures and registers the ALSA devices
+ *
+ */
+
+static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
+{
+
+       struct snd_card *card;
+       snd_card_saa7134_t *chip;
+       int err;
+
+
+       if (devnum >= SNDRV_CARDS)
+               return -ENODEV;
+       if (!enable[devnum])
+               return -ENODEV;
+
+       err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
+                             sizeof(snd_card_saa7134_t), &card);
+       if (err < 0)
+               return err;
+
+       strcpy(card->driver, "SAA7134");
+
+       /* Card "creation" */
+
+       card->private_free = snd_saa7134_free;
+       chip = card->private_data;
+
+       spin_lock_init(&chip->lock);
+       spin_lock_init(&chip->mixer_lock);
+
+       chip->dev = dev;
+
+       chip->card = card;
+
+       chip->pci = dev->pci;
+       chip->iobase = pci_resource_start(dev->pci, 0);
+
+
+       err = request_irq(dev->pci->irq, saa7134_alsa_irq,
+                               IRQF_SHARED | IRQF_DISABLED, dev->name,
+                               (void*) &dev->dmasound);
+
+       if (err < 0) {
+               printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n",
+                       dev->name, dev->pci->irq);
+               goto __nodev;
+       }
+
+       chip->irq = dev->pci->irq;
+
+       mutex_init(&dev->dmasound.lock);
+
+       if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
+               goto __nodev;
+
+       if ((err = snd_card_saa7134_pcm(chip, 0)) < 0)
+               goto __nodev;
+
+       snd_card_set_dev(card, &chip->pci->dev);
+
+       /* End of "creation" */
+
+       strcpy(card->shortname, "SAA7134");
+       sprintf(card->longname, "%s at 0x%lx irq %d",
+               chip->dev->name, chip->iobase, chip->irq);
+
+       printk(KERN_INFO "%s/alsa: %s registered as card %d\n",dev->name,card->longname,index[devnum]);
+
+       if ((err = snd_card_register(card)) == 0) {
+               snd_saa7134_cards[devnum] = card;
+               return 0;
+       }
+
+__nodev:
+       snd_card_free(card);
+       return err;
+}
+
+
+static int alsa_device_init(struct saa7134_dev *dev)
+{
+       dev->dmasound.priv_data = dev;
+       alsa_card_saa7134_create(dev,dev->nr);
+       return 1;
+}
+
+static int alsa_device_exit(struct saa7134_dev *dev)
+{
+
+       snd_card_free(snd_saa7134_cards[dev->nr]);
+       snd_saa7134_cards[dev->nr] = NULL;
+       return 1;
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+
+static int saa7134_alsa_init(void)
+{
+       struct saa7134_dev *dev = NULL;
+       struct list_head *list;
+
+       saa7134_dmasound_init = alsa_device_init;
+       saa7134_dmasound_exit = alsa_device_exit;
+
+       printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
+
+       list_for_each(list,&saa7134_devlist) {
+               dev = list_entry(list, struct saa7134_dev, devlist);
+               if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
+                       printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
+                               dev->name, saa7134_boards[dev->board].name);
+               else
+                       alsa_device_init(dev);
+       }
+
+       if (dev == NULL)
+               printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n");
+
+       return 0;
+
+}
+
+/*
+ * Module destructor
+ */
+
+static void saa7134_alsa_exit(void)
+{
+       int idx;
+
+       for (idx = 0; idx < SNDRV_CARDS; idx++) {
+               snd_card_free(snd_saa7134_cards[idx]);
+       }
+
+       saa7134_dmasound_init = NULL;
+       saa7134_dmasound_exit = NULL;
+       printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
+
+       return;
+}
+
+/* We initialize this late, to make sure the sound system is up and running */
+late_initcall(saa7134_alsa_init);
+module_exit(saa7134_alsa_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ricardo Cerqueira");
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
new file mode 100644 (file)
index 0000000..bc08f1d
--- /dev/null
@@ -0,0 +1,8026 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * card-specific stuff.
+ *
+ * (c) 2001-04 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, 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/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"
+#include "tda18271.h"
+#include "xc5000.h"
+#include "s5h1411.h"
+
+/* commly used strings */
+static char name_mute[]    = "mute";
+static char name_radio[]   = "Radio";
+static char name_tv[]      = "Television";
+static char name_tv_mono[] = "TV (mono only)";
+static char name_comp[]    = "Composite";
+static char name_comp1[]   = "Composite1";
+static char name_comp2[]   = "Composite2";
+static char name_comp3[]   = "Composite3";
+static char name_comp4[]   = "Composite4";
+static char name_svideo[]  = "S-Video";
+
+/* ------------------------------------------------------------------ */
+/* board config info                                                  */
+
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
+struct saa7134_board saa7134_boards[] = {
+       [SAA7134_BOARD_UNKNOWN] = {
+               .name           = "UNKNOWN/GENERIC",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .inputs         = {{
+                       .name = "default",
+                       .vmux = 0,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_PROTEUS_PRO] = {
+               /* /me */
+               .name           = "Proteus Pro [philips reference design]",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_FLYVIDEO3000] = {
+               /* "Marco d'Itri" <md@Linux.IT> */
+               .name           = "LifeView FlyVIDEO3000",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .gpiomask       = 0xe000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x8000,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x2000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x8000,
+               },
+       },
+       [SAA7134_BOARD_FLYVIDEO2000] = {
+               /* "TC Wan" <tcwan@cs.usm.my> */
+               .name           = "LifeView/Typhoon FlyVIDEO2000",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .gpiomask       = 0xe000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x2000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .gpio = 0x8000,
+               },
+       },
+       [SAA7134_BOARD_FLYTVPLATINUM_MINI] = {
+               /* "Arnaud Quette" <aquette@free.fr> */
+               .name           = "LifeView FlyTV Platinum Mini",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_FLYTVPLATINUM_FM] = {
+               /* LifeView FlyTV Platinum FM (LR214WF) */
+               /* "Peter Missel <peter.missel@onlinehome.de> */
+               .name           = "LifeView FlyTV Platinum FM / Gold",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .gpiomask       = 0x1E000,      /* Set GP16 and unused 15,14,13 to Output */
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x10000,        /* GP16=1 selects TV input */
+                       .tv   = 1,
+               },{
+/*                     .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+*/                     .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+/*                     .gpio = 0x4000,         */
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+/*                     .gpio = 0x4000,         */
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+/*                     .gpio = 0x4000,         */
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x00000,        /* GP16=0 selects FM radio antenna */
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x10000,
+               },
+       },
+       [SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM] = {
+               /* RoverMedia TV Link Pro FM (LR138 REV:I) */
+               /* Eugene Yudin <Eugene.Yudin@gmail.com> */
+               .name           = "RoverMedia TV Link Pro FM",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MFPE05 2 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0xe000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x8000,
+                       .tv   = 1,
+               }, {
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }, {
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x2000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x8000,
+               },
+       },
+       [SAA7134_BOARD_EMPRESS] = {
+               /* "Gert Vervoort" <gert.vervoort@philips.com> */
+               .name           = "EMPRESS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x20,
+
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               .mpeg      = SAA7134_MPEG_EMPRESS,
+               .video_out = CCIR656,
+       },
+       [SAA7134_BOARD_MONSTERTV] = {
+               /* "K.Ohta" <alpha292@bremen.or.jp> */
+               .name           = "SKNet Monster TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .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 = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_MD9717] = {
+               .name           = "Tevion MD 9717",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       /* workaround for problems with normal TV sound */
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+              .mute = {
+                      .name = name_mute,
+                      .amux = TV,
+              },
+       },
+       [SAA7134_BOARD_TVSTATION_RDS] = {
+               /* Typhoon TV Tuner RDS: Art.Nr. 50694 */
+               .name           = "KNC One TV-Station RDS / Typhoon TV Tuner RDS",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux   = LINE2,
+                       .tv   = 1,
+               },{
+
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+
+                       .name = "CVid over SVid",
+                       .vmux = 0,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_TVSTATION_DVR] = {
+               .name           = "KNC One TV-Station DVR",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x20,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x820000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x20000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x20000,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x20000,
+               }},
+               .radio          = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x20000,
+               },
+               .mpeg           = SAA7134_MPEG_EMPRESS,
+               .video_out      = CCIR656,
+       },
+       [SAA7134_BOARD_CINERGY400] = {
+               .name           = "Terratec Cinergy 400 TV",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .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 = 4,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2, /* CVideo over SVideo Connector */
+                       .vmux = 0,
+                       .amux = LINE1,
+               }}
+       },
+       [SAA7134_BOARD_MD5044] = {
+               .name           = "Medion 5044",
+               .audio_clock    = 0x00187de7, /* was: 0x00200000, */
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       /* workaround for problems with normal TV sound */
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_KWORLD] = {
+               .name           = "Kworld/KuroutoShikou SAA7130-TVPCI",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [SAA7134_BOARD_CINERGY600] = {
+               .name           = "Terratec Cinergy 600 TV",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2, /* CVideo over SVideo Connector */
+                       .vmux = 0,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_MD7134] = {
+               .name           = "Medion 7134",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .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,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+              },
+              .mute = {
+                      .name = name_mute,
+                      .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_TYPHOON_90031] = {
+               /* aka Typhoon "TV+Radio", Art.Nr 90031 */
+               /* Tom Zoerner <tomzo at users sourceforge net> */
+               .name           = "Typhoon TV+Radio 90031",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .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   = LINE2,
+               },
+       },
+       [SAA7134_BOARD_ELSA] = {
+               .name           = "ELSA EX-VISION 300TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_HITACHI_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 4,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [SAA7134_BOARD_ELSA_500TV] = {
+               .name           = "ELSA EX-VISION 500TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_HITACHI_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 7,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 8,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [SAA7134_BOARD_ELSA_700TV] = {
+               .name           = "ELSA EX-VISION 700TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_HITACHI_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 4,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 6,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 7,
+                       .amux = LINE1,
+               }},
+               .mute           = {
+                       .name = name_mute,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_ASUSTeK_TVFM7134] = {
+               .name           = "ASUS TV-FM 7134",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_ASUSTeK_TVFM7135] = {
+               .name           = "ASUS TV-FM 7135",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x200000,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .gpio = 0x0000,
+               },
+
+       },
+       [SAA7134_BOARD_VA1000POWER] = {
+               .name           = "AOPEN VA1000 POWER",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [SAA7134_BOARD_10MOONSTVMASTER] = {
+               /* "lilicheng" <llc@linuxfans.org> */
+               .name           = "10MOONS PCI TV CAPTURE CARD",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0xe000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x2000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .gpio = 0x8000,
+               },
+       },
+       [SAA7134_BOARD_BMK_MPEX_NOTUNER] = {
+               /* "Andrew de Quincey" <adq@lidskialf.net> */
+               .name           = "BMK MPEX No Tuner",
+               .audio_clock    = 0x200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x20,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp3,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp4,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .mpeg      = SAA7134_MPEG_EMPRESS,
+               .video_out = CCIR656,
+       },
+       [SAA7134_BOARD_VIDEOMATE_TV] = {
+               .name           = "Compro VideoMate TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS] = {
+               .name           = "Compro VideoMate TV Gold+",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .gpiomask       = 0x800c0000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x06c00012,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x0ac20012,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x08c20012,
+                       .tv   = 1,
+               }},                             /* radio and probably mute is missing */
+       },
+       [SAA7134_BOARD_CRONOS_PLUS] = {
+               /*
+               gpio pins:
+                       0  .. 3   BASE_ID
+                       4  .. 7   PROTECT_ID
+                       8  .. 11  USER_OUT
+                       12 .. 13  USER_IN
+                       14 .. 15  VIDIN_SEL
+               */
+               .name           = "Matrox CronosPlus",
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0xcf00,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .gpio = 2 << 14,
+               },{
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .gpio = 1 << 14,
+               },{
+                       .name = name_comp3,
+                       .vmux = 0,
+                       .gpio = 0 << 14,
+               },{
+                       .name = name_comp4,
+                       .vmux = 0,
+                       .gpio = 3 << 14,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .gpio = 2 << 14,
+               }},
+       },
+       [SAA7134_BOARD_MD2819] = {
+               .name           = "AverMedia M156 / Medion 2819",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x03,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x00,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               }, {
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+                       .gpio = 0x01,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x00,
+               },
+       },
+       [SAA7134_BOARD_BMK_MPEX_TUNER] = {
+               /* "Greg Wickham <greg.wickham@grangenet.net> */
+               .name           = "BMK MPEX Tuner",
+               .audio_clock    = 0x200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x20,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }},
+               .mpeg      = SAA7134_MPEG_EMPRESS,
+               .video_out = CCIR656,
+       },
+       [SAA7134_BOARD_ASUSTEK_TVFM7133] = {
+               .name           = "ASUS TV-FM 7133",
+               .audio_clock    = 0x00187de7,
+               /* probably wrong, the 7133 one is the NTSC version ...
+               * .tuner_type  = TUNER_PHILIPS_FM1236_MK3 */
+               .tuner_type     = TUNER_LG_NTSC_NEW_TAPC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+
+               },{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_PINNACLE_PCTV_STEREO] = {
+               .name           = "Pinnacle PCTV Stereo (saa7134)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_MT2032,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 1,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_MANLI_MTV002] = {
+               /* Ognjen Nastic <ognjen@logosoft.ba> */
+               .name           = "Manli MuchTV M-TV002",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_MANLI_MTV001] = {
+               /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
+               .name           = "Manli MuchTV M-TV001",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_TG3000TV] = {
+               /* TransGear 3000TV */
+               .name           = "Nagase Sangyo TransGear 3000TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_ECS_TVP3XP] = {
+               .name           = "Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) ",
+               .audio_clock    = 0x187de7,  /* xtal 32.1 MHz */
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_tv_mono,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               },{
+                       .name   = "CVid over SVid",
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+               },
+       },
+       [SAA7134_BOARD_ECS_TVP3XP_4CB5] = {
+               .name           = "Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_tv_mono,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               },{
+                       .name   = "CVid over SVid",
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+               },
+       },
+    [SAA7134_BOARD_ECS_TVP3XP_4CB6] = {
+               /* Barry Scott <barry.scott@onelan.co.uk> */
+               .name           = "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_tv_mono,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               },{
+                       .name   = "CVid over SVid",
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+               },
+       },
+       [SAA7134_BOARD_AVACSSMARTTV] = {
+               /* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */
+               .name           = "AVACS SmartTV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x200000,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER] = {
+               /* Michael Smith <msmith@cbnco.com> */
+               .name           = "AVerMedia DVD EZMaker",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 3,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+               }},
+       },
+       [SAA7134_BOARD_AVERMEDIA_M103] = {
+               /* Massimo Piccioni <dafastidio@libero.it> */
+               .name           = "AVerMedia MiniPCI DVB-T Hybrid M103",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+                .mpeg           = SAA7134_MPEG_DVB,
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                } },
+       },
+       [SAA7134_BOARD_NOVAC_PRIMETV7133] = {
+               /* toshii@netbsd.org */
+               .name           = "Noval Prime TV 7133",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ALPS_TSBH1_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 3,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+               }},
+       },
+       [SAA7134_BOARD_AVERMEDIA_STUDIO_305] = {
+               .name           = "AverMedia AverTV Studio 305",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_STUDIO_505] = {
+               /* Vasiliy Temnikov <vaka@newmail.ru> */
+               .name           = "AverMedia AverTV Studio 505",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               }, {
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_UPMOST_PURPLE_TV] = {
+               .name           = "UPMOST PURPLE TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 7,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 7,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_ITEMS_MTV005] = {
+               /* Norman Jonas <normanjonas@arcor.de> */
+               .name           = "Items MuchTV Plus / IT-005",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_CINERGY200] = {
+               .name           = "Terratec Cinergy 200 TV",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2, /* CVideo over SVideo Connector */
+                       .vmux = 0,
+                       .amux = LINE1,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_VIDEOMATE_TV_PVR] = {
+               /* Alain St-Denis <alain@topaze.homeip.net> */
+               .name           = "Compro VideoMate TV PVR/FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x808c0080,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x00080,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x00080,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2_LEFT,
+                       .tv   = 1,
+                       .gpio = 0x00080,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x80000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .gpio = 0x40000,
+               },
+       },
+       [SAA7134_BOARD_SABRENT_SBTTVFM] = {
+               /* Michael Rodriguez-Torrent <mrtorrent@asu.edu> */
+               .name           = "Sabrent SBT-TVFM (saa7130)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+               },
+       },
+       [SAA7134_BOARD_ZOLID_XPERT_TV7134] = {
+               /* Helge Jensen <helge.jensen@slog.dk> */
+               .name           = ":Zolid Xpert TV7134",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE] = {
+               /* "Matteo Az" <matte.az@nospam.libero.it> ;-) */
+               .name           = "Empire PCI TV-Radio LE",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x4000,
+               .inputs         = {{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x8000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x8000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+                       .gpio = 0x8000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+                       .gpio = 0x8000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio =0x8000,
+               }
+       },
+       [SAA7134_BOARD_AVERMEDIA_STUDIO_307] = {
+               /*
+               Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+               Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
+               */
+               .name           = "Avermedia AVerTV Studio 307",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x03,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x00,
+               },{
+                       .name = name_comp,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+                       .gpio = 0x01,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .amux = LINE1,
+                       .gpio = 0x00,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_GO_007_FM] = {
+               .name           = "Avermedia AVerTV GO 007 FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00300003,
+               /* .gpiomask       = 0x8c240003, */
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x01,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x00300001,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
+               /* Kees.Blom@cwi.nl */
+               .name           = "AVerMedia Cardbus TV/Radio (E500)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .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 = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = {
+               /* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+               .name           = "AVerMedia Cardbus TV/Radio (E501R)",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_ALPS_TSBE5_PAL,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = 0x61,
+               .radio_addr     = 0x60,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x08000000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x08000000,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x08000000,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x08000000,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x00000000,
+               },
+       },
+       [SAA7134_BOARD_CINERGY400_CARDBUS] = {
+               .name           = "Terratec Cinergy 400 mobile",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_ALPS_TSBE5_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_CINERGY600_MK3] = {
+               .name           = "Terratec Cinergy 600 TV MK3",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 4,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2, /* CVideo over SVideo Connector */
+                       .vmux = 0,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_VIDEOMATE_GOLD_PLUS] = {
+               /* Dylan Walkden <dylan_walkden@hotmail.com> */
+               .name           = "Compro VideoMate Gold+ Pal",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x1ce780,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 0,              /* CVideo over SVideo Connector - ok? */
+                       .amux = LINE1,
+                       .gpio = 0x008080,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x008080,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x008080,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x80000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .gpio = 0x0c8000,
+               },
+       },
+       [SAA7134_BOARD_PINNACLE_300I_DVBT_PAL] = {
+               .name           = "Pinnacle PCTV 300i DVB-T + PAL",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_MT2032,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 1,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_PROVIDEO_PV952] = {
+               /* andreas.kretschmer@web.de */
+               .name           = "ProVideo PV952",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_305] = {
+               /* much like the "studio" version but without radio
+               * and another tuner (sirspiritus@yandex.ru) */
+               .name           = "AverMedia AverTV/305",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_FLYDVBTDUO] = {
+               /* LifeView FlyDVB-T DUO */
+               /* "Nico Sabbi <nsabbi@tiscali.it>  Hartmut Hackmann hartmut.hackmann@t-online.de*/
+               .name           = "LifeView FlyDVB-T DUO / MSI TV@nywhere Duo",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00200000,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x200000,       /* GPIO21=High for TV input */
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
+               },
+       },
+       [SAA7134_BOARD_PHILIPS_TOUGH] = {
+               .name           = "Philips TOUGH DVB-T reference design",
+               .tuner_type     = TUNER_ABSENT,
+               .audio_clock    = 0x00187de7,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_AVERMEDIA_307] = {
+               /*
+               Davydov Vladimir <vladimir@iqmedia.com>
+               */
+               .name           = "Avermedia AVerTV 307",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_ADS_INSTANT_TV] = {
+               .name           = "ADS Tech Instant TV (saa7135)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .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 = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = {
+               .name           = "Kworld/Tevion V-Stream Xpert TV PVR7134",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_PAL_I,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x0700,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+                       .gpio   = 0x000,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,                /* gpio by DScaler */
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE1,
+                       .gpio   = 0x100,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x000,
+               },
+       },
+       [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
+               .name           = "LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x00200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x200000,       /* GPIO21=High for TV input */
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
+               },
+       },
+       [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
+               .name           = "Compro VideoMate TV Gold+II",
+               .audio_clock    = 0x002187de7,
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = 0x63,
+               .radio_addr     = 0x60,
+               .gpiomask       = 0x8c1880,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 0,
+                       .amux = LINE1,
+                       .gpio = 0x800800,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x801000,
+               },{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x800000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x880000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .gpio = 0x840000,
+               },
+       },
+       [SAA7134_BOARD_KWORLD_XPERT] = {
+               /*
+               FIXME:
+               - Remote control doesn't initialize properly.
+               - Audio volume starts muted,
+               then gradually increases after channel change.
+               - Overlay scaling problems (application error?)
+               - Composite S-Video untested.
+               From: Konrad Rzepecki <hannibal@megapolis.pl>
+               */
+               .name           = "Kworld Xpert TV PVR7134",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_TENA_9533_DI,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = 0x61,
+               .radio_addr     = 0x60,
+               .gpiomask       = 0x0700,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+                       .gpio   = 0x000,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,                /* gpio by DScaler */
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE1,
+                       .gpio   = 0x100,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x000,
+               },
+       },
+       [SAA7134_BOARD_FLYTV_DIGIMATRIX] = {
+               .name           = "FlyTV mini Asus Digimatrix",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_LG_TALN,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,             /* radio unconfirmed */
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_KWORLD_TERMINATOR] = {
+               /* Kworld V-Stream Studio TV Terminator */
+               /* "James Webb <jrwebb@qwest.net> */
+               .name           = "V-Stream Studio TV Terminator",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 1 << 21,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x0000000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x0000000,
+               },{
+                       .name = name_svideo,    /* S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x0000000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_YUAN_TUN900] = {
+               /* FIXME:
+                * S-Video and composite sources untested.
+                * Radio not working.
+                * Remote control not yet implemented.
+                * From : codemaster@webgeeks.be */
+               .name           = "Yuan TUN-900 (saa7135)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr= ADDR_UNSET,
+               .radio_addr= ADDR_UNSET,
+               .gpiomask       = 0x00010003,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x01,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x02,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE2,
+                       .gpio = 0x02,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+                       .gpio = 0x00010003,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
+       [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,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                         .name = name_tv,
+                         .vmux = 3,
+                         .amux = TV,
+                         .tv   = 1,
+               },{
+                         .name = name_comp1,
+                         .vmux = 1,
+                         .amux = LINE1,
+               },{
+                         .name = name_svideo,
+                         .vmux = 8,
+                         .amux = LINE1,
+               }},
+               .radio = {
+                         .name = name_radio,
+                         .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_GOTVIEW_7135] = {
+               /* Mike Baikov <mike@baikov.com> */
+               /* Andrey Cvetcov <ays14@yandex.ru> */
+               .name            = "GoTView 7135 PCI",
+               .audio_clock     = 0x00187de7,
+               .tuner_type      = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type      = UNSET,
+               .tuner_addr      = ADDR_UNSET,
+               .radio_addr      = ADDR_UNSET,
+               .tda9887_conf    = TDA9887_PRESENT,
+               .gpiomask        = 0x00200003,
+               .inputs          = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x00200003,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x00200003,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x00200003,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x00200003,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x00200003,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x00200003,
+               },
+       },
+       [SAA7134_BOARD_PHILIPS_EUROPA] = {
+               .name           = "Philips EUROPA V3 reference design",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TD1316,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE2,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_VIDEOMATE_DVBT_300] = {
+               .name           = "Compro Videomate DVB-T300",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TD1316,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+               .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,
+               }},
+       },
+       [SAA7134_BOARD_VIDEOMATE_DVBT_200] = {
+               .name           = "Compro Videomate DVB-T200",
+               .tuner_type     = TUNER_ABSENT,
+               .audio_clock    = 0x00187de7,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_RTD_VFG7350] = {
+               .name           = "RTD Embedded Technologies VFG7350",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x21,
+               .inputs         = {{
+                       .name   = "Composite 0",
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name   = "Composite 1",
+                       .vmux   = 1,
+                       .amux   = LINE2,
+               },{
+                       .name   = "Composite 2",
+                       .vmux   = 2,
+                       .amux   = LINE1,
+               },{
+                       .name   = "Composite 3",
+                       .vmux   = 3,
+                       .amux   = LINE2,
+               },{
+                       .name   = "S-Video 0",
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               },{
+                       .name   = "S-Video 1",
+                       .vmux   = 9,
+                       .amux   = LINE2,
+               }},
+               .mpeg           = SAA7134_MPEG_EMPRESS,
+               .video_out      = CCIR656,
+               .vid_port_opts  = ( SET_T_CODE_POLARITY_NON_INVERTED |
+                                   SET_CLOCK_NOT_DELAYED |
+                                   SET_CLOCK_INVERTED |
+                                   SET_VSYNC_OFF ),
+       },
+       [SAA7134_BOARD_RTD_VFG7330] = {
+               .name           = "RTD Embedded Technologies VFG7330",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name   = "Composite 0",
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name   = "Composite 1",
+                       .vmux   = 1,
+                       .amux   = LINE2,
+               },{
+                       .name   = "Composite 2",
+                       .vmux   = 2,
+                       .amux   = LINE1,
+               },{
+                       .name   = "Composite 3",
+                       .vmux   = 3,
+                       .amux   = LINE2,
+               },{
+                       .name   = "S-Video 0",
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               },{
+                       .name   = "S-Video 1",
+                       .vmux   = 9,
+                       .amux   = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = {
+               .name           = "LifeView FlyTV Platinum Mini2",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
+               /* Michael Krufky <mkrufky@m1k.net>
+                * Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
+                * AFAIK, there is no analog demod, thus,
+                * no support for analog television.
+                */
+               .name           = "AVerMedia AVerTVHD MCE A180",
+               .audio_clock    = 0x00187de7,
+               .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 = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_MONSTERTV_MOBILE] = {
+               .name           = "SKNet MonsterTV Mobile",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .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 = 6,
+                         .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_PINNACLE_PCTV_110i] = {
+              .name           = "Pinnacle PCTV 40i/50i/110i (saa7133)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x080200000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 4,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE2,
+               }, {
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE2,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = {
+               .name           = "ASUSTeK P7131 Dual",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 1 << 21,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x0000000,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_SEDNA_PC_TV_CARDBUS] = {
+               /* Paul Tom Zalac <pzalac@gmail.com> */
+               /* Pavel Mihaylov <bin@bash.info> */
+               .name           = "Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)",
+                               /* Sedna/MuchTV (OEM) Cardbus TV Tuner */
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0xe880c0,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV] = {
+               /* "Cyril Lacoux (Yack)" <clacoux@ifeelgood.org> */
+               .name           = "ASUS Digimatrix TV",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .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 = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_PHILIPS_TIGER] = {
+               .name           = "Philips Tiger reference design",
+               .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,
+               .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_MSI_TVATANYWHERE_PLUS] = {
+               .name           = "MSI TV@Anywhere plus",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 1 << 21,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE2,        /* unconfirmed, taken from Philips driver */
+               },{
+                       .name   = name_comp2,
+                       .vmux   = 0,            /* untested, Composite over S-Video */
+                       .amux   = LINE2,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_CINERGY250PCI] = {
+               /* remote-control does not work. The signal about a
+                  key press comes in via gpio, but the key code
+                  doesn't. Neither does it have an i2c remote control
+                  interface. */
+               .name           = "Terratec Cinergy 250 PCI TV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x80200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,  /* NOT tested */
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_FLYDVB_TRIO] = {
+               /* LifeView LR319 FlyDVB Trio */
+               /* Peter Missel <peter.missel@onlinehome.de> */
+               .name           = "LifeView FlyDVB Trio",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00200000,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,        /* Analog broadcast/cable TV */
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x200000,       /* GPIO21=High for TV input */
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_777] = {
+               .name           = "AverTV DVB-T 777",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_FLYDVBT_LR301] = {
+               /* LifeView FlyDVB-T */
+               /* Giampiero Giancipoli <gianci@libero.it> */
+               .name           = "LifeView FlyDVB-T / Genius VideoWonder DVB-T",
+               .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,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331] = {
+               .name           = "ADS Instant TV Duo Cardbus PTV331",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+                       .gpio   = 0x00200000,
+               }},
+       },
+       [SAA7134_BOARD_TEVION_DVBT_220RF] = {
+               .name           = "Tevion/KWorld DVB-T 220RF",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 1 << 21,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_comp2,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_KWORLD_DVBT_210] = {
+               .name           = "KWorld DVB-T 210",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 1 << 21,
+               .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_KWORLD_ATSC110] = {
+               .name           = "Kworld ATSC110/115",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TUV1236D,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .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 = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_AVERMEDIA_A169_B] = {
+               /* AVerMedia A169  */
+               /* Rickard Osser <ricky@osser.se>  */
+               /* This card has two saa7134 chips on it,
+                  but only one of them is currently working. */
+               .name           = "AVerMedia A169 B",
+               .audio_clock    = 0x02187de7,
+               .tuner_type     = TUNER_LG_TALN,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x0a60000,
+       },
+       [SAA7134_BOARD_AVERMEDIA_A169_B1] = {
+               /* AVerMedia A169 */
+               /* Rickard Osser <ricky@osser.se> */
+               .name           = "AVerMedia A169 B1",
+               .audio_clock    = 0x02187de7,
+               .tuner_type     = TUNER_LG_TALN,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0xca60000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 4,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x04a61000,
+               },{
+                       .name = name_comp2,  /*  Composite SVIDEO (B/W if signal is carried with SVIDEO) */
+                       .vmux = 1,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 9,           /* 9 is correct as S-VIDEO1 according to a169.inf! */
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_MD7134_BRIDGE_2] = {
+               /* 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",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x200000,       /* GPIO21=High for TV input */
+                       .tv   = 1,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp1,     /* Composite signal on S-Video input */
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
+               },
+       },
+       [SAA7134_BOARD_FLYVIDEO3000_NTSC] = {
+               /* "Zac Bowling" <zac@zacbowling.com> */
+               .name           = "LifeView FlyVIDEO3000 (NTSC)",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_NTSC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+
+               .gpiomask       = 0xe000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .gpio = 0x8000,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x4000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x2000,
+               },
+                       .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x8000,
+               },
+       },
+       [SAA7134_BOARD_MEDION_MD8800_QUADRO] = {
+               .name           = "Medion Md8800 Quadro",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .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_FLYDVBS_LR300] = {
+               /* LifeView FlyDVB-s */
+               /* Igor M. Liplianin <liplianin@tut.by> */
+               .name           = "LifeView FlyDVB-S /Acorp TV134DS",
+               .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,     /* Composite input */
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,    /* S-Video signal on S-Video input */
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_PROTEUS_2309] = {
+               .name           = "Proteus Pro 2309",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_A16AR] = {
+               /* Petr Baudis <pasky@ucw.cz> */
+               .name           = "AVerMedia TV Hybrid A16AR",
+               .audio_clock    = 0x187de7,
+               .tuner_type     = TUNER_PHILIPS_TD1316, /* untested */
+               .radio_type     = TUNER_TEA5767, /* untested */
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = 0x60,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .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 = LINE1,
+               },
+       },
+       [SAA7134_BOARD_ASUS_EUROPA2_HYBRID] = {
+               .name           = "Asus Europa2 OEM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT| TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 4,
+                       .amux   = LINE2,
+               },{
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               }},
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE1,
+               },
+       },
+       [SAA7134_BOARD_PINNACLE_PCTV_310i] = {
+               .name           = "Pinnacle PCTV 310i",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 1,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x000200000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 4,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE2,
+               },{
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = {
+               /* Mikhail Fedotov <mo_fedotov@mail.ru> */
+               .name           = "Avermedia AVerTV Studio 507",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x03,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x00,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x00,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x00,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x00,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x01,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .amux = LINE1,
+                       .gpio = 0x00,
+               },
+       },
+       [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = {
+               /* Francis Barber <fedora@barber-family.id.au> */
+               .name           = "Compro Videomate DVB-T200A",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+               .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,
+               }},
+       },
+       [SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
+               /* Thomas Genty <tomlohave@gmail.com> */
+               /* David Bentham <db260179@hotmail.com> */
+               .name           = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 1,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 0x0200100,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x0000100,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200100,
+               },
+       },
+       [SAA7134_BOARD_HAUPPAUGE_HVR1150] = {
+               .name           = "Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 3,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .ts_type        = SAA7134_MPEG_TS_SERIAL,
+               .ts_force_val   = 1,
+               .gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x0000100,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0800100, /* GPIO 23 HI for FM */
+               },
+       },
+       [SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
+               .name           = "Hauppauge WinTV-HVR1120 DVB-T/Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 3,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .ts_type        = SAA7134_MPEG_TS_SERIAL,
+               .gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x0000100,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0800100, /* GPIO 23 HI for FM */
+               },
+       },
+       [SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
+               .name           = "Terratec Cinergy HT PCMCIA",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .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   = 6,
+                       .amux   = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_ENCORE_ENLTV] = {
+       /* Steven Walter <stevenrwalter@gmail.com>
+          Juan Pablo Sormani <sorman@gmail.com> */
+               .name           = "Encore ENLTV",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = 3,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 7,
+                       .amux = 4,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = 2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 0,
+                       .amux = 2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+/*                     .gpio = 0x00300001,*/
+                       .gpio = 0x20000,
+
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = 0,
+               },
+       },
+       [SAA7134_BOARD_ENCORE_ENLTV_FM] = {
+  /*   Juan Pablo Sormani <sorman@gmail.com> */
+               .name           = "Encore ENLTV-FM",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FCV1236D,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = 3,
+                       .tv   = 1,
+               },{
+                       .name = name_tv_mono,
+                       .vmux = 7,
+                       .amux = 4,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = 2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 0,
+                       .amux = 2,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x20000,
+
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = 0,
+               },
+       },
+       [SAA7134_BOARD_ENCORE_ENLTV_FM53] = {
+               .name           = "Encore ENLTV-FM v5.3",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x7000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = 1,
+                       .tv   = 1,
+                       .gpio = 0x50000,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = 2,
+                       .gpio = 0x2000,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = 2,
+                       .gpio = 0x2000,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .vmux = 1,
+                       .amux = 1,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .gpio = 0xf000,
+                       .amux = 0,
+               },
+       },
+       [SAA7134_BOARD_ENCORE_ENLTV_FM3] = {
+               .name           = "Encore ENLTV-FM 3",
+               .audio_clock    = 0x02187de7,
+               .tuner_type     = TUNER_TENA_TNF_5337,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = 0x61,
+               .radio_addr     = 0x60,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+                       .gpio = 0x43000,
+               },
+       },
+       [SAA7134_BOARD_CINERGY_HT_PCI] = {
+               .name           = "Terratec Cinergy HT PCI",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .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   = 6,
+                       .amux   = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_PHILIPS_TIGER_S] = {
+               .name           = "Philips Tiger - S Reference design",
+               .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_M102] = {
+               .name           = "Avermedia M102",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 1<<21,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE2,
+               },{
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE2,
+               }},
+       },
+       [SAA7134_BOARD_ASUS_P7131_4871] = {
+               .name           = "ASUS P7131 4871",
+               .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,
+                       .gpio   = 0x0200000,
+               }},
+       },
+       [SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA] = {
+               .name           = "ASUSTeK P7131 Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .gpiomask       = 1 << 21,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x0000000,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
+               },{
+                       .name = name_comp2,
+                       .vmux = 0,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+                       .gpio = 0x0200000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = {
+              .name           = "ASUSTeK P7131 Analog",
+              .audio_clock    = 0x00187de7,
+              .tuner_type     = TUNER_PHILIPS_TDA8290,
+              .radio_type     = UNSET,
+              .tuner_addr     = ADDR_UNSET,
+              .radio_addr     = ADDR_UNSET,
+              .gpiomask       = 1 << 21,
+              .inputs         = {{
+                      .name = name_tv,
+                      .vmux = 1,
+                      .amux = TV,
+                      .tv   = 1,
+                      .gpio = 0x0000000,
+              }, {
+                      .name = name_comp1,
+                      .vmux = 3,
+                      .amux = LINE2,
+              }, {
+                      .name = name_comp2,
+                      .vmux = 0,
+                      .amux = LINE2,
+              }, {
+                      .name = name_svideo,
+                      .vmux = 8,
+                      .amux = LINE2,
+              } },
+              .radio = {
+                      .name = name_radio,
+                      .amux = TV,
+                      .gpio = 0x0200000,
+              },
+       },
+       [SAA7134_BOARD_SABRENT_TV_PCB05] = {
+               .name           = "Sabrent PCMCIA TV-PCB05",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .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_comp2,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_10MOONSTVMASTER3] = {
+               /* Tony Wan <aloha_cn@hotmail.com> */
+               .name           = "10MOONS TM300 TV Card",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x7000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x2000,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x2000,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .gpio = 0x3000,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_SUPER_007] = {
+               .name           = "Avermedia Super 007",
+               .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, /* FIXME: analog tv untested */
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               }},
+       },
+       [SAA7134_BOARD_AVERMEDIA_M135A] = {
+               .name           = "Avermedia PCI pure analog (M135A)",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .gpiomask       = 0x020200000,
+               .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 = 0x00200000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_M733A] = {
+               .name           = "Avermedia PCI M733A",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 0,
+               .gpiomask       = 0x020200000,
+               .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 = 0x00200000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
+       [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,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [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,
+                       .amux = LINE1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [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,
+                       .amux = LINE1,
+               },{
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [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,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+       },
+       [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,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [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,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0xc0c000,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+                       .gpio = 0xc0c000,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv = 1,
+                       .gpio = 0xc0c000,
+               }},
+       },
+       [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,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs = {{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0xc0c000,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+                       .gpio = 0xc0c000,
+               },{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv = 1,
+                       .gpio = 0xc0c000,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0xc0c000,
+               },
+       },
+       [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,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+       },
+       [SAA7134_BOARD_BEHOLD_505FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 505 FM",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_505RDS_MK5] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 505 RDS",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_507_9FM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 507 FM / BeholdTV 509 FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+                       .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_507RDS_MK5] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 507 RDS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+                       .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_507RDS_MK3] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 507 RDS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+                       .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /* Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV Columbus TV/FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ALPS_TSBE5_PAL,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = 0xc2 >> 1,
+               .radio_addr     = 0xc0 >> 1,
+               .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_607FM_MK3] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 607 FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_609FM_MK3] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 609 FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_607FM_MK5] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 607 FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_609FM_MK5] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 609 FM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_607RDS_MK3] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 607 RDS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_609RDS_MK3] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 609 RDS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_607RDS_MK5] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 607 RDS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_609RDS_MK5] = {
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               .name           = "Beholder BeholdTV 609 RDS",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_M6] = {
+               /* Igor Kuznetsov <igk@igk.ru> */
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+               /* Alexey Osipov <lion-simba@pridelands.ru> */
+               .name           = "Beholder BeholdTV M6",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x20,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               .mpeg  = SAA7134_MPEG_EMPRESS,
+               .video_out = CCIR656,
+               .vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+                                       SET_CLOCK_NOT_DELAYED |
+                                       SET_CLOCK_INVERTED |
+                                       SET_VSYNC_OFF),
+       },
+       [SAA7134_BOARD_BEHOLD_M63] = {
+               /* Igor Kuznetsov <igk@igk.ru> */
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV M63",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .empress_addr   = 0x20,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               .mpeg  = SAA7134_MPEG_EMPRESS,
+               .video_out = CCIR656,
+               .vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+                                       SET_CLOCK_NOT_DELAYED |
+                                       SET_CLOCK_INVERTED |
+                                       SET_VSYNC_OFF),
+       },
+       [SAA7134_BOARD_BEHOLD_M6_EXTRA] = {
+               /* Igor Kuznetsov <igk@igk.ru> */
+               /* Andrey Melnikoff <temnota@kmv.ru> */
+               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+               /* Alexey Osipov <lion-simba@pridelands.ru> */
+               .name           = "Beholder BeholdTV M6 Extra",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .empress_addr   = 0x20,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+               .mpeg  = SAA7134_MPEG_EMPRESS,
+               .video_out = CCIR656,
+               .vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+                                       SET_CLOCK_NOT_DELAYED |
+                                       SET_CLOCK_INVERTED |
+                                       SET_VSYNC_OFF),
+       },
+       [SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = {
+               .name           = "Twinhan Hybrid DTV-DVB 3056 PCI",
+               .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,            /* untested */
+                       .amux   = LINE1,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_GENIUS_TVGO_A11MCE] = {
+               /* Adrian Pardini <pardo.bsso@gmail.com> */
+               .name           = "Genius TVGO AM11MCE",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0xf000,
+               .inputs         = {{
+                       .name = name_tv_mono,
+                       .vmux = 1,
+                       .amux = LINE2,
+                       .gpio = 0x0000,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x2000,
+                       .tv = 1
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x2000,
+       } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x1000,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE2,
+                       .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,
+                .mpeg           = SAA7134_MPEG_DVB,
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                }, {
+                        .name = name_comp1,
+                        .vmux = 3,
+                        .amux = LINE1,
+                }, {
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE2,
+                } },
+                .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,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 0,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               },
+       },
+       [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     = 0x61,
+               .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,
+               .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_XC2028,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = { {
+                       .name   = name_tv,
+                       .vmux   = 4,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_H6] = {
+               /* Igor Kuznetsov <igk@igk.ru> */
+               .name           = "Beholder BeholdTV H6",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
+               .name           = "Asus Tiger 3in1",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .gpiomask       = 1 << 21,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 0,
+                       .amux = LINE2,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_ASUSTeK_PS3_100] = {
+               .name           = "Asus My Cinema PS3-100",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tuner_config   = 2,
+               .gpiomask       = 1 << 21,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 0,
+                       .amux = LINE2,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_REAL_ANGEL_220] = {
+               .name           = "Zogis Real Angel 220",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_TNF_5335MF,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x801a8087,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = LINE2,
+                       .tv     = 1,
+                       .gpio   = 0x624000,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+                       .gpio   = 0x624000,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+                       .gpio   = 0x624000,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = LINE2,
+                       .gpio   = 0x624001,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = {
+               .name           = "ADS Tech Instant HDTV",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TUV1236D,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp,
+                       .vmux = 4,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_ASUSTeK_TIGER] = {
+               .name           = "Asus Tiger Rev:1.00",
+               .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,
+               .gpiomask       = 0x0200000,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_comp2,
+                       .vmux   = 0,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0200000,
+               },
+       },
+       [SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG] = {
+               .name           = "Kworld Plus TV Analog Lite PCI",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_YMEC_TVF_5533MF,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = 0x60,
+               .gpiomask       = 0x80000700,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = LINE2,
+                       .tv     = 1,
+                       .gpio   = 0x100,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+                       .gpio   = 0x100,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .vmux = 8,
+                       .amux = 2,
+               },
+       },
+       [SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = {
+               .name           = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_type     = UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x8e054000,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+#if 0  /* FIXME */
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+                       .gpio   = 0x200,
+#endif
+               } },
+#if 0
+               .radio = {
+                       .name   = name_radio,
+                       .vmux   = 1,
+                       .amux   = LINE1,
+                       .gpio   = 0x100,
+               },
+#endif
+               .mute = {
+                       .name = name_mute,
+                       .vmux = 0,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = {
+               .name           = "Avermedia AVerTV GO 007 FM Plus",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00300003,
+               /* .gpiomask       = 0x8c240003, */
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x01,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 6,
+                       .amux = LINE1,
+                       .gpio = 0x02,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+                       .gpio = 0x00300001,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+                       .gpio = 0x01,
+               },
+       },
+       [SAA7134_BOARD_AVERMEDIA_STUDIO_507UA] = {
+               /* Andy Shevchenko <andy@smile.org.ua> */
+               .name           = "Avermedia AVerTV Studio 507UA",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* Should be MK5 */
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x03,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+                       .gpio = 0x00,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x00,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+                       .gpio = 0x00,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+                       .gpio = 0x01,
+               },
+               .mute  = {
+                       .name = name_mute,
+                       .amux = LINE1,
+                       .gpio = 0x00,
+               },
+       },
+       [SAA7134_BOARD_VIDEOMATE_S350] = {
+               /* Jan D. Louw <jd.louw@mweb.co.za */
+               .name           = "Compro VideoMate S350/S300",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = { {
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8, /* Not tested */
+                       .amux   = LINE1
+               } },
+       },
+       [SAA7134_BOARD_BEHOLD_X7] = {
+               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV X7",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 2,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 9,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
+               .name           = "Zolid Hybrid TV Tuner PCI",
+               .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,
+               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               } },
+               .radio = {      /* untested */
+                       .name = name_radio,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_ASUS_EUROPA_HYBRID] = {
+               .name           = "Asus Europa Hybrid OEM",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TD1316,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x61,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 4,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+       },
+       [SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S] = {
+               .name           = "Leadtek Winfast DTV1000S",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs         = { {
+                       .name = name_comp1,
+                       .vmux = 3,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+               } },
+       },
+       [SAA7134_BOARD_BEHOLD_505RDS_MK3] = {
+               /*       Beholder Intl. Ltd. 2008      */
+               /*Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 505 RDS",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .rds_addr       = 0x10,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .gpiomask       = 0x00008000,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE2,
+               },
+       },
+       [SAA7134_BOARD_HAWELL_HW_404M7] = {
+               /* Hawell HW-404M7 & Hawell HW-808M7  */
+               /* Bogoslovskiy Viktor <bogovic@bk.ru> */
+               .name         = "Hawell HW-404M7",
+               .audio_clock   = 0x00200000,
+               .tuner_type    = UNSET,
+               .radio_type    = UNSET,
+               .tuner_addr   = ADDR_UNSET,
+               .radio_addr   = ADDR_UNSET,
+               .gpiomask      = 0x389c00,
+               .inputs       = {{
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE1,
+                       .gpio = 0x01fc00,
+               } },
+       },
+       [SAA7134_BOARD_BEHOLD_H7] = {
+               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV H7",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 2,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 9,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_A7] = {
+               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV A7",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_XC5000,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 2,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 9,
+                       .amux = LINE1,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_TECHNOTREND_BUDGET_T3000] = {
+               .name           = "TechoTrend TT-budget T-3000",
+               .tuner_type     = TUNER_PHILIPS_TD1316,
+               .audio_clock    = 0x00187de7,
+               .radio_type     = UNSET,
+               .tuner_addr     = 0x63,
+               .radio_addr     = ADDR_UNSET,
+               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .inputs = {{
+                       .name   = name_tv,
+                       .vmux   = 3,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE2,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+       },
+       [SAA7134_BOARD_VIDEOMATE_M1F] = {
+               /* Pavel Osnova <pvosnova@gmail.com> */
+               .name           = "Compro VideoMate Vista M1F",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .radio_type     = TUNER_TEA5767,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = 0x60,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 3,
+                       .amux = LINE2,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE2,
+               } },
+               .radio = {
+                       .name = name_radio,
+                       .amux = LINE1,
+               },
+               .mute = {
+                       .name = name_mute,
+                       .amux = TV,
+               },
+       },
+       [SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2] = {
+               /* Timothy Lee <timothy.lee@siriushk.com> */
+               .name           = "MagicPro ProHDTV Pro2 DMB-TH/Hybrid",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_config   = 3,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x02050000,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
+               .inputs         = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+                       .gpio   = 0x00050000,
+               }, {
+                       .name   = name_comp1,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+                       .gpio   = 0x00050000,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+                       .gpio   = 0x00050000,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x00050000,
+               },
+               .mute = {
+                       .name   = name_mute,
+                       .vmux   = 0,
+                       .amux   = TV,
+                       .gpio   = 0x00050000,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_501] = {
+               /*       Beholder Intl. Ltd. 2010       */
+               /* Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 501",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_BEHOLD_503FM] = {
+               /*       Beholder Intl. Ltd. 2010       */
+               /* Dmitry Belimov <d.belimov@gmail.com> */
+               .name           = "Beholder BeholdTV 503 FM",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .gpiomask       = 0x00008000,
+               .inputs         = { {
+                       .name = name_tv,
+                       .vmux = 3,
+                       .amux = LINE2,
+                       .tv   = 1,
+               }, {
+                       .name = name_comp1,
+                       .vmux = 1,
+                       .amux = LINE1,
+               }, {
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               } },
+               .mute = {
+                       .name = name_mute,
+                       .amux = LINE1,
+               },
+       },
+       [SAA7134_BOARD_SENSORAY811_911] = {
+               .name           = "Sensoray 811/911",
+               .audio_clock    = 0x00200000,
+               .tuner_type     = TUNER_ABSENT,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .inputs         = {{
+                       .name   = name_comp1,
+                       .vmux   = 0,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_comp3,
+                       .vmux   = 2,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE1,
+               } },
+       },
+       [SAA7134_BOARD_KWORLD_PC150U] = {
+               .name           = "Kworld PC150-U",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_TDA8290,
+               .radio_type     = UNSET,
+               .tuner_addr     = ADDR_UNSET,
+               .radio_addr     = ADDR_UNSET,
+               .mpeg           = SAA7134_MPEG_DVB,
+               .gpiomask       = 1 << 21,
+               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
+               .inputs = { {
+                       .name   = name_tv,
+                       .vmux   = 1,
+                       .amux   = TV,
+                       .tv     = 1,
+               }, {
+                       .name   = name_comp,
+                       .vmux   = 3,
+                       .amux   = LINE1,
+               }, {
+                       .name   = name_svideo,
+                       .vmux   = 8,
+                       .amux   = LINE2,
+               } },
+               .radio = {
+                       .name   = name_radio,
+                       .amux   = TV,
+                       .gpio   = 0x0000000,
+               },
+       },
+
+};
+
+const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
+
+/* ------------------------------------------------------------------ */
+/* PCI ids + subsystem IDs                                            */
+
+struct pci_device_id saa7134_pci_tbl[] = {
+       {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2001,
+               .driver_data  = SAA7134_BOARD_PROTEUS_PRO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2001,
+               .driver_data  = SAA7134_BOARD_PROTEUS_PRO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x6752,
+               .driver_data  = SAA7134_BOARD_EMPRESS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x4e85,
+               .driver_data  = SAA7134_BOARD_MONSTERTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1142,
+               .driver_data  = SAA7134_BOARD_CINERGY400,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1143,
+               .driver_data  = SAA7134_BOARD_CINERGY600,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1158,
+               .driver_data  = SAA7134_BOARD_CINERGY600_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1162,
+               .driver_data  = SAA7134_BOARD_CINERGY400_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5169,
+               .subdevice    = 0x0138,
+               .driver_data  = SAA7134_BOARD_FLYVIDEO3000_NTSC,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0138,
+               .driver_data  = SAA7134_BOARD_FLYVIDEO3000,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x4e42,                         /* "Typhoon PCI Capture TV Card" Art.No. 50673 */
+               .subdevice    = 0x0138,
+               .driver_data  = SAA7134_BOARD_FLYVIDEO3000,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0138,
+               .driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x4e42,         /* Typhoon */
+               .subdevice    = 0x0138,         /* LifeView FlyTV Prime30 OEM */
+               .driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0212, /* minipci, LR212 */
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x14c0,
+               .subdevice    = 0x1212, /* minipci, LR1212 */
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI2,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x4e42,
+               .subdevice    = 0x0212, /* OEM minipci, LR212 */
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168, /* Animation Technologies (LifeView) */
+               .subdevice    = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168, /* Animation Technologies (LifeView) */
+               .subdevice    = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1489, /* KYE */
+               .subdevice    = 0x0214, /* Genius VideoWonder ProTV */
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM, /* is an LR214WF actually */
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0003,
+               .driver_data  = SAA7134_BOARD_MD7134,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x16be, /* CTX946 analog TV, HW mpeg, DVB-T */
+               .subdevice    = 0x5000, /* only analog TV and DVB-T for now */
+               .driver_data  = SAA7134_BOARD_MD7134,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1048,
+               .subdevice    = 0x226b,
+               .driver_data  = SAA7134_BOARD_ELSA,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1048,
+               .subdevice    = 0x226a,
+               .driver_data  = SAA7134_BOARD_ELSA_500TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1048,
+               .subdevice    = 0x226c,
+               .driver_data  = SAA7134_BOARD_ELSA_700TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
+               .subdevice    = 0x4842,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
+               .subdevice    = 0x4845,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7135,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
+               .subdevice    = 0x4830,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
+               .subdevice    = 0x4843,
+               .driver_data  = SAA7134_BOARD_ASUSTEK_TVFM7133,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
+               .subdevice    = 0x4840,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0xfe01,
+               .driver_data  = SAA7134_BOARD_TVSTATION_RDS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1894,
+               .subdevice    = 0xfe01,
+               .driver_data  = SAA7134_BOARD_TVSTATION_RDS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1894,
+               .subdevice    = 0xa006,
+               .driver_data  = SAA7134_BOARD_TVSTATION_DVR,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x7133,
+               .driver_data  = SAA7134_BOARD_VA1000POWER,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2001,
+               .driver_data  = SAA7134_BOARD_10MOONSTVMASTER,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc100,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc100,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_MATROX,
+               .subdevice    = 0x48d0,
+               .driver_data  = SAA7134_BOARD_CRONOS_PLUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .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 */
+               .subdevice    = 0x2115,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_305,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa115,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_505,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x2108,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_305,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x10ff,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER,
+       },{
+               /* AVerMedia CardBus */
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xd6ee,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS,
+       },{
+               /* AVerMedia CardBus */
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xb7e9,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_501,
+       }, {
+               /* TransGear 3000TV */
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x050c,
+               .driver_data  = SAA7134_BOARD_TG3000TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x11bd,
+               .subdevice    = 0x002b,
+               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_STEREO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x11bd,
+               .subdevice    = 0x002d,
+               .driver_data  = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1019,
+               .subdevice    = 0x4cb4,
+               .driver_data  = SAA7134_BOARD_ECS_TVP3XP,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1019,
+               .subdevice    = 0x4cb5,
+               .driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB5,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1019,
+               .subdevice    = 0x4cb6,
+               .driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB6,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x12ab,
+               .subdevice    = 0x0800,
+               .driver_data  = SAA7134_BOARD_UPMOST_PURPLE_TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1152,
+               .driver_data  = SAA7134_BOARD_CINERGY200,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc100,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_TV_PVR,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x9715,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_307,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa70a,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_307,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc200,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1540,
+               .subdevice    = 0x9524,
+               .driver_data  = SAA7134_BOARD_PROVIDEO_PV952,
+
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0502,                /* Cardbus version */
+               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0306,                /* PCI version */
+               .driver_data  = SAA7134_BOARD_FLYDVBTDUO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf31f,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
+
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf11d,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M135A,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x4155,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x4255,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2004,
+               .driver_data  = SAA7134_BOARD_PHILIPS_TOUGH,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1421,
+               .subdevice    = 0x0350,         /* PCI version */
+               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1421,
+               .subdevice    = 0x0351,         /* PCI version, new revision */
+               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1421,
+               .subdevice    = 0x0370,         /* cardbus version */
+               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1421,
+               .subdevice    = 0x1370,        /* cardbus version */
+               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x4e42,         /* Typhoon */
+               .subdevice    = 0x0502,         /* LifeView LR502 OEM */
+               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x0210,         /* mini pci NTSC version */
+               .driver_data  = SAA7134_BOARD_FLYTV_DIGIMATRIX,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x0210,         /* mini pci PAL/SECAM version */
+               .driver_data  = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV,
+
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */
+               .subdevice    = 0x4091,
+               .driver_data  = SAA7134_BOARD_BEHOLD_409FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5456, /* GoTView */
+               .subdevice    = 0x7135,
+               .driver_data  = SAA7134_BOARD_GOTVIEW_7135,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2004,
+               .driver_data  = SAA7134_BOARD_PHILIPS_EUROPA,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc900,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_DVBT_300,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc901,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_DVBT_200,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1435,
+               .subdevice    = 0x7350,
+               .driver_data  = SAA7134_BOARD_RTD_VFG7350,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1435,
+               .subdevice    = 0x7330,
+               .driver_data  = SAA7134_BOARD_RTD_VFG7330,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x1044,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x4ee9,
+               .driver_data  = SAA7134_BOARD_MONSTERTV_MOBILE,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x11bd,
+               .subdevice    = 0x002e,
+               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_110i,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4862,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2018,
+               .driver_data  = SAA7134_BOARD_PHILIPS_TIGER,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1462,
+               .subdevice    = 0x6231, /* tda8275a, ks003 IR */
+               .driver_data  = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1462,
+               .subdevice    = 0x8624, /* tda8275, ks003 IR */
+               .driver_data  = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1160,
+               .driver_data  = SAA7134_BOARD_CINERGY250PCI,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,  /* SAA 7131E */
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0319,
+               .driver_data  = SAA7134_BOARD_FLYDVB_TRIO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x2c05,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_777,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0301,
+               .driver_data  = SAA7134_BOARD_FLYDVBT_LR301,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0331,
+               .subdevice    = 0x1421,
+               .driver_data  = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x17de,
+               .subdevice    = 0x7201,
+               .driver_data  = SAA7134_BOARD_TEVION_DVBT_220RF,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x17de,
+               .subdevice    = 0x7250,
+               .driver_data  = SAA7134_BOARD_KWORLD_DVBT_210,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+               .subvendor    = 0x17de,
+               .subdevice    = 0x7350,
+               .driver_data  = SAA7134_BOARD_KWORLD_ATSC110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+               .subvendor    = 0x17de,
+               .subdevice    = 0x7352,
+               .driver_data  = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+               .subvendor    = 0x17de,
+               .subdevice    = 0xa134,
+               .driver_data  = SAA7134_BOARD_KWORLD_PC150U,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x7360,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A169_B,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x6360,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A169_B1,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0005,
+               .driver_data  = SAA7134_BOARD_MD7134_BRIDGE_2,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x0300,
+               .driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x4e42,
+               .subdevice    = 0x0300,/* LR300 */
+               .driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
+       },{
+               .vendor = PCI_VENDOR_ID_PHILIPS,
+               .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor = 0x1489,
+               .subdevice = 0x0301,
+               .driver_data = SAA7134_BOARD_FLYDVBT_LR301,
+       },{
+               .vendor = PCI_VENDOR_ID_PHILIPS,
+               .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor = 0x5168, /* Animation Technologies (LifeView) */
+               .subdevice = 0x0304,
+               .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x3306,
+               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x3502,  /* whats the difference to 0x3306 ?*/
+               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5168,
+               .subdevice    = 0x3307, /* FlyDVB-T Hybrid Mini PCI */
+               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0007,
+               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x0008,
+               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x16be,
+               .subdevice    = 0x000d, /* triple CTX948_V1.1.1 */
+               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x2c05,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_777,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1489,
+               .subdevice    = 0x0502,                /* Cardbus version */
+               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0919, /* Philips Proteus PRO 2309 */
+               .subdevice    = 0x2003,
+               .driver_data  = SAA7134_BOARD_PROTEUS_2309,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461,
+               .subdevice    = 0x2c00,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_A16AR,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4860,
+               .driver_data  = SAA7134_BOARD_ASUS_EUROPA2_HYBRID,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x11bd,
+               .subdevice    = 0x002f,
+               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_310i,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0x9715,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xa11b,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4876,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6700,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6701,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6702,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6703,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6704,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6705,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6706,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6707,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6708,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x6709,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0070,
+               .subdevice    = 0x670a,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1172,
+               .driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2342,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x2341,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x3016,
+               .subdevice    = 0x2344,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1131,
+               .subdevice    = 0x230f,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x1a7f,
+               .subdevice    = 0x2008,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM53,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1a7f,
+               .subdevice    = 0x2108,
+               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM3,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x153b,
+               .subdevice    = 0x1175,
+               .driver_data  = SAA7134_BOARD_CINERGY_HT_PCI,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf31e,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M102,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x4E42,         /* MSI */
+               .subdevice    = 0x0306,         /* TV@nywhere DUO */
+               .driver_data  = SAA7134_BOARD_FLYDVBTDUO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4871,
+               .driver_data  = SAA7134_BOARD_ASUS_P7131_4871,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4857,         /* REV:1.00 */
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TIGER,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */
+               .subdevice    = 0x2003, /* OEM cardbus */
+               .driver_data  = SAA7134_BOARD_SABRENT_TV_PCB05,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2304,
+               .driver_data  = SAA7134_BOARD_10MOONSTVMASTER3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf01d, /* AVerTV DVB-T Super 007 */
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_SUPER_007,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4016,
+               .driver_data  = SAA7134_BOARD_BEHOLD_401,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4036,
+               .driver_data  = SAA7134_BOARD_BEHOLD_403,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4037,
+               .driver_data  = SAA7134_BOARD_BEHOLD_403FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4050,
+               .driver_data  = SAA7134_BOARD_BEHOLD_405,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4051,
+               .driver_data  = SAA7134_BOARD_BEHOLD_405FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4070,
+               .driver_data  = SAA7134_BOARD_BEHOLD_407,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4071,
+               .driver_data  = SAA7134_BOARD_BEHOLD_407FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x4090,
+               .driver_data  = SAA7134_BOARD_BEHOLD_409,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x505B,
+               .driver_data  = SAA7134_BOARD_BEHOLD_505RDS_MK5,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x5051,
+               .driver_data  = SAA7134_BOARD_BEHOLD_505RDS_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x5050,
+               .driver_data  = SAA7134_BOARD_BEHOLD_505FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x5071,
+               .driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x507B,
+               .driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK5,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x5070,
+               .driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x5090,
+               .driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x0000,
+               .subdevice    = 0x5201,
+               .driver_data  = SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6070,
+               .driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6071,
+               .driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK5,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6072,
+               .driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6073,
+               .driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK5,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6090,
+               .driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6091,
+               .driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK5,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6092,
+               .driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK3,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6093,
+               .driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK5,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6190,
+               .driver_data  = SAA7134_BOARD_BEHOLD_M6,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6193,
+               .driver_data  = SAA7134_BOARD_BEHOLD_M6_EXTRA,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6191,
+               .driver_data  = SAA7134_BOARD_BEHOLD_M63,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x4e42,
+               .subdevice    = 0x3502,
+               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .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,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+               .subvendor    = 0x1421,
+               .subdevice    = 0x0380,
+               .driver_data  = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5169,
+               .subdevice    = 0x1502,
+               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x6290,
+               .driver_data  = SAA7134_BOARD_BEHOLD_H6,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf636,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf736,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4878, /* REV:1.02G */
+               .driver_data  = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x48cd,
+               .driver_data  = SAA7134_BOARD_ASUSTeK_PS3_100,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x17de,
+               .subdevice    = 0x7128,
+               .driver_data  = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x17de,
+               .subdevice    = 0xb136,
+               .driver_data  = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
+               .subdevice    = 0xf31d,
+               .driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc900,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_S350,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
+               .subdevice    = 0x7595,
+               .driver_data  = SAA7134_BOARD_BEHOLD_X7,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x19d1, /* RoverMedia */
+               .subdevice    = 0x0138, /* LifeView FlyTV Prime30 OEM */
+               .driver_data  = SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0x2004,
+               .driver_data  = SAA7134_BOARD_ZOLID_HYBRID_PCI,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x1043,
+               .subdevice    = 0x4847,
+               .driver_data  = SAA7134_BOARD_ASUS_EUROPA_HYBRID,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x107d,
+               .subdevice    = 0x6655,
+               .driver_data  = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x13c2,
+               .subdevice    = 0x2804,
+               .driver_data  = SAA7134_BOARD_TECHNOTREND_BUDGET_T3000,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
+               .subdevice    = 0x7190,
+               .driver_data  = SAA7134_BOARD_BEHOLD_H7,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
+               .subdevice    = 0x7090,
+               .driver_data  = SAA7134_BOARD_BEHOLD_A7,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+               .subvendor    = 0x185b,
+               .subdevice    = 0xc900,
+               .driver_data  = SAA7134_BOARD_VIDEOMATE_M1F,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x5030,
+               .driver_data  = SAA7134_BOARD_BEHOLD_503FM,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = 0x5ace,
+               .subdevice    = 0x5010,
+               .driver_data  = SAA7134_BOARD_BEHOLD_501,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = 0x17de,
+               .subdevice    = 0xd136,
+               .driver_data  = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x6000,
+               .subdevice    = 0x0811,
+               .driver_data  = SAA7134_BOARD_SENSORAY811_911,
+       }, {
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = 0x6000,
+               .subdevice    = 0x0911,
+               .driver_data  = SAA7134_BOARD_SENSORAY811_911,
+       }, {
+               /* --- boards without eeprom + subsystem ID --- */
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0,
+               .driver_data  = SAA7134_BOARD_NOAUTO,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_VENDOR_ID_PHILIPS,
+               .subdevice    = 0,
+               .driver_data  = SAA7134_BOARD_NOAUTO,
+       },{
+               /* --- default catch --- */
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+               .driver_data  = SAA7134_BOARD_UNKNOWN,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+               .driver_data  = SAA7134_BOARD_UNKNOWN,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+               .driver_data  = SAA7134_BOARD_UNKNOWN,
+       },{
+               .vendor       = PCI_VENDOR_ID_PHILIPS,
+               .device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+               .driver_data  = SAA7134_BOARD_UNKNOWN,
+       },{
+               /* --- end of list --- */
+       }
+};
+MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl);
+
+/* ----------------------------------------------------------- */
+/* flyvideo tweaks                                             */
+
+
+static void board_flyvideo(struct saa7134_dev *dev)
+{
+       printk("%s: there are different flyvideo cards with different tuners\n"
+              "%s: out there, you might have to use the tuner=<nr> insmod\n"
+              "%s: option to override the default value.\n",
+              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_GPSTATUS0 >> 2, 0x00008000, 0x00000000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+               switch (dev->board) {
+               case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               case SAA7134_BOARD_AVERMEDIA_M103:
+                       saa7134_set_gpio(dev, 23, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 23, 1);
+               break;
+               case SAA7134_BOARD_AVERMEDIA_A16D:
+                       saa7134_set_gpio(dev, 21, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 21, 1);
+               break;
+               case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+                       saa7134_set_gpio(dev, 18, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 18, 1);
+               break;
+               case SAA7134_BOARD_VIDEOMATE_T750:
+                       saa7134_set_gpio(dev, 20, 0);
+                       msleep(10);
+                       saa7134_set_gpio(dev, 20, 1);
+               break;
+               }
+       return 0;
+       }
+       return -EINVAL;
+}
+
+static int saa7134_xc5000_callback(struct saa7134_dev *dev,
+                                  int command, int arg)
+{
+       switch (dev->board) {
+       case SAA7134_BOARD_BEHOLD_X7:
+       case SAA7134_BOARD_BEHOLD_H7:
+       case SAA7134_BOARD_BEHOLD_A7:
+               if (command == XC5000_TUNER_RESET) {
+               /* Down and UP pheripherial RESET pin for reset all chips */
+                       saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
+                       msleep(10);
+                       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+                       msleep(10);
+               }
+               break;
+       default:
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
+               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);
+               break;
+       }
+       return 0;
+}
+
+static int saa7134_tda8290_827x_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;
+}
+
+static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev,
+                                                     enum tda18271_mode mode)
+{
+       /* toggle AGC switch through GPIO 26 */
+       switch (mode) {
+       case TDA18271_ANALOG:
+               saa7134_set_gpio(dev, 26, 0);
+               break;
+       case TDA18271_DIGITAL:
+               saa7134_set_gpio(dev, 26, 1);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev,
+                                                 enum tda18271_mode mode)
+{
+       /* toggle AGC switch through GPIO 27 */
+       switch (mode) {
+       case TDA18271_ANALOG:
+               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+               msleep(20);
+               break;
+       case TDA18271_DIGITAL:
+               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000);
+               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000);
+               msleep(20);
+               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000);
+               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000);
+               msleep(30);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev,
+                                           enum tda18271_mode mode)
+{
+       switch (mode) {
+       case TDA18271_ANALOG:
+               saa7134_set_gpio(dev, 18, 0);
+               break;
+       case TDA18271_DIGITAL:
+               saa7134_set_gpio(dev, 18, 1);
+               msleep(30);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev,
+                                         int command, int arg)
+{
+       int ret = 0;
+
+       switch (command) {
+       case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */
+               switch (dev->board) {
+               case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+               case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+               case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+                       ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
+                       break;
+               case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+                       ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg);
+                       break;
+               case SAA7134_BOARD_KWORLD_PC150U:
+                       ret = saa7134_kworld_pc150u_toggle_agc(dev, arg);
+                       break;
+               default:
+                       break;
+               }
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int saa7134_tda8290_callback(struct saa7134_dev *dev,
+                                   int command, int arg)
+{
+       int ret;
+
+       switch (dev->board) {
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+       case SAA7134_BOARD_AVERMEDIA_M733A:
+       case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+       case SAA7134_BOARD_KWORLD_PC150U:
+       case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+               /* tda8290 + tda18271 */
+               ret = saa7134_tda8290_18271_callback(dev, command, arg);
+               break;
+       default:
+               /* tda8290 + tda827x */
+               ret = saa7134_tda8290_827x_callback(dev, command, arg);
+               break;
+       }
+       return ret;
+}
+
+int saa7134_tuner_callback(void *priv, int component, 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);
+               case TUNER_XC5000:
+                       return saa7134_xc5000_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)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+
+       /* Make sure we support the board model */
+       switch (tv.model) {
+       case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */
+       case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
+       case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
+       case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
+       case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
+       case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
+       case 67569: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM) */
+       case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */
+       case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
+       case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
+       case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
+       case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
+               break;
+       default:
+               printk(KERN_WARNING "%s: warning: "
+                      "unknown hauppauge model #%d\n", dev->name, tv.model);
+               break;
+       }
+
+       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+              dev->name, tv.model);
+}
+
+/* ----------------------------------------------------------- */
+
+int saa7134_board_init1(struct saa7134_dev *dev)
+{
+       /* Always print gpio, often manufacturers encode tuner type and other info. */
+       saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0);
+       dev->gpio_value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+       printk(KERN_INFO "%s: board init: gpio is %x\n", dev->name, dev->gpio_value);
+
+       switch (dev->board) {
+       case SAA7134_BOARD_FLYVIDEO2000:
+       case SAA7134_BOARD_FLYVIDEO3000:
+       case SAA7134_BOARD_FLYVIDEO3000_NTSC:
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               board_flyvideo(dev);
+               break;
+       case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
+       case SAA7134_BOARD_FLYTVPLATINUM_FM:
+       case SAA7134_BOARD_CINERGY400:
+       case SAA7134_BOARD_CINERGY600:
+       case SAA7134_BOARD_CINERGY600_MK3:
+       case SAA7134_BOARD_ECS_TVP3XP:
+       case SAA7134_BOARD_ECS_TVP3XP_4CB5:
+       case SAA7134_BOARD_ECS_TVP3XP_4CB6:
+       case SAA7134_BOARD_MD2819:
+       case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
+       case SAA7134_BOARD_KWORLD_XPERT:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
+       case SAA7134_BOARD_AVERMEDIA_305:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+       case SAA7134_BOARD_AVERMEDIA_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
+       case SAA7134_BOARD_AVERMEDIA_777:
+       case SAA7134_BOARD_AVERMEDIA_M135A:
+/*      case SAA7134_BOARD_SABRENT_SBTTVFM:  */ /* not finished yet */
+       case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+       case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
+       case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
+       case SAA7134_BOARD_VIDEOMATE_M1F:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+       case SAA7134_BOARD_MANLI_MTV001:
+       case SAA7134_BOARD_MANLI_MTV002:
+       case SAA7134_BOARD_BEHOLD_409FM:
+       case SAA7134_BOARD_AVACSSMARTTV:
+       case SAA7134_BOARD_GOTVIEW_7135:
+       case SAA7134_BOARD_KWORLD_TERMINATOR:
+       case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
+       case SAA7134_BOARD_FLYDVBT_LR301:
+       case SAA7134_BOARD_ASUSTeK_PS3_100:
+       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+       case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
+       case SAA7134_BOARD_FLYDVBTDUO:
+       case SAA7134_BOARD_PROTEUS_2309:
+       case SAA7134_BOARD_AVERMEDIA_A16AR:
+       case SAA7134_BOARD_ENCORE_ENLTV:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM3:
+       case SAA7134_BOARD_10MOONSTVMASTER3:
+       case SAA7134_BOARD_BEHOLD_401:
+       case SAA7134_BOARD_BEHOLD_403:
+       case SAA7134_BOARD_BEHOLD_403FM:
+       case SAA7134_BOARD_BEHOLD_405:
+       case SAA7134_BOARD_BEHOLD_405FM:
+       case SAA7134_BOARD_BEHOLD_407:
+       case SAA7134_BOARD_BEHOLD_407FM:
+       case SAA7134_BOARD_BEHOLD_409:
+       case SAA7134_BOARD_BEHOLD_505FM:
+       case SAA7134_BOARD_BEHOLD_505RDS_MK5:
+       case SAA7134_BOARD_BEHOLD_505RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_507_9FM:
+       case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_507RDS_MK5:
+       case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
+       case SAA7134_BOARD_REAL_ANGEL_220:
+       case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
+       case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
+       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               break;
+       case SAA7134_BOARD_FLYDVBS_LR300:
+               saa_writeb(SAA7134_GPIO_GPMODE3, 0x80);
+               saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x40);
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               break;
+       case SAA7134_BOARD_MD5044:
+               printk("%s: seems there are two different versions of the MD5044\n"
+                      "%s: (with the same ID) out there.  If sound doesn't work for\n"
+                      "%s: you try the audio_clock_override=0x200000 insmod option.\n",
+                      dev->name,dev->name,dev->name);
+               break;
+       case SAA7134_BOARD_CINERGY400_CARDBUS:
+               /* power-up tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
+               break;
+       case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
+               /* this turns the remote control chip off to work around a bug in it */
+               saa_writeb(SAA7134_GPIO_GPMODE1, 0x80);
+               saa_writeb(SAA7134_GPIO_GPSTATUS1, 0x80);
+               break;
+       case SAA7134_BOARD_MONSTERTV_MOBILE:
+               /* power-up tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
+               break;
+       case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
+               /* turn the fan on */
+               saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
+               saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
+               break;
+       case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08000000, 0x08000000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS:
+       case SAA7134_BOARD_AVERMEDIA_M115:
+               /* 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(10);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+               /* power-down tuner chip */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0);
+               msleep(10);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000);
+               msleep(10);
+               dev->has_remote = SAA7134_REMOTE_I2C;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               saa7134_set_gpio(dev, 23, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 23, 1);
+               dev->has_remote = SAA7134_REMOTE_I2C;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_M103:
+               saa7134_set_gpio(dev, 23, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 23, 1);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               saa7134_set_gpio(dev, 21, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 21, 1);
+               msleep(1);
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               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:
+
+               /*
+                * Make sure Production Test Register at offset 0x1D1 is cleared
+                * to take chip out of test mode.  Clearing bit 4 (TST_EN_AOUT)
+                * prevents pin 105 from remaining low; keeping pin 105 low
+                * continually resets the SAA6752 chip.
+                */
+
+               saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               /* GPIO 26 high for digital, low for analog */
+               saa7134_set_gpio(dev, 26, 0);
+               msleep(1);
+
+               saa7134_set_gpio(dev, 22, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 22, 1);
+               break;
+       /* i2c remotes */
+       case SAA7134_BOARD_PINNACLE_PCTV_110i:
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
+       case SAA7134_BOARD_UPMOST_PURPLE_TV:
+       case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+       case SAA7134_BOARD_BEHOLD_607FM_MK3:
+       case SAA7134_BOARD_BEHOLD_607FM_MK5:
+       case SAA7134_BOARD_BEHOLD_609FM_MK3:
+       case SAA7134_BOARD_BEHOLD_609FM_MK5:
+       case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+       case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_609RDS_MK5:
+       case SAA7134_BOARD_BEHOLD_M6:
+       case SAA7134_BOARD_BEHOLD_M63:
+       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+       case SAA7134_BOARD_BEHOLD_H6:
+       case SAA7134_BOARD_BEHOLD_X7:
+       case SAA7134_BOARD_BEHOLD_H7:
+       case SAA7134_BOARD_BEHOLD_A7:
+       case SAA7134_BOARD_KWORLD_PC150U:
+               dev->has_remote = SAA7134_REMOTE_I2C;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A169_B:
+               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",
+                      dev->name,card(dev).name,dev->name,dev->name);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_M102:
+               /* enable tuner */
+              dev->has_remote = SAA7134_REMOTE_GPIO;
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
+               /* write windows gpio values */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
+               break;
+       case SAA7134_BOARD_VIDEOMATE_S350:
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0000C000, 0x0000C000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_M733A:
+               saa7134_set_gpio(dev, 1, 1);
+               msleep(10);
+               saa7134_set_gpio(dev, 1, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 1, 1);
+               dev->has_remote = SAA7134_REMOTE_GPIO;
+               break;
+       case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+               /* enable LGS-8G75 */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0e050000, 0x0c050000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0e050000, 0x0c050000);
+               break;
+       case SAA7134_BOARD_VIDEOMATE_T750:
+               /* enable the analog tuner */
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00008000, 0x00008000);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+               break;
+       }
+       return 0;
+}
+
+static void saa7134_tuner_setup(struct saa7134_dev *dev)
+{
+       struct tuner_setup tun_setup;
+       unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
+       tun_setup.tuner_callback = saa7134_tuner_callback;
+
+       if (saa7134_boards[dev->board].radio_type != UNSET) {
+               tun_setup.type = saa7134_boards[dev->board].radio_type;
+               tun_setup.addr = saa7134_boards[dev->board].radio_addr;
+
+               tun_setup.mode_mask = T_RADIO;
+
+               saa_call_all(dev, tuner, s_type_addr, &tun_setup);
+               mode_mask &= ~T_RADIO;
+       }
+
+       if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
+               tun_setup.type = dev->tuner_type;
+               tun_setup.addr = dev->tuner_addr;
+               tun_setup.config = saa7134_boards[dev->board].tuner_config;
+               tun_setup.tuner_callback = saa7134_tuner_callback;
+
+               tun_setup.mode_mask = mode_mask;
+
+               saa_call_all(dev, tuner, s_type_addr, &tun_setup);
+       }
+
+       if (dev->tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &dev->tda9887_conf;
+
+               saa_call_all(dev, tuner, s_config, &tda9887_cfg);
+       }
+
+       if (dev->tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+               ctl.max_len = 64;
+
+               switch (dev->board) {
+               case SAA7134_BOARD_AVERMEDIA_A16D:
+               case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               case SAA7134_BOARD_AVERMEDIA_M103:
+               case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+                       ctl.demod = XC3028_FE_ZARLINK456;
+                       break;
+               default:
+                       ctl.demod = XC3028_FE_OREN538;
+                       ctl.mts = 1;
+               }
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               saa_call_all(dev, tuner, s_config, &xc2028_cfg);
+       }
+}
+
+/* stuff which needs working i2c */
+int saa7134_board_init2(struct saa7134_dev *dev)
+{
+       unsigned char buf;
+       int board;
+
+       /* Put here the code that enables the chips that are needed
+          for analog mode and doesn't depend on the tuner attachment.
+          It is also a good idea to get tuner type from eeprom, etc before
+          initializing tuner, since we can avoid loading tuner driver
+          on devices that has TUNER_ABSENT
+        */
+       switch (dev->board) {
+       case SAA7134_BOARD_BMK_MPEX_NOTUNER:
+       case SAA7134_BOARD_BMK_MPEX_TUNER:
+               /* Checks if the device has a tuner at 0x60 addr
+                  If the device doesn't have a tuner, TUNER_ABSENT
+                  will be used at tuner_type, avoiding loading tuner
+                  without needing it
+                */
+               dev->i2c_client.addr = 0x60;
+               board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
+                       ? SAA7134_BOARD_BMK_MPEX_NOTUNER
+                       : SAA7134_BOARD_BMK_MPEX_TUNER;
+               if (board == dev->board)
+                       break;
+               dev->board = board;
+               printk("%s: board type fixup: %s\n", dev->name,
+               saa7134_boards[dev->board].name);
+               dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+
+               break;
+       case SAA7134_BOARD_MD7134:
+       {
+               u8 subaddr;
+               u8 data[3];
+               int ret, tuner_t;
+               struct i2c_msg msg[] = {{.addr=0x50, .flags=0, .buf=&subaddr, .len = 1},
+                                       {.addr=0x50, .flags=I2C_M_RD, .buf=data, .len = 3}};
+
+               subaddr= 0x14;
+               tuner_t = 0;
+
+               /* Retrieve device data from eeprom, checking for the
+                  proper tuner_type.
+                */
+               ret = i2c_transfer(&dev->i2c_adap, msg, 2);
+               if (ret != 2) {
+                       printk(KERN_ERR "EEPROM read failure\n");
+               } else if ((data[0] != 0) && (data[0] != 0xff)) {
+                       /* old config structure */
+                       subaddr = data[0] + 2;
+                       msg[1].len = 2;
+                       i2c_transfer(&dev->i2c_adap, msg, 2);
+                       tuner_t = (data[0] << 8) + data[1];
+                       switch (tuner_t){
+                       case 0x0103:
+                               dev->tuner_type = TUNER_PHILIPS_PAL;
+                               break;
+                       case 0x010C:
+                               dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+                               break;
+                       default:
+                               printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+                       }
+               } else if ((data[1] != 0) && (data[1] != 0xff)) {
+                       /* new config structure */
+                       subaddr = data[1] + 1;
+                       msg[1].len = 1;
+                       i2c_transfer(&dev->i2c_adap, msg, 2);
+                       subaddr = data[0] + 1;
+                       msg[1].len = 2;
+                       i2c_transfer(&dev->i2c_adap, msg, 2);
+                       tuner_t = (data[1] << 8) + data[0];
+                       switch (tuner_t) {
+                       case 0x0005:
+                               dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+                               break;
+                       case 0x001d:
+                               dev->tuner_type = TUNER_PHILIPS_FMD1216ME_MK3;
+                                       printk(KERN_INFO "%s Board has DVB-T\n", dev->name);
+                               break;
+                       default:
+                               printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+                       }
+               } else {
+                       printk(KERN_ERR "%s unexpected config structure\n", dev->name);
+               }
+
+               printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
+               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;
+               }
+               /* break intentionally omitted */
+       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+       case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+       case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
+       case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000:
+       {
+
+               /* The Philips EUROPA based hybrid boards have the tuner
+                  connected through the channel decoder. We have to make it
+                  transparent to find it
+                */
+               u8 data[] = { 0x07, 0x02};
+               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+               break;
+       }
+       case SAA7134_BOARD_PHILIPS_TIGER:
+       case SAA7134_BOARD_PHILIPS_TIGER_S:
+       {
+               u8 data[] = { 0x3c, 0x33, 0x60};
+               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+               if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
+                       dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
+                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
+                               dev->name, saa7134_boards[dev->board].name);
+               }
+               if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
+                       dev->tuner_type = TUNER_PHILIPS_TDA8290;
+
+                       data[2] = 0x68;
+                       i2c_transfer(&dev->i2c_adap, &msg, 1);
+                       break;
+               }
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
+       case SAA7134_BOARD_ASUSTeK_TVFM7135:
+       /* The card below is detected as card=53, but is different */
+              if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
+                      dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
+                      printk(KERN_INFO "%s: P7131 analog only, using "
+                                                      "entry of %s\n",
+                      dev->name, saa7134_boards[dev->board].name);
+
+                       /* IR init has already happened for other cards, so
+                        * we have to catch up. */
+                       dev->has_remote = SAA7134_REMOTE_GPIO;
+                       saa7134_input_init1(dev);
+              }
+              break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+               hauppauge_eeprom(dev, dev->eedata+0x80);
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+               hauppauge_eeprom(dev, dev->eedata+0x80);
+               /* break intentionally omitted */
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
+       case SAA7134_BOARD_KWORLD_DVBT_210:
+       case SAA7134_BOARD_TEVION_DVBT_220RF:
+       case SAA7134_BOARD_ASUSTeK_TIGER:
+       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+       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
+                */
+               u8 data[] = { 0x3c, 0x33, 0x60};
+               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
+       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+       {
+               u8 data[] = { 0x3c, 0x33, 0x60};
+               struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
+                                                       .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
+       case SAA7134_BOARD_ASUSTeK_PS3_100:
+       {
+               u8 data[] = { 0x3c, 0x33, 0x60};
+               struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
+                                                      .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
+       case SAA7134_BOARD_FLYDVB_TRIO:
+       {
+               u8 temp = 0;
+               int rc;
+               u8 data[] = { 0x3c, 0x33, 0x62};
+               struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+               /*
+                * send weak up message to pic16C505 chip
+                * @ LifeView FlyDVB Trio
+                */
+               msg.buf = &temp;
+               msg.addr = 0x0b;
+               msg.len = 1;
+               if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) {
+                       printk(KERN_WARNING "%s: send wake up byte to pic16C505"
+                                       "(IR chip) failed\n", dev->name);
+               } else {
+                       msg.flags = I2C_M_RD;
+                       rc = i2c_transfer(&dev->i2c_adap, &msg, 1);
+                       printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n",
+                                  dev->name, msg.addr,
+                                  (1 == rc) ? "yes" : "no");
+                       if (rc == 1)
+                               dev->has_remote = SAA7134_REMOTE_I2C;
+               }
+               break;
+       }
+       case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+       {
+               /* initialize analog mode  */
+               u8 data[] = { 0x3c, 0x33, 0x6a};
+               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
+       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+       case SAA7134_BOARD_CINERGY_HT_PCI:
+       {
+               /* initialize analog mode */
+               u8 data[] = { 0x3c, 0x33, 0x68};
+               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+               i2c_transfer(&dev->i2c_adap, &msg, 1);
+               break;
+       }
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+               /* The T200 and the T200A share the same pci id.  Consequently,
+                * we are going to query eeprom to try to find out which one we
+                * are actually looking at. */
+
+               /* Don't do this if the board was specifically selected with an
+                * insmod option or if we have the default configuration T200*/
+               if (!dev->autodetected || (dev->eedata[0x41] == 0xd0))
+                       break;
+               if (dev->eedata[0x41] == 0x02) {
+                       /* Reconfigure board  as T200A */
+                       dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
+                       dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
+                       dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
+                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
+                               dev->name, saa7134_boards[dev->board].name);
+               } else {
+                       printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
+                               dev->name, dev->eedata[0x41]);
+                       break;
+               }
+               break;
+       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
+       case SAA7134_BOARD_KWORLD_ATSC110:
+       {
+               struct i2c_msg msg = { .addr = 0x0a, .flags = 0 };
+               int i;
+               static u8 buffer[][2] = {
+                       { 0x10, 0x12 },
+                       { 0x13, 0x04 },
+                       { 0x16, 0x00 },
+                       { 0x14, 0x04 },
+                       { 0x17, 0x00 },
+               };
+
+               for (i = 0; i < ARRAY_SIZE(buffer); i++) {
+                       msg.buf = &buffer[i][0];
+                       msg.len = ARRAY_SIZE(buffer[0]);
+                       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+                               printk(KERN_WARNING
+                                      "%s: Unable to enable tuner(%i).\n",
+                                      dev->name, i);
+               }
+               break;
+       }
+       case SAA7134_BOARD_BEHOLD_H6:
+       {
+               u8 data[] = { 0x09, 0x9f, 0x86, 0x11};
+               struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = data,
+                                                       .len = sizeof(data)};
+
+               /* The tuner TUNER_PHILIPS_FMD1216MEX_MK3 after hardware    */
+               /* start has disabled IF and enabled DVB-T. When saa7134    */
+               /* scan I2C devices it not detect IF tda9887 and can`t      */
+               /* watch TV without software reboot. For solve this problem */
+               /* switch the tuner to analog TV mode manually.             */
+               if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+                               printk(KERN_WARNING
+                                     "%s: Unable to enable IF of the tuner.\n",
+                                      dev->name);
+               break;
+       }
+       case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+
+               saa7134_set_gpio(dev, 27, 0);
+               break;
+       } /* switch() */
+
+       /* initialize tuner */
+       if (TUNER_ABSENT != dev->tuner_type) {
+               int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
+
+               /* Note: radio tuner address is always filled in,
+                  so we do not need to probe for a radio tuner device. */
+               if (dev->radio_type != UNSET)
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "tuner",
+                               dev->radio_addr, NULL);
+               if (has_demod)
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+               if (dev->tuner_addr == ADDR_UNSET) {
+                       enum v4l2_i2c_tuner_type type =
+                               has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(type));
+               } else {
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "tuner",
+                               dev->tuner_addr, NULL);
+               }
+       }
+
+       saa7134_tuner_setup(dev);
+
+       switch (dev->board) {
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+       {
+               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;
+               saa_call_all(dev, tuner, s_config, &tea5767_cfg);
+               break;
+       }
+       } /* switch() */
+
+       return 0;
+}
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
new file mode 100644 (file)
index 0000000..5fbb4e4
--- /dev/null
@@ -0,0 +1,1368 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * driver core
+ *
+ * (c) 2001-03 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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/sound.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SAA7134_VERSION);
+
+
+/* ------------------------------------------------------------------ */
+
+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;
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+static unsigned int gpio_tracking;
+module_param(gpio_tracking, int, 0644);
+MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
+
+static unsigned int alsa = 1;
+module_param(alsa, int, 0644);
+MODULE_PARM_DESC(alsa,"enable/disable ALSA DMA sound [dmasound]");
+
+static unsigned int latency = UNSET;
+module_param(latency, int, 0444);
+MODULE_PARM_DESC(latency,"pci latency timer");
+
+int saa7134_no_overlay=-1;
+module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
+MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
+               " [some VIA/SIS chipsets are known to have problem with overlay]");
+
+static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int tuner[]    = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int card[]     = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr,   int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+module_param_array(tuner,    int, NULL, 0444);
+module_param_array(card,     int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device number");
+MODULE_PARM_DESC(vbi_nr,   "vbi device number");
+MODULE_PARM_DESC(radio_nr, "radio device number");
+MODULE_PARM_DESC(tuner,    "tuner type");
+MODULE_PARM_DESC(card,     "card type");
+
+DEFINE_MUTEX(saa7134_devlist_lock);
+EXPORT_SYMBOL(saa7134_devlist_lock);
+LIST_HEAD(saa7134_devlist);
+EXPORT_SYMBOL(saa7134_devlist);
+static LIST_HEAD(mops_list);
+static unsigned int saa7134_devcount;
+
+int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
+
+#define dprintk(fmt, arg...)   if (core_debug) \
+       printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
+
+void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
+{
+       unsigned long mode,status;
+
+       if (!gpio_tracking)
+               return;
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+       saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,0);
+       saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN);
+       mode   = saa_readl(SAA7134_GPIO_GPMODE0   >> 2) & 0xfffffff;
+       status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff;
+       printk(KERN_DEBUG
+              "%s: gpio: mode=0x%07lx in=0x%07lx out=0x%07lx [%s]\n",
+              dev->name, mode, (~mode) & status, mode & status, msg);
+}
+
+void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
+{
+       u32 index, bitval;
+
+       index = 1 << bit_no;
+       switch (value) {
+       case 0: /* static value */
+       case 1: dprintk("setting GPIO%d to static %d\n", bit_no, value);
+               /* turn sync mode off if necessary */
+               if (index & 0x00c00000)
+                       saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x00);
+               if (value)
+                       bitval = index;
+               else
+                       bitval = 0;
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, index);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, index, bitval);
+               break;
+       case 3: /* tristate */
+               dprintk("setting GPIO%d to tristate\n", bit_no);
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, 0);
+               break;
+       }
+}
+
+/* ------------------------------------------------------------------ */
+
+
+/* ----------------------------------------------------------- */
+/* delayed request_module                                      */
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+
+static void request_module_async(struct work_struct *work){
+       struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk);
+       if (card_is_empress(dev))
+               request_module("saa7134-empress");
+       if (card_is_dvb(dev))
+               request_module("saa7134-dvb");
+       if (alsa) {
+               if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
+                       request_module("saa7134-alsa");
+       }
+}
+
+static void request_submodules(struct saa7134_dev *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_submodules(struct saa7134_dev *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+
+#else
+#define request_submodules(dev)
+#define flush_request_submodules(dev)
+#endif /* CONFIG_MODULES */
+
+/* ------------------------------------------------------------------ */
+
+/* nr of (saa7134-)pages for the given buffer size */
+static int saa7134_buffer_pages(int size)
+{
+       size  = PAGE_ALIGN(size);
+       size += PAGE_SIZE; /* for non-page-aligned buffers */
+       size /= 4096;
+       return size;
+}
+
+/* calc max # of buffers from size (must not exceed the 4MB virtual
+ * address space per DMA channel) */
+int saa7134_buffer_count(unsigned int size, unsigned int count)
+{
+       unsigned int maxcount;
+
+       maxcount = 1024 / saa7134_buffer_pages(size);
+       if (count > maxcount)
+               count = maxcount;
+       return count;
+}
+
+int saa7134_buffer_startpage(struct saa7134_buf *buf)
+{
+       return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i;
+}
+
+unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
+{
+       unsigned long base;
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+       base  = saa7134_buffer_startpage(buf) * 4096;
+       base += dma->sglist[0].offset;
+       return base;
+}
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
+{
+       __le32       *cpu;
+       dma_addr_t   dma_addr = 0;
+
+       cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
+       if (NULL == cpu)
+               return -ENOMEM;
+       pt->size = SAA7134_PGTABLE_SIZE;
+       pt->cpu  = cpu;
+       pt->dma  = dma_addr;
+       return 0;
+}
+
+int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
+                         struct scatterlist *list, unsigned int length,
+                         unsigned int startpage)
+{
+       __le32        *ptr;
+       unsigned int  i,p;
+
+       BUG_ON(NULL == pt || NULL == pt->cpu);
+
+       ptr = pt->cpu + startpage;
+       for (i = 0; i < length; i++, list++)
+               for (p = 0; p * 4096 < list->length; p++, ptr++)
+                       *ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
+       return 0;
+}
+
+void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
+{
+       if (NULL == pt->cpu)
+               return;
+       pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
+       pt->cpu = NULL;
+}
+
+/* ------------------------------------------------------------------ */
+
+void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
+{
+       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+       BUG_ON(in_interrupt());
+
+       videobuf_waiton(q, &buf->vb, 0, 0);
+       videobuf_dma_unmap(q->dev, dma);
+       videobuf_dma_free(dma);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_buffer_queue(struct saa7134_dev *dev,
+                        struct saa7134_dmaqueue *q,
+                        struct saa7134_buf *buf)
+{
+       struct saa7134_buf *next = NULL;
+
+       assert_spin_locked(&dev->slock);
+       dprintk("buffer_queue %p\n",buf);
+       if (NULL == q->curr) {
+               if (!q->need_two) {
+                       q->curr = buf;
+                       buf->activate(dev,buf,NULL);
+               } else if (list_empty(&q->queue)) {
+                       list_add_tail(&buf->vb.queue,&q->queue);
+                       buf->vb.state = VIDEOBUF_QUEUED;
+               } else {
+                       next = list_entry(q->queue.next,struct saa7134_buf,
+                                         vb.queue);
+                       q->curr = buf;
+                       buf->activate(dev,buf,next);
+               }
+       } else {
+               list_add_tail(&buf->vb.queue,&q->queue);
+               buf->vb.state = VIDEOBUF_QUEUED;
+       }
+       return 0;
+}
+
+void saa7134_buffer_finish(struct saa7134_dev *dev,
+                          struct saa7134_dmaqueue *q,
+                          unsigned int state)
+{
+       assert_spin_locked(&dev->slock);
+       dprintk("buffer_finish %p\n",q->curr);
+
+       /* finish current buffer */
+       q->curr->vb.state = state;
+       do_gettimeofday(&q->curr->vb.ts);
+       wake_up(&q->curr->vb.done);
+       q->curr = NULL;
+}
+
+void saa7134_buffer_next(struct saa7134_dev *dev,
+                        struct saa7134_dmaqueue *q)
+{
+       struct saa7134_buf *buf,*next = NULL;
+
+       assert_spin_locked(&dev->slock);
+       BUG_ON(NULL != q->curr);
+
+       if (!list_empty(&q->queue)) {
+               /* activate next one from queue */
+               buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue);
+               dprintk("buffer_next %p [prev=%p/next=%p]\n",
+                       buf,q->queue.prev,q->queue.next);
+               list_del(&buf->vb.queue);
+               if (!list_empty(&q->queue))
+                       next = list_entry(q->queue.next,struct saa7134_buf,
+                                         vb.queue);
+               q->curr = buf;
+               buf->activate(dev,buf,next);
+               dprintk("buffer_next #2 prev=%p/next=%p\n",
+                       q->queue.prev,q->queue.next);
+       } else {
+               /* nothing to do -- just stop DMA */
+               dprintk("buffer_next %p\n",NULL);
+               saa7134_set_dmabits(dev);
+               del_timer(&q->timeout);
+
+               if (card_has_mpeg(dev))
+                       if (dev->ts_started)
+                               saa7134_ts_stop(dev);
+       }
+}
+
+void saa7134_buffer_timeout(unsigned long data)
+{
+       struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data;
+       struct saa7134_dev *dev = q->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->slock,flags);
+
+       /* try to reset the hardware (SWRST) */
+       saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+       saa_writeb(SAA7134_REGION_ENABLE, 0x80);
+       saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+
+       /* flag current buffer as failed,
+          try to start over with the next one. */
+       if (q->curr) {
+               dprintk("timeout on %p\n",q->curr);
+               saa7134_buffer_finish(dev,q,VIDEOBUF_ERROR);
+       }
+       saa7134_buffer_next(dev,q);
+       spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_set_dmabits(struct saa7134_dev *dev)
+{
+       u32 split, task=0, ctrl=0, irq=0;
+       enum v4l2_field cap = V4L2_FIELD_ANY;
+       enum v4l2_field ov  = V4L2_FIELD_ANY;
+
+       assert_spin_locked(&dev->slock);
+
+       if (dev->insuspend)
+               return 0;
+
+       /* video capture -- dma 0 + video task A */
+       if (dev->video_q.curr) {
+               task |= 0x01;
+               ctrl |= SAA7134_MAIN_CTRL_TE0;
+               irq  |= SAA7134_IRQ1_INTE_RA0_1 |
+                       SAA7134_IRQ1_INTE_RA0_0;
+               cap = dev->video_q.curr->vb.field;
+       }
+
+       /* video capture -- dma 1+2 (planar modes) */
+       if (dev->video_q.curr &&
+           dev->video_q.curr->fmt->planar) {
+               ctrl |= SAA7134_MAIN_CTRL_TE4 |
+                       SAA7134_MAIN_CTRL_TE5;
+       }
+
+       /* screen overlay -- dma 0 + video task B */
+       if (dev->ovenable) {
+               task |= 0x10;
+               ctrl |= SAA7134_MAIN_CTRL_TE1;
+               ov = dev->ovfield;
+       }
+
+       /* vbi capture -- dma 0 + vbi task A+B */
+       if (dev->vbi_q.curr) {
+               task |= 0x22;
+               ctrl |= SAA7134_MAIN_CTRL_TE2 |
+                       SAA7134_MAIN_CTRL_TE3;
+               irq  |= SAA7134_IRQ1_INTE_RA0_7 |
+                       SAA7134_IRQ1_INTE_RA0_6 |
+                       SAA7134_IRQ1_INTE_RA0_5 |
+                       SAA7134_IRQ1_INTE_RA0_4;
+       }
+
+       /* audio capture -- dma 3 */
+       if (dev->dmasound.dma_running) {
+               ctrl |= SAA7134_MAIN_CTRL_TE6;
+               irq  |= SAA7134_IRQ1_INTE_RA3_1 |
+                       SAA7134_IRQ1_INTE_RA3_0;
+       }
+
+       /* TS capture -- dma 5 */
+       if (dev->ts_q.curr) {
+               ctrl |= SAA7134_MAIN_CTRL_TE5;
+               irq  |= SAA7134_IRQ1_INTE_RA2_1 |
+                       SAA7134_IRQ1_INTE_RA2_0;
+       }
+
+       /* set task conditions + field handling */
+       if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
+               /* default config -- use full frames */
+               saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
+               saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
+               saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x02);
+               saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x02);
+               split = 0;
+       } else {
+               /* split fields between tasks */
+               if (V4L2_FIELD_TOP == cap) {
+                       /* odd A, even B, repeat */
+                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
+                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0e);
+               } else {
+                       /* odd B, even A, repeat */
+                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0e);
+                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
+               }
+               saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x01);
+               saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x01);
+               split = 1;
+       }
+
+       /* irqs */
+       saa_writeb(SAA7134_REGION_ENABLE, task);
+       saa_writel(SAA7134_IRQ1,          irq);
+       saa_andorl(SAA7134_MAIN_CTRL,
+                  SAA7134_MAIN_CTRL_TE0 |
+                  SAA7134_MAIN_CTRL_TE1 |
+                  SAA7134_MAIN_CTRL_TE2 |
+                  SAA7134_MAIN_CTRL_TE3 |
+                  SAA7134_MAIN_CTRL_TE4 |
+                  SAA7134_MAIN_CTRL_TE5 |
+                  SAA7134_MAIN_CTRL_TE6,
+                  ctrl);
+       dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
+               task, ctrl, irq, split ? "no" : "yes");
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* IRQ handler + helpers                                              */
+
+static char *irqbits[] = {
+       "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3",
+       "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
+       "TRIG_ERR", "CONF_ERR", "LOAD_ERR",
+       "GPIO16", "GPIO18", "GPIO22", "GPIO23"
+};
+#define IRQBITS ARRAY_SIZE(irqbits)
+
+static void print_irqstatus(struct saa7134_dev *dev, int loop,
+                           unsigned long report, unsigned long status)
+{
+       unsigned int i;
+
+       printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
+              dev->name,loop,jiffies,report,status);
+       for (i = 0; i < IRQBITS; i++) {
+               if (!(report & (1 << i)))
+                       continue;
+               printk(" %s",irqbits[i]);
+       }
+       if (report & SAA7134_IRQ_REPORT_DONE_RA0) {
+               printk(" | RA0=%s,%s,%s,%ld",
+                      (status & 0x40) ? "vbi"  : "video",
+                      (status & 0x20) ? "b"    : "a",
+                      (status & 0x10) ? "odd"  : "even",
+                      (status & 0x0f));
+       }
+       printk("\n");
+}
+
+static irqreturn_t saa7134_irq(int irq, void *dev_id)
+{
+       struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
+       unsigned long report,status;
+       int loop, handled = 0;
+
+       if (dev->insuspend)
+               goto out;
+
+       for (loop = 0; loop < 10; loop++) {
+               report = saa_readl(SAA7134_IRQ_REPORT);
+               status = saa_readl(SAA7134_IRQ_STATUS);
+
+               /* If dmasound support is active and we get a sound report,
+                * mask out the report and let the saa7134-alsa module deal
+                * with it */
+               if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
+                       (dev->dmasound.priv_data != NULL) )
+               {
+                       if (irq_debug > 1)
+                               printk(KERN_DEBUG "%s/irq: preserving DMA sound interrupt\n",
+                                      dev->name);
+                       report &= ~SAA7134_IRQ_REPORT_DONE_RA3;
+               }
+
+               if (0 == report) {
+                       if (irq_debug > 1)
+                               printk(KERN_DEBUG "%s/irq: no (more) work\n",
+                                      dev->name);
+                       goto out;
+               }
+
+               handled = 1;
+               saa_writel(SAA7134_IRQ_REPORT,report);
+               if (irq_debug)
+                       print_irqstatus(dev,loop,report,status);
+
+
+               if ((report & SAA7134_IRQ_REPORT_RDCAP) ||
+                       (report & SAA7134_IRQ_REPORT_INTL))
+                               saa7134_irq_video_signalchange(dev);
+
+
+               if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
+                   (status & 0x60) == 0)
+                       saa7134_irq_video_done(dev,status);
+
+               if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
+                   (status & 0x40) == 0x40)
+                       saa7134_irq_vbi_done(dev,status);
+
+               if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
+                   card_has_mpeg(dev))
+                       saa7134_irq_ts_done(dev,status);
+
+               if (report & SAA7134_IRQ_REPORT_GPIO16) {
+                       switch (dev->has_remote) {
+                               case SAA7134_REMOTE_GPIO:
+                                       if (!dev->remote)
+                                               break;
+                                       if  (dev->remote->mask_keydown & 0x10000) {
+                                               saa7134_input_irq(dev);
+                                       }
+                                       break;
+
+                               case SAA7134_REMOTE_I2C:
+                                       break;                  /* FIXME: invoke I2C get_key() */
+
+                               default:                        /* GPIO16 not used by IR remote */
+                                       break;
+                       }
+               }
+
+               if (report & SAA7134_IRQ_REPORT_GPIO18) {
+                       switch (dev->has_remote) {
+                               case SAA7134_REMOTE_GPIO:
+                                       if (!dev->remote)
+                                               break;
+                                       if ((dev->remote->mask_keydown & 0x40000) ||
+                                           (dev->remote->mask_keyup & 0x40000)) {
+                                               saa7134_input_irq(dev);
+                                       }
+                                       break;
+
+                               case SAA7134_REMOTE_I2C:
+                                       break;                  /* FIXME: invoke I2C get_key() */
+
+                               default:                        /* GPIO18 not used by IR remote */
+                                       break;
+                       }
+               }
+       }
+
+       if (10 == loop) {
+               print_irqstatus(dev,loop,report,status);
+               if (report & SAA7134_IRQ_REPORT_PE) {
+                       /* disable all parity error */
+                       printk(KERN_WARNING "%s/irq: looping -- "
+                              "clearing PE (parity error!) enable bit\n",dev->name);
+                       saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
+               } else if (report & SAA7134_IRQ_REPORT_GPIO16) {
+                       /* disable gpio16 IRQ */
+                       printk(KERN_WARNING "%s/irq: looping -- "
+                              "clearing GPIO16 enable bit\n",dev->name);
+                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_P);
+                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_N);
+               } else if (report & SAA7134_IRQ_REPORT_GPIO18) {
+                       /* disable gpio18 IRQs */
+                       printk(KERN_WARNING "%s/irq: looping -- "
+                              "clearing GPIO18 enable bit\n",dev->name);
+                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P);
+                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_N);
+               } else {
+                       /* disable all irqs */
+                       printk(KERN_WARNING "%s/irq: looping -- "
+                              "clearing all enable bits\n",dev->name);
+                       saa_writel(SAA7134_IRQ1,0);
+                       saa_writel(SAA7134_IRQ2,0);
+               }
+       }
+
+ out:
+       return IRQ_RETVAL(handled);
+}
+
+/* ------------------------------------------------------------------ */
+
+/* early init (no i2c, no irq) */
+
+static int saa7134_hw_enable1(struct saa7134_dev *dev)
+{
+       /* RAM FIFO config */
+       saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
+       saa_writel(SAA7134_THRESHOULD, 0x02020202);
+
+       /* enable audio + video processing */
+       saa_writel(SAA7134_MAIN_CTRL,
+                       SAA7134_MAIN_CTRL_VPLLE |
+                       SAA7134_MAIN_CTRL_APLLE |
+                       SAA7134_MAIN_CTRL_EXOSC |
+                       SAA7134_MAIN_CTRL_EVFE1 |
+                       SAA7134_MAIN_CTRL_EVFE2 |
+                       SAA7134_MAIN_CTRL_ESFE  |
+                       SAA7134_MAIN_CTRL_EBDAC);
+
+       /*
+       * Initialize OSS _after_ enabling audio clock PLL and audio processing.
+       * OSS initialization writes to registers via the audio DSP; these
+       * writes will fail unless the audio clock has been started.  At worst,
+       * audio will not work.
+       */
+
+       /* enable peripheral devices */
+       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+
+       /* set vertical line numbering start (vbi needs this) */
+       saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
+
+       return 0;
+}
+
+static int saa7134_hwinit1(struct saa7134_dev *dev)
+{
+       dprintk("hwinit1\n");
+
+       saa_writel(SAA7134_IRQ1, 0);
+       saa_writel(SAA7134_IRQ2, 0);
+
+       /* Clear any stale IRQ reports */
+       saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
+
+       mutex_init(&dev->lock);
+       spin_lock_init(&dev->slock);
+
+       saa7134_track_gpio(dev,"pre-init");
+       saa7134_video_init1(dev);
+       saa7134_vbi_init1(dev);
+       if (card_has_mpeg(dev))
+               saa7134_ts_init1(dev);
+       saa7134_input_init1(dev);
+
+       saa7134_hw_enable1(dev);
+
+       return 0;
+}
+
+/* late init (with i2c + irq) */
+static int saa7134_hw_enable2(struct saa7134_dev *dev)
+{
+
+       unsigned int irq2_mask;
+
+       /* enable IRQ's */
+       irq2_mask =
+               SAA7134_IRQ2_INTE_DEC3    |
+               SAA7134_IRQ2_INTE_DEC2    |
+               SAA7134_IRQ2_INTE_DEC1    |
+               SAA7134_IRQ2_INTE_DEC0    |
+               SAA7134_IRQ2_INTE_PE      |
+               SAA7134_IRQ2_INTE_AR;
+
+       if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) {
+               if (dev->remote->mask_keydown & 0x10000)
+                       irq2_mask |= SAA7134_IRQ2_INTE_GPIO16_N;
+               else {          /* Allow enabling both IRQ edge triggers */
+                       if (dev->remote->mask_keydown & 0x40000)
+                               irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_P;
+                       if (dev->remote->mask_keyup & 0x40000)
+                               irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_N;
+               }
+       }
+
+       if (dev->has_remote == SAA7134_REMOTE_I2C) {
+               request_module("ir-kbd-i2c");
+       }
+
+       saa_writel(SAA7134_IRQ1, 0);
+       saa_writel(SAA7134_IRQ2, irq2_mask);
+
+       return 0;
+}
+
+static int saa7134_hwinit2(struct saa7134_dev *dev)
+{
+
+       dprintk("hwinit2\n");
+
+       saa7134_video_init2(dev);
+       saa7134_tvaudio_init2(dev);
+
+       saa7134_hw_enable2(dev);
+
+       return 0;
+}
+
+
+/* shutdown */
+static int saa7134_hwfini(struct saa7134_dev *dev)
+{
+       dprintk("hwfini\n");
+
+       if (card_has_mpeg(dev))
+               saa7134_ts_fini(dev);
+       saa7134_input_fini(dev);
+       saa7134_vbi_fini(dev);
+       saa7134_tvaudio_fini(dev);
+       return 0;
+}
+
+static void __devinit must_configure_manually(int has_eeprom)
+{
+       unsigned int i,p;
+
+       if (!has_eeprom)
+               printk(KERN_WARNING
+                      "saa7134: <rant>\n"
+                      "saa7134:  Congratulations!  Your TV card vendor saved a few\n"
+                      "saa7134:  cents for a eeprom, thus your pci board has no\n"
+                      "saa7134:  subsystem ID and I can't identify it automatically\n"
+                      "saa7134: </rant>\n"
+                      "saa7134: I feel better now.  Ok, here are the good news:\n"
+                      "saa7134: You can use the card=<nr> insmod option to specify\n"
+                      "saa7134: which board do you have.  The list:\n");
+       else
+               printk(KERN_WARNING
+                      "saa7134: Board is currently unknown. You might try to use the card=<nr>\n"
+                      "saa7134: insmod option to specify which board do you have, but this is\n"
+                      "saa7134: somewhat risky, as might damage your card. It is better to ask\n"
+                      "saa7134: for support at linux-media@vger.kernel.org.\n"
+                      "saa7134: The supported cards are:\n");
+
+       for (i = 0; i < saa7134_bcount; i++) {
+               printk(KERN_WARNING "saa7134:   card=%d -> %-40.40s",
+                      i,saa7134_boards[i].name);
+               for (p = 0; saa7134_pci_tbl[p].driver_data; p++) {
+                       if (saa7134_pci_tbl[p].driver_data != i)
+                               continue;
+                       printk(" %04x:%04x",
+                              saa7134_pci_tbl[p].subvendor,
+                              saa7134_pci_tbl[p].subdevice);
+               }
+               printk("\n");
+       }
+}
+
+static struct video_device *vdev_init(struct saa7134_dev *dev,
+                                     struct video_device *template,
+                                     char *type)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->v4l2_dev  = &dev->v4l2_dev;
+       vfd->release = video_device_release;
+       vfd->debug   = video_debug;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
+                dev->name, type, saa7134_boards[dev->board].name);
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+static void saa7134_unregister_video(struct saa7134_dev *dev)
+{
+       if (dev->video_dev) {
+               if (video_is_registered(dev->video_dev))
+                       video_unregister_device(dev->video_dev);
+               else
+                       video_device_release(dev->video_dev);
+               dev->video_dev = NULL;
+       }
+       if (dev->vbi_dev) {
+               if (video_is_registered(dev->vbi_dev))
+                       video_unregister_device(dev->vbi_dev);
+               else
+                       video_device_release(dev->vbi_dev);
+               dev->vbi_dev = NULL;
+       }
+       if (dev->radio_dev) {
+               if (video_is_registered(dev->radio_dev))
+                       video_unregister_device(dev->radio_dev);
+               else
+                       video_device_release(dev->radio_dev);
+               dev->radio_dev = NULL;
+       }
+}
+
+static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops,
+                           struct saa7134_dev *dev)
+{
+       int err;
+
+       if (NULL != dev->mops)
+               return;
+       if (saa7134_boards[dev->board].mpeg != ops->type)
+               return;
+       err = ops->init(dev);
+       if (0 != err)
+               return;
+       dev->mops = ops;
+}
+
+static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
+                           struct saa7134_dev *dev)
+{
+       if (NULL == dev->mops)
+               return;
+       if (dev->mops != ops)
+               return;
+       dev->mops->fini(dev);
+       dev->mops = NULL;
+}
+
+static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
+                                    const struct pci_device_id *pci_id)
+{
+       struct saa7134_dev *dev;
+       struct saa7134_mpeg_ops *mops;
+       int err;
+
+       if (saa7134_devcount == SAA7134_MAXBOARDS)
+               return -ENOMEM;
+
+       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+       if (NULL == dev)
+               return -ENOMEM;
+
+       err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+       if (err)
+               goto fail0;
+
+       /* pci init */
+       dev->pci = pci_dev;
+       if (pci_enable_device(pci_dev)) {
+               err = -EIO;
+               goto fail1;
+       }
+
+       dev->nr = saa7134_devcount;
+       sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr);
+
+       /* pci quirks */
+       if (pci_pci_problems) {
+               if (pci_pci_problems & PCIPCI_TRITON)
+                       printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name);
+               if (pci_pci_problems & PCIPCI_NATOMA)
+                       printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name);
+               if (pci_pci_problems & PCIPCI_VIAETBF)
+                       printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name);
+               if (pci_pci_problems & PCIPCI_VSFX)
+                       printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);
+#ifdef PCIPCI_ALIMAGIK
+               if (pci_pci_problems & PCIPCI_ALIMAGIK) {
+                       printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
+                              dev->name);
+                       latency = 0x0A;
+               }
+#endif
+               if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
+                       printk(KERN_INFO "%s: quirk: this driver and your "
+                                       "chipset may not work together"
+                                       " in overlay mode.\n",dev->name);
+                       if (!saa7134_no_overlay) {
+                               printk(KERN_INFO "%s: quirk: overlay "
+                                               "mode will be disabled.\n",
+                                               dev->name);
+                               saa7134_no_overlay = 1;
+                       } else {
+                               printk(KERN_INFO "%s: quirk: overlay "
+                                               "mode will be forced. Use this"
+                                               " option at your own risk.\n",
+                                               dev->name);
+                       }
+               }
+       }
+       if (UNSET != latency) {
+               printk(KERN_INFO "%s: setting pci latency timer to %d\n",
+                      dev->name,latency);
+               pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
+       }
+
+       /* print pci info */
+       dev->pci_rev = pci_dev->revision;
+       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+       printk(KERN_INFO "%s: 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));
+       pci_set_master(pci_dev);
+       if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) {
+               printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
+               err = -EIO;
+               goto fail1;
+       }
+
+       /* board config */
+       dev->board = pci_id->driver_data;
+       if (card[dev->nr] >= 0 &&
+           card[dev->nr] < saa7134_bcount)
+               dev->board = card[dev->nr];
+       if (SAA7134_BOARD_UNKNOWN == dev->board)
+               must_configure_manually(0);
+       else if (SAA7134_BOARD_NOAUTO == dev->board) {
+               must_configure_manually(1);
+               dev->board = SAA7134_BOARD_UNKNOWN;
+       }
+       dev->autodetected = card[dev->nr] != dev->board;
+       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+       dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
+       dev->radio_type = saa7134_boards[dev->board].radio_type;
+       dev->radio_addr = saa7134_boards[dev->board].radio_addr;
+       dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
+       if (UNSET != tuner[dev->nr])
+               dev->tuner_type = tuner[dev->nr];
+       printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+               dev->name,pci_dev->subsystem_vendor,
+               pci_dev->subsystem_device,saa7134_boards[dev->board].name,
+               dev->board, dev->autodetected ?
+               "autodetected" : "insmod option");
+
+       /* get mmio */
+       if (!request_mem_region(pci_resource_start(pci_dev,0),
+                               pci_resource_len(pci_dev,0),
+                               dev->name)) {
+               err = -EBUSY;
+               printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+                      dev->name,(unsigned long long)pci_resource_start(pci_dev,0));
+               goto fail1;
+       }
+       dev->lmmio = ioremap(pci_resource_start(pci_dev, 0),
+                            pci_resource_len(pci_dev, 0));
+       dev->bmmio = (__u8 __iomem *)dev->lmmio;
+       if (NULL == dev->lmmio) {
+               err = -EIO;
+               printk(KERN_ERR "%s: can't ioremap() MMIO memory\n",
+                      dev->name);
+               goto fail2;
+       }
+
+       /* initialize hardware #1 */
+       saa7134_board_init1(dev);
+       saa7134_hwinit1(dev);
+
+       /* get irq */
+       err = request_irq(pci_dev->irq, saa7134_irq,
+                         IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+       if (err < 0) {
+               printk(KERN_ERR "%s: can't get IRQ %d\n",
+                      dev->name,pci_dev->irq);
+               goto fail3;
+       }
+
+       /* wait a bit, register i2c bus */
+       msleep(100);
+       saa7134_i2c_register(dev);
+       saa7134_board_init2(dev);
+
+       saa7134_hwinit2(dev);
+
+       /* load i2c helpers */
+       if (card_is_empress(dev)) {
+               struct v4l2_subdev *sd =
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                               "saa6752hs",
+                               saa7134_boards[dev->board].empress_addr, NULL);
+
+               if (sd)
+                       sd->grp_id = GRP_EMPRESS;
+       }
+
+       if (saa7134_boards[dev->board].rds_addr) {
+               struct v4l2_subdev *sd;
+
+               sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "saa6588",
+                               0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr));
+               if (sd) {
+                       printk(KERN_INFO "%s: found RDS decoder\n", dev->name);
+                       dev->has_rds = 1;
+               }
+       }
+
+       v4l2_prio_init(&dev->prio);
+
+       mutex_lock(&saa7134_devlist_lock);
+       list_for_each_entry(mops, &mops_list, next)
+               mpeg_ops_attach(mops, dev);
+       list_add_tail(&dev->devlist, &saa7134_devlist);
+       mutex_unlock(&saa7134_devlist_lock);
+
+       /* check for signal */
+       saa7134_irq_video_signalchange(dev);
+
+       if (TUNER_ABSENT != dev->tuner_type)
+               saa_call_all(dev, core, s_power, 0);
+
+       /* register v4l devices */
+       if (saa7134_no_overlay > 0)
+               printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
+
+       dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
+       err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
+                                   video_nr[dev->nr]);
+       if (err < 0) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                      dev->name);
+               goto fail4;
+       }
+       printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+              dev->name, video_device_node_name(dev->video_dev));
+
+       dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
+
+       err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
+                                   vbi_nr[dev->nr]);
+       if (err < 0)
+               goto fail4;
+       printk(KERN_INFO "%s: registered device %s\n",
+              dev->name, video_device_node_name(dev->vbi_dev));
+
+       if (card_has_radio(dev)) {
+               dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
+               err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
+                                           radio_nr[dev->nr]);
+               if (err < 0)
+                       goto fail4;
+               printk(KERN_INFO "%s: registered device %s\n",
+                      dev->name, video_device_node_name(dev->radio_dev));
+       }
+
+       /* everything worked */
+       saa7134_devcount++;
+
+       if (saa7134_dmasound_init && !dev->dmasound.priv_data)
+               saa7134_dmasound_init(dev);
+
+       request_submodules(dev);
+       return 0;
+
+ fail4:
+       saa7134_unregister_video(dev);
+       saa7134_i2c_unregister(dev);
+       free_irq(pci_dev->irq, dev);
+ fail3:
+       saa7134_hwfini(dev);
+       iounmap(dev->lmmio);
+ fail2:
+       release_mem_region(pci_resource_start(pci_dev,0),
+                          pci_resource_len(pci_dev,0));
+ fail1:
+       v4l2_device_unregister(&dev->v4l2_dev);
+ fail0:
+       kfree(dev);
+       return err;
+}
+
+static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
+       struct saa7134_mpeg_ops *mops;
+
+       flush_request_submodules(dev);
+
+       /* Release DMA sound modules if present */
+       if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
+               saa7134_dmasound_exit(dev);
+       }
+
+       /* debugging ... */
+       if (irq_debug) {
+               u32 report = saa_readl(SAA7134_IRQ_REPORT);
+               u32 status = saa_readl(SAA7134_IRQ_STATUS);
+               print_irqstatus(dev,42,report,status);
+       }
+
+       /* disable peripheral devices */
+       saa_writeb(SAA7134_SPECIAL_MODE,0);
+
+       /* shutdown hardware */
+       saa_writel(SAA7134_IRQ1,0);
+       saa_writel(SAA7134_IRQ2,0);
+       saa_writel(SAA7134_MAIN_CTRL,0);
+
+       /* shutdown subsystems */
+       saa7134_hwfini(dev);
+
+       /* unregister */
+       mutex_lock(&saa7134_devlist_lock);
+       list_del(&dev->devlist);
+       list_for_each_entry(mops, &mops_list, next)
+               mpeg_ops_detach(mops, dev);
+       mutex_unlock(&saa7134_devlist_lock);
+       saa7134_devcount--;
+
+       saa7134_i2c_unregister(dev);
+       saa7134_unregister_video(dev);
+
+
+       /* the DMA sound modules should be unloaded before reaching
+          this, but just in case they are still present... */
+       if (dev->dmasound.priv_data != NULL) {
+               free_irq(pci_dev->irq, &dev->dmasound);
+               dev->dmasound.priv_data = NULL;
+       }
+
+
+       /* release resources */
+       free_irq(pci_dev->irq, dev);
+       iounmap(dev->lmmio);
+       release_mem_region(pci_resource_start(pci_dev,0),
+                          pci_resource_len(pci_dev,0));
+
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       /* free memory */
+       kfree(dev);
+}
+
+#ifdef CONFIG_PM
+
+/* resends a current buffer in queue after resume */
+static int saa7134_buffer_requeue(struct saa7134_dev *dev,
+                                 struct saa7134_dmaqueue *q)
+{
+       struct saa7134_buf *buf, *next;
+
+       assert_spin_locked(&dev->slock);
+
+       buf  = q->curr;
+       next = buf;
+       dprintk("buffer_requeue\n");
+
+       if (!buf)
+               return 0;
+
+       dprintk("buffer_requeue : resending active buffers \n");
+
+       if (!list_empty(&q->queue))
+               next = list_entry(q->queue.next, struct saa7134_buf,
+                                         vb.queue);
+       buf->activate(dev, buf, next);
+
+       return 0;
+}
+
+static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
+
+       /* disable overlay - apps should enable it explicitly on resume*/
+       dev->ovenable = 0;
+
+       /* Disable interrupts, DMA, and rest of the chip*/
+       saa_writel(SAA7134_IRQ1, 0);
+       saa_writel(SAA7134_IRQ2, 0);
+       saa_writel(SAA7134_MAIN_CTRL, 0);
+
+       dev->insuspend = 1;
+       synchronize_irq(pci_dev->irq);
+
+       /* ACK interrupts once more, just in case,
+               since the IRQ handler won't ack them anymore*/
+
+       saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
+
+       /* Disable timeout timers - if we have active buffers, we will
+          fill them on resume*/
+
+       del_timer(&dev->video_q.timeout);
+       del_timer(&dev->vbi_q.timeout);
+       del_timer(&dev->ts_q.timeout);
+
+       if (dev->remote)
+               saa7134_ir_stop(dev);
+
+       pci_save_state(pci_dev);
+       pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
+
+       return 0;
+}
+
+static int saa7134_resume(struct pci_dev *pci_dev)
+{
+       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+       struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
+       unsigned long flags;
+
+       pci_set_power_state(pci_dev, PCI_D0);
+       pci_restore_state(pci_dev);
+
+       /* Do things that are done in saa7134_initdev ,
+               except of initializing memory structures.*/
+
+       saa7134_board_init1(dev);
+
+       /* saa7134_hwinit1 */
+       if (saa7134_boards[dev->board].video_out)
+               saa7134_videoport_init(dev);
+       if (card_has_mpeg(dev))
+               saa7134_ts_init_hw(dev);
+       if (dev->remote)
+               saa7134_ir_start(dev);
+       saa7134_hw_enable1(dev);
+
+       msleep(100);
+
+       saa7134_board_init2(dev);
+
+       /*saa7134_hwinit2*/
+       saa7134_set_tvnorm_hw(dev);
+       saa7134_tvaudio_setmute(dev);
+       saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
+       saa7134_tvaudio_init(dev);
+       saa7134_enable_i2s(dev);
+       saa7134_hw_enable2(dev);
+
+       saa7134_irq_video_signalchange(dev);
+
+       /*resume unfinished buffer(s)*/
+       spin_lock_irqsave(&dev->slock, flags);
+       saa7134_buffer_requeue(dev, &dev->video_q);
+       saa7134_buffer_requeue(dev, &dev->vbi_q);
+       saa7134_buffer_requeue(dev, &dev->ts_q);
+
+       /* FIXME: Disable DMA audio sound - temporary till proper support
+                 is implemented*/
+
+       dev->dmasound.dma_running = 0;
+
+       /* start DMA now*/
+       dev->insuspend = 0;
+       smp_wmb();
+       saa7134_set_dmabits(dev);
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       return 0;
+}
+#endif
+
+/* ----------------------------------------------------------- */
+
+int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
+{
+       struct saa7134_dev *dev;
+
+       mutex_lock(&saa7134_devlist_lock);
+       list_for_each_entry(dev, &saa7134_devlist, devlist)
+               mpeg_ops_attach(ops, dev);
+       list_add_tail(&ops->next,&mops_list);
+       mutex_unlock(&saa7134_devlist_lock);
+       return 0;
+}
+
+void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
+{
+       struct saa7134_dev *dev;
+
+       mutex_lock(&saa7134_devlist_lock);
+       list_del(&ops->next);
+       list_for_each_entry(dev, &saa7134_devlist, devlist)
+               mpeg_ops_detach(ops, dev);
+       mutex_unlock(&saa7134_devlist_lock);
+}
+
+EXPORT_SYMBOL(saa7134_ts_register);
+EXPORT_SYMBOL(saa7134_ts_unregister);
+
+/* ----------------------------------------------------------- */
+
+static struct pci_driver saa7134_pci_driver = {
+       .name     = "saa7134",
+       .id_table = saa7134_pci_tbl,
+       .probe    = saa7134_initdev,
+       .remove   = __devexit_p(saa7134_finidev),
+#ifdef CONFIG_PM
+       .suspend  = saa7134_suspend,
+       .resume   = saa7134_resume
+#endif
+};
+
+static int __init saa7134_init(void)
+{
+       INIT_LIST_HEAD(&saa7134_devlist);
+       printk(KERN_INFO "saa7130/34: v4l2 driver version %s loaded\n",
+              SAA7134_VERSION);
+       return pci_register_driver(&saa7134_pci_driver);
+}
+
+static void __exit saa7134_fini(void)
+{
+       pci_unregister_driver(&saa7134_pci_driver);
+}
+
+module_init(saa7134_init);
+module_exit(saa7134_fini);
+
+/* ----------------------------------------------------------- */
+
+EXPORT_SYMBOL(saa7134_set_gpio);
+EXPORT_SYMBOL(saa7134_boards);
+
+/* ----------------- for the DMA sound modules --------------- */
+
+EXPORT_SYMBOL(saa7134_dmasound_init);
+EXPORT_SYMBOL(saa7134_dmasound_exit);
+EXPORT_SYMBOL(saa7134_pgtable_free);
+EXPORT_SYMBOL(saa7134_pgtable_build);
+EXPORT_SYMBOL(saa7134_pgtable_alloc);
+EXPORT_SYMBOL(saa7134_set_dmabits);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-dvb.c b/drivers/media/pci/saa7134/saa7134-dvb.c
new file mode 100644 (file)
index 0000000..b209de4
--- /dev/null
@@ -0,0 +1,1936 @@
+/*
+ *
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ *  Extended 3 / 2005 by Hartmut Hackmann to support various
+ *  cards with the tda10046 DVB-T channel decoder
+ *
+ *  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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
+
+#include "saa7134-reg.h"
+#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 "xc5000.h"
+
+#include "tda10086.h"
+#include "tda826x.h"
+#include "tda827x.h"
+#include "isl6421.h"
+#include "isl6405.h"
+#include "lnbp21.h"
+#include "tuner-simple.h"
+#include "tda10048.h"
+#include "tda18271.h"
+#include "lgdt3305.h"
+#include "tda8290.h"
+#include "mb86a20s.h"
+#include "lgs8gxx.h"
+
+#include "zl10353.h"
+#include "qt1010.h"
+
+#include "zl10036.h"
+#include "zl10039.h"
+#include "mt312.h"
+#include "s5h1411.h"
+
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+
+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;
+module_param(use_frontend, int, 0644);
+MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
+
+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)
+
+/* Print a warning */
+#define wprintk(fmt, arg...) \
+       printk(KERN_WARNING "%s/dvb: " fmt, dev->name, ## arg)
+
+/* ------------------------------------------------------------------
+ * mt352 based DVB-T cards
+ */
+
+static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
+{
+       u32 ok;
+
+       if (!on) {
+               saa_setl(SAA7134_GPIO_GPMODE0 >> 2,     (1 << 26));
+               saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
+               return 0;
+       }
+
+       saa_setl(SAA7134_GPIO_GPMODE0 >> 2,     (1 << 26));
+       saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
+       udelay(10);
+
+       saa_setl(SAA7134_GPIO_GPMODE0 >> 2,     (1 << 28));
+       saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28));
+       udelay(10);
+       saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 28));
+       udelay(10);
+       ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
+       dprintk("%s %s\n", __func__, ok ? "on" : "off");
+
+       if (!ok)
+               saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
+       return ok;
+}
+
+static int mt352_pinnacle_init(struct dvb_frontend* fe)
+{
+       static u8 clock_config []  = { CLOCK_CTL,  0x3d, 0x28 };
+       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, 0x31 };
+       static u8 fsm_ctl_cfg[]    = { 0x7b,       0x04 };
+       static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x0f };
+       static u8 scan_ctl_cfg []  = { SCAN_CTL,   0x0d };
+       static u8 irq_cfg []       = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
+       struct saa7134_dev *dev= fe->dvb->priv;
+
+       dprintk("%s called\n", __func__);
+
+       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));
+       mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+
+       mt352_write(fe, fsm_ctl_cfg,    sizeof(fsm_ctl_cfg));
+       mt352_write(fe, scan_ctl_cfg,   sizeof(scan_ctl_cfg));
+       mt352_write(fe, irq_cfg,        sizeof(irq_cfg));
+
+       return 0;
+}
+
+static int mt352_aver777_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_avermedia_xc3028_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, 0xe };
+       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 dtv_frontend_properties *c = &fe->dtv_property_cache;
+       u8 off[] = { 0x00, 0xf1};
+       u8 on[]  = { 0x00, 0x71};
+       struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)};
+
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct v4l2_frequency f;
+
+       /* set frequency (mt2050) */
+       f.tuner     = 0;
+       f.type      = V4L2_TUNER_DIGITAL_TV;
+       f.frequency = c->frequency / 1000 * 16 / 1000;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       i2c_transfer(&dev->i2c_adap, &msg, 1);
+       saa_call_all(dev, tuner, s_frequency, &f);
+       msg.buf = on;
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+       pinnacle_antenna_pwr(dev, antenna_pwr);
+
+       /* mt352 setup */
+       return mt352_pinnacle_init(fe);
+}
+
+static struct mt352_config pinnacle_300i = {
+       .demod_address = 0x3c >> 1,
+       .adc_clock     = 20333,
+       .if2           = 36150,
+       .no_tuner      = 1,
+       .demod_init    = mt352_pinnacle_init,
+};
+
+static struct mt352_config avermedia_777 = {
+       .demod_address = 0xf,
+       .demod_init    = mt352_aver777_init,
+};
+
+static struct mt352_config avermedia_xc3028_mt352_dev = {
+       .demod_address   = (0x1e >> 1),
+       .no_tuner        = 1,
+       .demod_init      = mt352_avermedia_xc3028_init,
+};
+
+static struct tda18271_std_map mb86a20s_tda18271_std_map = {
+       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                     .if_lvl = 7, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config kworld_tda18271_config = {
+       .std_map = &mb86a20s_tda18271_std_map,
+       .gate    = TDA18271_GATE_DIGITAL,
+       .config  = 3,   /* Use tuner callback for AGC */
+
+};
+
+static const struct mb86a20s_config kworld_mb86a20s_config = {
+       .demod_address = 0x10,
+};
+
+static int kworld_sbtvd_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+
+       unsigned char initmsg[] = {0x45, 0x97};
+       unsigned char msg_enable[] = {0x45, 0xc1};
+       unsigned char msg_disable[] = {0x45, 0x81};
+       struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2};
+
+       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
+               wprintk("could not access the I2C gate\n");
+               return -EIO;
+       }
+       if (enable)
+               msg.buf = msg_enable;
+       else
+               msg.buf = msg_disable;
+       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
+               wprintk("could not access the I2C gate\n");
+               return -EIO;
+       }
+       msleep(20);
+       return 0;
+}
+
+/* ==================================================================
+ * tda1004x based DVB-T cards, helper functions
+ */
+
+static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
+                                          const struct firmware **fw, char *name)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       return request_firmware(fw, name, &dev->pci->dev);
+}
+
+/* ------------------------------------------------------------------
+ * these tuners are tu1216, td1316(a)
+ */
+
+static int philips_tda6651_pll_set(struct dvb_frontend *fe)
+{
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
+       u8 tuner_buf[4];
+       struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len =
+                       sizeof(tuner_buf) };
+       int tuner_frequency = 0;
+       u8 band, cp, filter;
+
+       /* determine charge pump */
+       tuner_frequency = c->frequency + 36166000;
+       if (tuner_frequency < 87000000)
+               return -EINVAL;
+       else if (tuner_frequency < 130000000)
+               cp = 3;
+       else if (tuner_frequency < 160000000)
+               cp = 5;
+       else if (tuner_frequency < 200000000)
+               cp = 6;
+       else if (tuner_frequency < 290000000)
+               cp = 3;
+       else if (tuner_frequency < 420000000)
+               cp = 5;
+       else if (tuner_frequency < 480000000)
+               cp = 6;
+       else if (tuner_frequency < 620000000)
+               cp = 3;
+       else if (tuner_frequency < 830000000)
+               cp = 5;
+       else if (tuner_frequency < 895000000)
+               cp = 7;
+       else
+               return -EINVAL;
+
+       /* determine band */
+       if (c->frequency < 49000000)
+               return -EINVAL;
+       else if (c->frequency < 161000000)
+               band = 1;
+       else if (c->frequency < 444000000)
+               band = 2;
+       else if (c->frequency < 861000000)
+               band = 4;
+       else
+               return -EINVAL;
+
+       /* setup PLL filter */
+       switch (c->bandwidth_hz) {
+       case 6000000:
+               filter = 0;
+               break;
+
+       case 7000000:
+               filter = 0;
+               break;
+
+       case 8000000:
+               filter = 1;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* calculate divisor
+        * ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
+        */
+       tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
+
+       /* setup tuner buffer */
+       tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
+       tuner_buf[1] = tuner_frequency & 0xff;
+       tuner_buf[2] = 0xca;
+       tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) {
+               wprintk("could not write to tuner at addr: 0x%02x\n",
+                       addr << 1);
+               return -EIO;
+       }
+       msleep(1);
+       return 0;
+}
+
+static int philips_tu1216_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
+       static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
+       struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
+
+       /* setup PLL configuration */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
+               return -EIO;
+       msleep(1);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct tda1004x_config philips_tu1216_60_config = {
+       .demod_address = 0x8,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_4M,
+       .agc_config    = TDA10046_AGC_DEFAULT,
+       .if_freq       = TDA10046_FREQ_3617,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config philips_tu1216_61_config = {
+
+       .demod_address = 0x8,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_4M,
+       .agc_config    = TDA10046_AGC_DEFAULT,
+       .if_freq       = TDA10046_FREQ_3617,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+/* ------------------------------------------------------------------ */
+
+static int philips_td1316_tuner_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
+       static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
+       struct i2c_msg init_msg = {.addr = addr,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+       /* setup PLL configuration */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
+               return -EIO;
+       return 0;
+}
+
+static int philips_td1316_tuner_set_params(struct dvb_frontend *fe)
+{
+       return philips_tda6651_pll_set(fe);
+}
+
+static int philips_td1316_tuner_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+       u8 addr = state->config->tuner_address;
+       static u8 msg[] = { 0x0b, 0xdc, 0x86, 0xa4 };
+       struct i2c_msg analog_msg = {.addr = addr,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+       /* switch the tuner to analog mode */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1)
+               return -EIO;
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int philips_europa_tuner_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       static u8 msg[] = { 0x00, 0x40};
+       struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+
+       if (philips_td1316_tuner_init(fe))
+               return -EIO;
+       msleep(1);
+       if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
+               return -EIO;
+
+       return 0;
+}
+
+static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+
+       static u8 msg[] = { 0x00, 0x14 };
+       struct i2c_msg analog_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
+
+       if (philips_td1316_tuner_sleep(fe))
+               return -EIO;
+
+       /* switch the board to analog mode */
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+       i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
+       return 0;
+}
+
+static int philips_europa_demod_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+
+       if (dev->original_demod_sleep)
+               dev->original_demod_sleep(fe);
+       fe->ops.i2c_gate_ctrl(fe, 1);
+       return 0;
+}
+
+static struct tda1004x_config philips_europa_config = {
+
+       .demod_address = 0x8,
+       .invert        = 0,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_4M,
+       .agc_config    = TDA10046_AGC_IFO_AUTO_POS,
+       .if_freq       = TDA10046_FREQ_052,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config medion_cardbus = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_IFO_AUTO_NEG,
+       .if_freq       = TDA10046_FREQ_3613,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config technotrend_budget_t3000_config = {
+       .demod_address = 0x8,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_4M,
+       .agc_config    = TDA10046_AGC_DEFAULT,
+       .if_freq       = TDA10046_FREQ_3617,
+       .tuner_address = 0x63,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+/* ------------------------------------------------------------------
+ * tda 1004x based cards with philips silicon tuner
+ */
+
+static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
+{
+       struct tda1004x_state *state = fe->demodulator_priv;
+
+       u8 addr = state->config->i2c_gate;
+       static u8 tda8290_close[] = { 0x21, 0xc0};
+       static u8 tda8290_open[]  = { 0x21, 0x80};
+       struct i2c_msg tda8290_msg = {.addr = addr,.flags = 0, .len = 2};
+       if (enable) {
+               tda8290_msg.buf = tda8290_close;
+       } else {
+               tda8290_msg.buf = tda8290_open;
+       }
+       if (i2c_transfer(state->i2c, &tda8290_msg, 1) != 1) {
+               struct saa7134_dev *dev = fe->dvb->priv;
+               wprintk("could not access tda8290 I2C gate\n");
+               return -EIO;
+       }
+       msleep(20);
+       return 0;
+}
+
+static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+
+       switch (state->config->antenna_switch) {
+       case 0: break;
+       case 1: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
+               saa7134_set_gpio(dev, 21, 0);
+               break;
+       case 2: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
+               saa7134_set_gpio(dev, 21, 1);
+               break;
+       }
+       return 0;
+}
+
+static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       struct tda1004x_state *state = fe->demodulator_priv;
+
+       switch (state->config->antenna_switch) {
+       case 0: break;
+       case 1: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
+               saa7134_set_gpio(dev, 21, 1);
+               break;
+       case 2: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
+               saa7134_set_gpio(dev, 21, 0);
+               break;
+       }
+       return 0;
+}
+
+static int configure_tda827x_fe(struct saa7134_dev *dev,
+                               struct tda1004x_config *cdec_conf,
+                               struct tda827x_config *tuner_conf)
+{
+       struct videobuf_dvb_frontend *fe0;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+
+       fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
+       if (fe0->dvb.frontend) {
+               if (cdec_conf->i2c_gate)
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
+               if (dvb_attach(tda827x_attach, fe0->dvb.frontend,
+                              cdec_conf->tuner_address,
+                              &dev->i2c_adap, tuner_conf))
+                       return 0;
+
+               wprintk("no tda827x tuner found at addr: %02x\n",
+                               cdec_conf->tuner_address);
+       }
+       return -EINVAL;
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct tda827x_config tda827x_cfg_0 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 0,
+       .switch_addr = 0
+};
+
+static struct tda827x_config tda827x_cfg_1 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 1,
+       .switch_addr = 0x4b
+};
+
+static struct tda827x_config tda827x_cfg_2 = {
+       .init = philips_tda827x_tuner_init,
+       .sleep = philips_tda827x_tuner_sleep,
+       .config = 2,
+       .switch_addr = 0x4b
+};
+
+static struct tda827x_config tda827x_cfg_2_sw42 = {
+       .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,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config philips_tiger_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config cinergy_ht_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config cinergy_ht_pci_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config philips_tiger_s_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config pinnacle_pctv_310i_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config hauppauge_hvr_1110_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config asus_p7131_dual_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 2,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config lifeview_trio_config = {
+       .demod_address = 0x09,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP00_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config tevion_dvbt220rf_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config md8800_dvbt_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x60,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config asus_p7131_4871_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 2,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config asus_p7131_hybrid_lna_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 2,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config kworld_dvb_t_210_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config avermedia_super_007_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x60,
+       .antenna_switch= 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP01_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x42,
+       .tuner_address = 0x61,
+       .antenna_switch = 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config asus_tiger_3in1_config = {
+       .demod_address = 0x0b,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch = 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct tda1004x_config asus_ps3_100_config = {
+       .demod_address = 0x0b,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP11_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .i2c_gate      = 0x4b,
+       .tuner_address = 0x61,
+       .antenna_switch = 1,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+/* ------------------------------------------------------------------
+ * special case: this card uses saa713x GPIO22 for the mode switch
+ */
+
+static int ads_duo_tuner_init(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       philips_tda827x_tuner_init(fe);
+       /* route TDA8275a AGC input to the channel decoder */
+       saa7134_set_gpio(dev, 22, 1);
+       return 0;
+}
+
+static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
+{
+       struct saa7134_dev *dev = fe->dvb->priv;
+       /* route TDA8275a AGC input to the analog IF chip*/
+       saa7134_set_gpio(dev, 22, 0);
+       philips_tda827x_tuner_sleep(fe);
+       return 0;
+}
+
+static struct tda827x_config ads_duo_cfg = {
+       .init = ads_duo_tuner_init,
+       .sleep = ads_duo_tuner_sleep,
+       .config = 0
+};
+
+static struct tda1004x_config ads_tech_duo_config = {
+       .demod_address = 0x08,
+       .invert        = 1,
+       .invert_oclk   = 0,
+       .xtal_freq     = TDA10046_XTAL_16M,
+       .agc_config    = TDA10046_AGC_TDA827X,
+       .gpio_config   = TDA10046_GP00_I,
+       .if_freq       = TDA10046_FREQ_045,
+       .tuner_address = 0x61,
+       .request_firmware = philips_tda1004x_request_firmware
+};
+
+static struct zl10353_config behold_h6_config = {
+       .demod_address = 0x1e>>1,
+       .no_tuner      = 1,
+       .parallel_ts   = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static struct xc5000_config behold_x7_tunerconfig = {
+       .i2c_address      = 0xc2>>1,
+       .if_khz           = 4560,
+       .radio_input      = XC5000_RADIO_FM1,
+};
+
+static struct zl10353_config behold_x7_config = {
+       .demod_address = 0x1e>>1,
+       .if2           = 45600,
+       .no_tuner      = 1,
+       .parallel_ts   = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static struct zl10353_config videomate_t750_zl10353_config = {
+       .demod_address         = 0x0f,
+       .no_tuner              = 1,
+       .parallel_ts           = 1,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static struct qt1010_config videomate_t750_qt1010_config = {
+       .i2c_address = 0x62
+};
+
+
+/* ==================================================================
+ * tda10086 based DVB-S cards, helper functions
+ */
+
+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
+ */
+
+static struct nxt200x_config avertvhda180 = {
+       .demod_address    = 0x0a,
+};
+
+static struct nxt200x_config kworldatsc110 = {
+       .demod_address    = 0x0a,
+};
+
+/* ------------------------------------------------------------------ */
+
+static struct mt312_config avertv_a700_mt312 = {
+       .demod_address = 0x0e,
+       .voltage_inverted = 1,
+};
+
+static struct zl10036_config avertv_a700_tuner = {
+       .tuner_address = 0x60,
+};
+
+static struct mt312_config zl10313_compro_s350_config = {
+       .demod_address = 0x0e,
+};
+
+static struct lgdt3305_config hcw_lgdt3305_config = {
+       .i2c_addr           = 0x0e,
+       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 1,
+       .qam_if_khz         = 4000,
+       .vsb_if_khz         = 3250,
+};
+
+static struct tda10048_config hcw_tda10048_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x58, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x58, },
+};
+
+static struct tda18271_config hcw_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .config  = 3,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+       .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda10048_config zolid_tda10048_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda18271_config zolid_tda18271_config = {
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static struct tda10048_config dtv1000s_tda10048_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3800,
+       .dtv8_if_freq_khz = TDA10048_IF_4300,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda18271_std_map dtv1000s_tda18271_std_map = {
+       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config dtv1000s_tda18271_config = {
+       .std_map = &dtv1000s_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static struct lgs8gxx_config prohdtv_pro2_lgs8g75_config = {
+       .prod = LGS8GXX_PROD_LGS8G75,
+       .demod_address = 0x1d,
+       .serial_ts = 0,
+       .ts_clk_pol = 1,
+       .ts_clk_gated = 0,
+       .if_clk_freq = 30400, /* 30.4 MHz */
+       .if_freq = 4000, /* 4.00 MHz */
+       .if_neg_center = 0,
+       .ext_adc = 0,
+       .adc_signed = 1,
+       .adc_vpp = 3, /* 2.0 Vpp */
+       .if_neg_edge = 1,
+};
+
+static struct tda18271_config prohdtv_pro2_tda18271_config = {
+       .gate = TDA18271_GATE_ANALOG,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_std_map kworld_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 3250, .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 kworld_pc150u_tda18271_config = {
+       .std_map = &kworld_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+       .config  = 3,   /* Use tuner callback for AGC */
+       .rf_cal_on_startup = 1
+};
+
+static struct s5h1411_config kworld_s5h1411_config = {
+       .output_mode   = S5H1411_PARALLEL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .qam_if        = S5H1411_IF_4000,
+       .vsb_if        = S5H1411_IF_3250,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   =
+               S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+
+/* ==================================================================
+ * Core code
+ */
+
+static int dvb_init(struct saa7134_dev *dev)
+{
+       int ret;
+       int attach_xc3028 = 0;
+       struct videobuf_dvb_frontend *fe0;
+
+       /* FIXME: add support for multi-frontend */
+       mutex_init(&dev->frontends.lock);
+       INIT_LIST_HEAD(&dev->frontends.felist);
+
+       printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
+       fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
+       if (!fe0) {
+               printk(KERN_ERR "%s() failed to alloc\n", __func__);
+               return -ENOMEM;
+       }
+
+       /* init struct videobuf_dvb */
+       dev->ts.nr_bufs    = 32;
+       dev->ts.nr_packets = 32*4;
+       fe0->dvb.name = dev->name;
+       videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
+                           &dev->pci->dev, &dev->slock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                           V4L2_FIELD_ALTERNATE,
+                           sizeof(struct saa7134_buf),
+                           dev, NULL);
+
+       switch (dev->board) {
+       case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
+               dprintk("pinnacle 300i dvb setup\n");
+               fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_AVERMEDIA_777:
+       case SAA7134_BOARD_AVERMEDIA_A16AR:
+               dprintk("avertv 777 dvb setup\n");
+               fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TD1316);
+               }
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               dprintk("AverMedia A16D dvb setup\n");
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_MD7134:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &medion_cardbus,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
+               }
+               break;
+       case SAA7134_BOARD_PHILIPS_TOUGH:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_tu1216_60_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
+               }
+               break;
+       case SAA7134_BOARD_FLYDVBTDUO:
+       case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
+               if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_PHILIPS_EUROPA:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+       case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_europa_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+                       fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &technotrend_budget_t3000_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+                       fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &philips_tu1216_61_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
+               }
+               break;
+       case SAA7134_BOARD_KWORLD_DVBT_210:
+               if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                                              &hcw_tda10048_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &hcw_tda18271_config);
+               }
+               break;
+       case SAA7134_BOARD_PHILIPS_TIGER:
+               if (configure_tda827x_fe(dev, &philips_tiger_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
+               if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config,
+                                        &tda827x_cfg_1) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+               if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config,
+                                        &tda827x_cfg_1) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+               fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
+                                              &hcw_lgdt3305_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &hcw_tda18271_config);
+               }
+               break;
+       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+               if (configure_tda827x_fe(dev, &asus_p7131_dual_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_FLYDVBT_LR301:
+               if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_FLYDVB_TRIO:
+               if (!use_frontend) {    /* terrestrial */
+                       if (configure_tda827x_fe(dev, &lifeview_trio_config,
+                                                &tda827x_cfg_0) < 0)
+                               goto detach_frontend;
+               } else {                /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63,
+                                                                       &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
+                                       goto detach_frontend;
+                               }
+                               if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap,
+                                                                               0x08, 0, 0) == NULL) {
+                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
+                                       goto detach_frontend;
+                               }
+                       }
+               }
+               break;
+       case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &ads_tech_duo_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(tda827x_attach,fe0->dvb.frontend,
+                                  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);
+                               goto detach_frontend;
+                       }
+               } else
+                       wprintk("failed to attach tda10046\n");
+               break;
+       case SAA7134_BOARD_TEVION_DVBT_220RF:
+               if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+               if (!use_frontend) {     /* terrestrial */
+                       if (configure_tda827x_fe(dev, &md8800_dvbt_config,
+                                                &tda827x_cfg_0) < 0)
+                               goto detach_frontend;
+               } else {        /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                                       &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               struct dvb_frontend *fe = fe0->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, fe0->dvb.frontend,
+                                               0x60, &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Medion Quadro, no tda826x "
+                                               "found !\n", __func__);
+                                       goto detach_frontend;
+                               }
+                               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__);
+                                               goto detach_frontend;
+                                       }
+                                       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:
+               fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend)
+                       dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61,
+                                  NULL, DVB_PLL_TDHU2);
+               break;
+       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
+       case SAA7134_BOARD_KWORLD_ATSC110:
+               fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend)
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_TUV1236D);
+               break;
+       case SAA7134_BOARD_KWORLD_PC150U:
+               saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */
+               saa7134_tuner_callback(dev, 0,
+                                      TDA18271_CALLBACK_CMD_AGC_ENABLE, 1);
+               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+                                              &kworld_s5h1411_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &kworld_pc150u_tda18271_config);
+               }
+               break;
+       case SAA7134_BOARD_FLYDVBS_LR300:
+               fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
+                                      &dev->i2c_adap, 0) == NULL) {
+                               wprintk("%s: No tda826x found!\n", __func__);
+                               goto detach_frontend;
+                       }
+                       if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
+                                      &dev->i2c_adap, 0x08, 0, 0) == NULL) {
+                               wprintk("%s: No ISL6421 found!\n", __func__);
+                               goto detach_frontend;
+                       }
+               }
+               break;
+       case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                                              &medion_cardbus,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
+                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, medion_cardbus.tuner_address,
+                                  TUNER_PHILIPS_FMD1216ME_MK3);
+               }
+               break;
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+               fe0->dvb.frontend = dvb_attach(tda10046_attach,
+                               &philips_europa_config,
+                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
+                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+               }
+               break;
+       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+               if (configure_tda827x_fe(dev, &cinergy_ht_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_CINERGY_HT_PCI:
+               if (configure_tda827x_fe(dev, &cinergy_ht_pci_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_PHILIPS_TIGER_S:
+               if (configure_tda827x_fe(dev, &philips_tiger_s_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_ASUS_P7131_4871:
+               if (configure_tda827x_fe(dev, &asus_p7131_4871_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+               if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+               if (configure_tda827x_fe(dev, &avermedia_super_007_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+               if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config,
+                                        &tda827x_cfg_2_sw42) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_PHILIPS_SNAKE:
+               fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
+                                       &dev->i2c_adap, 0) == NULL) {
+                               wprintk("%s: No tda826x found!\n", __func__);
+                               goto detach_frontend;
+                       }
+                       if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
+                                       &dev->i2c_adap, 0, 0) == NULL) {
+                               wprintk("%s: No lnbp21 found!\n", __func__);
+                               goto detach_frontend;
+                       }
+               }
+               break;
+       case SAA7134_BOARD_CREATIX_CTX953:
+               if (configure_tda827x_fe(dev, &md8800_dvbt_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
+               if (configure_tda827x_fe(dev, &philips_tiger_s_config,
+                                        &tda827x_cfg_2) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               dprintk("AverMedia E506R dvb setup\n");
+               saa7134_set_gpio(dev, 25, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 25, 1);
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_MD7134_BRIDGE_2:
+               fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &sd1878_4m, &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       struct dvb_frontend *fe;
+                       if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
+                                 &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
+                               wprintk("%s: MD7134 DVB-S, no SD1878 "
+                                       "found !\n", __func__);
+                               goto detach_frontend;
+                       }
+                       /* we need to open the i2c gate (we know it exists) */
+                       fe = fe0->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__);
+                               goto detach_frontend;
+                       }
+                       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;
+       case SAA7134_BOARD_AVERMEDIA_M103:
+               saa7134_set_gpio(dev, 25, 0);
+               msleep(10);
+               saa7134_set_gpio(dev, 25, 1);
+               fe0->dvb.frontend = dvb_attach(mt352_attach,
+                                               &avermedia_xc3028_mt352_dev,
+                                               &dev->i2c_adap);
+               attach_xc3028 = 1;
+               break;
+       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+               if (!use_frontend) {     /* terrestrial */
+                       if (configure_tda827x_fe(dev, &asus_tiger_3in1_config,
+                                                       &tda827x_cfg_2) < 0)
+                               goto detach_frontend;
+               } else {                /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                               &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach,
+                                               fe0->dvb.frontend, 0x60,
+                                               &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Asus Tiger 3in1, no "
+                                               "tda826x found!\n", __func__);
+                                       goto detach_frontend;
+                               }
+                               if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
+                                               &dev->i2c_adap, 0, 0) == NULL) {
+                                       wprintk("%s: Asus Tiger 3in1, no lnbp21"
+                                               " found!\n", __func__);
+                                      goto detach_frontend;
+                              }
+                      }
+              }
+              break;
+       case SAA7134_BOARD_ASUSTeK_PS3_100:
+               if (!use_frontend) {     /* terrestrial */
+                       if (configure_tda827x_fe(dev, &asus_ps3_100_config,
+                                                &tda827x_cfg_2) < 0)
+                               goto detach_frontend;
+              } else {                /* satellite */
+                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
+                                                      &flydvbs, &dev->i2c_adap);
+                       if (fe0->dvb.frontend) {
+                               if (dvb_attach(tda826x_attach,
+                                              fe0->dvb.frontend, 0x60,
+                                              &dev->i2c_adap, 0) == NULL) {
+                                       wprintk("%s: Asus My Cinema PS3-100, no "
+                                               "tda826x found!\n", __func__);
+                                       goto detach_frontend;
+                               }
+                               if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
+                                              &dev->i2c_adap, 0, 0) == NULL) {
+                                       wprintk("%s: Asus My Cinema PS3-100, no lnbp21"
+                                               " found!\n", __func__);
+                                       goto detach_frontend;
+                               }
+                       }
+               }
+               break;
+       case SAA7134_BOARD_ASUSTeK_TIGER:
+               if (configure_tda827x_fe(dev, &philips_tiger_config,
+                                        &tda827x_cfg_0) < 0)
+                       goto detach_frontend;
+               break;
+       case SAA7134_BOARD_BEHOLD_H6:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &behold_h6_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x61,
+                                  TUNER_PHILIPS_FMD1216MEX_MK3);
+               }
+               break;
+       case SAA7134_BOARD_BEHOLD_X7:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &behold_x7_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, &behold_x7_tunerconfig);
+               }
+               break;
+       case SAA7134_BOARD_BEHOLD_H7:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &behold_x7_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, &behold_x7_tunerconfig);
+               }
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
+       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+               /* Zarlink ZL10313 */
+               fe0->dvb.frontend = dvb_attach(mt312_attach,
+                       &avertv_a700_mt312, &dev->i2c_adap);
+               if (fe0->dvb.frontend) {
+                       if (dvb_attach(zl10036_attach, fe0->dvb.frontend,
+                                       &avertv_a700_tuner, &dev->i2c_adap) == NULL) {
+                               wprintk("%s: No zl10036 found!\n",
+                                       __func__);
+                       }
+               }
+               break;
+       case SAA7134_BOARD_VIDEOMATE_S350:
+               fe0->dvb.frontend = dvb_attach(mt312_attach,
+                               &zl10313_compro_s350_config, &dev->i2c_adap);
+               if (fe0->dvb.frontend)
+                       if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
+                                       0x60, &dev->i2c_adap) == NULL)
+                               wprintk("%s: No zl10039 found!\n",
+                                       __func__);
+
+               break;
+       case SAA7134_BOARD_VIDEOMATE_T750:
+               fe0->dvb.frontend = dvb_attach(zl10353_attach,
+                                               &videomate_t750_zl10353_config,
+                                               &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       if (dvb_attach(qt1010_attach,
+                                       fe0->dvb.frontend,
+                                       &dev->i2c_adap,
+                                       &videomate_t750_qt1010_config) == NULL)
+                               wprintk("error attaching QT1010\n");
+               }
+               break;
+       case SAA7134_BOARD_ZOLID_HYBRID_PCI:
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                                              &zolid_tda10048_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &zolid_tda18271_config);
+               }
+               break;
+       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+               fe0->dvb.frontend = dvb_attach(tda10048_attach,
+                                              &dtv1000s_tda10048_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &dtv1000s_tda18271_config);
+               }
+               break;
+       case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+               /* Switch to digital mode */
+               saa7134_tuner_callback(dev, 0,
+                                      TDA18271_CALLBACK_CMD_AGC_ENABLE, 1);
+               fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
+                                              &kworld_mb86a20s_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl;
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &kworld_tda18271_config);
+               }
+
+               /* mb86a20s need to use the I2C gateway */
+               break;
+       case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+               fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+                                              &prohdtv_pro2_lgs8g75_config,
+                                              &dev->i2c_adap);
+               if (fe0->dvb.frontend != NULL) {
+                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
+                                  &dev->i2c_adap, 0x4b,
+                                  &tda829x_no_probe);
+                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &prohdtv_pro2_tda18271_config);
+               }
+               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 (!fe0->dvb.frontend)
+                       goto detach_frontend;
+
+               fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
+               if (!fe) {
+                       printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+                              dev->name);
+                       goto detach_frontend;
+               }
+       }
+
+       if (NULL == fe0->dvb.frontend) {
+               printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
+               goto detach_frontend;
+       }
+       /* define general-purpose callback pointer */
+       fe0->dvb.frontend->callback = saa7134_tuner_callback;
+
+       /* register everything else */
+       ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+                                       &dev->pci->dev, adapter_nr, 0);
+
+       /* this sequence is necessary to make the tda1004x load its firmware
+        * and to enter analog mode of hybrid boards
+        */
+       if (!ret) {
+               if (fe0->dvb.frontend->ops.init)
+                       fe0->dvb.frontend->ops.init(fe0->dvb.frontend);
+               if (fe0->dvb.frontend->ops.sleep)
+                       fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend);
+               if (fe0->dvb.frontend->ops.tuner_ops.sleep)
+                       fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend);
+       }
+       return ret;
+
+detach_frontend:
+       videobuf_dvb_dealloc_frontends(&dev->frontends);
+       return -EINVAL;
+}
+
+static int dvb_fini(struct saa7134_dev *dev)
+{
+       struct videobuf_dvb_frontend *fe0;
+
+       /* Get the first frontend */
+       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+       if (!fe0)
+               return -EINVAL;
+
+       /* FIXME: I suspect that this code is bogus, since the entry for
+          Pinnacle 300I DVB-T PAL already defines the proper init to allow
+          the detection of mt2032 (TDA9887_PORT2_INACTIVE)
+        */
+       if (dev->board == SAA7134_BOARD_PINNACLE_300I_DVBT_PAL) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+               static int on  = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv  = &on;
+
+               /* otherwise we don't detect the tuner on next insmod */
+               saa_call_all(dev, tuner, s_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 = fe0->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_bus(&dev->frontends);
+       return 0;
+}
+
+static struct saa7134_mpeg_ops dvb_ops = {
+       .type          = SAA7134_MPEG_DVB,
+       .init          = dvb_init,
+       .fini          = dvb_fini,
+};
+
+static int __init dvb_register(void)
+{
+       return saa7134_ts_register(&dvb_ops);
+}
+
+static void __exit dvb_unregister(void)
+{
+       saa7134_ts_unregister(&dvb_ops);
+}
+
+module_init(dvb_register);
+module_exit(dvb_unregister);
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
new file mode 100644 (file)
index 0000000..dde361a
--- /dev/null
@@ -0,0 +1,590 @@
+/*
+ *
+ * (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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+#include <media/saa6752hs.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+/* ------------------------------------------------------------------ */
+
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+
+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;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages");
+
+#define dprintk(fmt, arg...)   if (debug)                      \
+       printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+
+static void ts_reset_encoder(struct saa7134_dev* dev)
+{
+       if (!dev->empress_started)
+               return;
+
+       saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
+       msleep(10);
+       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+       msleep(100);
+       dev->empress_started = 0;
+}
+
+static int ts_init_encoder(struct saa7134_dev* dev)
+{
+       u32 leading_null_bytes = 0;
+
+       /* If more cards start to need this, then this
+          should probably be added to the card definitions. */
+       switch (dev->board) {
+       case SAA7134_BOARD_BEHOLD_M6:
+       case SAA7134_BOARD_BEHOLD_M63:
+       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+               leading_null_bytes = 1;
+               break;
+       }
+       ts_reset_encoder(dev);
+       saa_call_all(dev, core, init, leading_null_bytes);
+       dev->empress_started = 1;
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int ts_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct saa7134_dev *dev = video_drvdata(file);
+       int err;
+
+       dprintk("open dev=%s\n", video_device_node_name(vdev));
+       err = -EBUSY;
+       if (!mutex_trylock(&dev->empress_tsq.vb_lock))
+               return err;
+       if (atomic_read(&dev->empress_users))
+               goto done;
+
+       /* Unmute audio */
+       saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
+               saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
+
+       atomic_inc(&dev->empress_users);
+       file->private_data = dev;
+       err = 0;
+
+done:
+       mutex_unlock(&dev->empress_tsq.vb_lock);
+       return err;
+}
+
+static int ts_release(struct file *file)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       videobuf_stop(&dev->empress_tsq);
+       videobuf_mmap_free(&dev->empress_tsq);
+
+       /* stop the encoder */
+       ts_reset_encoder(dev);
+
+       /* Mute audio */
+       saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
+               saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
+
+       atomic_dec(&dev->empress_users);
+
+       return 0;
+}
+
+static ssize_t
+ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       if (!dev->empress_started)
+               ts_init_encoder(dev);
+
+       return videobuf_read_stream(&dev->empress_tsq,
+                                   data, count, ppos, 0,
+                                   file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int
+ts_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_poll_stream(file, &dev->empress_tsq, wait);
+}
+
+
+static int
+ts_mmap(struct file *file, struct vm_area_struct * vma)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_mmap_mapper(&dev->empress_tsq, vma);
+}
+
+/*
+ * This function is _not_ called directly, but from
+ * video_generic_ioctl (and maybe others).  userspace
+ * copying is done already, arg is a kernel pointer.
+ */
+
+static int empress_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       strcpy(cap->driver, "saa7134");
+       strlcpy(cap->card, saa7134_boards[dev->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING;
+       return 0;
+}
+
+static int empress_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(i->name, "CCIR656");
+
+       return 0;
+}
+
+static int empress_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int empress_s_input(struct file *file, void *priv, unsigned int i)
+{
+       if (i != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "MPEG TS", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int empress_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7134_dev *dev = file->private_data;
+       struct v4l2_mbus_framefmt mbus_fmt;
+
+       saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
+
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+
+       return 0;
+}
+
+static int empress_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7134_dev *dev = file->private_data;
+       struct v4l2_mbus_framefmt mbus_fmt;
+
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+
+       return 0;
+}
+
+static int empress_try_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
+
+       return 0;
+}
+
+static int empress_reqbufs(struct file *file, void *priv,
+                                       struct v4l2_requestbuffers *p)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_reqbufs(&dev->empress_tsq, p);
+}
+
+static int empress_querybuf(struct file *file, void *priv,
+                                       struct v4l2_buffer *b)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_querybuf(&dev->empress_tsq, b);
+}
+
+static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_qbuf(&dev->empress_tsq, b);
+}
+
+static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_dqbuf(&dev->empress_tsq, b,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int empress_streamon(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_streamon(&dev->empress_tsq);
+}
+
+static int empress_streamoff(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return videobuf_streamoff(&dev->empress_tsq);
+}
+
+static int empress_s_ext_ctrls(struct file *file, void *priv,
+                              struct v4l2_ext_controls *ctrls)
+{
+       struct saa7134_dev *dev = file->private_data;
+       int err;
+
+       /* count == 0 is abused in saa6752hs.c, so that special
+               case is handled here explicitly. */
+       if (ctrls->count == 0)
+               return 0;
+
+       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
+       ts_init_encoder(dev);
+
+       return err;
+}
+
+static int empress_g_ext_ctrls(struct file *file, void *priv,
+                              struct v4l2_ext_controls *ctrls)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
+}
+
+static int empress_g_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *c)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_g_ctrl_internal(dev, NULL, c);
+}
+
+static int empress_s_ctrl(struct file *file, void *priv,
+                                       struct v4l2_control *c)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_s_ctrl_internal(dev, NULL, c);
+}
+
+static int empress_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *c)
+{
+       /* Must be sorted from low to high control ID! */
+       static const u32 user_ctrls[] = {
+               V4L2_CID_USER_CLASS,
+               V4L2_CID_BRIGHTNESS,
+               V4L2_CID_CONTRAST,
+               V4L2_CID_SATURATION,
+               V4L2_CID_HUE,
+               V4L2_CID_AUDIO_VOLUME,
+               V4L2_CID_AUDIO_MUTE,
+               V4L2_CID_HFLIP,
+               0
+       };
+
+       /* Must be sorted from low to high control ID! */
+       static const u32 mpeg_ctrls[] = {
+               V4L2_CID_MPEG_CLASS,
+               V4L2_CID_MPEG_STREAM_TYPE,
+               V4L2_CID_MPEG_STREAM_PID_PMT,
+               V4L2_CID_MPEG_STREAM_PID_AUDIO,
+               V4L2_CID_MPEG_STREAM_PID_VIDEO,
+               V4L2_CID_MPEG_STREAM_PID_PCR,
+               V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+               V4L2_CID_MPEG_AUDIO_ENCODING,
+               V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+               V4L2_CID_MPEG_VIDEO_ENCODING,
+               V4L2_CID_MPEG_VIDEO_ASPECT,
+               V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+               V4L2_CID_MPEG_VIDEO_BITRATE,
+               V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+               0
+       };
+       static const u32 *ctrl_classes[] = {
+               user_ctrls,
+               mpeg_ctrls,
+               NULL
+       };
+       struct saa7134_dev *dev = file->private_data;
+
+       c->id = v4l2_ctrl_next(ctrl_classes, c->id);
+       if (c->id == 0)
+               return -EINVAL;
+       if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
+               return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
+       if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
+               return saa7134_queryctrl(file, priv, c);
+       return saa_call_empress(dev, core, queryctrl, c);
+}
+
+static int empress_querymenu(struct file *file, void *priv,
+                                       struct v4l2_querymenu *c)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       return saa_call_empress(dev, core, querymenu, c);
+}
+
+static int empress_g_chip_ident(struct file *file, void *fh,
+              struct v4l2_dbg_chip_ident *chip)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+       if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
+           !strcmp(chip->match.name, "saa6752hs"))
+               return saa_call_empress(dev, core, g_chip_ident, chip);
+       if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR)
+               return saa_call_empress(dev, core, g_chip_ident, chip);
+       return -EINVAL;
+}
+
+static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       return saa7134_s_std_internal(dev, NULL, id);
+}
+
+static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_dev *dev = file->private_data;
+
+       *id = dev->tvnorm->id;
+       return 0;
+}
+
+static const struct v4l2_file_operations ts_fops =
+{
+       .owner    = THIS_MODULE,
+       .open     = ts_open,
+       .release  = ts_release,
+       .read     = ts_read,
+       .poll     = ts_poll,
+       .mmap     = ts_mmap,
+       .ioctl    = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops ts_ioctl_ops = {
+       .vidioc_querycap                = empress_querycap,
+       .vidioc_enum_fmt_vid_cap        = empress_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap         = empress_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap           = empress_s_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap           = empress_g_fmt_vid_cap,
+       .vidioc_reqbufs                 = empress_reqbufs,
+       .vidioc_querybuf                = empress_querybuf,
+       .vidioc_qbuf                    = empress_qbuf,
+       .vidioc_dqbuf                   = empress_dqbuf,
+       .vidioc_streamon                = empress_streamon,
+       .vidioc_streamoff               = empress_streamoff,
+       .vidioc_s_ext_ctrls             = empress_s_ext_ctrls,
+       .vidioc_g_ext_ctrls             = empress_g_ext_ctrls,
+       .vidioc_enum_input              = empress_enum_input,
+       .vidioc_g_input                 = empress_g_input,
+       .vidioc_s_input                 = empress_s_input,
+       .vidioc_queryctrl               = empress_queryctrl,
+       .vidioc_querymenu               = empress_querymenu,
+       .vidioc_g_ctrl                  = empress_g_ctrl,
+       .vidioc_s_ctrl                  = empress_s_ctrl,
+       .vidioc_g_chip_ident            = empress_g_chip_ident,
+       .vidioc_s_std                   = empress_s_std,
+       .vidioc_g_std                   = empress_g_std,
+};
+
+/* ----------------------------------------------------------- */
+
+static struct video_device saa7134_empress_template = {
+       .name          = "saa7134-empress",
+       .fops          = &ts_fops,
+       .ioctl_ops     = &ts_ioctl_ops,
+
+       .tvnorms                        = SAA7134_NORMS,
+       .current_norm                   = V4L2_STD_PAL,
+};
+
+static void empress_signal_update(struct work_struct *work)
+{
+       struct saa7134_dev* dev =
+               container_of(work, struct saa7134_dev, empress_workqueue);
+
+       if (dev->nosignal) {
+               dprintk("no video signal\n");
+       } else {
+               dprintk("video signal acquired\n");
+       }
+}
+
+static void empress_signal_change(struct saa7134_dev *dev)
+{
+       schedule_work(&dev->empress_workqueue);
+}
+
+
+static int empress_init(struct saa7134_dev *dev)
+{
+       int err;
+
+       dprintk("%s: %s\n",dev->name,__func__);
+       dev->empress_dev = video_device_alloc();
+       if (NULL == dev->empress_dev)
+               return -ENOMEM;
+       *(dev->empress_dev) = saa7134_empress_template;
+       dev->empress_dev->parent  = &dev->pci->dev;
+       dev->empress_dev->release = video_device_release;
+       snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
+                "%s empress (%s)", dev->name,
+                saa7134_boards[dev->board].name);
+
+       INIT_WORK(&dev->empress_workqueue, empress_signal_update);
+
+       video_set_drvdata(dev->empress_dev, dev);
+       err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
+                                   empress_nr[dev->nr]);
+       if (err < 0) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                      dev->name);
+               video_device_release(dev->empress_dev);
+               dev->empress_dev = NULL;
+               return err;
+       }
+       printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+              dev->name, video_device_node_name(dev->empress_dev));
+
+       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),
+                           dev, NULL);
+
+       empress_signal_update(&dev->empress_workqueue);
+       return 0;
+}
+
+static int empress_fini(struct saa7134_dev *dev)
+{
+       dprintk("%s: %s\n",dev->name,__func__);
+
+       if (NULL == dev->empress_dev)
+               return 0;
+       flush_work_sync(&dev->empress_workqueue);
+       video_unregister_device(dev->empress_dev);
+       dev->empress_dev = NULL;
+       return 0;
+}
+
+static struct saa7134_mpeg_ops empress_ops = {
+       .type          = SAA7134_MPEG_EMPRESS,
+       .init          = empress_init,
+       .fini          = empress_fini,
+       .signal_change = empress_signal_change,
+};
+
+static int __init empress_register(void)
+{
+       return saa7134_ts_register(&empress_ops);
+}
+
+static void __exit empress_unregister(void)
+{
+       saa7134_ts_unregister(&empress_ops);
+}
+
+module_init(empress_register);
+module_exit(empress_unregister);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-i2c.c b/drivers/media/pci/saa7134/saa7134-i2c.c
new file mode 100644 (file)
index 0000000..a176ec3
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * i2c interface support
+ *
+ * (c) 2001,02 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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+#include <media/v4l2-common.h>
+
+/* ----------------------------------------------------------- */
+
+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;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+#define d1printk if (1 == i2c_debug) printk
+#define d2printk if (2 == i2c_debug) printk
+
+#define I2C_WAIT_DELAY  32
+#define I2C_WAIT_RETRY  16
+
+/* ----------------------------------------------------------- */
+
+static char *str_i2c_status[] = {
+       "IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE",
+       "DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE",
+       "NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR"
+};
+
+enum i2c_status {
+       IDLE          = 0,  // no I2C command pending
+       DONE_STOP     = 1,  // I2C command done and STOP executed
+       BUSY          = 2,  // executing I2C command
+       TO_SCL        = 3,  // executing I2C command, time out on clock stretching
+       TO_ARB        = 4,  // time out on arbitration trial, still trying
+       DONE_WRITE    = 5,  // I2C command done and awaiting next write command
+       DONE_READ     = 6,  // I2C command done and awaiting next read command
+       DONE_WRITE_TO = 7,  // see 5, and time out on status echo
+       DONE_READ_TO  = 8,  // see 6, and time out on status echo
+       NO_DEVICE     = 9,  // no acknowledge on device slave address
+       NO_ACKN       = 10, // no acknowledge after data byte transfer
+       BUS_ERR       = 11, // bus error
+       ARB_LOST      = 12, // arbitration lost during transfer
+       SEQ_ERR       = 13, // erroneous programming sequence
+       ST_ERR        = 14, // wrong status echoing
+       SW_ERR        = 15  // software error
+};
+
+static char *str_i2c_attr[] = {
+       "NOP", "STOP", "CONTINUE", "START"
+};
+
+enum i2c_attr {
+       NOP           = 0,  // no operation on I2C bus
+       STOP          = 1,  // stop condition, no associated byte transfer
+       CONTINUE      = 2,  // continue with byte transfer
+       START         = 3   // start condition with byte transfer
+};
+
+static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
+{
+       enum i2c_status status;
+
+       status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
+       d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name,
+                str_i2c_status[status]);
+       return status;
+}
+
+static inline void i2c_set_status(struct saa7134_dev *dev,
+                                 enum i2c_status status)
+{
+       d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name,
+                str_i2c_status[status]);
+       saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
+}
+
+static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
+{
+       d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name,
+                str_i2c_attr[attr]);
+       saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
+}
+
+static inline int i2c_is_error(enum i2c_status status)
+{
+       switch (status) {
+       case NO_DEVICE:
+       case NO_ACKN:
+       case BUS_ERR:
+       case ARB_LOST:
+       case SEQ_ERR:
+       case ST_ERR:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static inline int i2c_is_idle(enum i2c_status status)
+{
+       switch (status) {
+       case IDLE:
+       case DONE_STOP:
+               return true;
+       default:
+               return false;
+       }
+}
+
+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;
+       }
+}
+
+static int i2c_is_busy_wait(struct saa7134_dev *dev)
+{
+       enum i2c_status status;
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               status = i2c_get_status(dev);
+               if (!i2c_is_busy(status))
+                       break;
+               saa_wait(I2C_WAIT_DELAY);
+       }
+       if (I2C_WAIT_RETRY == count)
+               return false;
+       return true;
+}
+
+static int i2c_reset(struct saa7134_dev *dev)
+{
+       enum i2c_status status;
+       int count;
+
+       d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
+       status = i2c_get_status(dev);
+       if (!i2c_is_error(status))
+               return true;
+       i2c_set_status(dev,status);
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               status = i2c_get_status(dev);
+               if (!i2c_is_error(status))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+       if (I2C_WAIT_RETRY == count)
+               return false;
+
+       if (!i2c_is_idle(status))
+               return false;
+
+       i2c_set_attr(dev,NOP);
+       return true;
+}
+
+static inline int i2c_send_byte(struct saa7134_dev *dev,
+                               enum i2c_attr attr,
+                               unsigned char data)
+{
+       enum i2c_status status;
+       __u32 dword;
+
+       /* have to write both attr + data in one 32bit word */
+       dword  = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
+       dword &= 0x0f;
+       dword |= (attr << 6);
+       dword |= ((__u32)data << 8);
+       dword |= 0x00 << 16;  /* 100 kHz */
+//     dword |= 0x40 << 16;  /* 400 kHz */
+       dword |= 0xf0 << 24;
+       saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
+       d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data);
+
+       if (!i2c_is_busy_wait(dev))
+               return -EIO;
+       status = i2c_get_status(dev);
+       if (i2c_is_error(status))
+               return -EIO;
+       return 0;
+}
+
+static inline int i2c_recv_byte(struct saa7134_dev *dev)
+{
+       enum i2c_status status;
+       unsigned char data;
+
+       i2c_set_attr(dev,CONTINUE);
+       if (!i2c_is_busy_wait(dev))
+               return -EIO;
+       status = i2c_get_status(dev);
+       if (i2c_is_error(status))
+               return -EIO;
+       data = saa_readb(SAA7134_I2C_DATA);
+       d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data);
+       return data;
+}
+
+static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
+                           struct i2c_msg *msgs, int num)
+{
+       struct saa7134_dev *dev = i2c_adap->algo_data;
+       enum i2c_status status;
+       unsigned char data;
+       int addr,rc,i,byte;
+
+       status = i2c_get_status(dev);
+       if (!i2c_is_idle(status))
+               if (!i2c_reset(dev))
+                       return -EIO;
+
+       d2printk("start xfer\n");
+       d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
+       for (i = 0; i < num; i++) {
+               if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
+                       /* send address */
+                       d2printk("send address\n");
+                       addr  = msgs[i].addr << 1;
+                       if (msgs[i].flags & I2C_M_RD)
+                               addr |= 1;
+                       if (i > 0 && msgs[i].flags &
+                           I2C_M_RD && msgs[i].addr != 0x40 &&
+                           msgs[i].addr != 0x19) {
+                               /* workaround for a saa7134 i2c bug
+                                * needed to talk to the mt352 demux
+                                * thanks to pinnacle for the hint */
+                               int quirk = 0xfe;
+                               d1printk(" [%02x quirk]",quirk);
+                               i2c_send_byte(dev,START,quirk);
+                               i2c_recv_byte(dev);
+                       }
+                       d1printk(" < %02x", addr);
+                       rc = i2c_send_byte(dev,START,addr);
+                       if (rc < 0)
+                                goto err;
+               }
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read bytes */
+                       d2printk("read bytes\n");
+                       for (byte = 0; byte < msgs[i].len; byte++) {
+                               d1printk(" =");
+                               rc = i2c_recv_byte(dev);
+                               if (rc < 0)
+                                       goto err;
+                               d1printk("%02x", rc);
+                               msgs[i].buf[byte] = rc;
+                       }
+                       /* discard mysterious extra byte when reading
+                          from Samsung S5H1411.  i2c bus gets error
+                          if we do not. */
+                       if (0x19 == msgs[i].addr) {
+                               d1printk(" ?");
+                               rc = i2c_recv_byte(dev);
+                               if (rc < 0)
+                                       goto err;
+                               d1printk("%02x", rc);
+                       }
+               } else {
+                       /* write bytes */
+                       d2printk("write bytes\n");
+                       for (byte = 0; byte < msgs[i].len; byte++) {
+                               data = msgs[i].buf[byte];
+                               d1printk(" %02x", data);
+                               rc = i2c_send_byte(dev,CONTINUE,data);
+                               if (rc < 0)
+                                       goto err;
+                       }
+               }
+       }
+       d2printk("xfer done\n");
+       d1printk(" >");
+       i2c_set_attr(dev,STOP);
+       rc = -EIO;
+       if (!i2c_is_busy_wait(dev))
+               goto err;
+       status = i2c_get_status(dev);
+       if (i2c_is_error(status))
+               goto err;
+       /* ensure that the bus is idle for at least one bit slot */
+       msleep(1);
+
+       d1printk("\n");
+       return num;
+ err:
+       if (1 == i2c_debug) {
+               status = i2c_get_status(dev);
+               printk(" ERROR: %s\n",str_i2c_status[status]);
+       }
+       return rc;
+}
+
+/* ----------------------------------------------------------- */
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm saa7134_algo = {
+       .master_xfer   = saa7134_i2c_xfer,
+       .functionality = functionality,
+};
+
+static struct i2c_adapter saa7134_adap_template = {
+       .owner         = THIS_MODULE,
+       .name          = "saa7134",
+       .algo          = &saa7134_algo,
+};
+
+static struct i2c_client saa7134_client_template = {
+       .name   = "saa7134 internal",
+};
+
+/* ----------------------------------------------------------- */
+
+static int
+saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
+{
+       unsigned char buf;
+       int i,err;
+
+       dev->i2c_client.addr = 0xa0 >> 1;
+       buf = 0;
+       if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
+               printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+                      dev->name,err);
+               return -1;
+       }
+       if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
+               printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
+                      dev->name,err);
+               return -1;
+       }
+       for (i = 0; i < len; i++) {
+               if (0 == (i % 16))
+                       printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i);
+               printk(" %02x",eedata[i]);
+               if (15 == (i % 16))
+                       printk("\n");
+       }
+       return 0;
+}
+
+static char *i2c_devs[128] = {
+       [ 0x20      ] = "mpeg encoder (saa6752hs)",
+       [ 0xa0 >> 1 ] = "eeprom",
+       [ 0xc0 >> 1 ] = "tuner (analog)",
+       [ 0x86 >> 1 ] = "tda9887",
+       [ 0x5a >> 1 ] = "remote control",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i,rc;
+
+       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c,&buf,0);
+               if (rc < 0)
+                       continue;
+               printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
+                      name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+}
+
+int saa7134_i2c_register(struct saa7134_dev *dev)
+{
+       dev->i2c_adap = saa7134_adap_template;
+       dev->i2c_adap.dev.parent = &dev->pci->dev;
+       strcpy(dev->i2c_adap.name,dev->name);
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+       i2c_add_adapter(&dev->i2c_adap);
+
+       dev->i2c_client = saa7134_client_template;
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
+       if (i2c_scan)
+               do_i2c_scan(dev->name,&dev->i2c_client);
+
+       /* Instantiate the IR receiver device, if present */
+       saa7134_probe_i2c_ir(dev);
+       return 0;
+}
+
+int saa7134_i2c_unregister(struct saa7134_dev *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
new file mode 100644 (file)
index 0000000..0f78f5e
--- /dev/null
@@ -0,0 +1,1041 @@
+/*
+ *
+ * handle saa7134 IR remotes via linux kernel input layer.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+#define MODULE_NAME "saa7134"
+
+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;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
+
+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)");
+
+#define dprintk(fmt, arg...)   if (ir_debug) \
+       printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
+#define i2cdprintk(fmt, arg...)    if (ir_debug) \
+       printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
+
+/* Helper function for raw decoding at GPIO16 or GPIO18 */
+static int saa7134_raw_decode_irq(struct saa7134_dev *dev);
+
+/* -------------------- GPIO generic keycode builder -------------------- */
+
+static int build_key(struct saa7134_dev *dev)
+{
+       struct saa7134_card_ir *ir = dev->remote;
+       u32 gpio, data;
+
+       /* here comes the additional handshake steps for some cards */
+       switch (dev->board) {
+       case SAA7134_BOARD_GOTVIEW_7135:
+               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x80);
+               saa_clearb(SAA7134_GPIO_GPSTATUS1, 0x80);
+               break;
+       }
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+       saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
+
+       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+       if (ir->polling) {
+               if (ir->last_gpio == gpio)
+                       return 0;
+               ir->last_gpio = gpio;
+       }
+
+       data = ir_extract_bits(gpio, ir->mask_keycode);
+       dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
+               gpio, ir->mask_keycode, data);
+
+       switch (dev->board) {
+       case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
+               if (data == ir->mask_keycode)
+                       rc_keyup(ir->dev);
+               else
+                       rc_keydown_notimeout(ir->dev, data, 0);
+               return 0;
+       }
+
+       if (ir->polling) {
+               if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
+                   (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
+                       rc_keydown_notimeout(ir->dev, data, 0);
+               } else {
+                       rc_keyup(ir->dev);
+               }
+       }
+       else {  /* IRQ driven mode - handle key press and release in one go */
+               if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
+                   (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
+                       rc_keydown_notimeout(ir->dev, data, 0);
+                       rc_keyup(ir->dev);
+               }
+       }
+
+       return 0;
+}
+
+/* --------------------- Chip specific I2C key builders ----------------- */
+
+static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       int gpio;
+       int attempt = 0;
+       unsigned char b;
+
+       /* We need this to access GPI Used by the saa_readl macro. */
+       struct saa7134_dev *dev = ir->c->adapter->algo_data;
+
+       if (dev == NULL) {
+               i2cdprintk("get_key_flydvb_trio: "
+                          "ir->c->adapter->algo_data is NULL!\n");
+               return -EIO;
+       }
+
+       /* rising SAA7134_GPIGPRESCAN reads the status */
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+       if (0x40000 & ~gpio)
+               return 0; /* No button press */
+
+       /* No button press - only before first key pressed */
+       if (b == 0xFF)
+               return 0;
+
+       /* poll IR chip */
+       /* weak up the IR chip */
+       b = 0;
+
+       while (1 != i2c_master_send(ir->c, &b, 1)) {
+               if ((attempt++) < 10) {
+                       /*
+                        * wait a bit for next attempt -
+                        * I don't know how make it better
+                        */
+                       msleep(10);
+                       continue;
+               }
+               i2cdprintk("send wake up byte to pic16C505 (IR chip)"
+                          "failed %dx\n", attempt);
+               return -EIO;
+       }
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
+static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
+                                      u32 *ir_raw)
+{
+       unsigned char b;
+       int gpio;
+
+       /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
+       struct saa7134_dev *dev = ir->c->adapter->algo_data;
+       if (dev == NULL) {
+               i2cdprintk("get_key_msi_tvanywhere_plus: "
+                          "ir->c->adapter->algo_data is NULL!\n");
+               return -EIO;
+       }
+
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+       /* GPIO&0x40 is pulsed low when a button is pressed. Don't do
+          I2C receive if gpio&0x40 is not low. */
+
+       if (gpio & 0x40)
+               return 0;       /* No button press */
+
+       /* GPIO says there is a button press. Get it. */
+
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       /* No button press */
+
+       if (b == 0xff)
+               return 0;
+
+       /* Button pressed */
+
+       dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
+/* copied and modified from get_key_msi_tvanywhere_plus() */
+static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
+                                       u32 *ir_raw)
+{
+       unsigned char b;
+       unsigned int gpio;
+
+       /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
+       struct saa7134_dev *dev = ir->c->adapter->algo_data;
+       if (dev == NULL) {
+               i2cdprintk("get_key_kworld_pc150u: "
+                          "ir->c->adapter->algo_data is NULL!\n");
+               return -EIO;
+       }
+
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+       /* GPIO&0x100 is pulsed low when a button is pressed. Don't do
+          I2C receive if gpio&0x100 is not low. */
+
+       if (gpio & 0x100)
+               return 0;       /* No button press */
+
+       /* GPIO says there is a button press. Get it. */
+
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       /* No button press */
+
+       if (b == 0xff)
+               return 0;
+
+       /* Button pressed */
+
+       dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
+static int get_key_purpletv(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)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       /* no button press */
+       if (b==0)
+               return 0;
+
+       /* repeating */
+       if (b & 0x80)
+               return 1;
+
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
+static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char buf[5];
+
+       /* poll IR chip */
+       if (5 != i2c_master_recv(ir->c, buf, 5))
+               return -EIO;
+
+       /* Check if some key were pressed */
+       if (!(buf[0] & 0x80))
+               return 0;
+
+       /*
+        * buf[3] & 0x80 is always high.
+        * buf[3] & 0x40 is a parity bit. A repeat event is marked
+        * by preserving it into two separate readings
+        * buf[4] bits 0 and 1, and buf[1] and buf[2] are always
+        * zero.
+        */
+       *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
+       *ir_raw = *ir_key;
+       return 1;
+}
+
+
+static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char data[12];
+       u32 gpio;
+
+       struct saa7134_dev *dev = ir->c->adapter->algo_data;
+
+       /* rising SAA7134_GPIO_GPRESCAN reads the status */
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+
+       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+
+       if (0x400000 & ~gpio)
+               return 0; /* No button press */
+
+       ir->c->addr = 0x5a >> 1;
+
+       if (12 != i2c_master_recv(ir->c, data, 12)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       if (data[9] != (unsigned char)(~data[8]))
+               return 0;
+
+       *ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
+       *ir_key = *ir_raw;
+
+       return 1;
+}
+
+/* Common (grey or coloured) pinnacle PCTV remote handling
+ *
+ */
+static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
+                           int parity_offset, int marker, int code_modulo)
+{
+       unsigned char b[4];
+       unsigned int start = 0,parity = 0,code = 0;
+
+       /* poll IR chip */
+       if (4 != i2c_master_recv(ir->c, b, 4)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       for (start = 0; start < ARRAY_SIZE(b); start++) {
+               if (b[start] == marker) {
+                       code=b[(start+parity_offset + 1) % 4];
+                       parity=b[(start+parity_offset) % 4];
+               }
+       }
+
+       /* Empty Request */
+       if (parity == 0)
+               return 0;
+
+       /* Repeating... */
+       if (ir->old == parity)
+               return 0;
+
+       ir->old = parity;
+
+       /* drop special codes when a key is held down a long time for the grey controller
+          In this case, the second bit of the code is asserted */
+       if (marker == 0xfe && (code & 0x40))
+               return 0;
+
+       code %= code_modulo;
+
+       *ir_raw = code;
+       *ir_key = code;
+
+       i2cdprintk("Pinnacle PCTV key %02x\n", code);
+
+       return 1;
+}
+
+/* The grey pinnacle PCTV remote
+ *
+ *  There are one issue with this remote:
+ *   - I2c packet does not change when the same key is pressed quickly. The workaround
+ *     is to hold down each key for about half a second, so that another code is generated
+ *     in the i2c packet, and the function can distinguish key presses.
+ *
+ * Sylvain Pasche <sylvain.pasche@gmail.com>
+ */
+static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+
+       return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
+}
+
+
+/* The new pinnacle PCTV remote (with the colored buttons)
+ *
+ * Ricardo Cerqueira <v4l@cerqueira.org>
+ */
+static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
+        *
+        * this is the only value that results in 42 unique
+        * codes < 128
+        */
+
+       return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
+}
+
+void saa7134_input_irq(struct saa7134_dev *dev)
+{
+       struct saa7134_card_ir *ir;
+
+       if (!dev || !dev->remote)
+               return;
+
+       ir = dev->remote;
+       if (!ir->running)
+               return;
+
+       if (!ir->polling && !ir->raw_decode) {
+               build_key(dev);
+       } else if (ir->raw_decode) {
+               saa7134_raw_decode_irq(dev);
+       }
+}
+
+static void saa7134_input_timer(unsigned long data)
+{
+       struct saa7134_dev *dev = (struct saa7134_dev *)data;
+       struct saa7134_card_ir *ir = dev->remote;
+
+       build_key(dev);
+       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+}
+
+static void ir_raw_decode_timer_end(unsigned long data)
+{
+       struct saa7134_dev *dev = (struct saa7134_dev *)data;
+
+       ir_raw_event_handle(dev->remote->dev);
+}
+
+static int __saa7134_ir_start(void *priv)
+{
+       struct saa7134_dev *dev = priv;
+       struct saa7134_card_ir *ir;
+
+       if (!dev || !dev->remote)
+               return -EINVAL;
+
+       ir  = dev->remote;
+       if (ir->running)
+               return 0;
+
+       /* Moved here from saa7134_input_init1() because the latter
+        * is not called on device resume */
+       switch (dev->board) {
+       case SAA7134_BOARD_MD2819:
+       case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
+       case SAA7134_BOARD_AVERMEDIA_305:
+       case SAA7134_BOARD_AVERMEDIA_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
+       case SAA7134_BOARD_AVERMEDIA_M102:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
+               /* Without this we won't receive key up events */
+               saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
+               saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_777:
+       case SAA7134_BOARD_AVERMEDIA_A16AR:
+               /* Without this we won't receive key up events */
+               saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
+               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               /* Without this we won't receive key up events */
+               saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
+               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+               break;
+       case SAA7134_BOARD_GOTVIEW_7135:
+               saa_setb(SAA7134_GPIO_GPMODE1, 0x80);
+               break;
+       }
+
+       ir->running = true;
+
+       if (ir->polling) {
+               setup_timer(&ir->timer, saa7134_input_timer,
+                           (unsigned long)dev);
+               ir->timer.expires = jiffies + HZ;
+               add_timer(&ir->timer);
+       } else if (ir->raw_decode) {
+               /* set timer_end for code completion */
+               setup_timer(&ir->timer, ir_raw_decode_timer_end,
+                           (unsigned long)dev);
+       }
+
+       return 0;
+}
+
+static void __saa7134_ir_stop(void *priv)
+{
+       struct saa7134_dev *dev = priv;
+       struct saa7134_card_ir *ir;
+
+       if (!dev || !dev->remote)
+               return;
+
+       ir  = dev->remote;
+       if (!ir->running)
+               return;
+
+       if (ir->polling || ir->raw_decode)
+               del_timer_sync(&ir->timer);
+
+       ir->running = false;
+
+       return;
+}
+
+int saa7134_ir_start(struct saa7134_dev *dev)
+{
+       if (dev->remote->users)
+               return __saa7134_ir_start(dev);
+
+       return 0;
+}
+
+void saa7134_ir_stop(struct saa7134_dev *dev)
+{
+       if (dev->remote->users)
+               __saa7134_ir_stop(dev);
+}
+
+static int saa7134_ir_open(struct rc_dev *rc)
+{
+       struct saa7134_dev *dev = rc->priv;
+
+       dev->remote->users++;
+       return __saa7134_ir_start(dev);
+}
+
+static void saa7134_ir_close(struct rc_dev *rc)
+{
+       struct saa7134_dev *dev = rc->priv;
+
+       dev->remote->users--;
+       if (!dev->remote->users)
+               __saa7134_ir_stop(dev);
+}
+
+int saa7134_input_init1(struct saa7134_dev *dev)
+{
+       struct saa7134_card_ir *ir;
+       struct rc_dev *rc;
+       char *ir_codes = NULL;
+       u32 mask_keycode = 0;
+       u32 mask_keydown = 0;
+       u32 mask_keyup   = 0;
+       unsigned polling = 0;
+       bool raw_decode  = false;
+       int err;
+
+       if (dev->has_remote != SAA7134_REMOTE_GPIO)
+               return -ENODEV;
+       if (disable_ir)
+               return -ENODEV;
+
+       /* detect & configure */
+       switch (dev->board) {
+       case SAA7134_BOARD_FLYVIDEO2000:
+       case SAA7134_BOARD_FLYVIDEO3000:
+       case SAA7134_BOARD_FLYTVPLATINUM_FM:
+       case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
+       case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
+               ir_codes     = RC_MAP_FLYVIDEO;
+               mask_keycode = 0xEC00000;
+               mask_keydown = 0x0040000;
+               break;
+       case SAA7134_BOARD_CINERGY400:
+       case SAA7134_BOARD_CINERGY600:
+       case SAA7134_BOARD_CINERGY600_MK3:
+               ir_codes     = RC_MAP_CINERGY;
+               mask_keycode = 0x00003f;
+               mask_keyup   = 0x040000;
+               break;
+       case SAA7134_BOARD_ECS_TVP3XP:
+       case SAA7134_BOARD_ECS_TVP3XP_4CB5:
+               ir_codes     = RC_MAP_EZTV;
+               mask_keycode = 0x00017c;
+               mask_keyup   = 0x000002;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_KWORLD_XPERT:
+       case SAA7134_BOARD_AVACSSMARTTV:
+               ir_codes     = RC_MAP_PIXELVIEW;
+               mask_keycode = 0x00001F;
+               mask_keyup   = 0x000020;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_MD2819:
+       case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
+       case SAA7134_BOARD_AVERMEDIA_305:
+       case SAA7134_BOARD_AVERMEDIA_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
+       case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
+       case SAA7134_BOARD_AVERMEDIA_M102:
+       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
+               ir_codes     = RC_MAP_AVERMEDIA;
+               mask_keycode = 0x0007C8;
+               mask_keydown = 0x000010;
+               polling      = 50; // ms
+               /* GPIO stuff moved to __saa7134_ir_start() */
+               break;
+       case SAA7134_BOARD_AVERMEDIA_M135A:
+               ir_codes     = RC_MAP_AVERMEDIA_M135A;
+               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = true;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_M733A:
+               ir_codes     = RC_MAP_AVERMEDIA_M733A_RM_K6;
+               mask_keydown = 0x0040000;
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = true;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_777:
+       case SAA7134_BOARD_AVERMEDIA_A16AR:
+               ir_codes     = RC_MAP_AVERMEDIA;
+               mask_keycode = 0x02F200;
+               mask_keydown = 0x000400;
+               polling      = 50; // ms
+               /* GPIO stuff moved to __saa7134_ir_start() */
+               break;
+       case SAA7134_BOARD_AVERMEDIA_A16D:
+               ir_codes     = RC_MAP_AVERMEDIA_A16D;
+               mask_keycode = 0x02F200;
+               mask_keydown = 0x000400;
+               polling      = 50; /* ms */
+               /* GPIO stuff moved to __saa7134_ir_start() */
+               break;
+       case SAA7134_BOARD_KWORLD_TERMINATOR:
+               ir_codes     = RC_MAP_PIXELVIEW;
+               mask_keycode = 0x00001f;
+               mask_keyup   = 0x000060;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_MANLI_MTV001:
+       case SAA7134_BOARD_MANLI_MTV002:
+               ir_codes     = RC_MAP_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:
+       case SAA7134_BOARD_BEHOLD_403FM:
+       case SAA7134_BOARD_BEHOLD_405:
+       case SAA7134_BOARD_BEHOLD_405FM:
+       case SAA7134_BOARD_BEHOLD_407:
+       case SAA7134_BOARD_BEHOLD_407FM:
+       case SAA7134_BOARD_BEHOLD_409:
+       case SAA7134_BOARD_BEHOLD_505FM:
+       case SAA7134_BOARD_BEHOLD_505RDS_MK5:
+       case SAA7134_BOARD_BEHOLD_505RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_507_9FM:
+       case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_507RDS_MK5:
+               ir_codes     = RC_MAP_MANLI;
+               mask_keycode = 0x003f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; /* ms */
+               break;
+       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+               ir_codes     = RC_MAP_BEHOLD_COLUMBUS;
+               mask_keycode = 0x003f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
+               ir_codes     = RC_MAP_PCTV_SEDNA;
+               mask_keycode = 0x001f00;
+               mask_keyup   = 0x004000;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_GOTVIEW_7135:
+               ir_codes     = RC_MAP_GOTVIEW7135;
+               mask_keycode = 0x0003CC;
+               mask_keydown = 0x000010;
+               polling      = 5; /* ms */
+               /* GPIO stuff moved to __saa7134_ir_start() */
+               break;
+       case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+       case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
+       case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
+               ir_codes     = RC_MAP_VIDEOMATE_TV_PVR;
+               mask_keycode = 0x00003F;
+               mask_keyup   = 0x400000;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_PROTEUS_2309:
+               ir_codes     = RC_MAP_PROTEUS_2309;
+               mask_keycode = 0x00007F;
+               mask_keyup   = 0x000080;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+               ir_codes     = RC_MAP_VIDEOMATE_TV_PVR;
+               mask_keycode = 0x003F00;
+               mask_keyup   = 0x040000;
+               break;
+       case SAA7134_BOARD_FLYDVBS_LR300:
+       case SAA7134_BOARD_FLYDVBT_LR301:
+       case SAA7134_BOARD_FLYDVBTDUO:
+               ir_codes     = RC_MAP_FLYDVB;
+               mask_keycode = 0x0001F00;
+               mask_keydown = 0x0040000;
+               break;
+       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+       case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
+               ir_codes     = RC_MAP_ASUS_PC39;
+               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = true;
+               break;
+       case SAA7134_BOARD_ASUSTeK_PS3_100:
+               ir_codes     = RC_MAP_ASUS_PS3_100;
+               mask_keydown = 0x0040000;
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = true;
+               break;
+       case SAA7134_BOARD_ENCORE_ENLTV:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM:
+               ir_codes     = RC_MAP_ENCORE_ENLTV;
+               mask_keycode = 0x00007f;
+               mask_keyup   = 0x040000;
+               polling      = 50; // ms
+               break;
+       case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+       case SAA7134_BOARD_ENCORE_ENLTV_FM3:
+               ir_codes     = RC_MAP_ENCORE_ENLTV_FM53;
+               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = true;
+               break;
+       case SAA7134_BOARD_10MOONSTVMASTER3:
+               ir_codes     = RC_MAP_ENCORE_ENLTV;
+               mask_keycode = 0x5f80000;
+               mask_keyup   = 0x8000000;
+               polling      = 50; //ms
+               break;
+       case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
+               ir_codes     = RC_MAP_GENIUS_TVGO_A11MCE;
+               mask_keycode = 0xff;
+               mask_keydown = 0xf00000;
+               polling = 50; /* ms */
+               break;
+       case SAA7134_BOARD_REAL_ANGEL_220:
+               ir_codes     = RC_MAP_REAL_AUDIO_220_32_KEYS;
+               mask_keycode = 0x3f00;
+               mask_keyup   = 0x4000;
+               polling = 50; /* ms */
+               break;
+       case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
+               ir_codes     = RC_MAP_KWORLD_PLUS_TV_ANALOG;
+               mask_keycode = 0x7f;
+               polling = 40; /* ms */
+               break;
+       case SAA7134_BOARD_VIDEOMATE_S350:
+               ir_codes     = RC_MAP_VIDEOMATE_S350;
+               mask_keycode = 0x003f00;
+               mask_keydown = 0x040000;
+               break;
+       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+               ir_codes     = RC_MAP_WINFAST;
+               mask_keycode = 0x5f00;
+               mask_keyup   = 0x020000;
+               polling      = 50; /* ms */
+               break;
+       case SAA7134_BOARD_VIDEOMATE_M1F:
+               ir_codes     = RC_MAP_VIDEOMATE_K100;
+               mask_keycode = 0x0ff00;
+               mask_keyup   = 0x040000;
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+               ir_codes     = RC_MAP_HAUPPAUGE;
+               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
+               mask_keyup   = 0x0040000;
+               mask_keycode = 0xffff;
+               raw_decode   = true;
+               break;
+       }
+       if (NULL == ir_codes) {
+               printk("%s: Oops: IR config error [card=%d]\n",
+                      dev->name, dev->board);
+               return -ENODEV;
+       }
+
+       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       rc = rc_allocate_device();
+       if (!ir || !rc) {
+               err = -ENOMEM;
+               goto err_out_free;
+       }
+
+       ir->dev = rc;
+       dev->remote = ir;
+
+       /* init hardware-specific stuff */
+       ir->mask_keycode = mask_keycode;
+       ir->mask_keydown = mask_keydown;
+       ir->mask_keyup   = mask_keyup;
+       ir->polling      = polling;
+       ir->raw_decode   = raw_decode;
+
+       /* init input device */
+       snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
+                saa7134_boards[dev->board].name);
+       snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
+                pci_name(dev->pci));
+
+       rc->priv = dev;
+       rc->open = saa7134_ir_open;
+       rc->close = saa7134_ir_close;
+       if (raw_decode)
+               rc->driver_type = RC_DRIVER_IR_RAW;
+
+       rc->input_name = ir->name;
+       rc->input_phys = ir->phys;
+       rc->input_id.bustype = BUS_PCI;
+       rc->input_id.version = 1;
+       if (dev->pci->subsystem_vendor) {
+               rc->input_id.vendor  = dev->pci->subsystem_vendor;
+               rc->input_id.product = dev->pci->subsystem_device;
+       } else {
+               rc->input_id.vendor  = dev->pci->vendor;
+               rc->input_id.product = dev->pci->device;
+       }
+       rc->dev.parent = &dev->pci->dev;
+       rc->map_name = ir_codes;
+       rc->driver_name = MODULE_NAME;
+
+       err = rc_register_device(rc);
+       if (err)
+               goto err_out_free;
+
+       return 0;
+
+err_out_free:
+       rc_free_device(rc);
+       dev->remote = NULL;
+       kfree(ir);
+       return err;
+}
+
+void saa7134_input_fini(struct saa7134_dev *dev)
+{
+       if (NULL == dev->remote)
+               return;
+
+       saa7134_ir_stop(dev);
+       rc_unregister_device(dev->remote->dev);
+       kfree(dev->remote);
+       dev->remote = NULL;
+}
+
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
+{
+       struct i2c_board_info info;
+       struct i2c_msg msg_msi = {
+               .addr = 0x50,
+               .flags = I2C_M_RD,
+               .len = 0,
+               .buf = NULL,
+       };
+       int rc;
+
+       if (disable_ir) {
+               dprintk("IR has been disabled, not probing for i2c remote\n");
+               return;
+       }
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       memset(&dev->init_data, 0, sizeof(dev->init_data));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
+       switch (dev->board) {
+       case SAA7134_BOARD_PINNACLE_PCTV_110i:
+       case SAA7134_BOARD_PINNACLE_PCTV_310i:
+               dev->init_data.name = "Pinnacle PCTV";
+               if (pinnacle_remote == 0) {
+                       dev->init_data.get_key = get_key_pinnacle_color;
+                       dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR;
+                       info.addr = 0x47;
+               } else {
+                       dev->init_data.get_key = get_key_pinnacle_grey;
+                       dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
+                       info.addr = 0x47;
+               }
+               break;
+       case SAA7134_BOARD_UPMOST_PURPLE_TV:
+               dev->init_data.name = "Purple TV";
+               dev->init_data.get_key = get_key_purpletv;
+               dev->init_data.ir_codes = RC_MAP_PURPLETV;
+               info.addr = 0x7a;
+               break;
+       case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
+               dev->init_data.name = "MSI TV@nywhere Plus";
+               dev->init_data.get_key = get_key_msi_tvanywhere_plus;
+               dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS;
+               /*
+                * MSI TV@nyware Plus requires more frequent polling
+                * otherwise it will miss some keypresses
+                */
+               dev->init_data.polling_interval = 50;
+               info.addr = 0x30;
+               /* MSI TV@nywhere Plus controller doesn't seem to
+                  respond to probes unless we read something from
+                  an existing device. Weird...
+                  REVISIT: might no longer be needed */
+               rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
+               dprintk("probe 0x%02x @ %s: %s\n",
+                       msg_msi.addr, dev->i2c_adap.name,
+                       (1 == rc) ? "yes" : "no");
+               break;
+       case SAA7134_BOARD_KWORLD_PC150U:
+               /* copied and modified from MSI TV@nywhere Plus */
+               dev->init_data.name = "Kworld PC150-U";
+               dev->init_data.get_key = get_key_kworld_pc150u;
+               dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U;
+               info.addr = 0x30;
+               /* MSI TV@nywhere Plus controller doesn't seem to
+                  respond to probes unless we read something from
+                  an existing device. Weird...
+                  REVISIT: might no longer be needed */
+               rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
+               dprintk("probe 0x%02x @ %s: %s\n",
+                       msg_msi.addr, dev->i2c_adap.name,
+                       (1 == rc) ? "yes" : "no");
+               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+               dev->init_data.name = "HVR 1110";
+               dev->init_data.get_key = get_key_hvr1110;
+               dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
+               info.addr = 0x71;
+               break;
+       case SAA7134_BOARD_BEHOLD_607FM_MK3:
+       case SAA7134_BOARD_BEHOLD_607FM_MK5:
+       case SAA7134_BOARD_BEHOLD_609FM_MK3:
+       case SAA7134_BOARD_BEHOLD_609FM_MK5:
+       case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+       case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+       case SAA7134_BOARD_BEHOLD_609RDS_MK5:
+       case SAA7134_BOARD_BEHOLD_M6:
+       case SAA7134_BOARD_BEHOLD_M63:
+       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+       case SAA7134_BOARD_BEHOLD_H6:
+       case SAA7134_BOARD_BEHOLD_X7:
+       case SAA7134_BOARD_BEHOLD_H7:
+       case SAA7134_BOARD_BEHOLD_A7:
+               dev->init_data.name = "BeholdTV";
+               dev->init_data.get_key = get_key_beholdm6xx;
+               dev->init_data.ir_codes = RC_MAP_BEHOLD;
+               dev->init_data.type = RC_TYPE_NEC;
+               info.addr = 0x2d;
+               break;
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+               info.addr = 0x40;
+               break;
+       case SAA7134_BOARD_FLYDVB_TRIO:
+               dev->init_data.name = "FlyDVB Trio";
+               dev->init_data.get_key = get_key_flydvb_trio;
+               dev->init_data.ir_codes = RC_MAP_FLYDVB;
+               info.addr = 0x0b;
+               break;
+       default:
+               dprintk("No I2C IR support for board %x\n", dev->board);
+               return;
+       }
+
+       if (dev->init_data.name)
+               info.platform_data = &dev->init_data;
+       i2c_new_device(&dev->i2c_adap, &info);
+}
+
+static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
+{
+       struct saa7134_card_ir *ir = dev->remote;
+       unsigned long timeout;
+       int space;
+
+       /* Generate initial event */
+       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
+       space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
+       ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE);
+
+       /*
+        * Wait 15 ms from the start of the first IR event before processing
+        * the event. This time is enough for NEC protocol. May need adjustments
+        * to work with other protocols.
+        */
+       smp_mb();
+
+       if (!timer_pending(&ir->timer)) {
+               timeout = jiffies + msecs_to_jiffies(15);
+               mod_timer(&ir->timer, timeout);
+       }
+
+       return 1;
+}
diff --git a/drivers/media/pci/saa7134/saa7134-reg.h b/drivers/media/pci/saa7134/saa7134-reg.h
new file mode 100644 (file)
index 0000000..e7e0af1
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ *
+ * philips saa7134 registers
+ */
+
+/* ------------------------------------------------------------------ */
+/*
+ * PCI ID's
+ */
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7130
+# define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130
+#endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7133
+# define PCI_DEVICE_ID_PHILIPS_SAA7133 0x7133
+#endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7134
+# define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134
+#endif
+#ifndef PCI_DEVICE_ID_PHILIPS_SAA7135
+# define PCI_DEVICE_ID_PHILIPS_SAA7135 0x7135
+#endif
+
+/* ------------------------------------------------------------------ */
+/*
+ *  registers -- 32 bit
+ */
+
+/* DMA channels, n = 0 ... 6 */
+#define SAA7134_RS_BA1(n)                      ((0x200 >> 2) + 4*n)
+#define SAA7134_RS_BA2(n)                      ((0x204 >> 2) + 4*n)
+#define SAA7134_RS_PITCH(n)                    ((0x208 >> 2) + 4*n)
+#define SAA7134_RS_CONTROL(n)                  ((0x20c >> 2) + 4*n)
+#define   SAA7134_RS_CONTROL_WSWAP             (0x01 << 25)
+#define   SAA7134_RS_CONTROL_BSWAP             (0x01 << 24)
+#define   SAA7134_RS_CONTROL_BURST_2           (0x01 << 21)
+#define   SAA7134_RS_CONTROL_BURST_4           (0x02 << 21)
+#define   SAA7134_RS_CONTROL_BURST_8           (0x03 << 21)
+#define   SAA7134_RS_CONTROL_BURST_16          (0x04 << 21)
+#define   SAA7134_RS_CONTROL_BURST_32          (0x05 << 21)
+#define   SAA7134_RS_CONTROL_BURST_64          (0x06 << 21)
+#define   SAA7134_RS_CONTROL_BURST_MAX         (0x07 << 21)
+#define   SAA7134_RS_CONTROL_ME                        (0x01 << 20)
+#define SAA7134_FIFO_SIZE                       (0x2a0 >> 2)
+#define SAA7134_THRESHOULD                      (0x2a4 >> 2)
+
+#define SAA7133_NUM_SAMPLES                    (0x588 >> 2)
+#define SAA7133_AUDIO_CHANNEL                  (0x58c >> 2)
+#define SAA7133_AUDIO_FORMAT                   (0x58f >> 2)
+#define SAA7133_DIGITAL_OUTPUT_SEL1            (0x46c >> 2)
+#define SAA7133_DIGITAL_OUTPUT_SEL2            (0x470 >> 2)
+#define SAA7133_DIGITAL_INPUT_XBAR1            (0x464 >> 2)
+#define SAA7133_ANALOG_IO_SELECT                (0x594 >> 2)
+
+/* main control */
+#define SAA7134_MAIN_CTRL                       (0x2a8 >> 2)
+#define   SAA7134_MAIN_CTRL_VPLLE              (1 << 15)
+#define   SAA7134_MAIN_CTRL_APLLE              (1 << 14)
+#define   SAA7134_MAIN_CTRL_EXOSC              (1 << 13)
+#define   SAA7134_MAIN_CTRL_EVFE1              (1 << 12)
+#define   SAA7134_MAIN_CTRL_EVFE2              (1 << 11)
+#define   SAA7134_MAIN_CTRL_ESFE               (1 << 10)
+#define   SAA7134_MAIN_CTRL_EBADC              (1 << 9)
+#define   SAA7134_MAIN_CTRL_EBDAC              (1 << 8)
+#define   SAA7134_MAIN_CTRL_TE6                        (1 << 6)
+#define   SAA7134_MAIN_CTRL_TE5                        (1 << 5)
+#define   SAA7134_MAIN_CTRL_TE4                        (1 << 4)
+#define   SAA7134_MAIN_CTRL_TE3                        (1 << 3)
+#define   SAA7134_MAIN_CTRL_TE2                        (1 << 2)
+#define   SAA7134_MAIN_CTRL_TE1                        (1 << 1)
+#define   SAA7134_MAIN_CTRL_TE0                        (1 << 0)
+
+/* DMA status */
+#define SAA7134_DMA_STATUS                      (0x2ac >> 2)
+
+/* audio / video status */
+#define SAA7134_AV_STATUS                      (0x2c0 >> 2)
+#define   SAA7134_AV_STATUS_STEREO             (1 << 17)
+#define   SAA7134_AV_STATUS_DUAL                (1 << 16)
+#define   SAA7134_AV_STATUS_PILOT               (1 << 15)
+#define   SAA7134_AV_STATUS_SMB                 (1 << 14)
+#define   SAA7134_AV_STATUS_DMB                 (1 << 13)
+#define   SAA7134_AV_STATUS_VDSP                (1 << 12)
+#define   SAA7134_AV_STATUS_IIC_STATUS          (3 << 10)
+#define   SAA7134_AV_STATUS_MVM                 (7 << 7)
+#define   SAA7134_AV_STATUS_FIDT                (1 << 6)
+#define   SAA7134_AV_STATUS_INTL                (1 << 5)
+#define   SAA7134_AV_STATUS_RDCAP               (1 << 4)
+#define   SAA7134_AV_STATUS_PWR_ON              (1 << 3)
+#define   SAA7134_AV_STATUS_LOAD_ERR            (1 << 2)
+#define   SAA7134_AV_STATUS_TRIG_ERR            (1 << 1)
+#define   SAA7134_AV_STATUS_CONF_ERR            (1 << 0)
+
+/* interrupt */
+#define SAA7134_IRQ1                            (0x2c4 >> 2)
+#define   SAA7134_IRQ1_INTE_RA3_1               (1 << 25)
+#define   SAA7134_IRQ1_INTE_RA3_0               (1 << 24)
+#define   SAA7134_IRQ1_INTE_RA2_3               (1 << 19)
+#define   SAA7134_IRQ1_INTE_RA2_2               (1 << 18)
+#define   SAA7134_IRQ1_INTE_RA2_1               (1 << 17)
+#define   SAA7134_IRQ1_INTE_RA2_0               (1 << 16)
+#define   SAA7134_IRQ1_INTE_RA1_3               (1 << 11)
+#define   SAA7134_IRQ1_INTE_RA1_2               (1 << 10)
+#define   SAA7134_IRQ1_INTE_RA1_1               (1 <<  9)
+#define   SAA7134_IRQ1_INTE_RA1_0               (1 <<  8)
+#define   SAA7134_IRQ1_INTE_RA0_7               (1 <<  7)
+#define   SAA7134_IRQ1_INTE_RA0_6               (1 <<  6)
+#define   SAA7134_IRQ1_INTE_RA0_5               (1 <<  5)
+#define   SAA7134_IRQ1_INTE_RA0_4               (1 <<  4)
+#define   SAA7134_IRQ1_INTE_RA0_3               (1 <<  3)
+#define   SAA7134_IRQ1_INTE_RA0_2               (1 <<  2)
+#define   SAA7134_IRQ1_INTE_RA0_1               (1 <<  1)
+#define   SAA7134_IRQ1_INTE_RA0_0               (1 <<  0)
+
+#define SAA7134_IRQ2                            (0x2c8 >> 2)
+#define   SAA7134_IRQ2_INTE_GPIO23_N             (1 << 17)     /* negative edge */
+#define   SAA7134_IRQ2_INTE_GPIO23_P             (1 << 16)     /* positive edge */
+#define   SAA7134_IRQ2_INTE_GPIO22_N             (1 << 15)     /* negative edge */
+#define   SAA7134_IRQ2_INTE_GPIO22_P             (1 << 14)     /* positive edge */
+#define   SAA7134_IRQ2_INTE_GPIO18_N             (1 << 13)     /* negative edge */
+#define   SAA7134_IRQ2_INTE_GPIO18_P             (1 << 12)     /* positive edge */
+#define   SAA7134_IRQ2_INTE_GPIO16_N             (1 << 11)     /* negative edge */
+#define   SAA7134_IRQ2_INTE_GPIO16_P             (1 << 10)     /* positive edge */
+#define   SAA7134_IRQ2_INTE_SC2                 (1 <<  9)
+#define   SAA7134_IRQ2_INTE_SC1                 (1 <<  8)
+#define   SAA7134_IRQ2_INTE_SC0                 (1 <<  7)
+#define   SAA7134_IRQ2_INTE_DEC4                (1 <<  6)
+#define   SAA7134_IRQ2_INTE_DEC3                (1 <<  5)
+#define   SAA7134_IRQ2_INTE_DEC2                (1 <<  4)
+#define   SAA7134_IRQ2_INTE_DEC1                (1 <<  3)
+#define   SAA7134_IRQ2_INTE_DEC0                (1 <<  2)
+#define   SAA7134_IRQ2_INTE_PE                  (1 <<  1)
+#define   SAA7134_IRQ2_INTE_AR                  (1 <<  0)
+
+#define SAA7134_IRQ_REPORT                      (0x2cc >> 2)
+#define   SAA7134_IRQ_REPORT_GPIO23             (1 << 17)
+#define   SAA7134_IRQ_REPORT_GPIO22             (1 << 16)
+#define   SAA7134_IRQ_REPORT_GPIO18             (1 << 15)
+#define   SAA7134_IRQ_REPORT_GPIO16             (1 << 14)
+#define   SAA7134_IRQ_REPORT_LOAD_ERR           (1 << 13)
+#define   SAA7134_IRQ_REPORT_CONF_ERR           (1 << 12)
+#define   SAA7134_IRQ_REPORT_TRIG_ERR           (1 << 11)
+#define   SAA7134_IRQ_REPORT_MMC                (1 << 10)
+#define   SAA7134_IRQ_REPORT_FIDT               (1 <<  9)
+#define   SAA7134_IRQ_REPORT_INTL               (1 <<  8)
+#define   SAA7134_IRQ_REPORT_RDCAP              (1 <<  7)
+#define   SAA7134_IRQ_REPORT_PWR_ON             (1 <<  6)
+#define   SAA7134_IRQ_REPORT_PE                 (1 <<  5)
+#define   SAA7134_IRQ_REPORT_AR                 (1 <<  4)
+#define   SAA7134_IRQ_REPORT_DONE_RA3           (1 <<  3)
+#define   SAA7134_IRQ_REPORT_DONE_RA2           (1 <<  2)
+#define   SAA7134_IRQ_REPORT_DONE_RA1           (1 <<  1)
+#define   SAA7134_IRQ_REPORT_DONE_RA0           (1 <<  0)
+#define SAA7134_IRQ_STATUS                      (0x2d0 >> 2)
+
+
+/* ------------------------------------------------------------------ */
+/*
+ *  registers -- 8 bit
+ */
+
+/* video decoder */
+#define SAA7134_INCR_DELAY                      0x101
+#define SAA7134_ANALOG_IN_CTRL1                 0x102
+#define SAA7134_ANALOG_IN_CTRL2                 0x103
+#define SAA7134_ANALOG_IN_CTRL3                 0x104
+#define SAA7134_ANALOG_IN_CTRL4                 0x105
+#define SAA7134_HSYNC_START                     0x106
+#define SAA7134_HSYNC_STOP                      0x107
+#define SAA7134_SYNC_CTRL                       0x108
+#define SAA7134_LUMA_CTRL                       0x109
+#define SAA7134_DEC_LUMA_BRIGHT                 0x10a
+#define SAA7134_DEC_LUMA_CONTRAST               0x10b
+#define SAA7134_DEC_CHROMA_SATURATION           0x10c
+#define SAA7134_DEC_CHROMA_HUE                  0x10d
+#define SAA7134_CHROMA_CTRL1                    0x10e
+#define SAA7134_CHROMA_GAIN                     0x10f
+#define SAA7134_CHROMA_CTRL2                    0x110
+#define SAA7134_MODE_DELAY_CTRL                 0x111
+
+#define SAA7134_ANALOG_ADC                      0x114
+#define SAA7134_VGATE_START                     0x115
+#define SAA7134_VGATE_STOP                      0x116
+#define SAA7134_MISC_VGATE_MSB                  0x117
+#define SAA7134_RAW_DATA_GAIN                   0x118
+#define SAA7134_RAW_DATA_OFFSET                 0x119
+#define SAA7134_STATUS_VIDEO1                   0x11e
+#define SAA7134_STATUS_VIDEO2                   0x11f
+
+/* video scaler */
+#define SAA7134_SOURCE_TIMING1                  0x000
+#define SAA7134_SOURCE_TIMING2                  0x001
+#define SAA7134_REGION_ENABLE                   0x004
+#define SAA7134_SCALER_STATUS0                  0x006
+#define SAA7134_SCALER_STATUS1                  0x007
+#define SAA7134_START_GREEN                     0x00c
+#define SAA7134_START_BLUE                      0x00d
+#define SAA7134_START_RED                       0x00e
+#define SAA7134_GREEN_PATH(x)                   (0x010 +x)
+#define SAA7134_BLUE_PATH(x)                    (0x020 +x)
+#define SAA7134_RED_PATH(x)                     (0x030 +x)
+
+#define TASK_A                                  0x040
+#define TASK_B                                  0x080
+#define SAA7134_TASK_CONDITIONS(t)              (0x000 +t)
+#define SAA7134_FIELD_HANDLING(t)               (0x001 +t)
+#define SAA7134_DATA_PATH(t)                    (0x002 +t)
+#define SAA7134_VBI_H_START1(t)                 (0x004 +t)
+#define SAA7134_VBI_H_START2(t)                 (0x005 +t)
+#define SAA7134_VBI_H_STOP1(t)                  (0x006 +t)
+#define SAA7134_VBI_H_STOP2(t)                  (0x007 +t)
+#define SAA7134_VBI_V_START1(t)                 (0x008 +t)
+#define SAA7134_VBI_V_START2(t)                 (0x009 +t)
+#define SAA7134_VBI_V_STOP1(t)                  (0x00a +t)
+#define SAA7134_VBI_V_STOP2(t)                  (0x00b +t)
+#define SAA7134_VBI_H_LEN1(t)                   (0x00c +t)
+#define SAA7134_VBI_H_LEN2(t)                   (0x00d +t)
+#define SAA7134_VBI_V_LEN1(t)                   (0x00e +t)
+#define SAA7134_VBI_V_LEN2(t)                   (0x00f +t)
+
+#define SAA7134_VIDEO_H_START1(t)               (0x014 +t)
+#define SAA7134_VIDEO_H_START2(t)               (0x015 +t)
+#define SAA7134_VIDEO_H_STOP1(t)                (0x016 +t)
+#define SAA7134_VIDEO_H_STOP2(t)                (0x017 +t)
+#define SAA7134_VIDEO_V_START1(t)               (0x018 +t)
+#define SAA7134_VIDEO_V_START2(t)               (0x019 +t)
+#define SAA7134_VIDEO_V_STOP1(t)                (0x01a +t)
+#define SAA7134_VIDEO_V_STOP2(t)                (0x01b +t)
+#define SAA7134_VIDEO_PIXELS1(t)                (0x01c +t)
+#define SAA7134_VIDEO_PIXELS2(t)                (0x01d +t)
+#define SAA7134_VIDEO_LINES1(t)                 (0x01e +t)
+#define SAA7134_VIDEO_LINES2(t)                 (0x01f +t)
+
+#define SAA7134_H_PRESCALE(t)                   (0x020 +t)
+#define SAA7134_ACC_LENGTH(t)                   (0x021 +t)
+#define SAA7134_LEVEL_CTRL(t)                   (0x022 +t)
+#define SAA7134_FIR_PREFILTER_CTRL(t)           (0x023 +t)
+#define SAA7134_LUMA_BRIGHT(t)                  (0x024 +t)
+#define SAA7134_LUMA_CONTRAST(t)                (0x025 +t)
+#define SAA7134_CHROMA_SATURATION(t)            (0x026 +t)
+#define SAA7134_VBI_H_SCALE_INC1(t)             (0x028 +t)
+#define SAA7134_VBI_H_SCALE_INC2(t)             (0x029 +t)
+#define SAA7134_VBI_PHASE_OFFSET_LUMA(t)        (0x02a +t)
+#define SAA7134_VBI_PHASE_OFFSET_CHROMA(t)      (0x02b +t)
+#define SAA7134_H_SCALE_INC1(t)                 (0x02c +t)
+#define SAA7134_H_SCALE_INC2(t)                 (0x02d +t)
+#define SAA7134_H_PHASE_OFF_LUMA(t)             (0x02e +t)
+#define SAA7134_H_PHASE_OFF_CHROMA(t)           (0x02f +t)
+#define SAA7134_V_SCALE_RATIO1(t)               (0x030 +t)
+#define SAA7134_V_SCALE_RATIO2(t)               (0x031 +t)
+#define SAA7134_V_FILTER(t)                     (0x032 +t)
+#define SAA7134_V_PHASE_OFFSET0(t)              (0x034 +t)
+#define SAA7134_V_PHASE_OFFSET1(t)              (0x035 +t)
+#define SAA7134_V_PHASE_OFFSET2(t)              (0x036 +t)
+#define SAA7134_V_PHASE_OFFSET3(t)              (0x037 +t)
+
+/* clipping & dma */
+#define SAA7134_OFMT_VIDEO_A                    0x300
+#define SAA7134_OFMT_DATA_A                     0x301
+#define SAA7134_OFMT_VIDEO_B                    0x302
+#define SAA7134_OFMT_DATA_B                     0x303
+#define SAA7134_ALPHA_NOCLIP                    0x304
+#define SAA7134_ALPHA_CLIP                      0x305
+#define SAA7134_UV_PIXEL                        0x308
+#define SAA7134_CLIP_RED                        0x309
+#define SAA7134_CLIP_GREEN                      0x30a
+#define SAA7134_CLIP_BLUE                       0x30b
+
+/* i2c bus */
+#define SAA7134_I2C_ATTR_STATUS                 0x180
+#define SAA7134_I2C_DATA                        0x181
+#define SAA7134_I2C_CLOCK_SELECT                0x182
+#define SAA7134_I2C_TIMER                       0x183
+
+/* audio */
+#define SAA7134_NICAM_ADD_DATA1                 0x140
+#define SAA7134_NICAM_ADD_DATA2                 0x141
+#define SAA7134_NICAM_STATUS                    0x142
+#define SAA7134_AUDIO_STATUS                    0x143
+#define SAA7134_NICAM_ERROR_COUNT               0x144
+#define SAA7134_IDENT_SIF                       0x145
+#define SAA7134_LEVEL_READOUT1                  0x146
+#define SAA7134_LEVEL_READOUT2                  0x147
+#define SAA7134_NICAM_ERROR_LOW                 0x148
+#define SAA7134_NICAM_ERROR_HIGH                0x149
+#define SAA7134_DCXO_IDENT_CTRL                 0x14a
+#define SAA7134_DEMODULATOR                     0x14b
+#define SAA7134_AGC_GAIN_SELECT                 0x14c
+#define SAA7134_CARRIER1_FREQ0                  0x150
+#define SAA7134_CARRIER1_FREQ1                  0x151
+#define SAA7134_CARRIER1_FREQ2                  0x152
+#define SAA7134_CARRIER2_FREQ0                  0x154
+#define SAA7134_CARRIER2_FREQ1                  0x155
+#define SAA7134_CARRIER2_FREQ2                  0x156
+#define SAA7134_NUM_SAMPLES0                    0x158
+#define SAA7134_NUM_SAMPLES1                    0x159
+#define SAA7134_NUM_SAMPLES2                    0x15a
+#define SAA7134_AUDIO_FORMAT_CTRL               0x15b
+#define SAA7134_MONITOR_SELECT                  0x160
+#define SAA7134_FM_DEEMPHASIS                   0x161
+#define SAA7134_FM_DEMATRIX                     0x162
+#define SAA7134_CHANNEL1_LEVEL                  0x163
+#define SAA7134_CHANNEL2_LEVEL                  0x164
+#define SAA7134_NICAM_CONFIG                    0x165
+#define SAA7134_NICAM_LEVEL_ADJUST              0x166
+#define SAA7134_STEREO_DAC_OUTPUT_SELECT        0x167
+#define SAA7134_I2S_OUTPUT_FORMAT               0x168
+#define SAA7134_I2S_OUTPUT_SELECT               0x169
+#define SAA7134_I2S_OUTPUT_LEVEL                0x16a
+#define SAA7134_DSP_OUTPUT_SELECT               0x16b
+#define SAA7134_AUDIO_MUTE_CTRL                 0x16c
+#define SAA7134_SIF_SAMPLE_FREQ                 0x16d
+#define SAA7134_ANALOG_IO_SELECT                0x16e
+#define SAA7134_AUDIO_CLOCK0                    0x170
+#define SAA7134_AUDIO_CLOCK1                    0x171
+#define SAA7134_AUDIO_CLOCK2                    0x172
+#define SAA7134_AUDIO_PLL_CTRL                  0x173
+#define SAA7134_AUDIO_CLOCKS_PER_FIELD0         0x174
+#define SAA7134_AUDIO_CLOCKS_PER_FIELD1         0x175
+#define SAA7134_AUDIO_CLOCKS_PER_FIELD2         0x176
+
+/* video port output */
+#define SAA7134_VIDEO_PORT_CTRL0                0x190
+#define SAA7134_VIDEO_PORT_CTRL1                0x191
+#define SAA7134_VIDEO_PORT_CTRL2                0x192
+#define SAA7134_VIDEO_PORT_CTRL3                0x193
+#define SAA7134_VIDEO_PORT_CTRL4                0x194
+#define SAA7134_VIDEO_PORT_CTRL5                0x195
+#define SAA7134_VIDEO_PORT_CTRL6                0x196
+#define SAA7134_VIDEO_PORT_CTRL7                0x197
+#define SAA7134_VIDEO_PORT_CTRL8                0x198
+
+/* transport stream interface */
+#define SAA7134_TS_PARALLEL                     0x1a0
+#define SAA7134_TS_PARALLEL_SERIAL              0x1a1
+#define SAA7134_TS_SERIAL0                      0x1a2
+#define SAA7134_TS_SERIAL1                      0x1a3
+#define SAA7134_TS_DMA0                         0x1a4
+#define SAA7134_TS_DMA1                         0x1a5
+#define SAA7134_TS_DMA2                         0x1a6
+
+/* GPIO Controls */
+#define SAA7134_GPIO_GPRESCAN                   0x80
+#define SAA7134_GPIO_27_25                      0x0E
+
+#define SAA7134_GPIO_GPMODE0                    0x1B0
+#define SAA7134_GPIO_GPMODE1                    0x1B1
+#define SAA7134_GPIO_GPMODE2                    0x1B2
+#define SAA7134_GPIO_GPMODE3                    0x1B3
+#define SAA7134_GPIO_GPSTATUS0                  0x1B4
+#define SAA7134_GPIO_GPSTATUS1                  0x1B5
+#define SAA7134_GPIO_GPSTATUS2                  0x1B6
+#define SAA7134_GPIO_GPSTATUS3                  0x1B7
+
+/* I2S output */
+#define SAA7134_I2S_AUDIO_OUTPUT                0x1c0
+
+/* test modes */
+#define SAA7134_SPECIAL_MODE                    0x1d0
+#define SAA7134_PRODUCTION_TEST_MODE            0x1d1
+
+/* audio -- saa7133 + saa7135 only */
+#define SAA7135_DSP_RWSTATE                     0x580
+#define SAA7135_DSP_RWSTATE_ERR                 (1 << 3)
+#define SAA7135_DSP_RWSTATE_IDA                 (1 << 2)
+#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
+
+#define SAA7133_I2S_AUDIO_CONTROL               0x591
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
new file mode 100644 (file)
index 0000000..2e3f4b4
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * video4linux video interface
+ *
+ * (c) 2001,02 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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int ts_debug;
+module_param(ts_debug, int, 0644);
+MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
+
+#define dprintk(fmt, arg...)   if (ts_debug) \
+       printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+
+static int buffer_activate(struct saa7134_dev *dev,
+                          struct saa7134_buf *buf,
+                          struct saa7134_buf *next)
+{
+
+       dprintk("buffer_activate [%p]",buf);
+       buf->vb.state = VIDEOBUF_ACTIVE;
+       buf->top_seen = 0;
+
+       if (NULL == next)
+               next = buf;
+       if (V4L2_FIELD_TOP == buf->vb.field) {
+               dprintk("- [top]     buf=%p next=%p\n",buf,next);
+               saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
+               saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
+       } else {
+               dprintk("- [bottom]  buf=%p next=%p\n",buf,next);
+               saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
+               saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
+       }
+
+       /* start DMA */
+       saa7134_set_dmabits(dev);
+
+       mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT);
+
+       if (!dev->ts_started)
+               saa7134_ts_start(dev);
+
+       return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+               enum v4l2_field field)
+{
+       struct saa7134_dev *dev = q->priv_data;
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+       unsigned int lines, llength, size;
+       int err;
+
+       dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
+
+       llength = TS_PACKET_SIZE;
+       lines = dev->ts.nr_packets;
+
+       size = lines * llength;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       if (buf->vb.size != size) {
+               saa7134_dma_free(q,buf);
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+
+               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+               dprintk("buffer_prepare: needs_init\n");
+
+               buf->vb.width  = llength;
+               buf->vb.height = lines;
+               buf->vb.size   = size;
+               buf->pt        = &dev->ts.pt_ts;
+
+               err = videobuf_iolock(q,&buf->vb,NULL);
+               if (err)
+                       goto oops;
+               err = saa7134_pgtable_build(dev->pci,buf->pt,
+                                           dma->sglist,
+                                           dma->sglen,
+                                           saa7134_buffer_startpage(buf));
+               if (err)
+                       goto oops;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       buf->activate = buffer_activate;
+       buf->vb.field = field;
+       return 0;
+
+ oops:
+       saa7134_dma_free(q,buf);
+       return err;
+}
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       struct saa7134_dev *dev = q->priv_data;
+
+       *size = TS_PACKET_SIZE * dev->ts.nr_packets;
+       if (0 == *count)
+               *count = dev->ts.nr_bufs;
+       *count = saa7134_buffer_count(*size,*count);
+
+       return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct saa7134_dev *dev = q->priv_data;
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
+       saa7134_buffer_queue(dev,&dev->ts_q,buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+       struct saa7134_dev *dev = q->priv_data;
+
+       if (dev->ts_started)
+               saa7134_ts_stop(dev);
+
+       saa7134_dma_free(q,buf);
+}
+
+struct videobuf_queue_ops saa7134_ts_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+EXPORT_SYMBOL_GPL(saa7134_ts_qops);
+
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+static unsigned int tsbufs = 8;
+module_param(tsbufs, int, 0444);
+MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32");
+
+static unsigned int ts_nr_packets = 64;
+module_param(ts_nr_packets, int, 0444);
+MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
+
+int saa7134_ts_init_hw(struct saa7134_dev *dev)
+{
+       /* deactivate TS softreset */
+       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+       /* TSSOP high active, TSVAL high active, TSLOCK ignored */
+       saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+       saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
+       saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
+       saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
+       /* TSNOPIT=0, TSCOLAP=0 */
+       saa_writeb(SAA7134_TS_DMA2,
+               ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00));
+
+       return 0;
+}
+
+int saa7134_ts_init1(struct saa7134_dev *dev)
+{
+       /* sanitycheck insmod options */
+       if (tsbufs < 2)
+               tsbufs = 2;
+       if (tsbufs > VIDEO_MAX_FRAME)
+               tsbufs = VIDEO_MAX_FRAME;
+       if (ts_nr_packets < 4)
+               ts_nr_packets = 4;
+       if (ts_nr_packets > 312)
+               ts_nr_packets = 312;
+       dev->ts.nr_bufs    = tsbufs;
+       dev->ts.nr_packets = ts_nr_packets;
+
+       INIT_LIST_HEAD(&dev->ts_q.queue);
+       init_timer(&dev->ts_q.timeout);
+       dev->ts_q.timeout.function = saa7134_buffer_timeout;
+       dev->ts_q.timeout.data     = (unsigned long)(&dev->ts_q);
+       dev->ts_q.dev              = dev;
+       dev->ts_q.need_two         = 1;
+       dev->ts_started            = 0;
+       saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
+
+       /* init TS hw */
+       saa7134_ts_init_hw(dev);
+
+       return 0;
+}
+
+/* Function for stop TS */
+int saa7134_ts_stop(struct saa7134_dev *dev)
+{
+       dprintk("TS stop\n");
+
+       BUG_ON(!dev->ts_started);
+
+       /* Stop TS stream */
+       switch (saa7134_boards[dev->board].ts_type) {
+       case SAA7134_MPEG_TS_PARALLEL:
+               saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
+               dev->ts_started = 0;
+               break;
+       case SAA7134_MPEG_TS_SERIAL:
+               saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+               dev->ts_started = 0;
+               break;
+       }
+       return 0;
+}
+
+/* Function for start TS */
+int saa7134_ts_start(struct saa7134_dev *dev)
+{
+       dprintk("TS start\n");
+
+       BUG_ON(dev->ts_started);
+
+       /* dma: setup channel 5 (= TS) */
+       saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
+       saa_writeb(SAA7134_TS_DMA1,
+               ((dev->ts.nr_packets - 1) >> 8) & 0xff);
+       /* TSNOPIT=0, TSCOLAP=0 */
+       saa_writeb(SAA7134_TS_DMA2,
+               (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
+       saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
+       saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
+                                         SAA7134_RS_CONTROL_ME |
+                                         (dev->ts.pt_ts.dma >> 12));
+
+       /* reset hardware TS buffers */
+       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+       saa_writeb(SAA7134_TS_SERIAL1, 0x03);
+       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+       saa_writeb(SAA7134_TS_SERIAL1, 0x01);
+
+       /* TS clock non-inverted */
+       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
+
+       /* Start TS stream */
+       switch (saa7134_boards[dev->board].ts_type) {
+       case SAA7134_MPEG_TS_PARALLEL:
+               saa_writeb(SAA7134_TS_SERIAL0, 0x40);
+               saa_writeb(SAA7134_TS_PARALLEL, 0xec |
+                       (saa7134_boards[dev->board].ts_force_val << 4));
+               break;
+       case SAA7134_MPEG_TS_SERIAL:
+               saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
+               saa_writeb(SAA7134_TS_PARALLEL, 0x6c |
+                       (saa7134_boards[dev->board].ts_force_val << 4));
+               saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
+               saa_writeb(SAA7134_TS_SERIAL1, 0x02);
+               break;
+       }
+
+       dev->ts_started = 1;
+
+       return 0;
+}
+
+int saa7134_ts_fini(struct saa7134_dev *dev)
+{
+       saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
+       return 0;
+}
+
+void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
+{
+       enum v4l2_field field;
+
+       spin_lock(&dev->slock);
+       if (dev->ts_q.curr) {
+               field = dev->ts_q.curr->vb.field;
+               if (field == V4L2_FIELD_TOP) {
+                       if ((status & 0x100000) != 0x000000)
+                               goto done;
+               } else {
+                       if ((status & 0x100000) != 0x100000)
+                               goto done;
+               }
+               saa7134_buffer_finish(dev,&dev->ts_q,VIDEOBUF_DONE);
+       }
+       saa7134_buffer_next(dev,&dev->ts_q);
+
+ done:
+       spin_unlock(&dev->slock);
+}
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-tvaudio.c b/drivers/media/pci/saa7134/saa7134-tvaudio.c
new file mode 100644 (file)
index 0000000..b7a99be
--- /dev/null
@@ -0,0 +1,1087 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * tv audio decoder (fm stereo, nicam, ...)
+ *
+ * (c) 2001-03 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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <asm/div64.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+/* ------------------------------------------------------------------ */
+
+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;
+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;
+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])");
+
+#define dprintk(fmt, arg...)   if (audio_debug) \
+       printk(KERN_DEBUG "%s/audio: " fmt, dev->name , ## arg)
+#define d2printk(fmt, arg...)  if (audio_debug > 1) \
+       printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
+
+#define print_regb(reg) printk("%s:   reg 0x%03x [%-16s]: 0x%02x\n", \
+               dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg)))
+
+/* msecs */
+#define SCAN_INITIAL_DELAY     1000
+#define SCAN_SAMPLE_DELAY       200
+#define SCAN_SUBCARRIER_DELAY  2000
+
+/* ------------------------------------------------------------------ */
+/* saa7134 code                                                       */
+
+static struct mainscan {
+       char         *name;
+       v4l2_std_id  std;
+       int          carr;
+} mainscan[] = {
+       {
+               .name = "MN",
+               .std  = V4L2_STD_MN,
+               .carr = 4500,
+       },{
+               .name = "BGH",
+               .std  = V4L2_STD_B | V4L2_STD_GH,
+               .carr = 5500,
+       },{
+               .name = "I",
+               .std  = V4L2_STD_PAL_I,
+               .carr = 6000,
+       },{
+               .name = "DKL",
+               .std  = V4L2_STD_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC,
+               .carr = 6500,
+       }
+};
+
+static struct saa7134_tvaudio tvaudio[] = {
+       {
+               .name          = "PAL-B/G FM-stereo",
+               .std           = V4L2_STD_PAL_BG,
+               .mode          = TVAUDIO_FM_BG_STEREO,
+               .carr1         = 5500,
+               .carr2         = 5742,
+       },{
+               .name          = "PAL-D/K1 FM-stereo",
+               .std           = V4L2_STD_PAL_DK,
+               .carr1         = 6500,
+               .carr2         = 6258,
+               .mode          = TVAUDIO_FM_BG_STEREO,
+       },{
+               .name          = "PAL-D/K2 FM-stereo",
+               .std           = V4L2_STD_PAL_DK,
+               .carr1         = 6500,
+               .carr2         = 6742,
+               .mode          = TVAUDIO_FM_BG_STEREO,
+       },{
+               .name          = "PAL-D/K3 FM-stereo",
+               .std           = V4L2_STD_PAL_DK,
+               .carr1         = 6500,
+               .carr2         = 5742,
+               .mode          = TVAUDIO_FM_BG_STEREO,
+       },{
+               .name          = "PAL-B/G NICAM",
+               .std           = V4L2_STD_PAL_BG,
+               .carr1         = 5500,
+               .carr2         = 5850,
+               .mode          = TVAUDIO_NICAM_FM,
+       },{
+               .name          = "PAL-I NICAM",
+               .std           = V4L2_STD_PAL_I,
+               .carr1         = 6000,
+               .carr2         = 6552,
+               .mode          = TVAUDIO_NICAM_FM,
+       },{
+               .name          = "PAL-D/K NICAM",
+               .std           = V4L2_STD_PAL_DK,
+               .carr1         = 6500,
+               .carr2         = 5850,
+               .mode          = TVAUDIO_NICAM_FM,
+       },{
+               .name          = "SECAM-L NICAM",
+               .std           = V4L2_STD_SECAM_L,
+               .carr1         = 6500,
+               .carr2         = 5850,
+               .mode          = TVAUDIO_NICAM_AM,
+       },{
+               .name          = "SECAM-D/K NICAM",
+               .std           = V4L2_STD_SECAM_DK,
+               .carr1         = 6500,
+               .carr2         = 5850,
+               .mode          = TVAUDIO_NICAM_FM,
+       },{
+               .name          = "NTSC-A2 FM-stereo",
+               .std           = V4L2_STD_NTSC,
+               .carr1         = 4500,
+               .carr2         = 4724,
+               .mode          = TVAUDIO_FM_K_STEREO,
+       },{
+               .name          = "NTSC-M",
+               .std           = V4L2_STD_NTSC,
+               .carr1         = 4500,
+               .carr2         = -1,
+               .mode          = TVAUDIO_FM_MONO,
+       }
+};
+#define TVAUDIO ARRAY_SIZE(tvaudio)
+
+/* ------------------------------------------------------------------ */
+
+static u32 tvaudio_carr2reg(u32 carrier)
+{
+       u64 a = carrier;
+
+       a <<= 24;
+       do_div(a,12288);
+       return a;
+}
+
+static void tvaudio_setcarrier(struct saa7134_dev *dev,
+                              int primary, int secondary)
+{
+       if (-1 == secondary)
+               secondary = primary;
+       saa_writel(SAA7134_CARRIER1_FREQ0 >> 2, tvaudio_carr2reg(primary));
+       saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary));
+}
+
+#define SAA7134_MUTE_MASK 0xbb
+#define SAA7134_MUTE_ANALOG 0x04
+#define SAA7134_MUTE_I2S 0x40
+
+static void mute_input_7134(struct saa7134_dev *dev)
+{
+       unsigned int mute;
+       struct saa7134_input *in;
+       int ausel=0, ics=0, ocs=0;
+       int mask;
+
+       /* look what is to do ... */
+       in   = dev->input;
+       mute = (dev->ctl_mute ||
+               (dev->automute  &&  (&card(dev).radio) != in));
+       if (card(dev).mute.name) {
+               /*
+                * 7130 - we'll mute using some unconnected audio input
+                * 7134 - we'll probably should switch external mux with gpio
+                */
+               if (mute)
+                       in = &card(dev).mute;
+       }
+
+       if (dev->hw_mute  == mute &&
+               dev->hw_input == in && !dev->insuspend) {
+               dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
+                       mute,in->name);
+               return;
+       }
+
+       dprintk("ctl_mute=%d automute=%d input=%s  =>  mute=%d input=%s\n",
+               dev->ctl_mute,dev->automute,dev->input->name,mute,in->name);
+       dev->hw_mute  = mute;
+       dev->hw_input = in;
+
+       if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
+               /* 7134 mute */
+               saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ?
+                                                   SAA7134_MUTE_MASK |
+                                                   SAA7134_MUTE_ANALOG |
+                                                   SAA7134_MUTE_I2S :
+                                                   SAA7134_MUTE_MASK);
+
+       /* switch internal audio mux */
+       switch (in->amux) {
+       case TV:         ausel=0xc0; ics=0x00; ocs=0x02; break;
+       case LINE1:      ausel=0x80; ics=0x00; ocs=0x00; break;
+       case LINE2:      ausel=0x80; ics=0x08; ocs=0x01; break;
+       case LINE2_LEFT: ausel=0x80; ics=0x08; ocs=0x05; break;
+       }
+       saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel);
+       saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics);
+       saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs);
+       // for oss, we need to change the clock configuration
+       if (in->amux == TV)
+               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x00);
+       else
+               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x01);
+
+       /* switch gpio-connected external audio mux */
+       if (0 == card(dev).gpiomask)
+               return;
+
+       mask = card(dev).gpiomask;
+       saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
+       saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio);
+       saa7134_track_gpio(dev,in->name);
+}
+
+static void tvaudio_setmode(struct saa7134_dev *dev,
+                           struct saa7134_tvaudio *audio,
+                           char *note)
+{
+       int acpf, tweak = 0;
+
+       if (dev->tvnorm->id == V4L2_STD_NTSC) {
+               acpf = 0x19066;
+       } else {
+               acpf = 0x1e000;
+       }
+       if (audio_clock_tweak > -1024 && audio_clock_tweak < 1024)
+               tweak = audio_clock_tweak;
+
+       if (note)
+               dprintk("tvaudio_setmode: %s %s [%d.%03d/%d.%03d MHz] acpf=%d%+d\n",
+                       note,audio->name,
+                       audio->carr1 / 1000, audio->carr1 % 1000,
+                       audio->carr2 / 1000, audio->carr2 % 1000,
+                       acpf, tweak);
+
+       acpf += tweak;
+       saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD0, (acpf & 0x0000ff) >> 0);
+       saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD1, (acpf & 0x00ff00) >> 8);
+       saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD2, (acpf & 0x030000) >> 16);
+       tvaudio_setcarrier(dev,audio->carr1,audio->carr2);
+
+       switch (audio->mode) {
+       case TVAUDIO_FM_MONO:
+       case TVAUDIO_FM_BG_STEREO:
+               saa_writeb(SAA7134_DEMODULATOR,               0x00);
+               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x00);
+               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x22);
+               saa_writeb(SAA7134_FM_DEMATRIX,               0x80);
+               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa0);
+               break;
+       case TVAUDIO_FM_K_STEREO:
+               saa_writeb(SAA7134_DEMODULATOR,               0x00);
+               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x01);
+               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x22);
+               saa_writeb(SAA7134_FM_DEMATRIX,               0x80);
+               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa0);
+               break;
+       case TVAUDIO_NICAM_FM:
+               saa_writeb(SAA7134_DEMODULATOR,               0x10);
+               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x00);
+               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x44);
+               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa1);
+               saa_writeb(SAA7134_NICAM_CONFIG,              0x00);
+               break;
+       case TVAUDIO_NICAM_AM:
+               saa_writeb(SAA7134_DEMODULATOR,               0x12);
+               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x00);
+               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x44);
+               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa1);
+               saa_writeb(SAA7134_NICAM_CONFIG,              0x00);
+               break;
+       case TVAUDIO_FM_SAT_STEREO:
+               /* not implemented (yet) */
+               break;
+       }
+}
+
+static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
+{
+       if (dev->thread.scan1 == dev->thread.scan2 &&
+           !kthread_should_stop()) {
+               if (timeout < 0) {
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       schedule();
+               } else {
+                       schedule_timeout_interruptible
+                                               (msecs_to_jiffies(timeout));
+               }
+       }
+       return dev->thread.scan1 != dev->thread.scan2;
+}
+
+static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
+{
+       __s32 left,right,value;
+
+       if (!(dev->tvnorm->id & scan->std)) {
+               value = 0;
+               dprintk("skipping %d.%03d MHz [%4s]\n",
+                       scan->carr / 1000, scan->carr % 1000, scan->name);
+               return 0;
+       }
+
+       if (audio_debug > 1) {
+               int i;
+               dprintk("debug %d:",scan->carr);
+               for (i = -150; i <= 150; i += 30) {
+                       tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i);
+                       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+                       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+                               return -1;
+                       value = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+                       if (0 == i)
+                               printk("  #  %6d  # ",value >> 16);
+                       else
+                               printk(" %6d",value >> 16);
+               }
+               printk("\n");
+       }
+
+       tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
+       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+               return -1;
+       left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+       tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
+       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
+               return -1;
+       right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
+
+       left >>= 16;
+       right >>= 16;
+       value = left > right ? left - right : right - left;
+       dprintk("scanning %d.%03d MHz [%4s] =>  dc is %5d [%d/%d]\n",
+               scan->carr / 1000, scan->carr % 1000,
+               scan->name, value, left, right);
+       return value;
+}
+
+
+static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio)
+{
+       __u32 idp, nicam, nicam_status;
+       int retval = -1;
+
+       switch (audio->mode) {
+       case TVAUDIO_FM_MONO:
+               return V4L2_TUNER_SUB_MONO;
+       case TVAUDIO_FM_K_STEREO:
+       case TVAUDIO_FM_BG_STEREO:
+               idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5;
+               dprintk("getstereo: fm/stereo: idp=0x%x\n",idp);
+               if (0x03 == (idp & 0x03))
+                       retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+               else if (0x05 == (idp & 0x05))
+                       retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+               else if (0x01 == (idp & 0x01))
+                       retval = V4L2_TUNER_SUB_MONO;
+               break;
+       case TVAUDIO_FM_SAT_STEREO:
+               /* not implemented (yet) */
+               break;
+       case TVAUDIO_NICAM_FM:
+       case TVAUDIO_NICAM_AM:
+               nicam = saa_readb(SAA7134_AUDIO_STATUS);
+               dprintk("getstereo: nicam=0x%x\n",nicam);
+               if (nicam & 0x1) {
+                       nicam_status = saa_readb(SAA7134_NICAM_STATUS);
+                       dprintk("getstereo: nicam_status=0x%x\n", nicam_status);
+
+                       switch (nicam_status & 0x03) {
+                           case 0x01:
+                               retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+                               break;
+                           case 0x02:
+                               retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+                               break;
+                           default:
+                               retval = V4L2_TUNER_SUB_MONO;
+                       }
+               } else {
+                       /* No nicam detected */
+               }
+               break;
+       }
+       if (retval != -1)
+               dprintk("found audio subchannels:%s%s%s%s\n",
+                       (retval & V4L2_TUNER_SUB_MONO)   ? " mono"   : "",
+                       (retval & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
+                       (retval & V4L2_TUNER_SUB_LANG1)  ? " lang1"  : "",
+                       (retval & V4L2_TUNER_SUB_LANG2)  ? " lang2"  : "");
+       return retval;
+}
+
+static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio,
+                            u32 mode)
+{
+       static char *name[] = {
+               [ V4L2_TUNER_MODE_MONO   ] = "mono",
+               [ V4L2_TUNER_MODE_STEREO ] = "stereo",
+               [ V4L2_TUNER_MODE_LANG1  ] = "lang1",
+               [ V4L2_TUNER_MODE_LANG2  ] = "lang2",
+               [ V4L2_TUNER_MODE_LANG1_LANG2  ] = "lang1+lang2",
+       };
+       static u32 fm[] = {
+               [ V4L2_TUNER_MODE_MONO   ] = 0x00,  /* ch1  */
+               [ V4L2_TUNER_MODE_STEREO ] = 0x80,  /* auto */
+               [ V4L2_TUNER_MODE_LANG1  ] = 0x00,  /* ch1  */
+               [ V4L2_TUNER_MODE_LANG2  ] = 0x01,  /* ch2  */
+               [ V4L2_TUNER_MODE_LANG1_LANG2 ] = 0x80,  /* auto */
+       };
+       u32 reg;
+
+       switch (audio->mode) {
+       case TVAUDIO_FM_MONO:
+               /* nothing to do ... */
+               break;
+       case TVAUDIO_FM_K_STEREO:
+       case TVAUDIO_FM_BG_STEREO:
+       case TVAUDIO_NICAM_AM:
+       case TVAUDIO_NICAM_FM:
+               dprintk("setstereo [fm] => %s\n",
+                       name[ mode % ARRAY_SIZE(name) ]);
+               reg = fm[ mode % ARRAY_SIZE(fm) ];
+               saa_writeb(SAA7134_FM_DEMATRIX, reg);
+               break;
+       case TVAUDIO_FM_SAT_STEREO:
+               /* Not implemented */
+               break;
+       }
+       return 0;
+}
+
+static int tvaudio_thread(void *data)
+{
+       struct saa7134_dev *dev = data;
+       int carr_vals[ARRAY_SIZE(mainscan)];
+       unsigned int i, audio, nscan;
+       int max1,max2,carrier,rx,mode,lastmode,default_carrier;
+
+       set_freezable();
+
+       for (;;) {
+               tvaudio_sleep(dev,-1);
+               if (kthread_should_stop())
+                       goto done;
+
+       restart:
+               try_to_freeze();
+
+               dev->thread.scan1 = dev->thread.scan2;
+               dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
+               dev->tvaudio  = NULL;
+
+               saa_writeb(SAA7134_MONITOR_SELECT,   0xa0);
+               saa_writeb(SAA7134_FM_DEMATRIX,      0x80);
+
+               if (dev->ctl_automute)
+                       dev->automute = 1;
+
+               mute_input_7134(dev);
+
+               /* give the tuner some time */
+               if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY))
+                       goto restart;
+
+               max1 = 0;
+               max2 = 0;
+               nscan = 0;
+               carrier = 0;
+               default_carrier = 0;
+               for (i = 0; i < ARRAY_SIZE(mainscan); i++) {
+                       if (!(dev->tvnorm->id & mainscan[i].std))
+                               continue;
+                       if (!default_carrier)
+                               default_carrier = mainscan[i].carr;
+                       nscan++;
+               }
+
+               if (1 == nscan) {
+                       /* only one candidate -- skip scan ;) */
+                       dprintk("only one main carrier candidate - skipping scan\n");
+                       max1 = 12345;
+                       carrier = default_carrier;
+               } else {
+                       /* scan for the main carrier */
+                       saa_writeb(SAA7134_MONITOR_SELECT,0x00);
+                       tvaudio_setmode(dev,&tvaudio[0],NULL);
+                       for (i = 0; i < ARRAY_SIZE(mainscan); i++) {
+                               carr_vals[i] = tvaudio_checkcarrier(dev, mainscan+i);
+                               if (dev->thread.scan1 != dev->thread.scan2)
+                                       goto restart;
+                       }
+                       for (max1 = 0, max2 = 0, i = 0; i < ARRAY_SIZE(mainscan); i++) {
+                               if (max1 < carr_vals[i]) {
+                                       max2 = max1;
+                                       max1 = carr_vals[i];
+                                       carrier = mainscan[i].carr;
+                               } else if (max2 < carr_vals[i]) {
+                                       max2 = carr_vals[i];
+                               }
+                       }
+               }
+
+               if (0 != carrier && max1 > 2000 && max1 > max2*3) {
+                       /* found good carrier */
+                       dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",
+                               dev->tvnorm->name, carrier/1000, carrier%1000,
+                               max1, max2);
+                       dev->last_carrier = carrier;
+                       dev->automute = 0;
+
+               } else if (0 != dev->last_carrier) {
+                       /* no carrier -- try last detected one as fallback */
+                       carrier = dev->last_carrier;
+                       dprintk("audio carrier scan failed, "
+                               "using %d.%03d MHz [last detected]\n",
+                               carrier/1000, carrier%1000);
+                       dev->automute = 1;
+
+               } else {
+                       /* no carrier + no fallback -- use default */
+                       carrier = default_carrier;
+                       dprintk("audio carrier scan failed, "
+                               "using %d.%03d MHz [default]\n",
+                               carrier/1000, carrier%1000);
+                       dev->automute = 1;
+               }
+               tvaudio_setcarrier(dev,carrier,carrier);
+               saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
+               saa7134_tvaudio_setmute(dev);
+               /* find the exact tv audio norm */
+               for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
+                       if (dev->tvnorm->id != UNSET &&
+                               !(dev->tvnorm->id & tvaudio[i].std))
+                               continue;
+                       if (tvaudio[i].carr1 != carrier)
+                               continue;
+                       /* Note: at least the primary carrier is right here */
+                       if (UNSET == audio)
+                               audio = i;
+                       tvaudio_setmode(dev,&tvaudio[i],"trying");
+                       if (tvaudio_sleep(dev,SCAN_SUBCARRIER_DELAY))
+                               goto restart;
+                       if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {
+                               audio = i;
+                               break;
+                       }
+               }
+               saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30);
+               if (UNSET == audio)
+                       continue;
+               tvaudio_setmode(dev,&tvaudio[audio],"using");
+
+               tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO);
+               dev->tvaudio = &tvaudio[audio];
+
+               lastmode = 42;
+               for (;;) {
+
+                       try_to_freeze();
+
+                       if (tvaudio_sleep(dev,5000))
+                               goto restart;
+                       if (kthread_should_stop())
+                               break;
+                       if (UNSET == dev->thread.mode) {
+                               rx = tvaudio_getstereo(dev, &tvaudio[audio]);
+                               mode = saa7134_tvaudio_rx2mode(rx);
+                       } else {
+                               mode = dev->thread.mode;
+                       }
+                       if (lastmode != mode) {
+                               tvaudio_setstereo(dev,&tvaudio[audio],mode);
+                               lastmode = mode;
+                       }
+               }
+       }
+
+ done:
+       dev->thread.stopped = 1;
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* saa7133 / saa7135 code                                             */
+
+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]",
+};
+
+#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)
+{
+       int state, count = DSP_RETRY;
+
+       state = saa_readb(SAA7135_DSP_RWSTATE);
+       if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
+               printk(KERN_WARNING "%s: dsp access error\n", dev->name);
+               saa_dsp_reset_error_bit(dev);
+               return -EIO;
+       }
+       while (0 == (state & bit)) {
+               if (unlikely(0 == count)) {
+                       printk("%s: dsp access wait timeout [bit=%s]\n",
+                              dev->name,
+                              (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" :
+                              (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" :
+                              (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" :
+                              "???");
+                       return -EIO;
+               }
+               saa_wait(DSP_DELAY);
+               state = saa_readb(SAA7135_DSP_RWSTATE);
+               count--;
+       }
+       return 0;
+}
+
+
+int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value)
+{
+       int err;
+
+       d2printk("dsp write reg 0x%x = 0x%06x\n",reg<<2,value);
+       err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
+       if (err < 0)
+               return err;
+       saa_writel(reg,value);
+       err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
+       if (err < 0)
+               return err;
+       return 0;
+}
+
+static int getstereo_7133(struct saa7134_dev *dev)
+{
+       int retval = V4L2_TUNER_SUB_MONO;
+       u32 value;
+
+       value = saa_readl(0x528 >> 2);
+       if (value & 0x20)
+               retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+       if (value & 0x40)
+               retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+       return retval;
+}
+
+static int mute_input_7133(struct saa7134_dev *dev)
+{
+       u32 reg = 0;
+       u32 xbarin, xbarout;
+       int mask;
+       struct saa7134_input *in;
+
+       xbarin = 0x03;
+       switch (dev->input->amux) {
+       case TV:
+               reg = 0x02;
+               xbarin = 0;
+               break;
+       case LINE1:
+               reg = 0x00;
+               break;
+       case LINE2:
+       case LINE2_LEFT:
+               reg = 0x09;
+               break;
+       }
+       saa_dsp_writel(dev, 0x464 >> 2, xbarin);
+       if (dev->ctl_mute) {
+               reg = 0x07;
+               xbarout = 0xbbbbbb;
+       } else
+               xbarout = 0xbbbb10;
+       saa_dsp_writel(dev, 0x46c >> 2, xbarout);
+
+       saa_writel(0x594 >> 2, reg);
+
+
+       /* switch gpio-connected external audio mux */
+       if (0 != card(dev).gpiomask) {
+               mask = card(dev).gpiomask;
+
+               if (card(dev).mute.name && dev->ctl_mute)
+                       in = &card(dev).mute;
+               else
+                       in = dev->input;
+
+               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
+               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio);
+               saa7134_track_gpio(dev,in->name);
+       }
+
+       return 0;
+}
+
+static int tvaudio_thread_ddep(void *data)
+{
+       struct saa7134_dev *dev = data;
+       u32 value, norms;
+
+       set_freezable();
+       for (;;) {
+               tvaudio_sleep(dev,-1);
+               if (kthread_should_stop())
+                       goto done;
+       restart:
+               try_to_freeze();
+
+               dev->thread.scan1 = dev->thread.scan2;
+               dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
+
+               if (audio_ddep >= 0x04 && audio_ddep <= 0x0e) {
+                       /* insmod option override */
+                       norms = (audio_ddep << 2) | 0x01;
+                       dprintk("ddep override: %s\n",stdres[audio_ddep]);
+               } else if (&card(dev).radio == dev->input) {
+                       dprintk("FM Radio\n");
+                       if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
+                               norms = (0x11 << 2) | 0x01;
+                               saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
+                       } else {
+                               norms = (0x0f << 2) | 0x01;
+                       }
+               } else {
+                       /* (let chip) scan for sound carrier */
+                       norms = 0;
+                       if (dev->tvnorm->id & (V4L2_STD_B | V4L2_STD_GH))
+                               norms |= 0x04;
+                       if (dev->tvnorm->id & V4L2_STD_PAL_I)
+                               norms |= 0x20;
+                       if (dev->tvnorm->id & V4L2_STD_DK)
+                               norms |= 0x08;
+                       if (dev->tvnorm->id & V4L2_STD_MN)
+                               norms |= 0x40;
+                       if (dev->tvnorm->id & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))
+                               norms |= 0x10;
+                       if (0 == norms)
+                               norms = 0x7c; /* all */
+                       dprintk("scanning:%s%s%s%s%s\n",
+                               (norms & 0x04) ? " B/G"  : "",
+                               (norms & 0x08) ? " D/K"  : "",
+                               (norms & 0x10) ? " L/L'" : "",
+                               (norms & 0x20) ? " I"    : "",
+                               (norms & 0x40) ? " M"    : "");
+               }
+
+               /* kick automatic standard detection */
+               saa_dsp_writel(dev, 0x454 >> 2, 0);
+               saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80);
+
+               /* setup crossbars */
+               saa_dsp_writel(dev, 0x464 >> 2, 0x000000);
+               saa_dsp_writel(dev, 0x470 >> 2, 0x101010);
+
+               if (tvaudio_sleep(dev,3000))
+                       goto restart;
+               value = saa_readl(0x528 >> 2) & 0xffffff;
+
+               dprintk("tvaudio thread status: 0x%x [%s%s%s]\n",
+                       value, stdres[value & 0x1f],
+                       (value & 0x000020) ? ",stereo" : "",
+                       (value & 0x000040) ? ",dual"   : "");
+               dprintk("detailed status: "
+                       "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+                       (value & 0x000080) ? " A2/EIAJ pilot tone "     : "",
+                       (value & 0x000100) ? " A2/EIAJ dual "           : "",
+                       (value & 0x000200) ? " A2/EIAJ stereo "         : "",
+                       (value & 0x000400) ? " A2/EIAJ noise mute "     : "",
+
+                       (value & 0x000800) ? " BTSC/FM radio pilot "    : "",
+                       (value & 0x001000) ? " SAP carrier "            : "",
+                       (value & 0x002000) ? " BTSC stereo noise mute " : "",
+                       (value & 0x004000) ? " SAP noise mute "         : "",
+                       (value & 0x008000) ? " VDSP "                   : "",
+
+                       (value & 0x010000) ? " NICST "                  : "",
+                       (value & 0x020000) ? " NICDU "                  : "",
+                       (value & 0x040000) ? " NICAM muted "            : "",
+                       (value & 0x080000) ? " NICAM reserve sound "    : "",
+
+                       (value & 0x100000) ? " init done "              : "");
+       }
+
+ done:
+       dev->thread.stopped = 1;
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* common stuff + external entry points                               */
+
+void saa7134_enable_i2s(struct saa7134_dev *dev)
+{
+       int i2s_format;
+
+       if (!card_is_empress(dev))
+               return;
+
+       if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
+               return;
+
+       /* configure GPIO for out */
+       saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0E000000, 0x00000000);
+
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+           /* Set I2S format (SONY) Â */
+           saa_writeb(SAA7133_I2S_AUDIO_CONTROL, 0x00);
+           /* Start I2S */
+           saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x11);
+           break;
+
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+           i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
+
+           /* enable I2S audio output for the mpeg encoder */
+           saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
+           saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format);
+           saa_writeb(SAA7134_I2S_OUTPUT_LEVEL,  0x0F);
+           saa_writeb(SAA7134_I2S_AUDIO_OUTPUT,  0x01);
+
+       default:
+           break;
+       }
+}
+
+int saa7134_tvaudio_rx2mode(u32 rx)
+{
+       u32 mode;
+
+       mode = V4L2_TUNER_MODE_MONO;
+       if (rx & V4L2_TUNER_SUB_STEREO)
+               mode = V4L2_TUNER_MODE_STEREO;
+       else if (rx & V4L2_TUNER_SUB_LANG1)
+               mode = V4L2_TUNER_MODE_LANG1;
+       else if (rx & V4L2_TUNER_SUB_LANG2)
+               mode = V4L2_TUNER_MODE_LANG2;
+       return mode;
+}
+
+void saa7134_tvaudio_setmute(struct saa7134_dev *dev)
+{
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7130:
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               mute_input_7134(dev);
+               break;
+       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+               mute_input_7133(dev);
+               break;
+       }
+}
+
+void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
+                             struct saa7134_input *in)
+{
+       dev->input = in;
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7130:
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               mute_input_7134(dev);
+               break;
+       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+               mute_input_7133(dev);
+               break;
+       }
+       saa7134_enable_i2s(dev);
+}
+
+void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
+{
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               saa_writeb(SAA7134_CHANNEL1_LEVEL,     level & 0x1f);
+               saa_writeb(SAA7134_CHANNEL2_LEVEL,     level & 0x1f);
+               saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
+               break;
+       }
+}
+
+int saa7134_tvaudio_getstereo(struct saa7134_dev *dev)
+{
+       int retval = V4L2_TUNER_SUB_MONO;
+
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               if (dev->tvaudio)
+                       retval = tvaudio_getstereo(dev,dev->tvaudio);
+               break;
+       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+               retval = getstereo_7133(dev);
+               break;
+       }
+       return retval;
+}
+
+void saa7134_tvaudio_init(struct saa7134_dev *dev)
+{
+       int clock = saa7134_boards[dev->board].audio_clock;
+
+       if (UNSET != audio_clock_override)
+               clock = audio_clock_override;
+
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               /* init all audio registers */
+               saa_writeb(SAA7134_AUDIO_PLL_CTRL,   0x00);
+               if (need_resched())
+                       schedule();
+               else
+                       udelay(10);
+
+               saa_writeb(SAA7134_AUDIO_CLOCK0,      clock        & 0xff);
+               saa_writeb(SAA7134_AUDIO_CLOCK1,     (clock >>  8) & 0xff);
+               saa_writeb(SAA7134_AUDIO_CLOCK2,     (clock >> 16) & 0xff);
+               /* frame locked audio is mandatory for NICAM */
+               saa_writeb(SAA7134_AUDIO_PLL_CTRL,   0x01);
+               saa_writeb(SAA7134_NICAM_ERROR_LOW,  0x14);
+               saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
+               break;
+       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+               saa_writel(0x598 >> 2, clock);
+               saa_dsp_writel(dev, 0x474 >> 2, 0x00);
+               saa_dsp_writel(dev, 0x450 >> 2, 0x00);
+       }
+}
+
+int saa7134_tvaudio_init2(struct saa7134_dev *dev)
+{
+       int (*my_thread)(void *data) = NULL;
+
+       switch (dev->pci->device) {
+       case PCI_DEVICE_ID_PHILIPS_SAA7134:
+               my_thread = tvaudio_thread;
+               break;
+       case PCI_DEVICE_ID_PHILIPS_SAA7133:
+       case PCI_DEVICE_ID_PHILIPS_SAA7135:
+               my_thread = tvaudio_thread_ddep;
+               break;
+       }
+
+       dev->thread.thread = NULL;
+       dev->thread.scan1 = dev->thread.scan2 = 0;
+       if (my_thread) {
+               saa7134_tvaudio_init(dev);
+               /* start tvaudio thread */
+               dev->thread.thread = kthread_run(my_thread, dev, "%s", dev->name);
+               if (IS_ERR(dev->thread.thread)) {
+                       printk(KERN_WARNING "%s: kernel_thread() failed\n",
+                              dev->name);
+                       /* XXX: missing error handling here */
+               }
+       }
+
+       saa7134_enable_i2s(dev);
+       return 0;
+}
+
+int saa7134_tvaudio_close(struct saa7134_dev *dev)
+{
+       dev->automute = 1;
+       /* anything else to undo? */
+       return 0;
+}
+
+int saa7134_tvaudio_fini(struct saa7134_dev *dev)
+{
+       /* shutdown tvaudio thread */
+       if (dev->thread.thread && !dev->thread.stopped)
+               kthread_stop(dev->thread.thread);
+
+       saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */
+       return 0;
+}
+
+int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
+{
+       if (dev->input->amux != TV) {
+               dprintk("sound IF not in use, skipping scan\n");
+               dev->automute = 0;
+               saa7134_tvaudio_setmute(dev);
+       } else if (dev->thread.thread) {
+               dev->thread.mode = UNSET;
+               dev->thread.scan2++;
+
+               if (!dev->insuspend && !dev->thread.stopped)
+                       wake_up_process(dev->thread.thread);
+       } else {
+               dev->automute = 0;
+               saa7134_tvaudio_setmute(dev);
+       }
+       return 0;
+}
+
+EXPORT_SYMBOL(saa_dsp_writel);
+EXPORT_SYMBOL(saa7134_tvaudio_setmute);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
new file mode 100644 (file)
index 0000000..e9aa94b
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * video4linux video interface
+ *
+ * (c) 2001,02 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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int vbi_debug;
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+
+static unsigned int vbibufs = 4;
+module_param(vbibufs, int, 0444);
+MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
+
+#define dprintk(fmt, arg...)   if (vbi_debug) \
+       printk(KERN_DEBUG "%s/vbi: " fmt, dev->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+
+#define VBI_LINE_COUNT     16
+#define VBI_LINE_LENGTH  2048
+#define VBI_SCALE       0x200
+
+static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
+                     int task)
+{
+       struct saa7134_tvnorm *norm = dev->tvnorm;
+
+       /* setup video scaler */
+       saa_writeb(SAA7134_VBI_H_START1(task), norm->h_start     &  0xff);
+       saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start     >> 8);
+       saa_writeb(SAA7134_VBI_H_STOP1(task),  norm->h_stop      &  0xff);
+       saa_writeb(SAA7134_VBI_H_STOP2(task),  norm->h_stop      >> 8);
+       saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 &  0xff);
+       saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
+       saa_writeb(SAA7134_VBI_V_STOP1(task),  norm->vbi_v_stop_0  &  0xff);
+       saa_writeb(SAA7134_VBI_V_STOP2(task),  norm->vbi_v_stop_0  >> 8);
+
+       saa_writeb(SAA7134_VBI_H_SCALE_INC1(task),        VBI_SCALE & 0xff);
+       saa_writeb(SAA7134_VBI_H_SCALE_INC2(task),        VBI_SCALE >> 8);
+       saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task),   0x00);
+       saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00);
+
+       saa_writeb(SAA7134_VBI_H_LEN1(task), buf->vb.width   & 0xff);
+       saa_writeb(SAA7134_VBI_H_LEN2(task), buf->vb.width   >> 8);
+       saa_writeb(SAA7134_VBI_V_LEN1(task), buf->vb.height  & 0xff);
+       saa_writeb(SAA7134_VBI_V_LEN2(task), buf->vb.height  >> 8);
+
+       saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int buffer_activate(struct saa7134_dev *dev,
+                          struct saa7134_buf *buf,
+                          struct saa7134_buf *next)
+{
+       unsigned long control,base;
+
+       dprintk("buffer_activate [%p]\n",buf);
+       buf->vb.state = VIDEOBUF_ACTIVE;
+       buf->top_seen = 0;
+
+       task_init(dev,buf,TASK_A);
+       task_init(dev,buf,TASK_B);
+       saa_writeb(SAA7134_OFMT_DATA_A, 0x06);
+       saa_writeb(SAA7134_OFMT_DATA_B, 0x06);
+
+       /* DMA: setup channel 2+3 (= VBI Task A+B) */
+       base    = saa7134_buffer_base(buf);
+       control = SAA7134_RS_CONTROL_BURST_16 |
+               SAA7134_RS_CONTROL_ME |
+               (buf->pt->dma >> 12);
+       saa_writel(SAA7134_RS_BA1(2),base);
+       saa_writel(SAA7134_RS_BA2(2),base + buf->vb.size/2);
+       saa_writel(SAA7134_RS_PITCH(2),buf->vb.width);
+       saa_writel(SAA7134_RS_CONTROL(2),control);
+       saa_writel(SAA7134_RS_BA1(3),base);
+       saa_writel(SAA7134_RS_BA2(3),base + buf->vb.size/2);
+       saa_writel(SAA7134_RS_PITCH(3),buf->vb.width);
+       saa_writel(SAA7134_RS_CONTROL(3),control);
+
+       /* start DMA */
+       saa7134_set_dmabits(dev);
+       mod_timer(&dev->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
+
+       return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q,
+                         struct videobuf_buffer *vb,
+                         enum v4l2_field field)
+{
+       struct saa7134_fh *fh   = q->priv_data;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+       struct saa7134_tvnorm *norm = dev->tvnorm;
+       unsigned int lines, llength, size;
+       int err;
+
+       lines   = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
+       if (lines > VBI_LINE_COUNT)
+               lines = VBI_LINE_COUNT;
+       llength = VBI_LINE_LENGTH;
+       size = lines * llength * 2;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       if (buf->vb.size != size)
+               saa7134_dma_free(q,buf);
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+               buf->vb.width  = llength;
+               buf->vb.height = lines;
+               buf->vb.size   = size;
+               buf->pt        = &fh->pt_vbi;
+
+               err = videobuf_iolock(q,&buf->vb,NULL);
+               if (err)
+                       goto oops;
+               err = saa7134_pgtable_build(dev->pci,buf->pt,
+                                           dma->sglist,
+                                           dma->sglen,
+                                           saa7134_buffer_startpage(buf));
+               if (err)
+                       goto oops;
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       buf->activate = buffer_activate;
+       buf->vb.field = field;
+       return 0;
+
+ oops:
+       saa7134_dma_free(q,buf);
+       return err;
+}
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       struct saa7134_fh *fh   = q->priv_data;
+       struct saa7134_dev *dev = fh->dev;
+       int llength,lines;
+
+       lines   = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
+       llength = VBI_LINE_LENGTH;
+       *size = lines * llength * 2;
+       if (0 == *count)
+               *count = vbibufs;
+       *count = saa7134_buffer_count(*size,*count);
+       return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct saa7134_fh *fh = q->priv_data;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
+       saa7134_buffer_queue(dev,&dev->vbi_q,buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
+       saa7134_dma_free(q,buf);
+}
+
+struct videobuf_queue_ops saa7134_vbi_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_vbi_init1(struct saa7134_dev *dev)
+{
+       INIT_LIST_HEAD(&dev->vbi_q.queue);
+       init_timer(&dev->vbi_q.timeout);
+       dev->vbi_q.timeout.function = saa7134_buffer_timeout;
+       dev->vbi_q.timeout.data     = (unsigned long)(&dev->vbi_q);
+       dev->vbi_q.dev              = dev;
+
+       if (vbibufs < 2)
+               vbibufs = 2;
+       if (vbibufs > VIDEO_MAX_FRAME)
+               vbibufs = VIDEO_MAX_FRAME;
+       return 0;
+}
+
+int saa7134_vbi_fini(struct saa7134_dev *dev)
+{
+       /* nothing */
+       return 0;
+}
+
+void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
+{
+       spin_lock(&dev->slock);
+       if (dev->vbi_q.curr) {
+               dev->vbi_fieldcount++;
+               /* make sure we have seen both fields */
+               if ((status & 0x10) == 0x00) {
+                       dev->vbi_q.curr->top_seen = 1;
+                       goto done;
+               }
+               if (!dev->vbi_q.curr->top_seen)
+                       goto done;
+
+               dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount;
+               saa7134_buffer_finish(dev,&dev->vbi_q,VIDEOBUF_DONE);
+       }
+       saa7134_buffer_next(dev,&dev->vbi_q);
+
+ done:
+       spin_unlock(&dev->slock);
+}
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
new file mode 100644 (file)
index 0000000..6de10b1
--- /dev/null
@@ -0,0 +1,2661 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * video4linux video interface
+ *
+ * (c) 2001-03 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, 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+#include <media/v4l2-common.h>
+#include <media/saa6588.h>
+
+/* ------------------------------------------------------------------ */
+
+unsigned int video_debug;
+static unsigned int gbuffers      = 8;
+static unsigned int noninterlaced; /* 0 */
+static unsigned int gbufsize      = 720*576*4;
+static unsigned int gbufsize_max  = 720*576*4;
+static char secam[] = "--";
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+module_param(gbuffers, int, 0444);
+MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
+module_param(noninterlaced, int, 0644);
+MODULE_PARM_DESC(noninterlaced,"capture non interlaced video");
+module_param_string(secam, secam, sizeof(secam), 0644);
+MODULE_PARM_DESC(secam, "force SECAM variant, either DK,L or Lc");
+
+
+#define dprintk(fmt, arg...)   if (video_debug&0x04) \
+       printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x191            */
+
+/* Bit 0: VIP code T bit polarity */
+
+#define VP_T_CODE_P_NON_INVERTED       0x00
+#define VP_T_CODE_P_INVERTED           0x01
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x195            */
+
+/* Bit 2: Video output clock delay control */
+
+#define VP_CLK_CTRL2_NOT_DELAYED       0x00
+#define VP_CLK_CTRL2_DELAYED           0x04
+
+/* Bit 1: Video output clock invert control */
+
+#define VP_CLK_CTRL1_NON_INVERTED      0x00
+#define VP_CLK_CTRL1_INVERTED          0x02
+
+/* ------------------------------------------------------------------ */
+/* Defines for Video Output Port Register at address 0x196            */
+
+/* Bits 2 to 0: VSYNC pin video vertical sync type */
+
+#define VP_VS_TYPE_MASK                        0x07
+
+#define VP_VS_TYPE_OFF                 0x00
+#define VP_VS_TYPE_V123                        0x01
+#define VP_VS_TYPE_V_ITU               0x02
+#define VP_VS_TYPE_VGATE_L             0x03
+#define VP_VS_TYPE_RESERVED1           0x04
+#define VP_VS_TYPE_RESERVED2           0x05
+#define VP_VS_TYPE_F_ITU               0x06
+#define VP_VS_TYPE_SC_FID              0x07
+
+/* ------------------------------------------------------------------ */
+/* data structs for video                                             */
+
+static int video_out[][9] = {
+       [CCIR656] = { 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x04, 0x06, 0x00, 0x00 },
+};
+
+static struct saa7134_format formats[] = {
+       {
+               .name     = "8 bpp gray",
+               .fourcc   = V4L2_PIX_FMT_GREY,
+               .depth    = 8,
+               .pm       = 0x06,
+       },{
+               .name     = "15 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB555,
+               .depth    = 16,
+               .pm       = 0x13 | 0x80,
+       },{
+               .name     = "15 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB555X,
+               .depth    = 16,
+               .pm       = 0x13 | 0x80,
+               .bswap    = 1,
+       },{
+               .name     = "16 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_RGB565,
+               .depth    = 16,
+               .pm       = 0x10 | 0x80,
+       },{
+               .name     = "16 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB565X,
+               .depth    = 16,
+               .pm       = 0x10 | 0x80,
+               .bswap    = 1,
+       },{
+               .name     = "24 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR24,
+               .depth    = 24,
+               .pm       = 0x11,
+       },{
+               .name     = "24 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB24,
+               .depth    = 24,
+               .pm       = 0x11,
+               .bswap    = 1,
+       },{
+               .name     = "32 bpp RGB, le",
+               .fourcc   = V4L2_PIX_FMT_BGR32,
+               .depth    = 32,
+               .pm       = 0x12,
+       },{
+               .name     = "32 bpp RGB, be",
+               .fourcc   = V4L2_PIX_FMT_RGB32,
+               .depth    = 32,
+               .pm       = 0x12,
+               .bswap    = 1,
+               .wswap    = 1,
+       },{
+               .name     = "4:2:2 packed, YUYV",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+               .pm       = 0x00,
+               .bswap    = 1,
+               .yuv      = 1,
+       },{
+               .name     = "4:2:2 packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+               .pm       = 0x00,
+               .yuv      = 1,
+       },{
+               .name     = "4:2:2 planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YUV422P,
+               .depth    = 16,
+               .pm       = 0x09,
+               .yuv      = 1,
+               .planar   = 1,
+               .hshift   = 1,
+               .vshift   = 0,
+       },{
+               .name     = "4:2:0 planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YUV420,
+               .depth    = 12,
+               .pm       = 0x0a,
+               .yuv      = 1,
+               .planar   = 1,
+               .hshift   = 1,
+               .vshift   = 1,
+       },{
+               .name     = "4:2:0 planar, Y-Cb-Cr",
+               .fourcc   = V4L2_PIX_FMT_YVU420,
+               .depth    = 12,
+               .pm       = 0x0a,
+               .yuv      = 1,
+               .planar   = 1,
+               .uvswap   = 1,
+               .hshift   = 1,
+               .vshift   = 1,
+       }
+};
+#define FORMATS ARRAY_SIZE(formats)
+
+#define NORM_625_50                    \
+               .h_start       = 0,     \
+               .h_stop        = 719,   \
+               .video_v_start = 24,    \
+               .video_v_stop  = 311,   \
+               .vbi_v_start_0 = 7,     \
+               .vbi_v_stop_0  = 22,    \
+               .vbi_v_start_1 = 319,   \
+               .src_timing    = 4
+
+#define NORM_525_60                    \
+               .h_start       = 0,     \
+               .h_stop        = 719,   \
+               .video_v_start = 23,    \
+               .video_v_stop  = 262,   \
+               .vbi_v_start_0 = 10,    \
+               .vbi_v_stop_0  = 21,    \
+               .vbi_v_start_1 = 273,   \
+               .src_timing    = 7
+
+static struct saa7134_tvnorm tvnorms[] = {
+       {
+               .name          = "PAL", /* autodetect */
+               .id            = V4L2_STD_PAL,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0x81,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x06,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "PAL-BG",
+               .id            = V4L2_STD_PAL_BG,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0x81,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x06,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "PAL-I",
+               .id            = V4L2_STD_PAL_I,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0x81,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x06,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "PAL-DK",
+               .id            = V4L2_STD_PAL_DK,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0x81,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x06,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "NTSC",
+               .id            = V4L2_STD_NTSC,
+               NORM_525_60,
+
+               .sync_control  = 0x59,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0x89,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x0e,
+               .vgate_misc    = 0x18,
+
+       },{
+               .name          = "SECAM",
+               .id            = V4L2_STD_SECAM,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x1b,
+               .chroma_ctrl1  = 0xd1,
+               .chroma_gain   = 0x80,
+               .chroma_ctrl2  = 0x00,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "SECAM-DK",
+               .id            = V4L2_STD_SECAM_DK,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x1b,
+               .chroma_ctrl1  = 0xd1,
+               .chroma_gain   = 0x80,
+               .chroma_ctrl2  = 0x00,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "SECAM-L",
+               .id            = V4L2_STD_SECAM_L,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x1b,
+               .chroma_ctrl1  = 0xd1,
+               .chroma_gain   = 0x80,
+               .chroma_ctrl2  = 0x00,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "SECAM-Lc",
+               .id            = V4L2_STD_SECAM_LC,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x1b,
+               .chroma_ctrl1  = 0xd1,
+               .chroma_gain   = 0x80,
+               .chroma_ctrl2  = 0x00,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "PAL-M",
+               .id            = V4L2_STD_PAL_M,
+               NORM_525_60,
+
+               .sync_control  = 0x59,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0xb9,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x0e,
+               .vgate_misc    = 0x18,
+
+       },{
+               .name          = "PAL-Nc",
+               .id            = V4L2_STD_PAL_Nc,
+               NORM_625_50,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0xa1,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x06,
+               .vgate_misc    = 0x1c,
+
+       },{
+               .name          = "PAL-60",
+               .id            = V4L2_STD_PAL_60,
+
+               .h_start       = 0,
+               .h_stop        = 719,
+               .video_v_start = 23,
+               .video_v_stop  = 262,
+               .vbi_v_start_0 = 10,
+               .vbi_v_stop_0  = 21,
+               .vbi_v_start_1 = 273,
+               .src_timing    = 7,
+
+               .sync_control  = 0x18,
+               .luma_control  = 0x40,
+               .chroma_ctrl1  = 0x81,
+               .chroma_gain   = 0x2a,
+               .chroma_ctrl2  = 0x06,
+               .vgate_misc    = 0x1c,
+       }
+};
+#define TVNORMS ARRAY_SIZE(tvnorms)
+
+#define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 4)
+
+static const struct v4l2_queryctrl no_ctrl = {
+       .name  = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+static const struct v4l2_queryctrl video_ctrls[] = {
+       /* --- video --- */
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 128,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_CONTRAST,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 68,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_SATURATION,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 64,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_HUE,
+               .name          = "Hue",
+               .minimum       = -128,
+               .maximum       = 127,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_HFLIP,
+               .name          = "Mirror",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },
+       /* --- audio --- */
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = -15,
+               .maximum       = 15,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },
+       /* --- private --- */
+       {
+               .id            = V4L2_CID_PRIVATE_INVERT,
+               .name          = "Invert",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       },{
+               .id            = V4L2_CID_PRIVATE_Y_ODD,
+               .name          = "y offset odd field",
+               .minimum       = 0,
+               .maximum       = 128,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_Y_EVEN,
+               .name          = "y offset even field",
+               .minimum       = 0,
+               .maximum       = 128,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       },{
+               .id            = V4L2_CID_PRIVATE_AUTOMUTE,
+               .name          = "automute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .default_value = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }
+};
+static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
+
+static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
+{
+       unsigned int i;
+
+       for (i = 0; i < CTRLS; i++)
+               if (video_ctrls[i].id == id)
+                       return video_ctrls+i;
+       return NULL;
+}
+
+static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < FORMATS; i++)
+               if (formats[i].fourcc == fourcc)
+                       return formats+i;
+       return NULL;
+}
+
+/* ----------------------------------------------------------------------- */
+/* resource management                                                     */
+
+static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit)
+{
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       /* is it free? */
+       mutex_lock(&dev->lock);
+       if (dev->resources & bit) {
+               /* no, someone else uses it */
+               mutex_unlock(&dev->lock);
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       dev->resources |= bit;
+       dprintk("res: get %d\n",bit);
+       mutex_unlock(&dev->lock);
+       return 1;
+}
+
+static int res_check(struct saa7134_fh *fh, unsigned int bit)
+{
+       return (fh->resources & bit);
+}
+
+static int res_locked(struct saa7134_dev *dev, unsigned int bit)
+{
+       return (dev->resources & bit);
+}
+
+static
+void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
+{
+       BUG_ON((fh->resources & bits) != bits);
+
+       mutex_lock(&dev->lock);
+       fh->resources  &= ~bits;
+       dev->resources &= ~bits;
+       dprintk("res: put %d\n",bits);
+       mutex_unlock(&dev->lock);
+}
+
+/* ------------------------------------------------------------------ */
+
+static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
+{
+       dprintk("set tv norm = %s\n",norm->name);
+       dev->tvnorm = norm;
+
+       /* setup cropping */
+       dev->crop_bounds.left    = norm->h_start;
+       dev->crop_defrect.left   = norm->h_start;
+       dev->crop_bounds.width   = norm->h_stop - norm->h_start +1;
+       dev->crop_defrect.width  = norm->h_stop - norm->h_start +1;
+
+       dev->crop_bounds.top     = (norm->vbi_v_stop_0+1)*2;
+       dev->crop_defrect.top    = norm->video_v_start*2;
+       dev->crop_bounds.height  = ((norm->id & V4L2_STD_525_60) ? 524 : 624)
+               - dev->crop_bounds.top;
+       dev->crop_defrect.height = (norm->video_v_stop - norm->video_v_start +1)*2;
+
+       dev->crop_current = dev->crop_defrect;
+
+       saa7134_set_tvnorm_hw(dev);
+}
+
+static void video_mux(struct saa7134_dev *dev, int input)
+{
+       dprintk("video input = %d [%s]\n", input, card_in(dev, input).name);
+       dev->ctl_input = input;
+       set_tvnorm(dev, dev->tvnorm);
+       saa7134_tvaudio_setinput(dev, &card_in(dev, input));
+}
+
+
+static void saa7134_set_decoder(struct saa7134_dev *dev)
+{
+       int luma_control, sync_control, mux;
+
+       struct saa7134_tvnorm *norm = dev->tvnorm;
+       mux = card_in(dev, dev->ctl_input).vmux;
+
+       luma_control = norm->luma_control;
+       sync_control = norm->sync_control;
+
+       if (mux > 5)
+               luma_control |= 0x80; /* svideo */
+       if (noninterlaced || dev->nosignal)
+               sync_control |= 0x20;
+
+       /* setup video decoder */
+       saa_writeb(SAA7134_INCR_DELAY,            0x08);
+       saa_writeb(SAA7134_ANALOG_IN_CTRL1,       0xc0 | mux);
+       saa_writeb(SAA7134_ANALOG_IN_CTRL2,       0x00);
+
+       saa_writeb(SAA7134_ANALOG_IN_CTRL3,       0x90);
+       saa_writeb(SAA7134_ANALOG_IN_CTRL4,       0x90);
+       saa_writeb(SAA7134_HSYNC_START,           0xeb);
+       saa_writeb(SAA7134_HSYNC_STOP,            0xe0);
+       saa_writeb(SAA7134_SOURCE_TIMING1,        norm->src_timing);
+
+       saa_writeb(SAA7134_SYNC_CTRL,             sync_control);
+       saa_writeb(SAA7134_LUMA_CTRL,             luma_control);
+       saa_writeb(SAA7134_DEC_LUMA_BRIGHT,       dev->ctl_bright);
+
+       saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
+               dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
+
+       saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
+               dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
+
+       saa_writeb(SAA7134_DEC_CHROMA_HUE,        dev->ctl_hue);
+       saa_writeb(SAA7134_CHROMA_CTRL1,          norm->chroma_ctrl1);
+       saa_writeb(SAA7134_CHROMA_GAIN,           norm->chroma_gain);
+
+       saa_writeb(SAA7134_CHROMA_CTRL2,          norm->chroma_ctrl2);
+       saa_writeb(SAA7134_MODE_DELAY_CTRL,       0x00);
+
+       saa_writeb(SAA7134_ANALOG_ADC,            0x01);
+       saa_writeb(SAA7134_VGATE_START,           0x11);
+       saa_writeb(SAA7134_VGATE_STOP,            0xfe);
+       saa_writeb(SAA7134_MISC_VGATE_MSB,        norm->vgate_misc);
+       saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);
+       saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);
+}
+
+void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
+{
+       saa7134_set_decoder(dev);
+
+       if (card_in(dev, dev->ctl_input).tv)
+               saa_call_all(dev, core, s_std, dev->tvnorm->id);
+       /* Set the correct norm for the saa6752hs. This function
+          does nothing if there is no saa6752hs. */
+       saa_call_empress(dev, core, s_std, dev->tvnorm->id);
+}
+
+static void set_h_prescale(struct saa7134_dev *dev, 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;
+
+       for (i = 0; i < count; i++)
+               if (vals[i].xpsc == prescale)
+                       break;
+       if (i == count)
+               return;
+
+       saa_writeb(SAA7134_H_PRESCALE(task), vals[i].xpsc);
+       saa_writeb(SAA7134_ACC_LENGTH(task), vals[i].xacl);
+       saa_writeb(SAA7134_LEVEL_CTRL(task),
+                  (vals[i].xc2_1 << 3) | (vals[i].xdcg));
+       saa_andorb(SAA7134_FIR_PREFILTER_CTRL(task), 0x0f,
+                  (vals[i].vpfy << 2) | vals[i].vpfy);
+}
+
+static void set_v_scale(struct saa7134_dev *dev, int task, int yscale)
+{
+       int val,mirror;
+
+       saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale &  0xff);
+       saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8);
+
+       mirror = (dev->ctl_mirror) ? 0x02 : 0x00;
+       if (yscale < 2048) {
+               /* LPI */
+               dprintk("yscale LPI yscale=%d\n",yscale);
+               saa_writeb(SAA7134_V_FILTER(task), 0x00 | mirror);
+               saa_writeb(SAA7134_LUMA_CONTRAST(task), 0x40);
+               saa_writeb(SAA7134_CHROMA_SATURATION(task), 0x40);
+       } else {
+               /* ACM */
+               val = 0x40 * 1024 / yscale;
+               dprintk("yscale ACM yscale=%d val=0x%x\n",yscale,val);
+               saa_writeb(SAA7134_V_FILTER(task), 0x01 | mirror);
+               saa_writeb(SAA7134_LUMA_CONTRAST(task), val);
+               saa_writeb(SAA7134_CHROMA_SATURATION(task), val);
+       }
+       saa_writeb(SAA7134_LUMA_BRIGHT(task),       0x80);
+}
+
+static void set_size(struct saa7134_dev *dev, int task,
+                    int width, int height, int interlace)
+{
+       int prescale,xscale,yscale,y_even,y_odd;
+       int h_start, h_stop, v_start, v_stop;
+       int div = interlace ? 2 : 1;
+
+       /* setup video scaler */
+       h_start = dev->crop_current.left;
+       v_start = dev->crop_current.top/2;
+       h_stop  = (dev->crop_current.left + dev->crop_current.width -1);
+       v_stop  = (dev->crop_current.top + dev->crop_current.height -1)/2;
+
+       saa_writeb(SAA7134_VIDEO_H_START1(task), h_start &  0xff);
+       saa_writeb(SAA7134_VIDEO_H_START2(task), h_start >> 8);
+       saa_writeb(SAA7134_VIDEO_H_STOP1(task),  h_stop  &  0xff);
+       saa_writeb(SAA7134_VIDEO_H_STOP2(task),  h_stop  >> 8);
+       saa_writeb(SAA7134_VIDEO_V_START1(task), v_start &  0xff);
+       saa_writeb(SAA7134_VIDEO_V_START2(task), v_start >> 8);
+       saa_writeb(SAA7134_VIDEO_V_STOP1(task),  v_stop  &  0xff);
+       saa_writeb(SAA7134_VIDEO_V_STOP2(task),  v_stop  >> 8);
+
+       prescale = dev->crop_current.width / width;
+       if (0 == prescale)
+               prescale = 1;
+       xscale = 1024 * dev->crop_current.width / prescale / width;
+       yscale = 512 * div * dev->crop_current.height / height;
+       dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
+       set_h_prescale(dev,task,prescale);
+       saa_writeb(SAA7134_H_SCALE_INC1(task),      xscale &  0xff);
+       saa_writeb(SAA7134_H_SCALE_INC2(task),      xscale >> 8);
+       set_v_scale(dev,task,yscale);
+
+       saa_writeb(SAA7134_VIDEO_PIXELS1(task),     width  & 0xff);
+       saa_writeb(SAA7134_VIDEO_PIXELS2(task),     width  >> 8);
+       saa_writeb(SAA7134_VIDEO_LINES1(task),      height/div & 0xff);
+       saa_writeb(SAA7134_VIDEO_LINES2(task),      height/div >> 8);
+
+       /* deinterlace y offsets */
+       y_odd  = dev->ctl_y_odd;
+       y_even = dev->ctl_y_even;
+       saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);
+       saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
+       saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
+       saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);
+}
+
+/* ------------------------------------------------------------------ */
+
+struct cliplist {
+       __u16 position;
+       __u8  enable;
+       __u8  disable;
+};
+
+static void set_cliplist(struct saa7134_dev *dev, int reg,
+                       struct cliplist *cl, int entries, char *name)
+{
+       __u8 winbits = 0;
+       int i;
+
+       for (i = 0; i < entries; i++) {
+               winbits |= cl[i].enable;
+               winbits &= ~cl[i].disable;
+               if (i < 15 && cl[i].position == cl[i+1].position)
+                       continue;
+               saa_writeb(reg + 0, winbits);
+               saa_writeb(reg + 2, cl[i].position & 0xff);
+               saa_writeb(reg + 3, cl[i].position >> 8);
+               dprintk("clip: %s winbits=%02x pos=%d\n",
+                       name,winbits,cl[i].position);
+               reg += 8;
+       }
+       for (; reg < 0x400; reg += 8) {
+               saa_writeb(reg+ 0, 0);
+               saa_writeb(reg + 1, 0);
+               saa_writeb(reg + 2, 0);
+               saa_writeb(reg + 3, 0);
+       }
+}
+
+static int clip_range(int val)
+{
+       if (val < 0)
+               val = 0;
+       return val;
+}
+
+/* Sort into smallest position first order */
+static int cliplist_cmp(const void *a, const void *b)
+{
+       const struct cliplist *cla = a;
+       const struct cliplist *clb = b;
+       if (cla->position < clb->position)
+               return -1;
+       if (cla->position > clb->position)
+               return 1;
+       return 0;
+}
+
+static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips,
+                         int nclips, int interlace)
+{
+       struct cliplist col[16], row[16];
+       int cols = 0, rows = 0, i;
+       int div = interlace ? 2 : 1;
+
+       memset(col, 0, sizeof(col));
+       memset(row, 0, sizeof(row));
+       for (i = 0; i < nclips && i < 8; i++) {
+               col[cols].position = clip_range(clips[i].c.left);
+               col[cols].enable   = (1 << i);
+               cols++;
+               col[cols].position = clip_range(clips[i].c.left+clips[i].c.width);
+               col[cols].disable  = (1 << i);
+               cols++;
+               row[rows].position = clip_range(clips[i].c.top / div);
+               row[rows].enable   = (1 << i);
+               rows++;
+               row[rows].position = clip_range((clips[i].c.top + clips[i].c.height)
+                                               / div);
+               row[rows].disable  = (1 << i);
+               rows++;
+       }
+       sort(col, cols, sizeof col[0], cliplist_cmp, NULL);
+       sort(row, rows, sizeof row[0], cliplist_cmp, NULL);
+       set_cliplist(dev,0x380,col,cols,"cols");
+       set_cliplist(dev,0x384,row,rows,"rows");
+       return 0;
+}
+
+static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win)
+{
+       enum v4l2_field field;
+       int maxw, maxh;
+
+       if (NULL == dev->ovbuf.base)
+               return -EINVAL;
+       if (NULL == dev->ovfmt)
+               return -EINVAL;
+       if (win->w.width < 48 || win->w.height <  32)
+               return -EINVAL;
+       if (win->clipcount > 2048)
+               return -EINVAL;
+
+       field = win->field;
+       maxw  = dev->crop_current.width;
+       maxh  = dev->crop_current.height;
+
+       if (V4L2_FIELD_ANY == field) {
+               field = (win->w.height > maxh/2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_TOP;
+       }
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       win->field = field;
+       if (win->w.width > maxw)
+               win->w.width = maxw;
+       if (win->w.height > maxh)
+               win->w.height = maxh;
+       return 0;
+}
+
+static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
+{
+       unsigned long base,control,bpl;
+       int err;
+
+       err = verify_preview(dev,&fh->win);
+       if (0 != err)
+               return err;
+
+       dev->ovfield = fh->win.field;
+       dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
+               fh->win.w.width,fh->win.w.height,
+               fh->win.w.left,fh->win.w.top,
+               dev->ovfmt->name,v4l2_field_names[dev->ovfield]);
+
+       /* setup window + clipping */
+       set_size(dev,TASK_B,fh->win.w.width,fh->win.w.height,
+                V4L2_FIELD_HAS_BOTH(dev->ovfield));
+       setup_clipping(dev,fh->clips,fh->nclips,
+                      V4L2_FIELD_HAS_BOTH(dev->ovfield));
+       if (dev->ovfmt->yuv)
+               saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03);
+       else
+               saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x01);
+       saa_writeb(SAA7134_OFMT_VIDEO_B, dev->ovfmt->pm | 0x20);
+
+       /* dma: setup channel 1 (= Video Task B) */
+       base  = (unsigned long)dev->ovbuf.base;
+       base += dev->ovbuf.fmt.bytesperline * fh->win.w.top;
+       base += dev->ovfmt->depth/8         * fh->win.w.left;
+       bpl   = dev->ovbuf.fmt.bytesperline;
+       control = SAA7134_RS_CONTROL_BURST_16;
+       if (dev->ovfmt->bswap)
+               control |= SAA7134_RS_CONTROL_BSWAP;
+       if (dev->ovfmt->wswap)
+               control |= SAA7134_RS_CONTROL_WSWAP;
+       if (V4L2_FIELD_HAS_BOTH(dev->ovfield)) {
+               saa_writel(SAA7134_RS_BA1(1),base);
+               saa_writel(SAA7134_RS_BA2(1),base+bpl);
+               saa_writel(SAA7134_RS_PITCH(1),bpl*2);
+               saa_writel(SAA7134_RS_CONTROL(1),control);
+       } else {
+               saa_writel(SAA7134_RS_BA1(1),base);
+               saa_writel(SAA7134_RS_BA2(1),base);
+               saa_writel(SAA7134_RS_PITCH(1),bpl);
+               saa_writel(SAA7134_RS_CONTROL(1),control);
+       }
+
+       /* start dma */
+       dev->ovenable = 1;
+       saa7134_set_dmabits(dev);
+
+       return 0;
+}
+
+static int stop_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
+{
+       dev->ovenable = 0;
+       saa7134_set_dmabits(dev);
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int buffer_activate(struct saa7134_dev *dev,
+                          struct saa7134_buf *buf,
+                          struct saa7134_buf *next)
+{
+       unsigned long base,control,bpl;
+       unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */
+
+       dprintk("buffer_activate buf=%p\n",buf);
+       buf->vb.state = VIDEOBUF_ACTIVE;
+       buf->top_seen = 0;
+
+       set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
+                V4L2_FIELD_HAS_BOTH(buf->vb.field));
+       if (buf->fmt->yuv)
+               saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x03);
+       else
+               saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x01);
+       saa_writeb(SAA7134_OFMT_VIDEO_A, buf->fmt->pm);
+
+       /* DMA: setup channel 0 (= Video Task A0) */
+       base  = saa7134_buffer_base(buf);
+       if (buf->fmt->planar)
+               bpl = buf->vb.width;
+       else
+               bpl = (buf->vb.width * buf->fmt->depth) / 8;
+       control = SAA7134_RS_CONTROL_BURST_16 |
+               SAA7134_RS_CONTROL_ME |
+               (buf->pt->dma >> 12);
+       if (buf->fmt->bswap)
+               control |= SAA7134_RS_CONTROL_BSWAP;
+       if (buf->fmt->wswap)
+               control |= SAA7134_RS_CONTROL_WSWAP;
+       if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {
+               /* interlaced */
+               saa_writel(SAA7134_RS_BA1(0),base);
+               saa_writel(SAA7134_RS_BA2(0),base+bpl);
+               saa_writel(SAA7134_RS_PITCH(0),bpl*2);
+       } else {
+               /* non-interlaced */
+               saa_writel(SAA7134_RS_BA1(0),base);
+               saa_writel(SAA7134_RS_BA2(0),base);
+               saa_writel(SAA7134_RS_PITCH(0),bpl);
+       }
+       saa_writel(SAA7134_RS_CONTROL(0),control);
+
+       if (buf->fmt->planar) {
+               /* DMA: setup channel 4+5 (= planar task A) */
+               bpl_uv   = bpl >> buf->fmt->hshift;
+               lines_uv = buf->vb.height >> buf->fmt->vshift;
+               base2    = base + bpl * buf->vb.height;
+               base3    = base2 + bpl_uv * lines_uv;
+               if (buf->fmt->uvswap)
+                       tmp = base2, base2 = base3, base3 = tmp;
+               dprintk("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",
+                       bpl_uv,lines_uv,base2,base3);
+               if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {
+                       /* interlaced */
+                       saa_writel(SAA7134_RS_BA1(4),base2);
+                       saa_writel(SAA7134_RS_BA2(4),base2+bpl_uv);
+                       saa_writel(SAA7134_RS_PITCH(4),bpl_uv*2);
+                       saa_writel(SAA7134_RS_BA1(5),base3);
+                       saa_writel(SAA7134_RS_BA2(5),base3+bpl_uv);
+                       saa_writel(SAA7134_RS_PITCH(5),bpl_uv*2);
+               } else {
+                       /* non-interlaced */
+                       saa_writel(SAA7134_RS_BA1(4),base2);
+                       saa_writel(SAA7134_RS_BA2(4),base2);
+                       saa_writel(SAA7134_RS_PITCH(4),bpl_uv);
+                       saa_writel(SAA7134_RS_BA1(5),base3);
+                       saa_writel(SAA7134_RS_BA2(5),base3);
+                       saa_writel(SAA7134_RS_PITCH(5),bpl_uv);
+               }
+               saa_writel(SAA7134_RS_CONTROL(4),control);
+               saa_writel(SAA7134_RS_CONTROL(5),control);
+       }
+
+       /* start DMA */
+       saa7134_set_dmabits(dev);
+       mod_timer(&dev->video_q.timeout, jiffies+BUFFER_TIMEOUT);
+       return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q,
+                         struct videobuf_buffer *vb,
+                         enum v4l2_field field)
+{
+       struct saa7134_fh *fh = q->priv_data;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+       unsigned int size;
+       int err;
+
+       /* sanity checks */
+       if (NULL == fh->fmt)
+               return -EINVAL;
+       if (fh->width    < 48 ||
+           fh->height   < 32 ||
+           fh->width/4  > dev->crop_current.width  ||
+           fh->height/4 > dev->crop_current.height ||
+           fh->width    > dev->crop_bounds.width  ||
+           fh->height   > dev->crop_bounds.height)
+               return -EINVAL;
+       size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+
+       dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
+               vb->i,fh->width,fh->height,size,v4l2_field_names[field],
+               fh->fmt->name);
+       if (buf->vb.width  != fh->width  ||
+           buf->vb.height != fh->height ||
+           buf->vb.size   != size       ||
+           buf->vb.field  != field      ||
+           buf->fmt       != fh->fmt) {
+               saa7134_dma_free(q,buf);
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+               buf->vb.width  = fh->width;
+               buf->vb.height = fh->height;
+               buf->vb.size   = size;
+               buf->vb.field  = field;
+               buf->fmt       = fh->fmt;
+               buf->pt        = &fh->pt_cap;
+               dev->video_q.curr = NULL;
+
+               err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
+               if (err)
+                       goto oops;
+               err = saa7134_pgtable_build(dev->pci,buf->pt,
+                                           dma->sglist,
+                                           dma->sglen,
+                                           saa7134_buffer_startpage(buf));
+               if (err)
+                       goto oops;
+       }
+       buf->vb.state = VIDEOBUF_PREPARED;
+       buf->activate = buffer_activate;
+       return 0;
+
+ oops:
+       saa7134_dma_free(q,buf);
+       return err;
+}
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+       struct saa7134_fh *fh = q->priv_data;
+
+       *size = fh->fmt->depth * fh->width * fh->height >> 3;
+       if (0 == *count)
+               *count = gbuffers;
+       *count = saa7134_buffer_count(*size,*count);
+       return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct saa7134_fh *fh = q->priv_data;
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
+       saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
+
+       saa7134_dma_free(q,buf);
+}
+
+static struct videobuf_queue_ops video_qops = {
+       .buf_setup    = buffer_setup,
+       .buf_prepare  = buffer_prepare,
+       .buf_queue    = buffer_queue,
+       .buf_release  = buffer_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
+{
+       const struct v4l2_queryctrl* ctrl;
+
+       ctrl = ctrl_by_id(c->id);
+       if (NULL == ctrl)
+               return -EINVAL;
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               c->value = dev->ctl_bright;
+               break;
+       case V4L2_CID_HUE:
+               c->value = dev->ctl_hue;
+               break;
+       case V4L2_CID_CONTRAST:
+               c->value = dev->ctl_contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               c->value = dev->ctl_saturation;
+               break;
+       case V4L2_CID_AUDIO_MUTE:
+               c->value = dev->ctl_mute;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               c->value = dev->ctl_volume;
+               break;
+       case V4L2_CID_PRIVATE_INVERT:
+               c->value = dev->ctl_invert;
+               break;
+       case V4L2_CID_HFLIP:
+               c->value = dev->ctl_mirror;
+               break;
+       case V4L2_CID_PRIVATE_Y_EVEN:
+               c->value = dev->ctl_y_even;
+               break;
+       case V4L2_CID_PRIVATE_Y_ODD:
+               c->value = dev->ctl_y_odd;
+               break;
+       case V4L2_CID_PRIVATE_AUTOMUTE:
+               c->value = dev->ctl_automute;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);
+
+static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
+{
+       struct saa7134_fh *fh = priv;
+
+       return saa7134_g_ctrl_internal(fh->dev, fh, c);
+}
+
+int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c)
+{
+       const struct v4l2_queryctrl* ctrl;
+       unsigned long flags;
+       int restart_overlay = 0;
+       int err;
+
+       /* When called from the empress code fh == NULL.
+          That needs to be fixed somehow, but for now this is
+          good enough. */
+       if (fh) {
+               err = v4l2_prio_check(&dev->prio, fh->prio);
+               if (0 != err)
+                       return err;
+       }
+       err = -EINVAL;
+
+       mutex_lock(&dev->lock);
+
+       ctrl = ctrl_by_id(c->id);
+       if (NULL == ctrl)
+               goto error;
+
+       dprintk("set_control name=%s val=%d\n",ctrl->name,c->value);
+       switch (ctrl->type) {
+       case V4L2_CTRL_TYPE_BOOLEAN:
+       case V4L2_CTRL_TYPE_MENU:
+       case V4L2_CTRL_TYPE_INTEGER:
+               if (c->value < ctrl->minimum)
+                       c->value = ctrl->minimum;
+               if (c->value > ctrl->maximum)
+                       c->value = ctrl->maximum;
+               break;
+       default:
+               /* nothing */;
+       };
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               dev->ctl_bright = c->value;
+               saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
+               break;
+       case V4L2_CID_HUE:
+               dev->ctl_hue = c->value;
+               saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);
+               break;
+       case V4L2_CID_CONTRAST:
+               dev->ctl_contrast = c->value;
+               saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
+                          dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
+               break;
+       case V4L2_CID_SATURATION:
+               dev->ctl_saturation = c->value;
+               saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
+                          dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
+               break;
+       case V4L2_CID_AUDIO_MUTE:
+               dev->ctl_mute = c->value;
+               saa7134_tvaudio_setmute(dev);
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               dev->ctl_volume = c->value;
+               saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
+               break;
+       case V4L2_CID_PRIVATE_INVERT:
+               dev->ctl_invert = c->value;
+               saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
+                          dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
+               saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
+                          dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
+               break;
+       case V4L2_CID_HFLIP:
+               dev->ctl_mirror = c->value;
+               restart_overlay = 1;
+               break;
+       case V4L2_CID_PRIVATE_Y_EVEN:
+               dev->ctl_y_even = c->value;
+               restart_overlay = 1;
+               break;
+       case V4L2_CID_PRIVATE_Y_ODD:
+               dev->ctl_y_odd = c->value;
+               restart_overlay = 1;
+               break;
+       case V4L2_CID_PRIVATE_AUTOMUTE:
+       {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &dev->tda9887_conf;
+
+               dev->ctl_automute = c->value;
+               if (dev->tda9887_conf) {
+                       if (dev->ctl_automute)
+                               dev->tda9887_conf |= TDA9887_AUTOMUTE;
+                       else
+                               dev->tda9887_conf &= ~TDA9887_AUTOMUTE;
+
+                       saa_call_all(dev, tuner, s_config, &tda9887_cfg);
+               }
+               break;
+       }
+       default:
+               goto error;
+       }
+       if (restart_overlay && fh && res_check(fh, RESOURCE_OVERLAY)) {
+               spin_lock_irqsave(&dev->slock,flags);
+               stop_preview(dev,fh);
+               start_preview(dev,fh);
+               spin_unlock_irqrestore(&dev->slock,flags);
+       }
+       err = 0;
+
+error:
+       mutex_unlock(&dev->lock);
+       return err;
+}
+EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);
+
+static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
+{
+       struct saa7134_fh *fh = f;
+
+       return saa7134_s_ctrl_internal(fh->dev, fh, c);
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh)
+{
+       struct videobuf_queue* q = NULL;
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               q = &fh->cap;
+               break;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               q = &fh->vbi;
+               break;
+       default:
+               BUG();
+       }
+       return q;
+}
+
+static int saa7134_resource(struct saa7134_fh *fh)
+{
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return RESOURCE_VIDEO;
+
+       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+               return RESOURCE_VBI;
+
+       BUG();
+       return 0;
+}
+
+static int video_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct saa7134_dev *dev = video_drvdata(file);
+       struct saa7134_fh *fh;
+       enum v4l2_buf_type type = 0;
+       int radio = 0;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev),
+               radio, v4l2_type_names[type]);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       file->private_data = fh;
+       fh->dev      = dev;
+       fh->radio    = radio;
+       fh->type     = type;
+       fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+       fh->width    = 720;
+       fh->height   = 576;
+       v4l2_prio_open(&dev->prio, &fh->prio);
+
+       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, NULL);
+       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),
+                           fh, NULL);
+       saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
+       saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
+
+       if (fh->radio) {
+               /* switch to radio mode */
+               saa7134_tvaudio_setinput(dev,&card(dev).radio);
+               saa_call_all(dev, tuner, s_radio);
+       } else {
+               /* switch to video/vbi mode */
+               video_mux(dev,dev->ctl_input);
+       }
+       return 0;
+}
+
+static ssize_t
+video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+       struct saa7134_fh *fh = file->private_data;
+
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               if (res_locked(fh->dev,RESOURCE_VIDEO))
+                       return -EBUSY;
+               return videobuf_read_one(saa7134_queue(fh),
+                                        data, count, ppos,
+                                        file->f_flags & O_NONBLOCK);
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (!res_get(fh->dev,fh,RESOURCE_VBI))
+                       return -EBUSY;
+               return videobuf_read_stream(saa7134_queue(fh),
+                                           data, count, ppos, 1,
+                                           file->f_flags & O_NONBLOCK);
+               break;
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+static unsigned int
+video_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct saa7134_fh *fh = file->private_data;
+       struct videobuf_buffer *buf = NULL;
+       unsigned int rc = 0;
+
+       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
+               return videobuf_poll_stream(file, &fh->vbi, wait);
+
+       if (res_check(fh,RESOURCE_VIDEO)) {
+               mutex_lock(&fh->cap.vb_lock);
+               if (!list_empty(&fh->cap.stream))
+                       buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
+       } else {
+               mutex_lock(&fh->cap.vb_lock);
+               if (UNSET == fh->cap.read_off) {
+                       /* need to capture a new frame */
+                       if (res_locked(fh->dev,RESOURCE_VIDEO))
+                               goto err;
+                       if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field))
+                               goto err;
+                       fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
+                       fh->cap.read_off = 0;
+               }
+               buf = fh->cap.read_buf;
+       }
+
+       if (!buf)
+               goto err;
+
+       poll_wait(file, &buf->done, wait);
+       if (buf->state == VIDEOBUF_DONE ||
+           buf->state == VIDEOBUF_ERROR)
+               rc = POLLIN|POLLRDNORM;
+       mutex_unlock(&fh->cap.vb_lock);
+       return rc;
+
+err:
+       mutex_unlock(&fh->cap.vb_lock);
+       return POLLERR;
+}
+
+static int video_release(struct file *file)
+{
+       struct saa7134_fh  *fh  = file->private_data;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa6588_command cmd;
+       unsigned long flags;
+
+       saa7134_tvaudio_close(dev);
+
+       /* turn off overlay */
+       if (res_check(fh, RESOURCE_OVERLAY)) {
+               spin_lock_irqsave(&dev->slock,flags);
+               stop_preview(dev,fh);
+               spin_unlock_irqrestore(&dev->slock,flags);
+               res_free(dev,fh,RESOURCE_OVERLAY);
+       }
+
+       /* stop video capture */
+       if (res_check(fh, RESOURCE_VIDEO)) {
+               videobuf_streamoff(&fh->cap);
+               res_free(dev,fh,RESOURCE_VIDEO);
+       }
+       if (fh->cap.read_buf) {
+               buffer_release(&fh->cap,fh->cap.read_buf);
+               kfree(fh->cap.read_buf);
+       }
+
+       /* stop vbi capture */
+       if (res_check(fh, RESOURCE_VBI)) {
+               videobuf_stop(&fh->vbi);
+               res_free(dev,fh,RESOURCE_VBI);
+       }
+
+       /* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/
+       saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0);
+       saa_andorb(SAA7134_OFMT_VIDEO_B, 0x1f, 0);
+       saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
+       saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
+
+       saa_call_all(dev, core, s_power, 0);
+       if (fh->radio)
+               saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
+
+       /* free stuff */
+       videobuf_mmap_free(&fh->cap);
+       videobuf_mmap_free(&fh->vbi);
+       saa7134_pgtable_free(dev->pci,&fh->pt_cap);
+       saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
+
+       v4l2_prio_close(&dev->prio, fh->prio);
+       file->private_data = NULL;
+       kfree(fh);
+       return 0;
+}
+
+static int video_mmap(struct file *file, struct vm_area_struct * vma)
+{
+       struct saa7134_fh *fh = file->private_data;
+
+       return videobuf_mmap_mapper(saa7134_queue(fh), vma);
+}
+
+static ssize_t radio_read(struct file *file, char __user *data,
+                        size_t count, loff_t *ppos)
+{
+       struct saa7134_fh *fh = file->private_data;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa6588_command cmd;
+
+       cmd.block_count = count/3;
+       cmd.buffer = data;
+       cmd.instance = file;
+       cmd.result = -ENODEV;
+
+       saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd);
+
+       return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+       struct saa7134_fh *fh = file->private_data;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa6588_command cmd;
+
+       cmd.instance = file;
+       cmd.event_list = wait;
+       cmd.result = -ENODEV;
+       saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd);
+
+       return cmd.result;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_tvnorm *norm = dev->tvnorm;
+
+       f->fmt.vbi.sampling_rate = 6750000 * 4;
+       f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
+       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       f->fmt.vbi.offset = 64 * 4;
+       f->fmt.vbi.start[0] = norm->vbi_v_start_0;
+       f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
+       f->fmt.vbi.start[1] = norm->vbi_v_start_1;
+       f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+       f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */
+
+       return 0;
+}
+
+static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->cap.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+       return 0;
+}
+
+static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+
+       if (saa7134_no_overlay > 0) {
+               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+               return -EINVAL;
+       }
+       f->fmt.win = fh->win;
+
+       return 0;
+}
+
+static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_format *fmt;
+       enum v4l2_field field;
+       unsigned int maxw, maxh;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       field = f->fmt.pix.field;
+       maxw  = min(dev->crop_current.width*4,  dev->crop_bounds.width);
+       maxh  = min(dev->crop_current.height*4, dev->crop_bounds.height);
+
+       if (V4L2_FIELD_ANY == field) {
+               field = (f->fmt.pix.height > maxh/2)
+                       ? V4L2_FIELD_INTERLACED
+                       : V4L2_FIELD_BOTTOM;
+       }
+       switch (field) {
+       case V4L2_FIELD_TOP:
+       case V4L2_FIELD_BOTTOM:
+               maxh = maxh / 2;
+               break;
+       case V4L2_FIELD_INTERLACED:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       f->fmt.pix.field = field;
+       if (f->fmt.pix.width  < 48)
+               f->fmt.pix.width  = 48;
+       if (f->fmt.pix.height < 32)
+               f->fmt.pix.height = 32;
+       if (f->fmt.pix.width > maxw)
+               f->fmt.pix.width = maxw;
+       if (f->fmt.pix.height > maxh)
+               f->fmt.pix.height = maxh;
+       f->fmt.pix.width &= ~0x03;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (saa7134_no_overlay > 0) {
+               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+               return -EINVAL;
+       }
+
+       return verify_preview(dev, &f->fmt.win);
+}
+
+static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+       int err;
+
+       err = saa7134_try_fmt_vid_cap(file, priv, f);
+       if (0 != err)
+               return err;
+
+       fh->fmt       = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->width     = f->fmt.pix.width;
+       fh->height    = f->fmt.pix.height;
+       fh->cap.field = f->fmt.pix.field;
+       return 0;
+}
+
+static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int err;
+       unsigned long flags;
+
+       if (saa7134_no_overlay > 0) {
+               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+               return -EINVAL;
+       }
+       err = verify_preview(dev, &f->fmt.win);
+       if (0 != err)
+               return err;
+
+       mutex_lock(&dev->lock);
+
+       fh->win    = f->fmt.win;
+       fh->nclips = f->fmt.win.clipcount;
+
+       if (fh->nclips > 8)
+               fh->nclips = 8;
+
+       if (copy_from_user(fh->clips, f->fmt.win.clips,
+                          sizeof(struct v4l2_clip)*fh->nclips)) {
+               mutex_unlock(&dev->lock);
+               return -EFAULT;
+       }
+
+       if (res_check(fh, RESOURCE_OVERLAY)) {
+               spin_lock_irqsave(&dev->slock, flags);
+               stop_preview(dev, fh);
+               start_preview(dev, fh);
+               spin_unlock_irqrestore(&dev->slock, flags);
+       }
+
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c)
+{
+       const struct v4l2_queryctrl *ctrl;
+
+       if ((c->id <  V4L2_CID_BASE ||
+            c->id >= V4L2_CID_LASTP1) &&
+           (c->id <  V4L2_CID_PRIVATE_BASE ||
+            c->id >= V4L2_CID_PRIVATE_LASTP1))
+               return -EINVAL;
+       ctrl = ctrl_by_id(c->id);
+       *c = (NULL != ctrl) ? *ctrl : no_ctrl;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(saa7134_queryctrl);
+
+static int saa7134_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *i)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       unsigned int n;
+
+       n = i->index;
+       if (n >= SAA7134_INPUT_MAX)
+               return -EINVAL;
+       if (NULL == card_in(dev, i->index).name)
+               return -EINVAL;
+       i->index = n;
+       i->type  = V4L2_INPUT_TYPE_CAMERA;
+       strcpy(i->name, card_in(dev, n).name);
+       if (card_in(dev, n).tv)
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       i->audioset = 1;
+       if (n == dev->ctl_input) {
+               int v1 = saa_readb(SAA7134_STATUS_VIDEO1);
+               int v2 = saa_readb(SAA7134_STATUS_VIDEO2);
+
+               if (0 != (v1 & 0x40))
+                       i->status |= V4L2_IN_ST_NO_H_LOCK;
+               if (0 != (v2 & 0x40))
+                       i->status |= V4L2_IN_ST_NO_SYNC;
+               if (0 != (v2 & 0x0e))
+                       i->status |= V4L2_IN_ST_MACROVISION;
+       }
+       i->std = SAA7134_NORMS;
+       return 0;
+}
+
+static int saa7134_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       *i = dev->ctl_input;
+       return 0;
+}
+
+static int saa7134_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int err;
+
+       err = v4l2_prio_check(&dev->prio, fh->prio);
+       if (0 != err)
+               return err;
+
+       if (i >= SAA7134_INPUT_MAX)
+               return -EINVAL;
+       if (NULL == card_in(dev, i).name)
+               return -EINVAL;
+       mutex_lock(&dev->lock);
+       video_mux(dev, i);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+static int saa7134_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       unsigned int tuner_type = dev->tuner_type;
+
+       strcpy(cap->driver, "saa7134");
+       strlcpy(cap->card, saa7134_boards[dev->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_VBI_CAPTURE |
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING |
+               V4L2_CAP_TUNER;
+       if (dev->has_rds)
+               cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
+       if (saa7134_no_overlay <= 0)
+               cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
+       if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET))
+               cap->capabilities &= ~V4L2_CAP_TUNER;
+       return 0;
+}
+
+int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
+{
+       unsigned long flags;
+       unsigned int i;
+       v4l2_std_id fixup;
+       int err;
+
+       /* When called from the empress code fh == NULL.
+          That needs to be fixed somehow, but for now this is
+          good enough. */
+       if (fh) {
+               err = v4l2_prio_check(&dev->prio, fh->prio);
+               if (0 != err)
+                       return err;
+       } else if (res_locked(dev, RESOURCE_OVERLAY)) {
+               /* Don't change the std from the mpeg device
+                  if overlay is active. */
+               return -EBUSY;
+       }
+
+       for (i = 0; i < TVNORMS; i++)
+               if (*id == tvnorms[i].id)
+                       break;
+
+       if (i == TVNORMS)
+               for (i = 0; i < TVNORMS; i++)
+                       if (*id & tvnorms[i].id)
+                               break;
+       if (i == TVNORMS)
+               return -EINVAL;
+
+       if ((*id & V4L2_STD_SECAM) && (secam[0] != '-')) {
+               if (secam[0] == 'L' || secam[0] == 'l') {
+                       if (secam[1] == 'C' || secam[1] == 'c')
+                               fixup = V4L2_STD_SECAM_LC;
+                       else
+                               fixup = V4L2_STD_SECAM_L;
+               } else {
+                       if (secam[0] == 'D' || secam[0] == 'd')
+                               fixup = V4L2_STD_SECAM_DK;
+                       else
+                               fixup = V4L2_STD_SECAM;
+               }
+               for (i = 0; i < TVNORMS; i++) {
+                       if (fixup == tvnorms[i].id)
+                               break;
+               }
+               if (i == TVNORMS)
+                       return -EINVAL;
+       }
+
+       *id = tvnorms[i].id;
+
+       mutex_lock(&dev->lock);
+       if (fh && res_check(fh, RESOURCE_OVERLAY)) {
+               spin_lock_irqsave(&dev->slock, flags);
+               stop_preview(dev, fh);
+               spin_unlock_irqrestore(&dev->slock, flags);
+
+               set_tvnorm(dev, &tvnorms[i]);
+
+               spin_lock_irqsave(&dev->slock, flags);
+               start_preview(dev, fh);
+               spin_unlock_irqrestore(&dev->slock, flags);
+       } else
+               set_tvnorm(dev, &tvnorms[i]);
+
+       saa7134_tvaudio_do_scan(dev);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
+
+static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_fh *fh = priv;
+
+       return saa7134_s_std_internal(fh->dev, fh, id);
+}
+
+static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       *id = dev->tvnorm->id;
+       return 0;
+}
+
+static int saa7134_cropcap(struct file *file, void *priv,
+                                       struct v4l2_cropcap *cap)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+               return -EINVAL;
+       cap->bounds  = dev->crop_bounds;
+       cap->defrect = dev->crop_defrect;
+       cap->pixelaspect.numerator   = 1;
+       cap->pixelaspect.denominator = 1;
+       if (dev->tvnorm->id & V4L2_STD_525_60) {
+               cap->pixelaspect.numerator   = 11;
+               cap->pixelaspect.denominator = 10;
+       }
+       if (dev->tvnorm->id & V4L2_STD_625_50) {
+               cap->pixelaspect.numerator   = 54;
+               cap->pixelaspect.denominator = 59;
+       }
+       return 0;
+}
+
+static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+               return -EINVAL;
+       crop->c = dev->crop_current;
+       return 0;
+}
+
+static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+       struct v4l2_rect *b = &dev->crop_bounds;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+               return -EINVAL;
+       if (crop->c.height < 0)
+               return -EINVAL;
+       if (crop->c.width < 0)
+               return -EINVAL;
+
+       if (res_locked(fh->dev, RESOURCE_OVERLAY))
+               return -EBUSY;
+       if (res_locked(fh->dev, RESOURCE_VIDEO))
+               return -EBUSY;
+
+       if (crop->c.top < b->top)
+               crop->c.top = b->top;
+       if (crop->c.top > b->top + b->height)
+               crop->c.top = b->top + b->height;
+       if (crop->c.height > b->top - crop->c.top + b->height)
+               crop->c.height = b->top - crop->c.top + b->height;
+
+       if (crop->c.left < b->left)
+               crop->c.left = b->left;
+       if (crop->c.left > b->left + b->width)
+               crop->c.left = b->left + b->width;
+       if (crop->c.width > b->left - crop->c.left + b->width)
+               crop->c.width = b->left - crop->c.left + b->width;
+
+       dev->crop_current = crop->c;
+       return 0;
+}
+
+static int saa7134_g_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int n;
+
+       if (0 != t->index)
+               return -EINVAL;
+       memset(t, 0, sizeof(*t));
+       for (n = 0; n < SAA7134_INPUT_MAX; n++) {
+               if (card_in(dev, n).tv)
+                       break;
+       }
+       if (n == SAA7134_INPUT_MAX)
+               return -EINVAL;
+       if (NULL != card_in(dev, n).name) {
+               strcpy(t->name, "Television");
+               t->type = V4L2_TUNER_ANALOG_TV;
+               t->capability = V4L2_TUNER_CAP_NORM |
+                       V4L2_TUNER_CAP_STEREO |
+                       V4L2_TUNER_CAP_LANG1 |
+                       V4L2_TUNER_CAP_LANG2;
+               t->rangehigh = 0xffffffffUL;
+               t->rxsubchans = saa7134_tvaudio_getstereo(dev);
+               t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans);
+       }
+       if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03))
+               t->signal = 0xffff;
+       return 0;
+}
+
+static int saa7134_s_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int rx, mode, err;
+
+       err = v4l2_prio_check(&dev->prio, fh->prio);
+       if (0 != err)
+               return err;
+
+       mode = dev->thread.mode;
+       if (UNSET == mode) {
+               rx   = saa7134_tvaudio_getstereo(dev);
+               mode = saa7134_tvaudio_rx2mode(rx);
+       }
+       if (mode != t->audmode)
+               dev->thread.mode = t->audmode;
+
+       return 0;
+}
+
+static int saa7134_g_frequency(struct file *file, void *priv,
+                                       struct v4l2_frequency *f)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->ctl_freq;
+
+       return 0;
+}
+
+static int saa7134_s_frequency(struct file *file, void *priv,
+                                       struct v4l2_frequency *f)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int err;
+
+       err = v4l2_prio_check(&dev->prio, fh->prio);
+       if (0 != err)
+               return err;
+
+       if (0 != f->tuner)
+               return -EINVAL;
+       if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
+               return -EINVAL;
+       if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
+               return -EINVAL;
+       mutex_lock(&dev->lock);
+       dev->ctl_freq = f->frequency;
+
+       saa_call_all(dev, tuner, s_frequency, f);
+
+       saa7134_tvaudio_do_scan(dev);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+static int saa7134_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       strcpy(a->name, "audio");
+       return 0;
+}
+
+static int saa7134_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       return 0;
+}
+
+static int saa7134_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+
+       *p = v4l2_prio_max(&dev->prio);
+       return 0;
+}
+
+static int saa7134_s_priority(struct file *file, void *f,
+                                       enum v4l2_priority prio)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+
+       return v4l2_prio_change(&dev->prio, &fh->prio, prio);
+}
+
+static int saa7134_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (f->index >= FORMATS)
+               return -EINVAL;
+
+       strlcpy(f->description, formats[f->index].name,
+               sizeof(f->description));
+
+       f->pixelformat = formats[f->index].fourcc;
+
+       return 0;
+}
+
+static int saa7134_enum_fmt_vid_overlay(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (saa7134_no_overlay > 0) {
+               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+               return -EINVAL;
+       }
+
+       if ((f->index >= FORMATS) || formats[f->index].planar)
+               return -EINVAL;
+
+       strlcpy(f->description, formats[f->index].name,
+               sizeof(f->description));
+
+       f->pixelformat = formats[f->index].fourcc;
+
+       return 0;
+}
+
+static int saa7134_g_fbuf(struct file *file, void *f,
+                               struct v4l2_framebuffer *fb)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+
+       *fb = dev->ovbuf;
+       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+
+       return 0;
+}
+
+static int saa7134_s_fbuf(struct file *file, void *f,
+                                       struct v4l2_framebuffer *fb)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+       struct saa7134_format *fmt;
+
+       if (!capable(CAP_SYS_ADMIN) &&
+          !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       /* check args */
+       fmt = format_by_fourcc(fb->fmt.pixelformat);
+       if (NULL == fmt)
+               return -EINVAL;
+
+       /* ok, accept it */
+       dev->ovbuf = *fb;
+       dev->ovfmt = fmt;
+       if (0 == dev->ovbuf.fmt.bytesperline)
+               dev->ovbuf.fmt.bytesperline =
+                       dev->ovbuf.fmt.width*fmt->depth/8;
+       return 0;
+}
+
+static int saa7134_overlay(struct file *file, void *f, unsigned int on)
+{
+       struct saa7134_fh *fh = f;
+       struct saa7134_dev *dev = fh->dev;
+       unsigned long flags;
+
+       if (on) {
+               if (saa7134_no_overlay > 0) {
+                       dprintk("no_overlay\n");
+                       return -EINVAL;
+               }
+
+               if (!res_get(dev, fh, RESOURCE_OVERLAY))
+                       return -EBUSY;
+               spin_lock_irqsave(&dev->slock, flags);
+               start_preview(dev, fh);
+               spin_unlock_irqrestore(&dev->slock, flags);
+       }
+       if (!on) {
+               if (!res_check(fh, RESOURCE_OVERLAY))
+                       return -EINVAL;
+               spin_lock_irqsave(&dev->slock, flags);
+               stop_preview(dev, fh);
+               spin_unlock_irqrestore(&dev->slock, flags);
+               res_free(dev, fh, RESOURCE_OVERLAY);
+       }
+       return 0;
+}
+
+static int saa7134_reqbufs(struct file *file, void *priv,
+                                       struct v4l2_requestbuffers *p)
+{
+       struct saa7134_fh *fh = priv;
+       return videobuf_reqbufs(saa7134_queue(fh), p);
+}
+
+static int saa7134_querybuf(struct file *file, void *priv,
+                                       struct v4l2_buffer *b)
+{
+       struct saa7134_fh *fh = priv;
+       return videobuf_querybuf(saa7134_queue(fh), b);
+}
+
+static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct saa7134_fh *fh = priv;
+       return videobuf_qbuf(saa7134_queue(fh), b);
+}
+
+static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct saa7134_fh *fh = priv;
+       return videobuf_dqbuf(saa7134_queue(fh), b,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int saa7134_streamon(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int res = saa7134_resource(fh);
+
+       if (!res_get(dev, fh, res))
+               return -EBUSY;
+
+       return videobuf_streamon(saa7134_queue(fh));
+}
+
+static int saa7134_streamoff(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       int err;
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+       int res = saa7134_resource(fh);
+
+       err = videobuf_streamoff(saa7134_queue(fh));
+       if (err < 0)
+               return err;
+       res_free(dev, fh, res);
+       return 0;
+}
+
+static int saa7134_g_parm(struct file *file, void *fh,
+                               struct v4l2_streamparm *parm)
+{
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *priv,
+                             struct v4l2_dbg_register *reg)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+       reg->val = saa_readb(reg->reg);
+       reg->size = 1;
+       return 0;
+}
+
+static int vidioc_s_register (struct file *file, void *priv,
+                               struct v4l2_dbg_register *reg)
+{
+       struct saa7134_fh *fh = priv;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+       saa_writeb(reg->reg&0xffffff, reg->val);
+       return 0;
+}
+#endif
+
+static int radio_querycap(struct file *file, void *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct saa7134_fh *fh = file->private_data;
+       struct saa7134_dev *dev = fh->dev;
+
+       strcpy(cap->driver, "saa7134");
+       strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+       cap->capabilities = V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct saa7134_fh *fh = file->private_data;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       memset(t, 0, sizeof(*t));
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
+
+       saa_call_all(dev, tuner, g_tuner, t);
+       if (dev->input->amux == TV) {
+               t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11);
+               t->rxsubchans = (saa_readb(0x529) & 0x08) ?
+                               V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
+       }
+       return 0;
+}
+static int radio_s_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct saa7134_fh *fh = file->private_data;
+       struct saa7134_dev *dev = fh->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       saa_call_all(dev, tuner, s_tuner, t);
+       return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+
+       strcpy(i->name, "Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
+
+       return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       memset(a, 0, sizeof(*a));
+       strcpy(a->name, "Radio");
+       return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+       return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *c)
+{
+       const struct v4l2_queryctrl *ctrl;
+
+       if (c->id <  V4L2_CID_BASE ||
+           c->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
+               ctrl = ctrl_by_id(c->id);
+               *c = *ctrl;
+       } else
+               *c = no_ctrl;
+       return 0;
+}
+
+static const struct v4l2_file_operations video_fops =
+{
+       .owner    = THIS_MODULE,
+       .open     = video_open,
+       .release  = video_release,
+       .read     = video_read,
+       .poll     = video_poll,
+       .mmap     = video_mmap,
+       .ioctl    = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap                = saa7134_querycap,
+       .vidioc_enum_fmt_vid_cap        = saa7134_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap           = saa7134_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap         = saa7134_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap           = saa7134_s_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_overlay    = saa7134_enum_fmt_vid_overlay,
+       .vidioc_g_fmt_vid_overlay       = saa7134_g_fmt_vid_overlay,
+       .vidioc_try_fmt_vid_overlay     = saa7134_try_fmt_vid_overlay,
+       .vidioc_s_fmt_vid_overlay       = saa7134_s_fmt_vid_overlay,
+       .vidioc_g_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
+       .vidioc_try_fmt_vbi_cap         = saa7134_try_get_set_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
+       .vidioc_g_audio                 = saa7134_g_audio,
+       .vidioc_s_audio                 = saa7134_s_audio,
+       .vidioc_cropcap                 = saa7134_cropcap,
+       .vidioc_reqbufs                 = saa7134_reqbufs,
+       .vidioc_querybuf                = saa7134_querybuf,
+       .vidioc_qbuf                    = saa7134_qbuf,
+       .vidioc_dqbuf                   = saa7134_dqbuf,
+       .vidioc_s_std                   = saa7134_s_std,
+       .vidioc_g_std                   = saa7134_g_std,
+       .vidioc_enum_input              = saa7134_enum_input,
+       .vidioc_g_input                 = saa7134_g_input,
+       .vidioc_s_input                 = saa7134_s_input,
+       .vidioc_queryctrl               = saa7134_queryctrl,
+       .vidioc_g_ctrl                  = saa7134_g_ctrl,
+       .vidioc_s_ctrl                  = saa7134_s_ctrl,
+       .vidioc_streamon                = saa7134_streamon,
+       .vidioc_streamoff               = saa7134_streamoff,
+       .vidioc_g_tuner                 = saa7134_g_tuner,
+       .vidioc_s_tuner                 = saa7134_s_tuner,
+       .vidioc_g_crop                  = saa7134_g_crop,
+       .vidioc_s_crop                  = saa7134_s_crop,
+       .vidioc_g_fbuf                  = saa7134_g_fbuf,
+       .vidioc_s_fbuf                  = saa7134_s_fbuf,
+       .vidioc_overlay                 = saa7134_overlay,
+       .vidioc_g_priority              = saa7134_g_priority,
+       .vidioc_s_priority              = saa7134_s_priority,
+       .vidioc_g_parm                  = saa7134_g_parm,
+       .vidioc_g_frequency             = saa7134_g_frequency,
+       .vidioc_s_frequency             = saa7134_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register              = vidioc_g_register,
+       .vidioc_s_register              = vidioc_s_register,
+#endif
+};
+
+static const struct v4l2_file_operations radio_fops = {
+       .owner    = THIS_MODULE,
+       .open     = video_open,
+       .read     = radio_read,
+       .release  = video_release,
+       .ioctl    = video_ioctl2,
+       .poll     = radio_poll,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap        = radio_querycap,
+       .vidioc_g_tuner         = radio_g_tuner,
+       .vidioc_enum_input      = radio_enum_input,
+       .vidioc_g_audio         = radio_g_audio,
+       .vidioc_s_tuner         = radio_s_tuner,
+       .vidioc_s_audio         = radio_s_audio,
+       .vidioc_s_input         = radio_s_input,
+       .vidioc_s_std           = radio_s_std,
+       .vidioc_queryctrl       = radio_queryctrl,
+       .vidioc_g_input         = radio_g_input,
+       .vidioc_g_ctrl          = saa7134_g_ctrl,
+       .vidioc_s_ctrl          = saa7134_s_ctrl,
+       .vidioc_g_frequency     = saa7134_g_frequency,
+       .vidioc_s_frequency     = saa7134_s_frequency,
+};
+
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+struct video_device saa7134_video_template = {
+       .name                           = "saa7134-video",
+       .fops                           = &video_fops,
+       .ioctl_ops                      = &video_ioctl_ops,
+       .tvnorms                        = SAA7134_NORMS,
+       .current_norm                   = V4L2_STD_PAL,
+};
+
+struct video_device saa7134_radio_template = {
+       .name                   = "saa7134-radio",
+       .fops                   = &radio_fops,
+       .ioctl_ops              = &radio_ioctl_ops,
+};
+
+int saa7134_video_init1(struct saa7134_dev *dev)
+{
+       /* sanitycheck insmod options */
+       if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
+               gbuffers = 2;
+       if (gbufsize < 0 || gbufsize > gbufsize_max)
+               gbufsize = gbufsize_max;
+       gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
+
+       /* put some sensible defaults into the data structures ... */
+       dev->ctl_bright     = ctrl_by_id(V4L2_CID_BRIGHTNESS)->default_value;
+       dev->ctl_contrast   = ctrl_by_id(V4L2_CID_CONTRAST)->default_value;
+       dev->ctl_hue        = ctrl_by_id(V4L2_CID_HUE)->default_value;
+       dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
+       dev->ctl_volume     = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
+       dev->ctl_mute       = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
+       dev->ctl_invert     = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
+       dev->ctl_automute   = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
+
+       if (dev->tda9887_conf && dev->ctl_automute)
+               dev->tda9887_conf |= TDA9887_AUTOMUTE;
+       dev->automute       = 0;
+
+       INIT_LIST_HEAD(&dev->video_q.queue);
+       init_timer(&dev->video_q.timeout);
+       dev->video_q.timeout.function = saa7134_buffer_timeout;
+       dev->video_q.timeout.data     = (unsigned long)(&dev->video_q);
+       dev->video_q.dev              = dev;
+
+       if (saa7134_boards[dev->board].video_out)
+               saa7134_videoport_init(dev);
+
+       return 0;
+}
+
+int saa7134_videoport_init(struct saa7134_dev *dev)
+{
+       /* enable video output */
+       int vo = saa7134_boards[dev->board].video_out;
+       int video_reg;
+       unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;
+
+       /* Configure videoport */
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);
+       video_reg = video_out[vo][1];
+       if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)
+               video_reg &= ~VP_T_CODE_P_INVERTED;
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);
+       video_reg = video_out[vo][5];
+       if (vid_port_opts & SET_CLOCK_NOT_DELAYED)
+               video_reg &= ~VP_CLK_CTRL2_DELAYED;
+       if (vid_port_opts & SET_CLOCK_INVERTED)
+               video_reg |= VP_CLK_CTRL1_INVERTED;
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg);
+       video_reg = video_out[vo][6];
+       if (vid_port_opts & SET_VSYNC_OFF) {
+               video_reg &= ~VP_VS_TYPE_MASK;
+               video_reg |= VP_VS_TYPE_OFF;
+       }
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg);
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);
+
+       /* Start videoport */
+       saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
+
+       return 0;
+}
+
+int saa7134_video_init2(struct saa7134_dev *dev)
+{
+       /* init video hw */
+       set_tvnorm(dev,&tvnorms[0]);
+       video_mux(dev,0);
+       saa7134_tvaudio_setmute(dev);
+       saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
+       return 0;
+}
+
+void saa7134_irq_video_signalchange(struct saa7134_dev *dev)
+{
+       static const char *st[] = {
+               "(no signal)", "NTSC", "PAL", "SECAM" };
+       u32 st1,st2;
+
+       st1 = saa_readb(SAA7134_STATUS_VIDEO1);
+       st2 = saa_readb(SAA7134_STATUS_VIDEO2);
+       dprintk("DCSDT: pll: %s, sync: %s, norm: %s\n",
+               (st1 & 0x40) ? "not locked" : "locked",
+               (st2 & 0x40) ? "no"         : "yes",
+               st[st1 & 0x03]);
+       dev->nosignal = (st1 & 0x40) || (st2 & 0x40)  || !(st2 & 0x1);
+
+       if (dev->nosignal) {
+               /* no video signal -> mute audio */
+               if (dev->ctl_automute)
+                       dev->automute = 1;
+               saa7134_tvaudio_setmute(dev);
+       } else {
+               /* wake up tvaudio audio carrier scan thread */
+               saa7134_tvaudio_do_scan(dev);
+       }
+
+       if ((st2 & 0x80) && !noninterlaced && !dev->nosignal)
+               saa_clearb(SAA7134_SYNC_CTRL, 0x20);
+       else
+               saa_setb(SAA7134_SYNC_CTRL, 0x20);
+
+       if (dev->mops && dev->mops->signal_change)
+               dev->mops->signal_change(dev);
+}
+
+
+void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
+{
+       enum v4l2_field field;
+
+       spin_lock(&dev->slock);
+       if (dev->video_q.curr) {
+               dev->video_fieldcount++;
+               field = dev->video_q.curr->vb.field;
+               if (V4L2_FIELD_HAS_BOTH(field)) {
+                       /* make sure we have seen both fields */
+                       if ((status & 0x10) == 0x00) {
+                               dev->video_q.curr->top_seen = 1;
+                               goto done;
+                       }
+                       if (!dev->video_q.curr->top_seen)
+                               goto done;
+               } else if (field == V4L2_FIELD_TOP) {
+                       if ((status & 0x10) != 0x10)
+                               goto done;
+               } else if (field == V4L2_FIELD_BOTTOM) {
+                       if ((status & 0x10) != 0x00)
+                               goto done;
+               }
+               dev->video_q.curr->vb.field_count = dev->video_fieldcount;
+               saa7134_buffer_finish(dev,&dev->video_q,VIDEOBUF_DONE);
+       }
+       saa7134_buffer_next(dev,&dev->video_q);
+
+ done:
+       spin_unlock(&dev->slock);
+}
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
new file mode 100644 (file)
index 0000000..c24b651
--- /dev/null
@@ -0,0 +1,855 @@
+/*
+ *
+ * v4l2 device driver for philips saa7134 based TV cards
+ *
+ * (c) 2001,02 Gerd Knorr <kraxel@bytesex.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.
+ */
+
+#define SAA7134_VERSION "0, 2, 17"
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/kdev_t.h>
+#include <linux/input.h>
+#include <linux/notifier.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/rc-core.h>
+#include <media/ir-kbd-i2c.h>
+#include <media/videobuf-dma-sg.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
+#include <media/videobuf-dvb.h>
+#endif
+
+#define UNSET (-1U)
+
+/* ----------------------------------------------------------- */
+/* enums                                                       */
+
+enum saa7134_tvaudio_mode {
+       TVAUDIO_FM_MONO       = 1,
+       TVAUDIO_FM_BG_STEREO  = 2,
+       TVAUDIO_FM_SAT_STEREO = 3,
+       TVAUDIO_FM_K_STEREO   = 4,
+       TVAUDIO_NICAM_AM      = 5,
+       TVAUDIO_NICAM_FM      = 6,
+};
+
+enum saa7134_audio_in {
+       TV    = 1,
+       LINE1 = 2,
+       LINE2 = 3,
+       LINE2_LEFT,
+};
+
+enum saa7134_video_out {
+       CCIR656 = 1,
+};
+
+/* ----------------------------------------------------------- */
+/* static data                                                 */
+
+struct saa7134_tvnorm {
+       char          *name;
+       v4l2_std_id   id;
+
+       /* video decoder */
+       unsigned int  sync_control;
+       unsigned int  luma_control;
+       unsigned int  chroma_ctrl1;
+       unsigned int  chroma_gain;
+       unsigned int  chroma_ctrl2;
+       unsigned int  vgate_misc;
+
+       /* video scaler */
+       unsigned int  h_start;
+       unsigned int  h_stop;
+       unsigned int  video_v_start;
+       unsigned int  video_v_stop;
+       unsigned int  vbi_v_start_0;
+       unsigned int  vbi_v_stop_0;
+       unsigned int  src_timing;
+       unsigned int  vbi_v_start_1;
+};
+
+struct saa7134_tvaudio {
+       char         *name;
+       v4l2_std_id  std;
+       enum         saa7134_tvaudio_mode mode;
+       int          carr1;
+       int          carr2;
+};
+
+struct saa7134_format {
+       char           *name;
+       unsigned int   fourcc;
+       unsigned int   depth;
+       unsigned int   pm;
+       unsigned int   vshift;   /* vertical downsampling (for planar yuv) */
+       unsigned int   hshift;   /* horizontal downsampling (for planar yuv) */
+       unsigned int   bswap:1;
+       unsigned int   wswap:1;
+       unsigned int   yuv:1;
+       unsigned int   planar:1;
+       unsigned int   uvswap:1;
+};
+
+struct saa7134_card_ir {
+       struct rc_dev           *dev;
+
+       char                    name[32];
+       char                    phys[32];
+       unsigned                users;
+
+       u32                     polling;
+       u32                     last_gpio;
+       u32                     mask_keycode, mask_keydown, mask_keyup;
+
+       bool                    running;
+
+       struct timer_list       timer;
+
+       /* IR core raw decoding */
+       u32                     raw_decode;
+};
+
+/* ----------------------------------------------------------- */
+/* card configuration                                          */
+
+#define SAA7134_BOARD_NOAUTO        UNSET
+#define SAA7134_BOARD_UNKNOWN           0
+#define SAA7134_BOARD_PROTEUS_PRO       1
+#define SAA7134_BOARD_FLYVIDEO3000      2
+#define SAA7134_BOARD_FLYVIDEO2000      3
+#define SAA7134_BOARD_EMPRESS           4
+#define SAA7134_BOARD_MONSTERTV         5
+#define SAA7134_BOARD_MD9717            6
+#define SAA7134_BOARD_TVSTATION_RDS     7
+#define SAA7134_BOARD_CINERGY400       8
+#define SAA7134_BOARD_MD5044           9
+#define SAA7134_BOARD_KWORLD           10
+#define SAA7134_BOARD_CINERGY600       11
+#define SAA7134_BOARD_MD7134           12
+#define SAA7134_BOARD_TYPHOON_90031    13
+#define SAA7134_BOARD_ELSA             14
+#define SAA7134_BOARD_ELSA_500TV       15
+#define SAA7134_BOARD_ASUSTeK_TVFM7134 16
+#define SAA7134_BOARD_VA1000POWER      17
+#define SAA7134_BOARD_BMK_MPEX_NOTUNER 18
+#define SAA7134_BOARD_VIDEOMATE_TV     19
+#define SAA7134_BOARD_CRONOS_PLUS      20
+#define SAA7134_BOARD_10MOONSTVMASTER  21
+#define SAA7134_BOARD_MD2819           22
+#define SAA7134_BOARD_BMK_MPEX_TUNER   23
+#define SAA7134_BOARD_TVSTATION_DVR    24
+#define SAA7134_BOARD_ASUSTEK_TVFM7133 25
+#define SAA7134_BOARD_PINNACLE_PCTV_STEREO 26
+#define SAA7134_BOARD_MANLI_MTV002     27
+#define SAA7134_BOARD_MANLI_MTV001     28
+#define SAA7134_BOARD_TG3000TV         29
+#define SAA7134_BOARD_ECS_TVP3XP       30
+#define SAA7134_BOARD_ECS_TVP3XP_4CB5  31
+#define SAA7134_BOARD_AVACSSMARTTV     32
+#define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33
+#define SAA7134_BOARD_NOVAC_PRIMETV7133 34
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_305 35
+#define SAA7134_BOARD_UPMOST_PURPLE_TV 36
+#define SAA7134_BOARD_ITEMS_MTV005     37
+#define SAA7134_BOARD_CINERGY200       38
+#define SAA7134_BOARD_FLYTVPLATINUM_MINI 39
+#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40
+#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS 41
+#define SAA7134_BOARD_SABRENT_SBTTVFM  42
+#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43
+#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_307    45
+#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
+#define SAA7134_BOARD_CINERGY400_CARDBUS 47
+#define SAA7134_BOARD_CINERGY600_MK3   48
+#define SAA7134_BOARD_VIDEOMATE_GOLD_PLUS 49
+#define SAA7134_BOARD_PINNACLE_300I_DVBT_PAL 50
+#define SAA7134_BOARD_PROVIDEO_PV952   51
+#define SAA7134_BOARD_AVERMEDIA_305    52
+#define SAA7134_BOARD_ASUSTeK_TVFM7135 53
+#define SAA7134_BOARD_FLYTVPLATINUM_FM 54
+#define SAA7134_BOARD_FLYDVBTDUO 55
+#define SAA7134_BOARD_AVERMEDIA_307    56
+#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
+#define SAA7134_BOARD_ADS_INSTANT_TV 58
+#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
+#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
+#define SAA7134_BOARD_PHILIPS_TOUGH 61
+#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
+#define SAA7134_BOARD_KWORLD_XPERT 63
+#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
+#define SAA7134_BOARD_KWORLD_TERMINATOR 65
+#define SAA7134_BOARD_YUAN_TUN900 66
+#define SAA7134_BOARD_BEHOLD_409FM 67
+#define SAA7134_BOARD_GOTVIEW_7135 68
+#define SAA7134_BOARD_PHILIPS_EUROPA  69
+#define SAA7134_BOARD_VIDEOMATE_DVBT_300 70
+#define SAA7134_BOARD_VIDEOMATE_DVBT_200 71
+#define SAA7134_BOARD_RTD_VFG7350 72
+#define SAA7134_BOARD_RTD_VFG7330 73
+#define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74
+#define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75
+#define SAA7134_BOARD_MONSTERTV_MOBILE 76
+#define SAA7134_BOARD_PINNACLE_PCTV_110i 77
+#define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78
+#define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS     79
+#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
+#define SAA7134_BOARD_PHILIPS_TIGER  81
+#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS  82
+#define SAA7134_BOARD_CINERGY250PCI 83
+#define SAA7134_BOARD_FLYDVB_TRIO 84
+#define SAA7134_BOARD_AVERMEDIA_777 85
+#define SAA7134_BOARD_FLYDVBT_LR301 86
+#define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87
+#define SAA7134_BOARD_TEVION_DVBT_220RF 88
+#define SAA7134_BOARD_ELSA_700TV       89
+#define SAA7134_BOARD_KWORLD_ATSC110   90
+#define SAA7134_BOARD_AVERMEDIA_A169_B 91
+#define SAA7134_BOARD_AVERMEDIA_A169_B1 92
+#define SAA7134_BOARD_MD7134_BRIDGE_2     93
+#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
+#define SAA7134_BOARD_FLYVIDEO3000_NTSC 95
+#define SAA7134_BOARD_MEDION_MD8800_QUADRO 96
+#define SAA7134_BOARD_FLYDVBS_LR300 97
+#define SAA7134_BOARD_PROTEUS_2309 98
+#define SAA7134_BOARD_AVERMEDIA_A16AR   99
+#define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100
+#define SAA7134_BOARD_PINNACLE_PCTV_310i  101
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102
+#define SAA7134_BOARD_VIDEOMATE_DVBT_200A  103
+#define SAA7134_BOARD_HAUPPAUGE_HVR1110    104
+#define SAA7134_BOARD_CINERGY_HT_PCMCIA    105
+#define SAA7134_BOARD_ENCORE_ENLTV         106
+#define SAA7134_BOARD_ENCORE_ENLTV_FM      107
+#define SAA7134_BOARD_CINERGY_HT_PCI       108
+#define SAA7134_BOARD_PHILIPS_TIGER_S      109
+#define SAA7134_BOARD_AVERMEDIA_M102      110
+#define SAA7134_BOARD_ASUS_P7131_4871     111
+#define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112
+#define SAA7134_BOARD_ECS_TVP3XP_4CB6  113
+#define SAA7134_BOARD_KWORLD_DVBT_210 114
+#define SAA7134_BOARD_SABRENT_TV_PCB05     115
+#define SAA7134_BOARD_10MOONSTVMASTER3     116
+#define SAA7134_BOARD_AVERMEDIA_SUPER_007  117
+#define SAA7134_BOARD_BEHOLD_401       118
+#define SAA7134_BOARD_BEHOLD_403       119
+#define SAA7134_BOARD_BEHOLD_403FM     120
+#define SAA7134_BOARD_BEHOLD_405       121
+#define SAA7134_BOARD_BEHOLD_405FM     122
+#define SAA7134_BOARD_BEHOLD_407       123
+#define SAA7134_BOARD_BEHOLD_407FM     124
+#define SAA7134_BOARD_BEHOLD_409       125
+#define SAA7134_BOARD_BEHOLD_505FM     126
+#define SAA7134_BOARD_BEHOLD_507_9FM   127
+#define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128
+#define SAA7134_BOARD_BEHOLD_607FM_MK3 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_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_BOARD_BEHOLD_H6      142
+#define SAA7134_BOARD_BEHOLD_M63      143
+#define SAA7134_BOARD_BEHOLD_M6_EXTRA    144
+#define SAA7134_BOARD_AVERMEDIA_M103    145
+#define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146
+#define SAA7134_BOARD_ASUSTeK_TIGER_3IN1   147
+#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148
+#define SAA7134_BOARD_AVERMEDIA_M135A    149
+#define SAA7134_BOARD_REAL_ANGEL_220     150
+#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI  151
+#define SAA7134_BOARD_ASUSTeK_TIGER         152
+#define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
+#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
+#define SAA7134_BOARD_HAUPPAUGE_HVR1150     155
+#define SAA7134_BOARD_HAUPPAUGE_HVR1120   156
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157
+#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158
+#define SAA7134_BOARD_BEHOLD_505RDS_MK5     159
+#define SAA7134_BOARD_BEHOLD_507RDS_MK3     160
+#define SAA7134_BOARD_BEHOLD_507RDS_MK5     161
+#define SAA7134_BOARD_BEHOLD_607FM_MK5      162
+#define SAA7134_BOARD_BEHOLD_609FM_MK3      163
+#define SAA7134_BOARD_BEHOLD_609FM_MK5      164
+#define SAA7134_BOARD_BEHOLD_607RDS_MK3     165
+#define SAA7134_BOARD_BEHOLD_607RDS_MK5     166
+#define SAA7134_BOARD_BEHOLD_609RDS_MK3     167
+#define SAA7134_BOARD_BEHOLD_609RDS_MK5     168
+#define SAA7134_BOARD_VIDEOMATE_S350        169
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_505  170
+#define SAA7134_BOARD_BEHOLD_X7             171
+#define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172
+#define SAA7134_BOARD_ZOLID_HYBRID_PCI         173
+#define SAA7134_BOARD_ASUS_EUROPA_HYBRID       174
+#define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175
+#define SAA7134_BOARD_BEHOLD_505RDS_MK3     176
+#define SAA7134_BOARD_HAWELL_HW_404M7          177
+#define SAA7134_BOARD_BEHOLD_H7             178
+#define SAA7134_BOARD_BEHOLD_A7             179
+#define SAA7134_BOARD_AVERMEDIA_M733A       180
+#define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181
+#define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182
+#define SAA7134_BOARD_VIDEOMATE_M1F         183
+#define SAA7134_BOARD_ENCORE_ENLTV_FM3      184
+#define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185
+#define SAA7134_BOARD_BEHOLD_501            186
+#define SAA7134_BOARD_BEHOLD_503FM          187
+#define SAA7134_BOARD_SENSORAY811_911       188
+#define SAA7134_BOARD_KWORLD_PC150U         189
+#define SAA7134_BOARD_ASUSTeK_PS3_100      190
+
+#define SAA7134_MAXBOARDS 32
+#define SAA7134_INPUT_MAX 8
+
+/* ----------------------------------------------------------- */
+/* Since we support 2 remote types, lets tell them apart       */
+
+#define SAA7134_REMOTE_GPIO  1
+#define SAA7134_REMOTE_I2C   2
+
+/* ----------------------------------------------------------- */
+/* Video Output Port Register Initialization Options           */
+
+#define SET_T_CODE_POLARITY_NON_INVERTED       (1 << 0)
+#define SET_CLOCK_NOT_DELAYED                  (1 << 1)
+#define SET_CLOCK_INVERTED                     (1 << 2)
+#define SET_VSYNC_OFF                          (1 << 3)
+
+struct saa7134_input {
+       char                    *name;
+       unsigned int            vmux;
+       enum saa7134_audio_in   amux;
+       unsigned int            gpio;
+       unsigned int            tv:1;
+};
+
+enum saa7134_mpeg_type {
+       SAA7134_MPEG_UNUSED,
+       SAA7134_MPEG_EMPRESS,
+       SAA7134_MPEG_DVB,
+};
+
+enum saa7134_mpeg_ts_type {
+       SAA7134_MPEG_TS_PARALLEL = 0,
+       SAA7134_MPEG_TS_SERIAL,
+};
+
+struct saa7134_board {
+       char                    *name;
+       unsigned int            audio_clock;
+
+       /* input switching */
+       unsigned int            gpiomask;
+       struct saa7134_input    inputs[SAA7134_INPUT_MAX];
+       struct saa7134_input    radio;
+       struct saa7134_input    mute;
+
+       /* i2c chip info */
+       unsigned int            tuner_type;
+       unsigned int            radio_type;
+       unsigned char           tuner_addr;
+       unsigned char           radio_addr;
+       unsigned char           empress_addr;
+       unsigned char           rds_addr;
+
+       unsigned int            tda9887_conf;
+       unsigned int            tuner_config;
+
+       /* peripheral I/O */
+       enum saa7134_video_out  video_out;
+       enum saa7134_mpeg_type  mpeg;
+       enum saa7134_mpeg_ts_type ts_type;
+       unsigned int            vid_port_opts;
+       unsigned int            ts_force_val:1;
+};
+
+#define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
+#define card_is_empress(dev)  (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg)
+#define card_is_dvb(dev)      (SAA7134_MPEG_DVB     == saa7134_boards[dev->board].mpeg)
+#define card_has_mpeg(dev)    (SAA7134_MPEG_UNUSED  != saa7134_boards[dev->board].mpeg)
+#define card(dev)             (saa7134_boards[dev->board])
+#define card_in(dev,n)        (saa7134_boards[dev->board].inputs[n])
+
+/* ----------------------------------------------------------- */
+/* device / file handle status                                 */
+
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO         2
+#define RESOURCE_VBI           4
+
+#define INTERLACE_AUTO         0
+#define INTERLACE_ON           1
+#define INTERLACE_OFF          2
+
+#define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
+#define TS_BUFFER_TIMEOUT  msecs_to_jiffies(1000)  /* 1 second */
+
+struct saa7134_dev;
+struct saa7134_dma;
+
+/* saa7134 page table */
+struct saa7134_pgtable {
+       unsigned int               size;
+       __le32                     *cpu;
+       dma_addr_t                 dma;
+};
+
+/* tvaudio thread status */
+struct saa7134_thread {
+       struct task_struct         *thread;
+       unsigned int               scan1;
+       unsigned int               scan2;
+       unsigned int               mode;
+       unsigned int               stopped;
+};
+
+/* buffer for one video/vbi/ts frame */
+struct saa7134_buf {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       /* saa7134 specific */
+       struct saa7134_format   *fmt;
+       unsigned int            top_seen;
+       int (*activate)(struct saa7134_dev *dev,
+                       struct saa7134_buf *buf,
+                       struct saa7134_buf *next);
+
+       /* page tables */
+       struct saa7134_pgtable  *pt;
+};
+
+struct saa7134_dmaqueue {
+       struct saa7134_dev         *dev;
+       struct saa7134_buf         *curr;
+       struct list_head           queue;
+       struct timer_list          timeout;
+       unsigned int               need_two;
+};
+
+/* video filehandle status */
+struct saa7134_fh {
+       struct saa7134_dev         *dev;
+       unsigned int               radio;
+       enum v4l2_buf_type         type;
+       unsigned int               resources;
+       enum v4l2_priority         prio;
+
+       /* video overlay */
+       struct v4l2_window         win;
+       struct v4l2_clip           clips[8];
+       unsigned int               nclips;
+
+       /* video capture */
+       struct saa7134_format      *fmt;
+       unsigned int               width,height;
+       struct videobuf_queue      cap;
+       struct saa7134_pgtable     pt_cap;
+
+       /* vbi capture */
+       struct videobuf_queue      vbi;
+       struct saa7134_pgtable     pt_vbi;
+};
+
+/* dmasound dsp status */
+struct saa7134_dmasound {
+       struct mutex               lock;
+       int                        minor_mixer;
+       int                        minor_dsp;
+       unsigned int               users_dsp;
+
+       /* mixer */
+       enum saa7134_audio_in      input;
+       unsigned int               count;
+       unsigned int               line1;
+       unsigned int               line2;
+
+       /* dsp */
+       unsigned int               afmt;
+       unsigned int               rate;
+       unsigned int               channels;
+       unsigned int               recording_on;
+       unsigned int               dma_running;
+       unsigned int               blocks;
+       unsigned int               blksize;
+       unsigned int               bufsize;
+       struct saa7134_pgtable     pt;
+       struct videobuf_dmabuf     dma;
+       unsigned int               dma_blk;
+       unsigned int               read_offset;
+       unsigned int               read_count;
+       void *                     priv_data;
+       struct snd_pcm_substream   *substream;
+};
+
+/* ts/mpeg status */
+struct saa7134_ts {
+       /* TS capture */
+       struct saa7134_pgtable     pt_ts;
+       int                        nr_packets;
+       int                        nr_bufs;
+};
+
+/* ts/mpeg ops */
+struct saa7134_mpeg_ops {
+       enum saa7134_mpeg_type     type;
+       struct list_head           next;
+       int                        (*init)(struct saa7134_dev *dev);
+       int                        (*fini)(struct saa7134_dev *dev);
+       void                       (*signal_change)(struct saa7134_dev *dev);
+};
+
+/* global device status */
+struct saa7134_dev {
+       struct list_head           devlist;
+       struct mutex               lock;
+       spinlock_t                 slock;
+       struct v4l2_prio_state     prio;
+       struct v4l2_device         v4l2_dev;
+       /* workstruct for loading modules */
+       struct work_struct request_module_wk;
+
+       /* insmod option/autodetected */
+       int                        autodetected;
+
+       /* various device info */
+       unsigned int               resources;
+       struct video_device        *video_dev;
+       struct video_device        *radio_dev;
+       struct video_device        *vbi_dev;
+       struct saa7134_dmasound    dmasound;
+
+       /* infrared remote */
+       int                        has_remote;
+       struct saa7134_card_ir     *remote;
+
+       /* pci i/o */
+       char                       name[32];
+       int                        nr;
+       struct pci_dev             *pci;
+       unsigned char              pci_rev,pci_lat;
+       __u32                      __iomem *lmmio;
+       __u8                       __iomem *bmmio;
+
+       /* config info */
+       unsigned int               board;
+       unsigned int               tuner_type;
+       unsigned int               radio_type;
+       unsigned char              tuner_addr;
+       unsigned char              radio_addr;
+
+       unsigned int               tda9887_conf;
+       unsigned int               gpio_value;
+
+       /* i2c i/o */
+       struct i2c_adapter         i2c_adap;
+       struct i2c_client          i2c_client;
+       unsigned char              eedata[256];
+       int                        has_rds;
+
+       /* video overlay */
+       struct v4l2_framebuffer    ovbuf;
+       struct saa7134_format      *ovfmt;
+       unsigned int               ovenable;
+       enum v4l2_field            ovfield;
+
+       /* video+ts+vbi capture */
+       struct saa7134_dmaqueue    video_q;
+       struct saa7134_dmaqueue    vbi_q;
+       unsigned int               video_fieldcount;
+       unsigned int               vbi_fieldcount;
+
+       /* various v4l controls */
+       struct saa7134_tvnorm      *tvnorm;              /* video */
+       struct saa7134_tvaudio     *tvaudio;
+       unsigned int               ctl_input;
+       int                        ctl_bright;
+       int                        ctl_contrast;
+       int                        ctl_hue;
+       int                        ctl_saturation;
+       int                        ctl_freq;
+       int                        ctl_mute;             /* audio */
+       int                        ctl_volume;
+       int                        ctl_invert;           /* private */
+       int                        ctl_mirror;
+       int                        ctl_y_odd;
+       int                        ctl_y_even;
+       int                        ctl_automute;
+
+       /* crop */
+       struct v4l2_rect           crop_bounds;
+       struct v4l2_rect           crop_defrect;
+       struct v4l2_rect           crop_current;
+
+       /* other global state info */
+       unsigned int               automute;
+       struct saa7134_thread      thread;
+       struct saa7134_input       *input;
+       struct saa7134_input       *hw_input;
+       unsigned int               hw_mute;
+       int                        last_carrier;
+       int                        nosignal;
+       unsigned int               insuspend;
+
+       /* I2C keyboard data */
+       struct IR_i2c_init_data    init_data;
+
+       /* SAA7134_MPEG_* */
+       struct saa7134_ts          ts;
+       struct saa7134_dmaqueue    ts_q;
+       int                        ts_started;
+       struct saa7134_mpeg_ops    *mops;
+
+       /* SAA7134_MPEG_EMPRESS only */
+       struct video_device        *empress_dev;
+       struct videobuf_queue      empress_tsq;
+       atomic_t                   empress_users;
+       struct work_struct         empress_workqueue;
+       int                        empress_started;
+
+#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
+       /* SAA7134_MPEG_DVB only */
+       struct videobuf_dvb_frontends frontends;
+       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
+       void (*gate_ctrl)(struct saa7134_dev *dev, int open);
+};
+
+/* ----------------------------------------------------------- */
+
+#define saa_readl(reg)             readl(dev->lmmio + (reg))
+#define saa_writel(reg,value)      writel((value), dev->lmmio + (reg));
+#define saa_andorl(reg,mask,value) \
+  writel((readl(dev->lmmio+(reg)) & ~(mask)) |\
+  ((value) & (mask)), dev->lmmio+(reg))
+#define saa_setl(reg,bit)          saa_andorl((reg),(bit),(bit))
+#define saa_clearl(reg,bit)        saa_andorl((reg),(bit),0)
+
+#define saa_readb(reg)             readb(dev->bmmio + (reg))
+#define saa_writeb(reg,value)      writeb((value), dev->bmmio + (reg));
+#define saa_andorb(reg,mask,value) \
+  writeb((readb(dev->bmmio+(reg)) & ~(mask)) |\
+  ((value) & (mask)), dev->bmmio+(reg))
+#define saa_setb(reg,bit)          saa_andorb((reg),(bit),(bit))
+#define saa_clearb(reg,bit)        saa_andorb((reg),(bit),0)
+
+#define saa_wait(us) { udelay(us); }
+
+#define SAA7134_NORMS  (\
+               V4L2_STD_PAL    | V4L2_STD_PAL_N | \
+               V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
+               V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
+               V4L2_STD_PAL_60)
+
+#define GRP_EMPRESS (1)
+#define saa_call_all(dev, o, f, args...) do {                          \
+       if (dev->gate_ctrl)                                             \
+               dev->gate_ctrl(dev, 1);                                 \
+       v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args);       \
+       if (dev->gate_ctrl)                                             \
+               dev->gate_ctrl(dev, 0);                                 \
+} while (0)
+
+#define saa_call_empress(dev, o, f, args...) ({                                \
+       long _rc;                                                       \
+       if (dev->gate_ctrl)                                             \
+               dev->gate_ctrl(dev, 1);                                 \
+       _rc = v4l2_device_call_until_err(&(dev)->v4l2_dev,              \
+                                        GRP_EMPRESS, o, f , ##args);   \
+       if (dev->gate_ctrl)                                             \
+               dev->gate_ctrl(dev, 0);                                 \
+       _rc;                                                            \
+})
+
+/* ----------------------------------------------------------- */
+/* saa7134-core.c                                              */
+
+extern struct list_head  saa7134_devlist;
+extern struct mutex saa7134_devlist_lock;
+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);
+
+#define SAA7134_PGTABLE_SIZE 4096
+
+int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt);
+int  saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
+                          struct scatterlist *list, unsigned int length,
+                          unsigned int startpage);
+void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt);
+
+int saa7134_buffer_count(unsigned int size, unsigned int count);
+int saa7134_buffer_startpage(struct saa7134_buf *buf);
+unsigned long saa7134_buffer_base(struct saa7134_buf *buf);
+
+int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
+                        struct saa7134_buf *buf);
+void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
+                          unsigned int state);
+void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
+void saa7134_buffer_timeout(unsigned long data);
+void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
+
+int saa7134_set_dmabits(struct saa7134_dev *dev);
+
+extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
+
+
+/* ----------------------------------------------------------- */
+/* saa7134-cards.c                                             */
+
+extern struct saa7134_board saa7134_boards[];
+extern const unsigned int saa7134_bcount;
+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 component, int command, int arg);
+
+
+/* ----------------------------------------------------------- */
+/* saa7134-i2c.c                                               */
+
+int saa7134_i2c_register(struct saa7134_dev *dev);
+int saa7134_i2c_unregister(struct saa7134_dev *dev);
+
+
+/* ----------------------------------------------------------- */
+/* saa7134-video.c                                             */
+
+extern unsigned int video_debug;
+extern struct video_device saa7134_video_template;
+extern struct video_device saa7134_radio_template;
+
+int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
+int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
+int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
+int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id *id);
+
+int saa7134_videoport_init(struct saa7134_dev *dev);
+void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
+
+int saa7134_video_init1(struct saa7134_dev *dev);
+int saa7134_video_init2(struct saa7134_dev *dev);
+void saa7134_irq_video_signalchange(struct saa7134_dev *dev);
+void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
+
+
+/* ----------------------------------------------------------- */
+/* saa7134-ts.c                                                */
+
+#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
+
+extern struct videobuf_queue_ops saa7134_ts_qops;
+
+int saa7134_ts_init1(struct saa7134_dev *dev);
+int saa7134_ts_fini(struct saa7134_dev *dev);
+void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status);
+
+int saa7134_ts_register(struct saa7134_mpeg_ops *ops);
+void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops);
+
+int saa7134_ts_init_hw(struct saa7134_dev *dev);
+
+int saa7134_ts_start(struct saa7134_dev *dev);
+int saa7134_ts_stop(struct saa7134_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* saa7134-vbi.c                                               */
+
+extern struct videobuf_queue_ops saa7134_vbi_qops;
+extern struct video_device saa7134_vbi_template;
+
+int saa7134_vbi_init1(struct saa7134_dev *dev);
+int saa7134_vbi_fini(struct saa7134_dev *dev);
+void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status);
+
+
+/* ----------------------------------------------------------- */
+/* saa7134-tvaudio.c                                           */
+
+int saa7134_tvaudio_rx2mode(u32 rx);
+
+void saa7134_tvaudio_setmute(struct saa7134_dev *dev);
+void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
+                             struct saa7134_input *in);
+void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level);
+int saa7134_tvaudio_getstereo(struct saa7134_dev *dev);
+
+void saa7134_tvaudio_init(struct saa7134_dev *dev);
+int saa7134_tvaudio_init2(struct saa7134_dev *dev);
+int saa7134_tvaudio_fini(struct saa7134_dev *dev);
+int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
+int saa7134_tvaudio_close(struct saa7134_dev *dev);
+
+int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
+
+void saa7134_enable_i2s(struct saa7134_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* saa7134-oss.c                                               */
+
+extern const struct file_operations saa7134_dsp_fops;
+extern const struct file_operations saa7134_mixer_fops;
+
+int saa7134_oss_init1(struct saa7134_dev *dev);
+int saa7134_oss_fini(struct saa7134_dev *dev);
+void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status);
+
+/* ----------------------------------------------------------- */
+/* saa7134-input.c                                             */
+
+#if defined(CONFIG_VIDEO_SAA7134_RC)
+int  saa7134_input_init1(struct saa7134_dev *dev);
+void saa7134_input_fini(struct saa7134_dev *dev);
+void saa7134_input_irq(struct saa7134_dev *dev);
+void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
+int saa7134_ir_start(struct saa7134_dev *dev);
+void saa7134_ir_stop(struct saa7134_dev *dev);
+#else
+#define saa7134_input_init1(dev)       ((void)0)
+#define saa7134_input_fini(dev)                ((void)0)
+#define saa7134_input_irq(dev)         ((void)0)
+#define saa7134_probe_i2c_ir(dev)      ((void)0)
+#define saa7134_ir_start(dev)          ((void)0)
+#define saa7134_ir_stop(dev)           ((void)0)
+#endif
diff --git a/drivers/media/pci/saa7164/Kconfig b/drivers/media/pci/saa7164/Kconfig
new file mode 100644 (file)
index 0000000..3532637
--- /dev/null
@@ -0,0 +1,18 @@
+config VIDEO_SAA7164
+       tristate "NXP SAA7164 support"
+       depends on DVB_CORE && PCI && I2C
+       select I2C_ALGOBIT
+       select FW_LOADER
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEOBUF_DVB
+       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       ---help---
+         This is a video4linux driver for NXP SAA7164 based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7164
+
diff --git a/drivers/media/pci/saa7164/Makefile b/drivers/media/pci/saa7164/Makefile
new file mode 100644 (file)
index 0000000..847110c
--- /dev/null
@@ -0,0 +1,12 @@
+saa7164-objs   := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \
+                       saa7164-fw.o saa7164-bus.o saa7164-cmd.o saa7164-api.o \
+                       saa7164-buffer.o saa7164-encoder.o saa7164-vbi.o
+
+obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
+
+ccflags-y += -I$(srctree)/drivers/media/video
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
+
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/pci/saa7164/saa7164-api.c b/drivers/media/pci/saa7164/saa7164-api.c
new file mode 100644 (file)
index 0000000..eff7135
--- /dev/null
@@ -0,0 +1,1524 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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/wait.h>
+#include <linux/slab.h>
+
+#include "saa7164.h"
+
+int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i)
+{
+       int ret;
+
+       if (!(saa_debug & DBGLVL_CPU))
+               return 0;
+
+       dprintk(DBGLVL_API, "%s()\n", __func__);
+
+       i->deviceinst = 0;
+       i->devicespec = 0;
+       i->mode = 0;
+       i->status = 0;
+
+       ret = saa7164_cmd_send(dev, 0, GET_CUR,
+               GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad);
+
+       return ret;
+}
+
+int saa7164_api_collect_debug(struct saa7164_dev *dev)
+{
+       struct tmComResDebugGetData d;
+       u8 more = 255;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s()\n", __func__);
+
+       while (more--) {
+
+               memset(&d, 0, sizeof(d));
+
+               ret = saa7164_cmd_send(dev, 0, GET_CUR,
+                       GET_DEBUG_DATA_CONTROL, sizeof(d), &d);
+               if (ret != SAA_OK)
+                       printk(KERN_ERR "%s() error, ret = 0x%x\n",
+                               __func__, ret);
+
+               if (d.dwResult != SAA_OK)
+                       break;
+
+               printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr,
+                       d.ucDebugData);
+       }
+
+       return 0;
+}
+
+int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level)
+{
+       struct tmComResDebugSetLevel lvl;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s(level=%d)\n", __func__, level);
+
+       /* Retrieve current state */
+       ret = saa7164_cmd_send(dev, 0, GET_CUR,
+               SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel);
+
+       lvl.dwDebugLevel = level;
+
+       /* set new state */
+       ret = saa7164_cmd_send(dev, 0, SET_CUR,
+               SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_set_vbi_format(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResProbeCommit fmt, rsp;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s(nr=%d, unitid=0x%x)\n", __func__,
+               port->nr, port->hwcfg.unitid);
+
+       fmt.bmHint = 0;
+       fmt.bFormatIndex = 1;
+       fmt.bFrameIndex = 1;
+
+       /* Probe, see if it can support this format */
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
+               SET_CUR, SAA_PROBE_CONTROL, sizeof(fmt), &fmt);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() set error, ret = 0x%x\n", __func__, ret);
+
+       /* See of the format change was successful */
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
+               GET_CUR, SAA_PROBE_CONTROL, sizeof(rsp), &rsp);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() get error, ret = 0x%x\n", __func__, ret);
+       } else {
+               /* Compare requested vs received, should be same */
+               if (memcmp(&fmt, &rsp, sizeof(rsp)) == 0) {
+                       dprintk(DBGLVL_API, "SET/PROBE Verified\n");
+
+                       /* Ask the device to select the negotiated format */
+                       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
+                               SET_CUR, SAA_COMMIT_CONTROL, sizeof(fmt), &fmt);
+                       if (ret != SAA_OK)
+                               printk(KERN_ERR "%s() commit error, ret = 0x%x\n",
+                                       __func__, ret);
+
+                       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
+                               GET_CUR, SAA_COMMIT_CONTROL, sizeof(rsp), &rsp);
+                       if (ret != SAA_OK)
+                               printk(KERN_ERR "%s() GET commit error, ret = 0x%x\n",
+                                       __func__, ret);
+
+                       if (memcmp(&fmt, &rsp, sizeof(rsp)) != 0) {
+                               printk(KERN_ERR "%s() memcmp error, ret = 0x%x\n",
+                                       __func__, ret);
+                       } else
+                               dprintk(DBGLVL_API, "SET/COMMIT Verified\n");
+
+                       dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint);
+                       dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n",
+                               rsp.bFormatIndex);
+                       dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n",
+                               rsp.bFrameIndex);
+               } else
+                       printk(KERN_ERR "%s() compare failed\n", __func__);
+       }
+
+       if (ret == SAA_OK)
+               dprintk(DBGLVL_API, "%s(nr=%d) Success\n", __func__, port->nr);
+
+       return ret;
+}
+
+int saa7164_api_set_gop_size(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResEncVideoGopStructure gs;
+       int ret;
+
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       gs.ucRefFrameDist = port->encoder_params.refdist;
+       gs.ucGOPSize = port->encoder_params.gop_size;
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
+               EU_VIDEO_GOP_STRUCTURE_CONTROL,
+               sizeof(gs), &gs);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_set_encoder(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResEncVideoBitRate vb;
+       struct tmComResEncAudioBitRate ab;
+       int ret;
+
+       dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
+               port->hwcfg.sourceid);
+
+       if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
+               port->encoder_profile = EU_PROFILE_PS_DVD;
+       else
+               port->encoder_profile = EU_PROFILE_TS_HQ;
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
+               EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Resolution */
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
+               EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Establish video bitrates */
+       if (port->encoder_params.bitrate_mode ==
+               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+               vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT;
+       else
+               vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK;
+       vb.dwVideoBitRate = port->encoder_params.bitrate;
+       vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak;
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
+               EU_VIDEO_BIT_RATE_CONTROL,
+               sizeof(struct tmComResEncVideoBitRate),
+               &vb);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Establish audio bitrates */
+       ab.ucAudioBitRateMode = 0;
+       ab.dwAudioBitRate = 384000;
+       ab.dwAudioBitRatePeak = ab.dwAudioBitRate;
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
+               EU_AUDIO_BIT_RATE_CONTROL,
+               sizeof(struct tmComResEncAudioBitRate),
+               &ab);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
+                       ret);
+
+       saa7164_api_set_aspect_ratio(port);
+       saa7164_api_set_gop_size(port);
+
+       return ret;
+}
+
+int saa7164_api_get_encoder(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResEncVideoBitRate v;
+       struct tmComResEncAudioBitRate a;
+       struct tmComResEncVideoInputAspectRatio ar;
+       int ret;
+
+       dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
+               port->hwcfg.sourceid);
+
+       port->encoder_profile = 0;
+       port->video_format = 0;
+       port->video_resolution = 0;
+       port->audio_format = 0;
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8),
+               &port->video_resolution);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_VIDEO_FORMAT_CONTROL, sizeof(u8), &port->video_format);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_VIDEO_BIT_RATE_CONTROL, sizeof(v), &v);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_AUDIO_FORMAT_CONTROL, sizeof(u8), &port->audio_format);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_AUDIO_BIT_RATE_CONTROL, sizeof(a), &a);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Aspect Ratio */
+       ar.width = 0;
+       ar.height = 0;
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
+               EU_VIDEO_INPUT_ASPECT_CONTROL,
+               sizeof(struct tmComResEncVideoInputAspectRatio), &ar);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       dprintk(DBGLVL_ENC, "encoder_profile = %d\n", port->encoder_profile);
+       dprintk(DBGLVL_ENC, "video_format    = %d\n", port->video_format);
+       dprintk(DBGLVL_ENC, "audio_format    = %d\n", port->audio_format);
+       dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution);
+       dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n",
+               v.ucVideoBitRateMode);
+       dprintk(DBGLVL_ENC, "v.dwVideoBitRate     = %d\n",
+               v.dwVideoBitRate);
+       dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n",
+               v.dwVideoBitRatePeak);
+       dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n",
+               a.ucAudioBitRateMode);
+       dprintk(DBGLVL_ENC, "a.dwVideoBitRate     = %d\n",
+               a.dwAudioBitRate);
+       dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n",
+               a.dwAudioBitRatePeak);
+       dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n",
+               ar.width, ar.height);
+
+       return ret;
+}
+
+int saa7164_api_set_aspect_ratio(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResEncVideoInputAspectRatio ar;
+       int ret;
+
+       dprintk(DBGLVL_ENC, "%s(%d)\n", __func__,
+               port->encoder_params.ctl_aspect);
+
+       switch (port->encoder_params.ctl_aspect) {
+       case V4L2_MPEG_VIDEO_ASPECT_1x1:
+               ar.width = 1;
+               ar.height = 1;
+               break;
+       case V4L2_MPEG_VIDEO_ASPECT_4x3:
+               ar.width = 4;
+               ar.height = 3;
+               break;
+       case V4L2_MPEG_VIDEO_ASPECT_16x9:
+               ar.width = 16;
+               ar.height = 9;
+               break;
+       case V4L2_MPEG_VIDEO_ASPECT_221x100:
+               ar.width = 221;
+               ar.height = 100;
+               break;
+       default:
+               BUG();
+       }
+
+       dprintk(DBGLVL_ENC, "%s(%d) now %d:%d\n", __func__,
+               port->encoder_params.ctl_aspect,
+               ar.width, ar.height);
+
+       /* Aspect Ratio */
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
+               EU_VIDEO_INPUT_ASPECT_CONTROL,
+               sizeof(struct tmComResEncVideoInputAspectRatio), &ar);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+       u16 val;
+
+       if (ctl == PU_BRIGHTNESS_CONTROL)
+               val = port->ctl_brightness;
+       else
+       if (ctl == PU_CONTRAST_CONTROL)
+               val = port->ctl_contrast;
+       else
+       if (ctl == PU_HUE_CONTROL)
+               val = port->ctl_hue;
+       else
+       if (ctl == PU_SATURATION_CONTROL)
+               val = port->ctl_saturation;
+       else
+       if (ctl == PU_SHARPNESS_CONTROL)
+               val = port->ctl_sharpness;
+       else
+               return -EINVAL;
+
+       dprintk(DBGLVL_ENC, "%s() unitid=0x%x ctl=%d, val=%d\n",
+               __func__, port->encunit.vsourceid, ctl, val);
+
+       ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, SET_CUR,
+               ctl, sizeof(u16), &val);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+       u16 val;
+
+       ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, GET_CUR,
+               ctl, sizeof(u16), &val);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+               return ret;
+       }
+
+       dprintk(DBGLVL_ENC, "%s() ctl=%d, val=%d\n",
+               __func__, ctl, val);
+
+       if (ctl == PU_BRIGHTNESS_CONTROL)
+               port->ctl_brightness = val;
+       else
+       if (ctl == PU_CONTRAST_CONTROL)
+               port->ctl_contrast = val;
+       else
+       if (ctl == PU_HUE_CONTROL)
+               port->ctl_hue = val;
+       else
+       if (ctl == PU_SATURATION_CONTROL)
+               port->ctl_saturation = val;
+       else
+       if (ctl == PU_SHARPNESS_CONTROL)
+               port->ctl_sharpness = val;
+
+       return ret;
+}
+
+int saa7164_api_set_videomux(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       u8 inputs[] = { 1, 2, 2, 2, 5, 5, 5 };
+       int ret;
+
+       dprintk(DBGLVL_ENC, "%s() v_mux=%d a_mux=%d\n",
+               __func__, port->mux_input, inputs[port->mux_input - 1]);
+
+       /* Audio Mute */
+       ret = saa7164_api_audio_mute(port, 1);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Video Mux */
+       ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, SET_CUR,
+               SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Audio Mux */
+       ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR,
+               SU_INPUT_SELECT_CONTROL, sizeof(u8),
+               &inputs[port->mux_input - 1]);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Audio UnMute */
+       ret = saa7164_api_audio_mute(port, 0);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_audio_mute(struct saa7164_port *port, int mute)
+{
+       struct saa7164_dev *dev = port->dev;
+       u8 v = mute;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s(%d)\n", __func__, mute);
+
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
+               MUTE_CONTROL, sizeof(u8), &v);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+/* 0 = silence, 0xff = full */
+int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level)
+{
+       struct saa7164_dev *dev = port->dev;
+       s16 v, min, max;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s(%d)\n", __func__, level);
+
+       /* Obtain the min/max ranges */
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MIN,
+               VOLUME_CONTROL, sizeof(u16), &min);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MAX,
+               VOLUME_CONTROL, sizeof(u16), &max);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
+               (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,
+               level, min, max, v);
+
+       v = level;
+       if (v < min)
+               v = min;
+       if (v > max)
+               v = max;
+
+       /* Left */
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
+               (0x01 << 8) | VOLUME_CONTROL, sizeof(s16), &v);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Right */
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
+               (0x02 << 8) | VOLUME_CONTROL, sizeof(s16), &v);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
+               (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,
+               level, min, max, v);
+
+       return ret;
+}
+
+int saa7164_api_set_audio_std(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResAudioDefaults lvl;
+       struct tmComResTunerStandard tvaudio;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s()\n", __func__);
+
+       /* Establish default levels */
+       lvl.ucDecoderLevel = TMHW_LEV_ADJ_DECLEV_DEFAULT;
+       lvl.ucDecoderFM_Level = TMHW_LEV_ADJ_DECLEV_DEFAULT;
+       lvl.ucMonoLevel = TMHW_LEV_ADJ_MONOLEV_DEFAULT;
+       lvl.ucNICAM_Level = TMHW_LEV_ADJ_NICLEV_DEFAULT;
+       lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT;
+       lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT;
+       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
+               AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults),
+               &lvl);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       /* Manually select the appropriate TV audio standard */
+       if (port->encodernorm.id & V4L2_STD_NTSC) {
+               tvaudio.std = TU_STANDARD_NTSC_M;
+               tvaudio.country = 1;
+       } else {
+               tvaudio.std = TU_STANDARD_PAL_I;
+               tvaudio.country = 44;
+       }
+
+       ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
+               TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n",
+                       __func__, ret);
+       return ret;
+}
+
+int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct tmComResTunerStandardAuto p;
+       int ret;
+
+       dprintk(DBGLVL_API, "%s(%d)\n", __func__, autodetect);
+
+       /* Disable TV Audio autodetect if not already set (buggy) */
+       if (autodetect)
+               p.mode = TU_STANDARD_AUTO;
+       else
+               p.mode = TU_STANDARD_MANUAL;
+       ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
+               TU_STANDARD_AUTO_CONTROL, sizeof(p), &p);
+       if (ret != SAA_OK)
+               printk(KERN_ERR
+                       "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n",
+                       __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_get_videomux(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, GET_CUR,
+               SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       dprintk(DBGLVL_ENC, "%s() v_mux=%d\n",
+               __func__, port->mux_input);
+
+       return ret;
+}
+
+int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       u16 len = 0;
+       u8 buf[256];
+       int ret;
+       u8 mas;
+
+       dprintk(DBGLVL_API, "%s(nr=%d type=%d val=%x)\n", __func__,
+               port->nr, port->type, val);
+
+       if (port->nr == 0)
+               mas = 0xd0;
+       else
+               mas = 0xe0;
+
+       memset(buf, 0, sizeof(buf));
+
+       buf[0x00] = 0x04;
+       buf[0x01] = 0x00;
+       buf[0x02] = 0x00;
+       buf[0x03] = 0x00;
+
+       buf[0x04] = 0x04;
+       buf[0x05] = 0x00;
+       buf[0x06] = 0x00;
+       buf[0x07] = 0x00;
+
+       buf[0x08] = reg;
+       buf[0x09] = 0x26;
+       buf[0x0a] = mas;
+       buf[0x0b] = 0xb0;
+
+       buf[0x0c] = val;
+       buf[0x0d] = 0x00;
+       buf[0x0e] = 0x00;
+       buf[0x0f] = 0x00;
+
+       ret = saa7164_cmd_send(dev, port->ifunit.unitid, GET_LEN,
+               EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
+               return -EIO;
+       }
+
+       ret = saa7164_cmd_send(dev, port->ifunit.unitid, SET_CUR,
+               EXU_REGISTER_ACCESS_CONTROL, len, &buf);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
+#if 0
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, 16,
+                      false);
+#endif
+       return ret == SAA_OK ? 0 : -EIO;
+}
+
+/* Disable the IF block AGC controls */
+int saa7164_api_configure_dif(struct saa7164_port *port, u32 std)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+       u8 agc_disable;
+
+       dprintk(DBGLVL_API, "%s(nr=%d, 0x%x)\n", __func__, port->nr, std);
+
+       if (std & V4L2_STD_NTSC) {
+               dprintk(DBGLVL_API, " NTSC\n");
+               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_PAL_I) {
+               dprintk(DBGLVL_API, " PAL-I\n");
+               saa7164_api_set_dif(port, 0x00, 0x08); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_PAL_M) {
+               dprintk(DBGLVL_API, " PAL-M\n");
+               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_PAL_N) {
+               dprintk(DBGLVL_API, " PAL-N\n");
+               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_PAL_Nc) {
+               dprintk(DBGLVL_API, " PAL-Nc\n");
+               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_PAL_B) {
+               dprintk(DBGLVL_API, " PAL-B\n");
+               saa7164_api_set_dif(port, 0x00, 0x02); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_PAL_DK) {
+               dprintk(DBGLVL_API, " PAL-DK\n");
+               saa7164_api_set_dif(port, 0x00, 0x10); /* Video Standard */
+               agc_disable = 0;
+       } else if (std & V4L2_STD_SECAM_L) {
+               dprintk(DBGLVL_API, " SECAM-L\n");
+               saa7164_api_set_dif(port, 0x00, 0x20); /* Video Standard */
+               agc_disable = 0;
+       } else {
+               /* Unknown standard, assume DTV */
+               dprintk(DBGLVL_API, " Unknown (assuming DTV)\n");
+               /* Undefinded Video Standard */
+               saa7164_api_set_dif(port, 0x00, 0x80);
+               agc_disable = 1;
+       }
+
+       saa7164_api_set_dif(port, 0x48, 0xa0); /* AGC Functions 1 */
+       saa7164_api_set_dif(port, 0xc0, agc_disable); /* AGC Output Disable */
+       saa7164_api_set_dif(port, 0x7c, 0x04); /* CVBS EQ */
+       saa7164_api_set_dif(port, 0x04, 0x01); /* Active */
+       msleep(100);
+       saa7164_api_set_dif(port, 0x04, 0x00); /* Active (again) */
+       msleep(100);
+
+       return ret;
+}
+
+/* Ensure the dif is in the correct state for the operating mode
+ * (analog / dtv). We only configure the diff through the analog encoder
+ * so when we're in digital mode we need to find the appropriate encoder
+ * and use it to configure the DIF.
+ */
+int saa7164_api_initialize_dif(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_port *p = NULL;
+       int ret = -EINVAL;
+       u32 std = 0;
+
+       dprintk(DBGLVL_API, "%s(nr=%d type=%d)\n", __func__,
+               port->nr, port->type);
+
+       if (port->type == SAA7164_MPEG_ENCODER) {
+               /* Pick any analog standard to init the diff.
+                * we'll come back during encoder_init'
+                * and set the correct standard if requried.
+                */
+               std = V4L2_STD_NTSC;
+       } else
+       if (port->type == SAA7164_MPEG_DVB) {
+               if (port->nr == SAA7164_PORT_TS1)
+                       p = &dev->ports[SAA7164_PORT_ENC1];
+               else
+                       p = &dev->ports[SAA7164_PORT_ENC2];
+       } else
+       if (port->type == SAA7164_MPEG_VBI) {
+               std = V4L2_STD_NTSC;
+               if (port->nr == SAA7164_PORT_VBI1)
+                       p = &dev->ports[SAA7164_PORT_ENC1];
+               else
+                       p = &dev->ports[SAA7164_PORT_ENC2];
+       } else
+               BUG();
+
+       if (p)
+               ret = saa7164_api_configure_dif(p, std);
+
+       return ret;
+}
+
+int saa7164_api_transition_port(struct saa7164_port *port, u8 mode)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       int ret;
+
+       dprintk(DBGLVL_API, "%s(nr=%d unitid=0x%x,%d)\n",
+               __func__, port->nr, port->hwcfg.unitid, mode);
+
+       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR,
+               SAA_STATE_CONTROL, sizeof(mode), &mode);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s(portnr %d unitid 0x%x) error, ret = 0x%x\n",
+                       __func__, port->nr, port->hwcfg.unitid, ret);
+
+       return ret;
+}
+
+int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version)
+{
+       int ret;
+
+       ret = saa7164_cmd_send(dev, 0, GET_CUR,
+               GET_FW_VERSION_CONTROL, sizeof(u32), version);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
+{
+       u8 reg[] = { 0x0f, 0x00 };
+
+       if (buflen < 128)
+               return -ENOMEM;
+
+       /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */
+       /* TODO: Pull the details from the boards struct */
+       return saa7164_api_i2c_read(&dev->i2c_bus[0], 0xa0 >> 1, sizeof(reg),
+               &reg[0], 128, buf);
+}
+
+int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
+       struct saa7164_port *port)
+{
+       struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc;
+
+       dprintk(DBGLVL_API, "    bFormatIndex  = 0x%x\n", fmt->bFormatIndex);
+       dprintk(DBGLVL_API, "    VideoStandard = 0x%x\n", fmt->VideoStandard);
+       dprintk(DBGLVL_API, "    StartLine     = %d\n", fmt->StartLine);
+       dprintk(DBGLVL_API, "    EndLine       = %d\n", fmt->EndLine);
+       dprintk(DBGLVL_API, "    FieldRate     = %d\n", fmt->FieldRate);
+       dprintk(DBGLVL_API, "    bNumLines     = %d\n", fmt->bNumLines);
+
+       /* Cache the hardware configuration in the port */
+
+       port->bufcounter = port->hwcfg.BARLocation;
+       port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
+       port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
+       port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
+       port->bufptr32l = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
+       port->bufptr32h = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount);
+       port->bufptr64 = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount);
+       dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",
+               port->hwcfg.BARLocation);
+
+       dprintk(DBGLVL_API, "   = VS_FORMAT_VBI (becomes dev->en[%d])\n",
+               port->nr);
+
+       return 0;
+}
+
+int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
+       struct saa7164_port *port,
+       struct tmComResTSFormatDescrHeader *tsfmt)
+{
+       dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
+       dprintk(DBGLVL_API, "    bDataOffset  = 0x%x\n", tsfmt->bDataOffset);
+       dprintk(DBGLVL_API, "    bPacketLength= 0x%x\n", tsfmt->bPacketLength);
+       dprintk(DBGLVL_API, "    bStrideLength= 0x%x\n", tsfmt->bStrideLength);
+       dprintk(DBGLVL_API, "    bguid        = (....)\n");
+
+       /* Cache the hardware configuration in the port */
+
+       port->bufcounter = port->hwcfg.BARLocation;
+       port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
+       port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
+       port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
+       port->bufptr32l = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
+       port->bufptr32h = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount);
+       port->bufptr64 = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount);
+       dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",
+               port->hwcfg.BARLocation);
+
+       dprintk(DBGLVL_API, "   = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",
+               port->nr);
+
+       return 0;
+}
+
+int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
+       struct saa7164_port *port,
+       struct tmComResPSFormatDescrHeader *fmt)
+{
+       dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", fmt->bFormatIndex);
+       dprintk(DBGLVL_API, "    wPacketLength= 0x%x\n", fmt->wPacketLength);
+       dprintk(DBGLVL_API, "    wPackLength=   0x%x\n", fmt->wPackLength);
+       dprintk(DBGLVL_API, "    bPackDataType= 0x%x\n", fmt->bPackDataType);
+
+       /* Cache the hardware configuration in the port */
+       /* TODO: CHECK THIS in the port config */
+       port->bufcounter = port->hwcfg.BARLocation;
+       port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
+       port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
+       port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
+       port->bufptr32l = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
+       port->bufptr32h = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount);
+       port->bufptr64 = port->hwcfg.BARLocation +
+               (4 * sizeof(u32)) +
+               (sizeof(u32) * port->hwcfg.buffercount);
+       dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",
+               port->hwcfg.BARLocation);
+
+       dprintk(DBGLVL_API, "   = VS_FORMAT_MPEGPS (becomes dev->enc[%d])\n",
+               port->nr);
+
+       return 0;
+}
+
+int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
+{
+       struct saa7164_port *tsport = NULL;
+       struct saa7164_port *encport = NULL;
+       struct saa7164_port *vbiport = NULL;
+       u32 idx, next_offset;
+       int i;
+       struct tmComResDescrHeader *hdr, *t;
+       struct tmComResExtDevDescrHeader *exthdr;
+       struct tmComResPathDescrHeader *pathhdr;
+       struct tmComResAntTermDescrHeader *anttermhdr;
+       struct tmComResTunerDescrHeader *tunerunithdr;
+       struct tmComResDMATermDescrHeader *vcoutputtermhdr;
+       struct tmComResTSFormatDescrHeader *tsfmt;
+       struct tmComResPSFormatDescrHeader *psfmt;
+       struct tmComResSelDescrHeader *psel;
+       struct tmComResProcDescrHeader *pdh;
+       struct tmComResAFeatureDescrHeader *afd;
+       struct tmComResEncoderDescrHeader *edh;
+       struct tmComResVBIFormatDescrHeader *vbifmt;
+       u32 currpath = 0;
+
+       dprintk(DBGLVL_API,
+               "%s(?,?,%d) sizeof(struct tmComResDescrHeader) = %d bytes\n",
+               __func__, len, (u32)sizeof(struct tmComResDescrHeader));
+
+       for (idx = 0; idx < (len - sizeof(struct tmComResDescrHeader));) {
+
+               hdr = (struct tmComResDescrHeader *)(buf + idx);
+
+               if (hdr->type != CS_INTERFACE)
+                       return SAA_ERR_NOT_SUPPORTED;
+
+               dprintk(DBGLVL_API, "@ 0x%x =\n", idx);
+               switch (hdr->subtype) {
+               case GENERAL_REQUEST:
+                       dprintk(DBGLVL_API, " GENERAL_REQUEST\n");
+                       break;
+               case VC_TUNER_PATH:
+                       dprintk(DBGLVL_API, " VC_TUNER_PATH\n");
+                       pathhdr = (struct tmComResPathDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, "  pathid = 0x%x\n",
+                               pathhdr->pathid);
+                       currpath = pathhdr->pathid;
+                       break;
+               case VC_INPUT_TERMINAL:
+                       dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n");
+                       anttermhdr =
+                               (struct tmComResAntTermDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, "  terminalid   = 0x%x\n",
+                               anttermhdr->terminalid);
+                       dprintk(DBGLVL_API, "  terminaltype = 0x%x\n",
+                               anttermhdr->terminaltype);
+                       switch (anttermhdr->terminaltype) {
+                       case ITT_ANTENNA:
+                               dprintk(DBGLVL_API, "   = ITT_ANTENNA\n");
+                               break;
+                       case LINE_CONNECTOR:
+                               dprintk(DBGLVL_API, "   = LINE_CONNECTOR\n");
+                               break;
+                       case SPDIF_CONNECTOR:
+                               dprintk(DBGLVL_API, "   = SPDIF_CONNECTOR\n");
+                               break;
+                       case COMPOSITE_CONNECTOR:
+                               dprintk(DBGLVL_API,
+                                       "   = COMPOSITE_CONNECTOR\n");
+                               break;
+                       case SVIDEO_CONNECTOR:
+                               dprintk(DBGLVL_API, "   = SVIDEO_CONNECTOR\n");
+                               break;
+                       case COMPONENT_CONNECTOR:
+                               dprintk(DBGLVL_API,
+                                       "   = COMPONENT_CONNECTOR\n");
+                               break;
+                       case STANDARD_DMA:
+                               dprintk(DBGLVL_API, "   = STANDARD_DMA\n");
+                               break;
+                       default:
+                               dprintk(DBGLVL_API, "   = undefined (0x%x)\n",
+                                       anttermhdr->terminaltype);
+                       }
+                       dprintk(DBGLVL_API, "  assocterminal= 0x%x\n",
+                               anttermhdr->assocterminal);
+                       dprintk(DBGLVL_API, "  iterminal    = 0x%x\n",
+                               anttermhdr->iterminal);
+                       dprintk(DBGLVL_API, "  controlsize  = 0x%x\n",
+                               anttermhdr->controlsize);
+                       break;
+               case VC_OUTPUT_TERMINAL:
+                       dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n");
+                       vcoutputtermhdr =
+                               (struct tmComResDMATermDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
+                               vcoutputtermhdr->unitid);
+                       dprintk(DBGLVL_API, "  terminaltype = 0x%x\n",
+                               vcoutputtermhdr->terminaltype);
+                       switch (vcoutputtermhdr->terminaltype) {
+                       case ITT_ANTENNA:
+                               dprintk(DBGLVL_API, "   = ITT_ANTENNA\n");
+                               break;
+                       case LINE_CONNECTOR:
+                               dprintk(DBGLVL_API, "   = LINE_CONNECTOR\n");
+                               break;
+                       case SPDIF_CONNECTOR:
+                               dprintk(DBGLVL_API, "   = SPDIF_CONNECTOR\n");
+                               break;
+                       case COMPOSITE_CONNECTOR:
+                               dprintk(DBGLVL_API,
+                                       "   = COMPOSITE_CONNECTOR\n");
+                               break;
+                       case SVIDEO_CONNECTOR:
+                               dprintk(DBGLVL_API, "   = SVIDEO_CONNECTOR\n");
+                               break;
+                       case COMPONENT_CONNECTOR:
+                               dprintk(DBGLVL_API,
+                                       "   = COMPONENT_CONNECTOR\n");
+                               break;
+                       case STANDARD_DMA:
+                               dprintk(DBGLVL_API, "   = STANDARD_DMA\n");
+                               break;
+                       default:
+                               dprintk(DBGLVL_API, "   = undefined (0x%x)\n",
+                                       vcoutputtermhdr->terminaltype);
+                       }
+                       dprintk(DBGLVL_API, "  assocterminal= 0x%x\n",
+                               vcoutputtermhdr->assocterminal);
+                       dprintk(DBGLVL_API, "  sourceid     = 0x%x\n",
+                               vcoutputtermhdr->sourceid);
+                       dprintk(DBGLVL_API, "  iterminal    = 0x%x\n",
+                               vcoutputtermhdr->iterminal);
+                       dprintk(DBGLVL_API, "  BARLocation  = 0x%x\n",
+                               vcoutputtermhdr->BARLocation);
+                       dprintk(DBGLVL_API, "  flags        = 0x%x\n",
+                               vcoutputtermhdr->flags);
+                       dprintk(DBGLVL_API, "  interruptid  = 0x%x\n",
+                               vcoutputtermhdr->interruptid);
+                       dprintk(DBGLVL_API, "  buffercount  = 0x%x\n",
+                               vcoutputtermhdr->buffercount);
+                       dprintk(DBGLVL_API, "  metadatasize = 0x%x\n",
+                               vcoutputtermhdr->metadatasize);
+                       dprintk(DBGLVL_API, "  controlsize  = 0x%x\n",
+                               vcoutputtermhdr->controlsize);
+                       dprintk(DBGLVL_API, "  numformats   = 0x%x\n",
+                               vcoutputtermhdr->numformats);
+
+                       t = (struct tmComResDescrHeader *)
+                               ((struct tmComResDMATermDescrHeader *)(buf + idx));
+                       next_offset = idx + (vcoutputtermhdr->len);
+                       for (i = 0; i < vcoutputtermhdr->numformats; i++) {
+                               t = (struct tmComResDescrHeader *)
+                                       (buf + next_offset);
+                               switch (t->subtype) {
+                               case VS_FORMAT_MPEG2TS:
+                                       tsfmt =
+                                       (struct tmComResTSFormatDescrHeader *)t;
+                                       if (currpath == 1)
+                                               tsport = &dev->ports[SAA7164_PORT_TS1];
+                                       else
+                                               tsport = &dev->ports[SAA7164_PORT_TS2];
+                                       memcpy(&tsport->hwcfg, vcoutputtermhdr,
+                                               sizeof(*vcoutputtermhdr));
+                                       saa7164_api_configure_port_mpeg2ts(dev,
+                                               tsport, tsfmt);
+                                       break;
+                               case VS_FORMAT_MPEG2PS:
+                                       psfmt =
+                                       (struct tmComResPSFormatDescrHeader *)t;
+                                       if (currpath == 1)
+                                               encport = &dev->ports[SAA7164_PORT_ENC1];
+                                       else
+                                               encport = &dev->ports[SAA7164_PORT_ENC2];
+                                       memcpy(&encport->hwcfg, vcoutputtermhdr,
+                                               sizeof(*vcoutputtermhdr));
+                                       saa7164_api_configure_port_mpeg2ps(dev,
+                                               encport, psfmt);
+                                       break;
+                               case VS_FORMAT_VBI:
+                                       vbifmt =
+                                       (struct tmComResVBIFormatDescrHeader *)t;
+                                       if (currpath == 1)
+                                               vbiport = &dev->ports[SAA7164_PORT_VBI1];
+                                       else
+                                               vbiport = &dev->ports[SAA7164_PORT_VBI2];
+                                       memcpy(&vbiport->hwcfg, vcoutputtermhdr,
+                                               sizeof(*vcoutputtermhdr));
+                                       memcpy(&vbiport->vbi_fmt_ntsc, vbifmt,
+                                               sizeof(*vbifmt));
+                                       saa7164_api_configure_port_vbi(dev,
+                                               vbiport);
+                                       break;
+                               case VS_FORMAT_RDS:
+                                       dprintk(DBGLVL_API,
+                                               "   = VS_FORMAT_RDS\n");
+                                       break;
+                               case VS_FORMAT_UNCOMPRESSED:
+                                       dprintk(DBGLVL_API,
+                                       "   = VS_FORMAT_UNCOMPRESSED\n");
+                                       break;
+                               case VS_FORMAT_TYPE:
+                                       dprintk(DBGLVL_API,
+                                               "   = VS_FORMAT_TYPE\n");
+                                       break;
+                               default:
+                                       dprintk(DBGLVL_API,
+                                               "   = undefined (0x%x)\n",
+                                               t->subtype);
+                               }
+                               next_offset += t->len;
+                       }
+
+                       break;
+               case TUNER_UNIT:
+                       dprintk(DBGLVL_API, " TUNER_UNIT\n");
+                       tunerunithdr =
+                               (struct tmComResTunerDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
+                               tunerunithdr->unitid);
+                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
+                               tunerunithdr->sourceid);
+                       dprintk(DBGLVL_API, "  iunit = 0x%x\n",
+                               tunerunithdr->iunit);
+                       dprintk(DBGLVL_API, "  tuningstandards = 0x%x\n",
+                               tunerunithdr->tuningstandards);
+                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
+                               tunerunithdr->controlsize);
+                       dprintk(DBGLVL_API, "  controls = 0x%x\n",
+                               tunerunithdr->controls);
+
+                       if (tunerunithdr->unitid == tunerunithdr->iunit) {
+                               if (currpath == 1)
+                                       encport = &dev->ports[SAA7164_PORT_ENC1];
+                               else
+                                       encport = &dev->ports[SAA7164_PORT_ENC2];
+                               memcpy(&encport->tunerunit, tunerunithdr,
+                                       sizeof(struct tmComResTunerDescrHeader));
+                               dprintk(DBGLVL_API,
+                                       "  (becomes dev->enc[%d] tuner)\n",
+                                       encport->nr);
+                       }
+                       break;
+               case VC_SELECTOR_UNIT:
+                       psel = (struct tmComResSelDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n");
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
+                               psel->unitid);
+                       dprintk(DBGLVL_API, "  nrinpins = 0x%x\n",
+                               psel->nrinpins);
+                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
+                               psel->sourceid);
+                       break;
+               case VC_PROCESSING_UNIT:
+                       pdh = (struct tmComResProcDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n");
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
+                               pdh->unitid);
+                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
+                               pdh->sourceid);
+                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
+                               pdh->controlsize);
+                       if (pdh->controlsize == 0x04) {
+                               if (currpath == 1)
+                                       encport = &dev->ports[SAA7164_PORT_ENC1];
+                               else
+                                       encport = &dev->ports[SAA7164_PORT_ENC2];
+                               memcpy(&encport->vidproc, pdh,
+                                       sizeof(struct tmComResProcDescrHeader));
+                               dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",
+                                       encport->nr);
+                       }
+                       break;
+               case FEATURE_UNIT:
+                       afd = (struct tmComResAFeatureDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, " FEATURE_UNIT\n");
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
+                               afd->unitid);
+                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
+                               afd->sourceid);
+                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
+                               afd->controlsize);
+                       if (currpath == 1)
+                               encport = &dev->ports[SAA7164_PORT_ENC1];
+                       else
+                               encport = &dev->ports[SAA7164_PORT_ENC2];
+                       memcpy(&encport->audfeat, afd,
+                               sizeof(struct tmComResAFeatureDescrHeader));
+                       dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",
+                               encport->nr);
+                       break;
+               case ENCODER_UNIT:
+                       edh = (struct tmComResEncoderDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, " ENCODER_UNIT\n");
+                       dprintk(DBGLVL_API, "  subtype = 0x%x\n", edh->subtype);
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n", edh->unitid);
+                       dprintk(DBGLVL_API, "  vsourceid = 0x%x\n",
+                       edh->vsourceid);
+                       dprintk(DBGLVL_API, "  asourceid = 0x%x\n",
+                               edh->asourceid);
+                       dprintk(DBGLVL_API, "  iunit = 0x%x\n", edh->iunit);
+                       if (edh->iunit == edh->unitid) {
+                               if (currpath == 1)
+                                       encport = &dev->ports[SAA7164_PORT_ENC1];
+                               else
+                                       encport = &dev->ports[SAA7164_PORT_ENC2];
+                               memcpy(&encport->encunit, edh,
+                                       sizeof(struct tmComResEncoderDescrHeader));
+                               dprintk(DBGLVL_API,
+                                       "  (becomes dev->enc[%d])\n",
+                                       encport->nr);
+                       }
+                       break;
+               case EXTENSION_UNIT:
+                       dprintk(DBGLVL_API, " EXTENSION_UNIT\n");
+                       exthdr = (struct tmComResExtDevDescrHeader *)(buf + idx);
+                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
+                               exthdr->unitid);
+                       dprintk(DBGLVL_API, "  deviceid = 0x%x\n",
+                               exthdr->deviceid);
+                       dprintk(DBGLVL_API, "  devicetype = 0x%x\n",
+                               exthdr->devicetype);
+                       if (exthdr->devicetype & 0x1)
+                               dprintk(DBGLVL_API, "   = Decoder Device\n");
+                       if (exthdr->devicetype & 0x2)
+                               dprintk(DBGLVL_API, "   = GPIO Source\n");
+                       if (exthdr->devicetype & 0x4)
+                               dprintk(DBGLVL_API, "   = Video Decoder\n");
+                       if (exthdr->devicetype & 0x8)
+                               dprintk(DBGLVL_API, "   = Audio Decoder\n");
+                       if (exthdr->devicetype & 0x20)
+                               dprintk(DBGLVL_API, "   = Crossbar\n");
+                       if (exthdr->devicetype & 0x40)
+                               dprintk(DBGLVL_API, "   = Tuner\n");
+                       if (exthdr->devicetype & 0x80)
+                               dprintk(DBGLVL_API, "   = IF PLL\n");
+                       if (exthdr->devicetype & 0x100)
+                               dprintk(DBGLVL_API, "   = Demodulator\n");
+                       if (exthdr->devicetype & 0x200)
+                               dprintk(DBGLVL_API, "   = RDS Decoder\n");
+                       if (exthdr->devicetype & 0x400)
+                               dprintk(DBGLVL_API, "   = Encoder\n");
+                       if (exthdr->devicetype & 0x800)
+                               dprintk(DBGLVL_API, "   = IR Decoder\n");
+                       if (exthdr->devicetype & 0x1000)
+                               dprintk(DBGLVL_API, "   = EEPROM\n");
+                       if (exthdr->devicetype & 0x2000)
+                               dprintk(DBGLVL_API,
+                                       "   = VBI Decoder\n");
+                       if (exthdr->devicetype & 0x10000)
+                               dprintk(DBGLVL_API,
+                                       "   = Streaming Device\n");
+                       if (exthdr->devicetype & 0x20000)
+                               dprintk(DBGLVL_API,
+                                       "   = DRM Device\n");
+                       if (exthdr->devicetype & 0x40000000)
+                               dprintk(DBGLVL_API,
+                                       "   = Generic Device\n");
+                       if (exthdr->devicetype & 0x80000000)
+                               dprintk(DBGLVL_API,
+                                       "   = Config Space Device\n");
+                       dprintk(DBGLVL_API, "  numgpiopins = 0x%x\n",
+                               exthdr->numgpiopins);
+                       dprintk(DBGLVL_API, "  numgpiogroups = 0x%x\n",
+                               exthdr->numgpiogroups);
+                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
+                               exthdr->controlsize);
+                       if (exthdr->devicetype & 0x80) {
+                               if (currpath == 1)
+                                       encport = &dev->ports[SAA7164_PORT_ENC1];
+                               else
+                                       encport = &dev->ports[SAA7164_PORT_ENC2];
+                               memcpy(&encport->ifunit, exthdr,
+                                       sizeof(struct tmComResExtDevDescrHeader));
+                               dprintk(DBGLVL_API,
+                                       "  (becomes dev->enc[%d])\n",
+                                       encport->nr);
+                       }
+                       break;
+               case PVC_INFRARED_UNIT:
+                       dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n");
+                       break;
+               case DRM_UNIT:
+                       dprintk(DBGLVL_API, " DRM_UNIT\n");
+                       break;
+               default:
+                       dprintk(DBGLVL_API, "default %d\n", hdr->subtype);
+               }
+
+               dprintk(DBGLVL_API, " 1.%x\n", hdr->len);
+               dprintk(DBGLVL_API, " 2.%x\n", hdr->type);
+               dprintk(DBGLVL_API, " 3.%x\n", hdr->subtype);
+               dprintk(DBGLVL_API, " 4.%x\n", hdr->unitid);
+
+               idx += hdr->len;
+       }
+
+       return 0;
+}
+
+int saa7164_api_enum_subdevs(struct saa7164_dev *dev)
+{
+       int ret;
+       u32 buflen = 0;
+       u8 *buf;
+
+       dprintk(DBGLVL_API, "%s()\n", __func__);
+
+       /* Get the total descriptor length */
+       ret = saa7164_cmd_send(dev, 0, GET_LEN,
+               GET_DESCRIPTORS_CONTROL, sizeof(buflen), &buflen);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+
+       dprintk(DBGLVL_API, "%s() total descriptor size = %d bytes.\n",
+               __func__, buflen);
+
+       /* Allocate enough storage for all of the descs */
+       buf = kzalloc(buflen, GFP_KERNEL);
+       if (!buf)
+               return SAA_ERR_NO_RESOURCES;
+
+       /* Retrieve them */
+       ret = saa7164_cmd_send(dev, 0, GET_CUR,
+               GET_DESCRIPTORS_CONTROL, buflen, buf);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
+               goto out;
+       }
+
+       if (saa_debug & DBGLVL_API)
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,
+                              buflen & ~15, false);
+
+       saa7164_api_dump_subdevs(dev, buf, buflen);
+
+out:
+       kfree(buf);
+       return ret;
+}
+
+int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
+       u32 datalen, u8 *data)
+{
+       struct saa7164_dev *dev = bus->dev;
+       u16 len = 0;
+       int unitid;
+       u8 buf[256];
+       int ret;
+
+       dprintk(DBGLVL_API, "%s()\n", __func__);
+
+       if (reglen > 4)
+               return -EIO;
+
+       /* Prepare the send buffer */
+       /* Bytes 00-03 source register length
+        *       04-07 source bytes to read
+        *       08... register address
+        */
+       memset(buf, 0, sizeof(buf));
+       memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);
+       *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
+       *((u32 *)(buf + 1 * sizeof(u32))) = datalen;
+
+       unitid = saa7164_i2caddr_to_unitid(bus, addr);
+       if (unitid < 0) {
+               printk(KERN_ERR
+                       "%s() error, cannot translate regaddr 0x%x to unitid\n",
+                       __func__, addr);
+               return -EIO;
+       }
+
+       ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
+               EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
+               return -EIO;
+       }
+
+       dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
+
+       if (saa_debug & DBGLVL_I2C)
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,
+                              32, false);
+
+       ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR,
+               EXU_REGISTER_ACCESS_CONTROL, len, &buf);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
+       else {
+               if (saa_debug & DBGLVL_I2C)
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                                      buf, sizeof(buf), false);
+               memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen);
+       }
+
+       return ret == SAA_OK ? 0 : -EIO;
+}
+
+/* For a given 8 bit i2c address device, write the buffer */
+int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
+       u8 *data)
+{
+       struct saa7164_dev *dev = bus->dev;
+       u16 len = 0;
+       int unitid;
+       int reglen;
+       u8 buf[256];
+       int ret;
+
+       dprintk(DBGLVL_API, "%s()\n", __func__);
+
+       if ((datalen == 0) || (datalen > 232))
+               return -EIO;
+
+       memset(buf, 0, sizeof(buf));
+
+       unitid = saa7164_i2caddr_to_unitid(bus, addr);
+       if (unitid < 0) {
+               printk(KERN_ERR
+                       "%s() error, cannot translate regaddr 0x%x to unitid\n",
+                       __func__, addr);
+               return -EIO;
+       }
+
+       reglen = saa7164_i2caddr_to_reglen(bus, addr);
+       if (reglen < 0) {
+               printk(KERN_ERR
+                       "%s() error, cannot translate regaddr to reglen\n",
+                       __func__);
+               return -EIO;
+       }
+
+       ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
+               EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
+               return -EIO;
+       }
+
+       dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
+
+       /* Prepare the send buffer */
+       /* Bytes 00-03 dest register length
+        *       04-07 dest bytes to write
+        *       08... register address
+        */
+       *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
+       *((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen;
+       memcpy((buf + 2 * sizeof(u32)), data, datalen);
+
+       if (saa_debug & DBGLVL_I2C)
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                              buf, sizeof(buf), false);
+
+       ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR,
+               EXU_REGISTER_ACCESS_CONTROL, len, &buf);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
+
+       return ret == SAA_OK ? 0 : -EIO;
+}
+
+int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
+       u8 pin, u8 state)
+{
+       int ret;
+       struct tmComResGPIO t;
+
+       dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n",
+               __func__, unitid, pin, state);
+
+       if ((pin > 7) || (state > 2))
+               return SAA_ERR_BAD_PARAMETER;
+
+       t.pin = pin;
+       t.state = state;
+
+       ret = saa7164_cmd_send(dev, unitid, SET_CUR,
+               EXU_GPIO_CONTROL, sizeof(t), &t);
+       if (ret != SAA_OK)
+               printk(KERN_ERR "%s() error, ret = 0x%x\n",
+                       __func__, ret);
+
+       return ret;
+}
+
+int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid,
+       u8 pin)
+{
+       return saa7164_api_modify_gpio(dev, unitid, pin, 1);
+}
+
+int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid,
+       u8 pin)
+{
+       return saa7164_api_modify_gpio(dev, unitid, pin, 0);
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-buffer.c b/drivers/media/pci/saa7164/saa7164-buffer.c
new file mode 100644 (file)
index 0000000..66696fa
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 "saa7164.h"
+
+/* The PCI address space for buffer handling looks like this:
+ *
+ * +-u32 wide-------------+
+ * |                      +
+ * +-u64 wide------------------------------------+
+ * +                                             +
+ * +----------------------+
+ * | CurrentBufferPtr     + Pointer to current PCI buffer >-+
+ * +----------------------+                                 |
+ * | Unused               +                                 |
+ * +----------------------+                                 |
+ * | Pitch                + = 188 (bytes)                   |
+ * +----------------------+                                 |
+ * | PCI buffer size      + = pitch * number of lines (312) |
+ * +----------------------+                                 |
+ * |0| Buf0 Write Offset  +                                 |
+ * +----------------------+                                 v
+ * |1| Buf1 Write Offset  +                                 |
+ * +----------------------+                                 |
+ * |2| Buf2 Write Offset  +                                 |
+ * +----------------------+                                 |
+ * |3| Buf3 Write Offset  +                                 |
+ * +----------------------+                                 |
+ * ... More write offsets                                   |
+ * +---------------------------------------------+          |
+ * +0| set of ptrs to PCI pagetables             +          |
+ * +---------------------------------------------+          |
+ * +1| set of ptrs to PCI pagetables             + <--------+
+ * +---------------------------------------------+
+ * +2| set of ptrs to PCI pagetables             +
+ * +---------------------------------------------+
+ * +3| set of ptrs to PCI pagetables             + >--+
+ * +---------------------------------------------+    |
+ * ... More buffer pointers                           |  +----------------+
+ *                                                 +->| pt[0] TS data  |
+ *                                                 |  +----------------+
+ *                                                 |
+ *                                                 |  +----------------+
+ *                                                 +->| pt[1] TS data  |
+ *                                                 |  +----------------+
+ *                                                 | etc
+ */
+
+void saa7164_buffer_display(struct saa7164_buffer *buf)
+{
+       struct saa7164_dev *dev = buf->port->dev;
+       int i;
+
+       dprintk(DBGLVL_BUF, "%s()   buffer @ 0x%p nr=%d\n",
+               __func__, buf, buf->idx);
+       dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08llx len = 0x%x\n",
+               buf->cpu, (long long)buf->dma, buf->pci_size);
+       dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08llx len = 0x%x\n",
+               buf->pt_cpu, (long long)buf->pt_dma, buf->pt_size);
+
+       /* Format the Page Table Entries to point into the data buffer */
+       for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) {
+
+               dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
+                       i, buf->pt_cpu, (u64)*(buf->pt_cpu));
+
+       }
+}
+/* Allocate a new buffer structure and associated PCI space in bytes.
+ * len must be a multiple of sizeof(u64)
+ */
+struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
+       u32 len)
+{
+       struct tmHWStreamParameters *params = &port->hw_streamingparams;
+       struct saa7164_buffer *buf = NULL;
+       struct saa7164_dev *dev = port->dev;
+       int i;
+
+       if ((len == 0) || (len >= 65536) || (len % sizeof(u64))) {
+               log_warn("%s() SAA_ERR_BAD_PARAMETER\n", __func__);
+               goto ret;
+       }
+
+       buf = kzalloc(sizeof(struct saa7164_buffer), GFP_KERNEL);
+       if (!buf) {
+               log_warn("%s() SAA_ERR_NO_RESOURCES\n", __func__);
+               goto ret;
+       }
+
+       buf->idx = -1;
+       buf->port = port;
+       buf->flags = SAA7164_BUFFER_FREE;
+       buf->pos = 0;
+       buf->actual_size = params->pitch * params->numberoflines;
+       buf->crc = 0;
+       /* TODO: arg len is being ignored */
+       buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
+       buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
+
+       /* Allocate contiguous memory */
+       buf->cpu = pci_alloc_consistent(port->dev->pci, buf->pci_size,
+               &buf->dma);
+       if (!buf->cpu)
+               goto fail1;
+
+       buf->pt_cpu = pci_alloc_consistent(port->dev->pci, buf->pt_size,
+               &buf->pt_dma);
+       if (!buf->pt_cpu)
+               goto fail2;
+
+       /* init the buffers to a known pattern, easier during debugging */
+       memset_io(buf->cpu, 0xff, buf->pci_size);
+       buf->crc = crc32(0, buf->cpu, buf->actual_size);
+       memset_io(buf->pt_cpu, 0xff, buf->pt_size);
+
+       dprintk(DBGLVL_BUF, "%s()   allocated buffer @ 0x%p (%d pageptrs)\n",
+               __func__, buf, params->numpagetables);
+       dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08lx len = 0x%x\n",
+               buf->cpu, (long)buf->dma, buf->pci_size);
+       dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n",
+               buf->pt_cpu, (long)buf->pt_dma, buf->pt_size);
+
+       /* Format the Page Table Entries to point into the data buffer */
+       for (i = 0 ; i < params->numpagetables; i++) {
+
+               *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */
+               dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
+                       i, buf->pt_cpu, (u64)*(buf->pt_cpu));
+
+       }
+
+       goto ret;
+
+fail2:
+       pci_free_consistent(port->dev->pci, buf->pci_size, buf->cpu, buf->dma);
+fail1:
+       kfree(buf);
+
+       buf = NULL;
+ret:
+       return buf;
+}
+
+int saa7164_buffer_dealloc(struct saa7164_buffer *buf)
+{
+       struct saa7164_dev *dev;
+
+       if (!buf || !buf->port)
+               return SAA_ERR_BAD_PARAMETER;
+       dev = buf->port->dev;
+
+       dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n",
+               __func__, buf);
+
+       if (buf->flags != SAA7164_BUFFER_FREE)
+               log_warn(" freeing a non-free buffer\n");
+
+       pci_free_consistent(dev->pci, buf->pci_size, buf->cpu, buf->dma);
+       pci_free_consistent(dev->pci, buf->pt_size, buf->pt_cpu, buf->pt_dma);
+
+       kfree(buf);
+
+       return SAA_OK;
+}
+
+int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       if ((i < 0) || (i >= port->hwcfg.buffercount))
+               return -EINVAL;
+
+       dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
+
+       saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
+
+       return 0;
+}
+
+/* Write a buffer into the hardware */
+int saa7164_buffer_activate(struct saa7164_buffer *buf, int i)
+{
+       struct saa7164_port *port = buf->port;
+       struct saa7164_dev *dev = port->dev;
+
+       if ((i < 0) || (i >= port->hwcfg.buffercount))
+               return -EINVAL;
+
+       dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
+
+       buf->idx = i; /* Note of which buffer list index position we occupy */
+       buf->flags = SAA7164_BUFFER_BUSY;
+       buf->pos = 0;
+
+       /* TODO: Review this in light of 32v64 assignments */
+       saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
+       saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma);
+       saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
+
+       dprintk(DBGLVL_BUF, "   buf[%d] offset 0x%llx (0x%x) "
+               "buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
+               buf->idx,
+               (u64)port->bufoffset + (i * sizeof(u32)),
+               saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
+               (u64)port->bufptr32h + ((sizeof(u32) * 2) * i),
+               (u64)port->bufptr32l + ((sizeof(u32) * 2) * i),
+               saa7164_readl(port->bufptr32h + ((sizeof(u32) * i) * 2)),
+               saa7164_readl(port->bufptr32l + ((sizeof(u32) * i) * 2)),
+               buf->idx);
+
+       return 0;
+}
+
+int saa7164_buffer_cfg_port(struct saa7164_port *port)
+{
+       struct tmHWStreamParameters *params = &port->hw_streamingparams;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct list_head *c, *n;
+       int i = 0;
+
+       dprintk(DBGLVL_BUF, "%s(port=%d)\n", __func__, port->nr);
+
+       saa7164_writel(port->bufcounter, 0);
+       saa7164_writel(port->pitch, params->pitch);
+       saa7164_writel(port->bufsize, params->pitch * params->numberoflines);
+
+       dprintk(DBGLVL_BUF, " configured:\n");
+       dprintk(DBGLVL_BUF, "   lmmio       0x%p\n", dev->lmmio);
+       dprintk(DBGLVL_BUF, "   bufcounter  0x%x = 0x%x\n", port->bufcounter,
+               saa7164_readl(port->bufcounter));
+
+       dprintk(DBGLVL_BUF, "   pitch       0x%x = %d\n", port->pitch,
+               saa7164_readl(port->pitch));
+
+       dprintk(DBGLVL_BUF, "   bufsize     0x%x = %d\n", port->bufsize,
+               saa7164_readl(port->bufsize));
+
+       dprintk(DBGLVL_BUF, "   buffercount = %d\n", port->hwcfg.buffercount);
+       dprintk(DBGLVL_BUF, "   bufoffset = 0x%x\n", port->bufoffset);
+       dprintk(DBGLVL_BUF, "   bufptr32h = 0x%x\n", port->bufptr32h);
+       dprintk(DBGLVL_BUF, "   bufptr32l = 0x%x\n", port->bufptr32l);
+
+       /* Poke the buffers and offsets into PCI space */
+       mutex_lock(&port->dmaqueue_lock);
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               buf = list_entry(c, struct saa7164_buffer, list);
+
+               if (buf->flags != SAA7164_BUFFER_FREE)
+                       BUG();
+
+               /* Place the buffer in the h/w queue */
+               saa7164_buffer_activate(buf, i);
+
+               /* Don't exceed the device maximum # bufs */
+               if (i++ > port->hwcfg.buffercount)
+                       BUG();
+
+       }
+       mutex_unlock(&port->dmaqueue_lock);
+
+       return 0;
+}
+
+struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev,
+       u32 len)
+{
+       struct saa7164_user_buffer *buf;
+
+       buf = kzalloc(sizeof(struct saa7164_user_buffer), GFP_KERNEL);
+       if (!buf)
+               return NULL;
+
+       buf->data = kzalloc(len, GFP_KERNEL);
+
+       if (!buf->data) {
+               kfree(buf);
+               return NULL;
+       }
+
+       buf->actual_size = len;
+       buf->pos = 0;
+       buf->crc = 0;
+
+       dprintk(DBGLVL_BUF, "%s()   allocated user buffer @ 0x%p\n",
+               __func__, buf);
+
+       return buf;
+}
+
+void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf)
+{
+       if (!buf)
+               return;
+
+       kfree(buf->data);
+       buf->data = NULL;
+
+       kfree(buf);
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c
new file mode 100644 (file)
index 0000000..a7f58a9
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 "saa7164.h"
+
+/* The message bus to/from the firmware is a ring buffer in PCI address
+ * space. Establish the defaults.
+ */
+int saa7164_bus_setup(struct saa7164_dev *dev)
+{
+       struct tmComResBusInfo *b       = &dev->bus;
+
+       mutex_init(&b->lock);
+
+       b->Type                 = TYPE_BUS_PCIe;
+       b->m_wMaxReqSize        = SAA_DEVICE_MAXREQUESTSIZE;
+
+       b->m_pdwSetRing         = (u8 *)(dev->bmmio +
+               ((u32)dev->busdesc.CommandRing));
+
+       b->m_dwSizeSetRing      = SAA_DEVICE_BUFFERBLOCKSIZE;
+
+       b->m_pdwGetRing         = (u8 *)(dev->bmmio +
+               ((u32)dev->busdesc.ResponseRing));
+
+       b->m_dwSizeGetRing      = SAA_DEVICE_BUFFERBLOCKSIZE;
+
+       b->m_dwSetWritePos      = ((u32)dev->intfdesc.BARLocation) +
+               (2 * sizeof(u64));
+       b->m_dwSetReadPos       = b->m_dwSetWritePos + (1 * sizeof(u32));
+
+       b->m_dwGetWritePos      = b->m_dwSetWritePos + (2 * sizeof(u32));
+       b->m_dwGetReadPos       = b->m_dwSetWritePos + (3 * sizeof(u32));
+
+       return 0;
+}
+
+void saa7164_bus_dump(struct saa7164_dev *dev)
+{
+       struct tmComResBusInfo *b = &dev->bus;
+
+       dprintk(DBGLVL_BUS, "Dumping the bus structure:\n");
+       dprintk(DBGLVL_BUS, " .type             = %d\n", b->Type);
+       dprintk(DBGLVL_BUS, " .dev->bmmio       = 0x%p\n", dev->bmmio);
+       dprintk(DBGLVL_BUS, " .m_wMaxReqSize    = 0x%x\n", b->m_wMaxReqSize);
+       dprintk(DBGLVL_BUS, " .m_pdwSetRing     = 0x%p\n", b->m_pdwSetRing);
+       dprintk(DBGLVL_BUS, " .m_dwSizeSetRing  = 0x%x\n", b->m_dwSizeSetRing);
+       dprintk(DBGLVL_BUS, " .m_pdwGetRing     = 0x%p\n", b->m_pdwGetRing);
+       dprintk(DBGLVL_BUS, " .m_dwSizeGetRing  = 0x%x\n", b->m_dwSizeGetRing);
+
+       dprintk(DBGLVL_BUS, " .m_dwSetReadPos   = 0x%x (0x%08x)\n",
+               b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
+
+       dprintk(DBGLVL_BUS, " .m_dwSetWritePos  = 0x%x (0x%08x)\n",
+               b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
+
+       dprintk(DBGLVL_BUS, " .m_dwGetReadPos   = 0x%x (0x%08x)\n",
+               b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
+
+       dprintk(DBGLVL_BUS, " .m_dwGetWritePos  = 0x%x (0x%08x)\n",
+               b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
+
+}
+
+/* Intensionally throw a BUG() if the state of the message bus looks corrupt */
+void saa7164_bus_verify(struct saa7164_dev *dev)
+{
+       struct tmComResBusInfo *b = &dev->bus;
+       int bug = 0;
+
+       if (saa7164_readl(b->m_dwSetReadPos) > b->m_dwSizeSetRing)
+               bug++;
+
+       if (saa7164_readl(b->m_dwSetWritePos) > b->m_dwSizeSetRing)
+               bug++;
+
+       if (saa7164_readl(b->m_dwGetReadPos) > b->m_dwSizeGetRing)
+               bug++;
+
+       if (saa7164_readl(b->m_dwGetWritePos) > b->m_dwSizeGetRing)
+               bug++;
+
+       if (bug) {
+               saa_debug = 0xffff; /* Ensure we get the bus dump */
+               saa7164_bus_dump(dev);
+               saa_debug = 1024; /* Ensure we get the bus dump */
+               BUG();
+       }
+}
+
+void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m,
+       void *buf)
+{
+       dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
+       dprintk(DBGLVL_BUS, " .id               = %d\n",   m->id);
+       dprintk(DBGLVL_BUS, " .flags            = 0x%x\n", m->flags);
+       dprintk(DBGLVL_BUS, " .size             = 0x%x\n", m->size);
+       dprintk(DBGLVL_BUS, " .command          = 0x%x\n", m->command);
+       dprintk(DBGLVL_BUS, " .controlselector  = 0x%x\n", m->controlselector);
+       dprintk(DBGLVL_BUS, " .seqno            = %d\n",   m->seqno);
+       if (buf)
+               dprintk(DBGLVL_BUS, " .buffer (ignored)\n");
+}
+
+/*
+ * Places a command or a response on the bus. The implementation does not
+ * know if it is a command or a response it just places the data on the
+ * bus depending on the bus information given in the struct tmComResBusInfo
+ * structure. If the command or response does not fit into the bus ring
+ * buffer it will be refused.
+ *
+ * Return Value:
+ *  SAA_OK     The function executed successfully.
+ *  < 0        One or more members are not initialized.
+ */
+int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
+       void *buf)
+{
+       struct tmComResBusInfo *bus = &dev->bus;
+       u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
+       u32 new_swp, space_rem;
+       int ret = SAA_ERR_BAD_PARAMETER;
+
+       if (!msg) {
+               printk(KERN_ERR "%s() !msg\n", __func__);
+               return SAA_ERR_BAD_PARAMETER;
+       }
+
+       dprintk(DBGLVL_BUS, "%s()\n", __func__);
+
+       saa7164_bus_verify(dev);
+
+       msg->size = cpu_to_le16(msg->size);
+       msg->command = cpu_to_le32(msg->command);
+       msg->controlselector = cpu_to_le16(msg->controlselector);
+
+       if (msg->size > dev->bus.m_wMaxReqSize) {
+               printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
+                       __func__);
+               return SAA_ERR_BAD_PARAMETER;
+       }
+
+       if ((msg->size > 0) && (buf == NULL)) {
+               printk(KERN_ERR "%s() Missing message buffer\n", __func__);
+               return SAA_ERR_BAD_PARAMETER;
+       }
+
+       /* Lock the bus from any other access */
+       mutex_lock(&bus->lock);
+
+       bytes_to_write = sizeof(*msg) + msg->size;
+       free_write_space = 0;
+       timeout = SAA_BUS_TIMEOUT;
+       curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
+       curr_swp = le32_to_cpu(saa7164_readl(bus->m_dwSetWritePos));
+
+       /* Deal with ring wrapping issues */
+       if (curr_srp > curr_swp)
+               /* Deal with the wrapped ring */
+               free_write_space = curr_srp - curr_swp;
+       else
+               /* The ring has not wrapped yet */
+               free_write_space = (curr_srp + bus->m_dwSizeSetRing) - curr_swp;
+
+       dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__,
+               bytes_to_write);
+
+       dprintk(DBGLVL_BUS, "%s() free_write_space = %d\n", __func__,
+               free_write_space);
+
+       dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp);
+       dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp);
+
+       /* Process the msg and write the content onto the bus */
+       while (bytes_to_write >= free_write_space) {
+
+               if (timeout-- == 0) {
+                       printk(KERN_ERR "%s() bus timeout\n", __func__);
+                       ret = SAA_ERR_NO_RESOURCES;
+                       goto out;
+               }
+
+               /* TODO: Review this delay, efficient? */
+               /* Wait, allowing the hardware fetch time */
+               mdelay(1);
+
+               /* Check the space usage again */
+               curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
+
+               /* Deal with ring wrapping issues */
+               if (curr_srp > curr_swp)
+                       /* Deal with the wrapped ring */
+                       free_write_space = curr_srp - curr_swp;
+               else
+                       /* Read didn't wrap around the buffer */
+                       free_write_space = (curr_srp + bus->m_dwSizeSetRing) -
+                               curr_swp;
+
+       }
+
+       /* Calculate the new write position */
+       new_swp = curr_swp + bytes_to_write;
+
+       dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
+       dprintk(DBGLVL_BUS, "%s() bus->m_dwSizeSetRing = %x\n", __func__,
+               bus->m_dwSizeSetRing);
+
+       /* Mental Note: line 462 tmmhComResBusPCIe.cpp */
+
+       /* Check if we're going to wrap again */
+       if (new_swp > bus->m_dwSizeSetRing) {
+
+               /* Ring wraps */
+               new_swp -= bus->m_dwSizeSetRing;
+
+               space_rem = bus->m_dwSizeSetRing - curr_swp;
+
+               dprintk(DBGLVL_BUS, "%s() space_rem = %x\n", __func__,
+                       space_rem);
+
+               dprintk(DBGLVL_BUS, "%s() sizeof(*msg) = %d\n", __func__,
+                       (u32)sizeof(*msg));
+
+               if (space_rem < sizeof(*msg)) {
+                       dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
+
+                       /* Split the msg into pieces as the ring wraps */
+                       memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem);
+                       memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem,
+                               sizeof(*msg) - space_rem);
+
+                       memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
+                               buf, msg->size);
+
+               } else if (space_rem == sizeof(*msg)) {
+                       dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
+
+                       /* Additional data at the beginning of the ring */
+                       memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+                       memcpy(bus->m_pdwSetRing, buf, msg->size);
+
+               } else {
+                       /* Additional data wraps around the ring */
+                       memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+                       if (msg->size > 0) {
+                               memcpy(bus->m_pdwSetRing + curr_swp +
+                                       sizeof(*msg), buf, space_rem -
+                                       sizeof(*msg));
+                               memcpy(bus->m_pdwSetRing, (u8 *)buf +
+                                       space_rem - sizeof(*msg),
+                                       bytes_to_write - space_rem);
+                       }
+
+               }
+
+       } /* (new_swp > bus->m_dwSizeSetRing) */
+       else {
+               dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
+
+               /* The ring buffer doesn't wrap, two simple copies */
+               memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+               memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
+                       msg->size);
+       }
+
+       dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
+
+       /* Update the bus write position */
+       saa7164_writel(bus->m_dwSetWritePos, cpu_to_le32(new_swp));
+       ret = SAA_OK;
+
+out:
+       saa7164_bus_dump(dev);
+       mutex_unlock(&bus->lock);
+       saa7164_bus_verify(dev);
+       return ret;
+}
+
+/*
+ * Receive a command or a response from the bus. The implementation does not
+ * know if it is a command or a response it simply dequeues the data,
+ * depending on the bus information given in the struct tmComResBusInfo
+ * structure.
+ *
+ * Return Value:
+ *  0          The function executed successfully.
+ *  < 0        One or more members are not initialized.
+ */
+int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
+       void *buf, int peekonly)
+{
+       struct tmComResBusInfo *bus = &dev->bus;
+       u32 bytes_to_read, write_distance, curr_grp, curr_gwp,
+               new_grp, buf_size, space_rem;
+       struct tmComResInfo msg_tmp;
+       int ret = SAA_ERR_BAD_PARAMETER;
+
+       saa7164_bus_verify(dev);
+
+       if (msg == NULL)
+               return ret;
+
+       if (msg->size > dev->bus.m_wMaxReqSize) {
+               printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
+                       __func__);
+               return ret;
+       }
+
+       if ((peekonly == 0) && (msg->size > 0) && (buf == NULL)) {
+               printk(KERN_ERR
+                       "%s() Missing msg buf, size should be %d bytes\n",
+                       __func__, msg->size);
+               return ret;
+       }
+
+       mutex_lock(&bus->lock);
+
+       /* Peek the bus to see if a msg exists, if it's not what we're expecting
+        * then return cleanly else read the message from the bus.
+        */
+       curr_gwp = le32_to_cpu(saa7164_readl(bus->m_dwGetWritePos));
+       curr_grp = le32_to_cpu(saa7164_readl(bus->m_dwGetReadPos));
+
+       if (curr_gwp == curr_grp) {
+               ret = SAA_ERR_EMPTY;
+               goto out;
+       }
+
+       bytes_to_read = sizeof(*msg);
+
+       /* Calculate write distance to current read position */
+       write_distance = 0;
+       if (curr_gwp >= curr_grp)
+               /* Write doesn't wrap around the ring */
+               write_distance = curr_gwp - curr_grp;
+       else
+               /* Write wraps around the ring */
+               write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
+
+       if (bytes_to_read > write_distance) {
+               printk(KERN_ERR "%s() No message/response found\n", __func__);
+               ret = SAA_ERR_INVALID_COMMAND;
+               goto out;
+       }
+
+       /* Calculate the new read position */
+       new_grp = curr_grp + bytes_to_read;
+       if (new_grp > bus->m_dwSizeGetRing) {
+
+               /* Ring wraps */
+               new_grp -= bus->m_dwSizeGetRing;
+               space_rem = bus->m_dwSizeGetRing - curr_grp;
+
+               memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
+               memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
+                       bytes_to_read - space_rem);
+
+       } else {
+               /* No wrapping */
+               memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
+       }
+
+       /* No need to update the read positions, because this was a peek */
+       /* If the caller specifically want to peek, return */
+       if (peekonly) {
+               memcpy(msg, &msg_tmp, sizeof(*msg));
+               goto peekout;
+       }
+
+       /* Check if the command/response matches what is expected */
+       if ((msg_tmp.id != msg->id) || (msg_tmp.command != msg->command) ||
+               (msg_tmp.controlselector != msg->controlselector) ||
+               (msg_tmp.seqno != msg->seqno) || (msg_tmp.size != msg->size)) {
+
+               printk(KERN_ERR "%s() Unexpected msg miss-match\n", __func__);
+               saa7164_bus_dumpmsg(dev, msg, buf);
+               saa7164_bus_dumpmsg(dev, &msg_tmp, NULL);
+               ret = SAA_ERR_INVALID_COMMAND;
+               goto out;
+       }
+
+       /* Get the actual command and response from the bus */
+       buf_size = msg->size;
+
+       bytes_to_read = sizeof(*msg) + msg->size;
+       /* Calculate write distance to current read position */
+       write_distance = 0;
+       if (curr_gwp >= curr_grp)
+               /* Write doesn't wrap around the ring */
+               write_distance = curr_gwp - curr_grp;
+       else
+               /* Write wraps around the ring */
+               write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
+
+       if (bytes_to_read > write_distance) {
+               printk(KERN_ERR "%s() Invalid bus state, missing msg "
+                       "or mangled ring, faulty H/W / bad code?\n", __func__);
+               ret = SAA_ERR_INVALID_COMMAND;
+               goto out;
+       }
+
+       /* Calculate the new read position */
+       new_grp = curr_grp + bytes_to_read;
+       if (new_grp > bus->m_dwSizeGetRing) {
+
+               /* Ring wraps */
+               new_grp -= bus->m_dwSizeGetRing;
+               space_rem = bus->m_dwSizeGetRing - curr_grp;
+
+               if (space_rem < sizeof(*msg)) {
+                       /* msg wraps around the ring */
+                       memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem);
+                       memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing,
+                               sizeof(*msg) - space_rem);
+                       if (buf)
+                               memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) -
+                                       space_rem, buf_size);
+
+               } else if (space_rem == sizeof(*msg)) {
+                       memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+                       if (buf)
+                               memcpy(buf, bus->m_pdwGetRing, buf_size);
+               } else {
+                       /* Additional data wraps around the ring */
+                       memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+                       if (buf) {
+                               memcpy(buf, bus->m_pdwGetRing + curr_grp +
+                                       sizeof(*msg), space_rem - sizeof(*msg));
+                               memcpy(buf + space_rem - sizeof(*msg),
+                                       bus->m_pdwGetRing, bytes_to_read -
+                                       space_rem);
+                       }
+
+               }
+
+       } else {
+               /* No wrapping */
+               memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+               if (buf)
+                       memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
+                               buf_size);
+       }
+
+       /* Update the read positions, adjusting the ring */
+       saa7164_writel(bus->m_dwGetReadPos, cpu_to_le32(new_grp));
+
+peekout:
+       msg->size = le16_to_cpu(msg->size);
+       msg->command = le32_to_cpu(msg->command);
+       msg->controlselector = le16_to_cpu(msg->controlselector);
+       ret = SAA_OK;
+out:
+       mutex_unlock(&bus->lock);
+       saa7164_bus_verify(dev);
+       return ret;
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-cards.c b/drivers/media/pci/saa7164/saa7164-cards.c
new file mode 100644 (file)
index 0000000..5b72da5
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "saa7164.h"
+
+/* The Bridge API needs to understand register widths (in bytes) for the
+ * attached I2C devices, so we can simplify the virtual i2c mechansms
+ * and keep the -i2c.c implementation clean.
+ */
+#define REGLEN_8bit    1
+#define REGLEN_16bit   2
+
+struct saa7164_board saa7164_boards[] = {
+       [SAA7164_BOARD_UNKNOWN] = {
+               /* Bridge will not load any firmware, without knowing
+                * the rev this would be fatal. */
+               .name           = "Unknown",
+       },
+       [SAA7164_BOARD_UNKNOWN_REV2] = {
+               /* Bridge will load the v2 f/w and dump descriptors */
+               /* Required during new board bringup */
+               .name           = "Generic Rev2",
+               .chiprev        = SAA7164_CHIP_REV2,
+       },
+       [SAA7164_BOARD_UNKNOWN_REV3] = {
+               /* Bridge will load the v2 f/w and dump descriptors */
+               /* Required during new board bringup */
+               .name           = "Generic Rev3",
+               .chiprev        = SAA7164_CHIP_REV3,
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2200] = {
+               .name           = "Hauppauge WinTV-HVR2200",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV3,
+               .unit           = {{
+                       .id             = 0x1d,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1b,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1e,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x10 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1f,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x12 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2200_2] = {
+               .name           = "Hauppauge WinTV-HVR2200",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV2,
+               .unit           = {{
+                       .id             = 0x06,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x05,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x10 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1e,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1f,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x12 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2200_3] = {
+               .name           = "Hauppauge WinTV-HVR2200",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV2,
+               .unit           = {{
+                       .id             = 0x1d,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x05,
+                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
+                       .name           = "TDA8290-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x84 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1b,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1c,
+                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
+                       .name           = "TDA8290-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x84 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1e,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x10 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1f,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x12 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = {
+               .name           = "Hauppauge WinTV-HVR2200",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV3,
+               .unit           = {{
+                       .id             = 0x1d,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x05,
+                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
+                       .name           = "TDA8290-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x84 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1b,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1c,
+                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
+                       .name           = "TDA8290-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x84 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1e,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x10 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1f,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x12 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
+               .name           = "Hauppauge WinTV-HVR2250",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV3,
+               .unit           = {{
+                       .id             = 0x22,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x07,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-1 (TOP)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x32 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x08,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-1 (QAM)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x34 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x1e,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x20,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-2 (TOP)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x32 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x23,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-2 (QAM)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x34 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = {
+               .name           = "Hauppauge WinTV-HVR2250",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV3,
+               .unit           = {{
+                       .id             = 0x28,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x07,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-1 (TOP)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x32 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x08,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-1 (QAM)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x34 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x24,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x26,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-2 (TOP)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x32 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x29,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-2 (QAM)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x34 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = {
+               .name           = "Hauppauge WinTV-HVR2250",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .portc          = SAA7164_MPEG_ENCODER,
+               .portd          = SAA7164_MPEG_ENCODER,
+               .porte          = SAA7164_MPEG_VBI,
+               .portf          = SAA7164_MPEG_VBI,
+               .chiprev        = SAA7164_CHIP_REV3,
+               .unit           = {{
+                       .id             = 0x26,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x07,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-1 (TOP)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x32 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x08,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-1 (QAM)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x34 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x22,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x24,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-2 (TOP)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x32 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x27,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "CX24228/S5H1411-2 (QAM)",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x34 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+       [SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
+               .name           = "Hauppauge WinTV-HVR2200",
+               .porta          = SAA7164_MPEG_DVB,
+               .portb          = SAA7164_MPEG_DVB,
+               .chiprev        = SAA7164_CHIP_REV3,
+               .unit           = {{
+                       .id             = 0x23,
+                       .type           = SAA7164_UNIT_EEPROM,
+                       .name           = "4K EEPROM",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
+                       .i2c_bus_addr   = 0xa0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x04,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x05,
+                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
+                       .name           = "TDA8290-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x84 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x21,
+                       .type           = SAA7164_UNIT_TUNER,
+                       .name           = "TDA18271-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0xc0 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x22,
+                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
+                       .name           = "TDA8290-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x84 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x24,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-1",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
+                       .i2c_bus_addr   = 0x10 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               }, {
+                       .id             = 0x25,
+                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
+                       .name           = "TDA10048-2",
+                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
+                       .i2c_bus_addr   = 0x12 >> 1,
+                       .i2c_reg_len    = REGLEN_8bit,
+               } },
+       },
+};
+const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
+
+/* ------------------------------------------------------------------ */
+/* PCI subsystem IDs                                                  */
+
+struct saa7164_subid saa7164_subids[] = {
+       {
+               .subvendor = 0x0070,
+               .subdevice = 0x8880,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8810,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8980,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8900,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_2,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8901,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_3,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x88A1,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_3,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8891,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8851,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8940,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
+       }, {
+               .subvendor = 0x0070,
+               .subdevice = 0x8953,
+               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
+       },
+};
+const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
+
+void saa7164_card_list(struct saa7164_dev *dev)
+{
+       int i;
+
+       if (0 == dev->pci->subsystem_vendor &&
+           0 == dev->pci->subsystem_device) {
+               printk(KERN_ERR
+                       "%s: Board has no valid PCIe Subsystem ID and can't\n"
+                       "%s: be autodetected. Pass card=<n> insmod option to\n"
+                       "%s: workaround that. Send complaints to the vendor\n"
+                       "%s: of the TV card. Best regards,\n"
+                       "%s:         -- tux\n",
+                       dev->name, dev->name, dev->name, dev->name, dev->name);
+       } else {
+               printk(KERN_ERR
+                       "%s: Your board isn't known (yet) to the driver.\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",
+                       dev->name, dev->name, dev->name, dev->name);
+       }
+
+       printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod "
+               "option:\n", dev->name);
+
+       for (i = 0; i < saa7164_bcount; i++)
+               printk(KERN_ERR "%s:    card=%d -> %s\n",
+                      dev->name, i, saa7164_boards[i].name);
+}
+
+/* TODO: clean this define up into the -cards.c structs */
+#define PCIEBRIDGE_UNITID 2
+
+void saa7164_gpio_setup(struct saa7164_dev *dev)
+{
+       switch (dev->board) {
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+               /*
+               GPIO 2: s5h1411 / tda10048-1 demod reset
+               GPIO 3: s5h1411 / tda10048-2 demod reset
+               GPIO 7: IRBlaster Zilog reset
+                */
+
+               /* Reset parts by going in and out of reset */
+               saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
+               saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
+
+               msleep(20);
+
+               saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
+               saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
+               break;
+       }
+}
+
+static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
+{
+       struct tveeprom tv;
+
+       /* TODO: Assumption: eeprom on bus 0 */
+       tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
+               eeprom_data);
+
+       /* Make sure we support the board model */
+       switch (tv.model) {
+       case 88001:
+               /* Development board - Limit circulation */
+               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
+                * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
+       case 88021:
+               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
+                * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */
+               break;
+       case 88041:
+               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
+                * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
+               break;
+       case 88061:
+               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
+                * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */
+               break;
+       case 89519:
+       case 89609:
+               /* WinTV-HVR2200 (PCIe, Retail, full-height)
+                * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
+               break;
+       case 89619:
+               /* WinTV-HVR2200 (PCIe, Retail, half-height)
+                * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
+               break;
+       default:
+               printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
+                       dev->name, tv.model);
+               break;
+       }
+
+       printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name,
+               tv.model);
+}
+
+void saa7164_card_setup(struct saa7164_dev *dev)
+{
+       static u8 eeprom[256];
+
+       if (dev->i2c_bus[0].i2c_rc == 0) {
+               if (saa7164_api_read_eeprom(dev, &eeprom[0],
+                       sizeof(eeprom)) < 0)
+                       return;
+       }
+
+       switch (dev->board) {
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+               hauppauge_eeprom(dev, &eeprom[0]);
+               break;
+       }
+}
+
+/* With most other drivers, the kernel expects to communicate with subdrivers
+ * through i2c. This bridge does not allow that, it does not expose any direct
+ * access to I2C. Instead we have to communicate through the device f/w for
+ * register access to 'processing units'. Each unit has a unique
+ * id, regardless of how the physical implementation occurs across
+ * the three physical i2c busses. The being said if we want leverge of
+ * the existing kernel drivers for tuners and demods we have to 'speak i2c',
+ * to this bridge implements 3 virtual i2c buses. This is a helper function
+ * for those.
+ *
+ * Description: Translate the kernels notion of an i2c address and bus into
+ * the appropriate unitid.
+ */
+int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr)
+{
+       /* For a given bus and i2c device address, return the saa7164 unique
+        * unitid. < 0 on error */
+
+       struct saa7164_dev *dev = bus->dev;
+       struct saa7164_unit *unit;
+       int i;
+
+       for (i = 0; i < SAA7164_MAX_UNITS; i++) {
+               unit = &saa7164_boards[dev->board].unit[i];
+
+               if (unit->type == SAA7164_UNIT_UNDEFINED)
+                       continue;
+               if ((bus->nr == unit->i2c_bus_nr) &&
+                       (addr == unit->i2c_bus_addr))
+                       return unit->id;
+       }
+
+       return -1;
+}
+
+/* The 7164 API needs to know the i2c register length in advance.
+ * this is a helper function. Based on a specific chip addr and bus return the
+ * reg length.
+ */
+int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr)
+{
+       /* For a given bus and i2c device address, return the
+        * saa7164 registry address width. < 0 on error
+        */
+
+       struct saa7164_dev *dev = bus->dev;
+       struct saa7164_unit *unit;
+       int i;
+
+       for (i = 0; i < SAA7164_MAX_UNITS; i++) {
+               unit = &saa7164_boards[dev->board].unit[i];
+
+               if (unit->type == SAA7164_UNIT_UNDEFINED)
+                       continue;
+
+               if ((bus->nr == unit->i2c_bus_nr) &&
+                       (addr == unit->i2c_bus_addr))
+                       return unit->i2c_reg_len;
+       }
+
+       return -1;
+}
+/* TODO: implement a 'findeeprom' functio like the above and fix any other
+ * eeprom related todo's in -api.c.
+ */
+
+/* Translate a unitid into a x readable device name, for display purposes.  */
+char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid)
+{
+       char *undefed = "UNDEFINED";
+       char *bridge = "BRIDGE";
+       struct saa7164_unit *unit;
+       int i;
+
+       if (unitid == 0)
+               return bridge;
+
+       for (i = 0; i < SAA7164_MAX_UNITS; i++) {
+               unit = &saa7164_boards[dev->board].unit[i];
+
+               if (unit->type == SAA7164_UNIT_UNDEFINED)
+                       continue;
+
+               if (unitid == unit->id)
+                               return unit->name;
+       }
+
+       return undefed;
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-cmd.c b/drivers/media/pci/saa7164/saa7164-cmd.c
new file mode 100644 (file)
index 0000000..62fac7f
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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/wait.h>
+
+#include "saa7164.h"
+
+int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
+{
+       int i, ret = -1;
+
+       mutex_lock(&dev->lock);
+       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
+               if (dev->cmds[i].inuse == 0) {
+                       dev->cmds[i].inuse = 1;
+                       dev->cmds[i].signalled = 0;
+                       dev->cmds[i].timeout = 0;
+                       ret = dev->cmds[i].seqno;
+                       break;
+               }
+       }
+       mutex_unlock(&dev->lock);
+
+       return ret;
+}
+
+void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
+{
+       mutex_lock(&dev->lock);
+       if ((dev->cmds[seqno].inuse == 1) &&
+               (dev->cmds[seqno].seqno == seqno)) {
+               dev->cmds[seqno].inuse = 0;
+               dev->cmds[seqno].signalled = 0;
+               dev->cmds[seqno].timeout = 0;
+       }
+       mutex_unlock(&dev->lock);
+}
+
+void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
+{
+       mutex_lock(&dev->lock);
+       if ((dev->cmds[seqno].inuse == 1) &&
+               (dev->cmds[seqno].seqno == seqno)) {
+               dev->cmds[seqno].timeout = 1;
+       }
+       mutex_unlock(&dev->lock);
+}
+
+u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
+{
+       int ret = 0;
+
+       mutex_lock(&dev->lock);
+       if ((dev->cmds[seqno].inuse == 1) &&
+               (dev->cmds[seqno].seqno == seqno)) {
+               ret = dev->cmds[seqno].timeout;
+       }
+       mutex_unlock(&dev->lock);
+
+       return ret;
+}
+
+/* Commands to the f/w get marshelled to/from this code then onto the PCI
+ * -bus/c running buffer. */
+int saa7164_irq_dequeue(struct saa7164_dev *dev)
+{
+       int ret = SAA_OK, i = 0;
+       u32 timeout;
+       wait_queue_head_t *q = NULL;
+       u8 tmp[512];
+       dprintk(DBGLVL_CMD, "%s()\n", __func__);
+
+       /* While any outstand message on the bus exists... */
+       do {
+
+               /* Peek the msg bus */
+               struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
+               ret = saa7164_bus_get(dev, &tRsp, NULL, 1);
+               if (ret != SAA_OK)
+                       break;
+
+               q = &dev->cmds[tRsp.seqno].wait;
+               timeout = saa7164_cmd_timeout_get(dev, tRsp.seqno);
+               dprintk(DBGLVL_CMD, "%s() timeout = %d\n", __func__, timeout);
+               if (!timeout) {
+                       dprintk(DBGLVL_CMD,
+                               "%s() signalled seqno(%d) (for dequeue)\n",
+                               __func__, tRsp.seqno);
+                       dev->cmds[tRsp.seqno].signalled = 1;
+                       wake_up(q);
+               } else {
+                       printk(KERN_ERR
+                               "%s() found timed out command on the bus\n",
+                                       __func__);
+
+                       /* Clean the bus */
+                       ret = saa7164_bus_get(dev, &tRsp, &tmp, 0);
+                       printk(KERN_ERR "%s() ret = %x\n", __func__, ret);
+                       if (ret == SAA_ERR_EMPTY)
+                               /* Someone else already fetched the response */
+                               return SAA_OK;
+
+                       if (ret != SAA_OK)
+                               return ret;
+               }
+
+               /* It's unlikely to have more than 4 or 5 pending messages,
+                * ensure we exit at some point regardless.
+                */
+       } while (i++ < 32);
+
+       return ret;
+}
+
+/* Commands to the f/w get marshelled to/from this code then onto the PCI
+ * -bus/c running buffer. */
+int saa7164_cmd_dequeue(struct saa7164_dev *dev)
+{
+       int loop = 1;
+       int ret;
+       u32 timeout;
+       wait_queue_head_t *q = NULL;
+       u8 tmp[512];
+       dprintk(DBGLVL_CMD, "%s()\n", __func__);
+
+       while (loop) {
+
+               struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
+               ret = saa7164_bus_get(dev, &tRsp, NULL, 1);
+               if (ret == SAA_ERR_EMPTY)
+                       return SAA_OK;
+
+               if (ret != SAA_OK)
+                       return ret;
+
+               q = &dev->cmds[tRsp.seqno].wait;
+               timeout = saa7164_cmd_timeout_get(dev, tRsp.seqno);
+               dprintk(DBGLVL_CMD, "%s() timeout = %d\n", __func__, timeout);
+               if (timeout) {
+                       printk(KERN_ERR "found timed out command on the bus\n");
+
+                       /* Clean the bus */
+                       ret = saa7164_bus_get(dev, &tRsp, &tmp, 0);
+                       printk(KERN_ERR "ret = %x\n", ret);
+                       if (ret == SAA_ERR_EMPTY)
+                               /* Someone else already fetched the response */
+                               return SAA_OK;
+
+                       if (ret != SAA_OK)
+                               return ret;
+
+                       if (tRsp.flags & PVC_CMDFLAG_CONTINUE)
+                               printk(KERN_ERR "split response\n");
+                       else
+                               saa7164_cmd_free_seqno(dev, tRsp.seqno);
+
+                       printk(KERN_ERR " timeout continue\n");
+                       continue;
+               }
+
+               dprintk(DBGLVL_CMD, "%s() signalled seqno(%d) (for dequeue)\n",
+                       __func__, tRsp.seqno);
+               dev->cmds[tRsp.seqno].signalled = 1;
+               wake_up(q);
+               return SAA_OK;
+       }
+
+       return SAA_OK;
+}
+
+int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
+       void *buf)
+{
+       struct tmComResBusInfo *bus = &dev->bus;
+       u8 cmd_sent;
+       u16 size, idx;
+       u32 cmds;
+       void *tmp;
+       int ret = -1;
+
+       if (!msg) {
+               printk(KERN_ERR "%s() !msg\n", __func__);
+               return SAA_ERR_BAD_PARAMETER;
+       }
+
+       mutex_lock(&dev->cmds[msg->id].lock);
+
+       size = msg->size;
+       idx = 0;
+       cmds = size / bus->m_wMaxReqSize;
+       if (size % bus->m_wMaxReqSize == 0)
+               cmds -= 1;
+
+       cmd_sent = 0;
+
+       /* Split the request into smaller chunks */
+       for (idx = 0; idx < cmds; idx++) {
+
+               msg->flags |= SAA_CMDFLAG_CONTINUE;
+               msg->size = bus->m_wMaxReqSize;
+               tmp = buf + idx * bus->m_wMaxReqSize;
+
+               ret = saa7164_bus_set(dev, msg, tmp);
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "%s() set failed %d\n", __func__, ret);
+
+                       if (cmd_sent) {
+                               ret = SAA_ERR_BUSY;
+                               goto out;
+                       }
+                       ret = SAA_ERR_OVERFLOW;
+                       goto out;
+               }
+               cmd_sent = 1;
+       }
+
+       /* If not the last command... */
+       if (idx != 0)
+               msg->flags &= ~SAA_CMDFLAG_CONTINUE;
+
+       msg->size = size - idx * bus->m_wMaxReqSize;
+
+       ret = saa7164_bus_set(dev, msg, buf + idx * bus->m_wMaxReqSize);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() set last failed %d\n", __func__, ret);
+
+               if (cmd_sent) {
+                       ret = SAA_ERR_BUSY;
+                       goto out;
+               }
+               ret = SAA_ERR_OVERFLOW;
+               goto out;
+       }
+       ret = SAA_OK;
+
+out:
+       mutex_unlock(&dev->cmds[msg->id].lock);
+       return ret;
+}
+
+/* Wait for a signal event, without holding a mutex. Either return TIMEOUT if
+ * the event never occurred, or SAA_OK if it was signaled during the wait.
+ */
+int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
+{
+       wait_queue_head_t *q = NULL;
+       int ret = SAA_BUS_TIMEOUT;
+       unsigned long stamp;
+       int r;
+
+       if (saa_debug >= 4)
+               saa7164_bus_dump(dev);
+
+       dprintk(DBGLVL_CMD, "%s(seqno=%d)\n", __func__, seqno);
+
+       mutex_lock(&dev->lock);
+       if ((dev->cmds[seqno].inuse == 1) &&
+               (dev->cmds[seqno].seqno == seqno)) {
+               q = &dev->cmds[seqno].wait;
+       }
+       mutex_unlock(&dev->lock);
+
+       if (q) {
+               /* If we haven't been signalled we need to wait */
+               if (dev->cmds[seqno].signalled == 0) {
+                       stamp = jiffies;
+                       dprintk(DBGLVL_CMD,
+                               "%s(seqno=%d) Waiting (signalled=%d)\n",
+                               __func__, seqno, dev->cmds[seqno].signalled);
+
+                       /* Wait for signalled to be flagged or timeout */
+                       /* In a highly stressed system this can easily extend
+                        * into multiple seconds before the deferred worker
+                        * is scheduled, and we're woken up via signal.
+                        * We typically are signalled in < 50ms but it can
+                        * take MUCH longer.
+                        */
+                       wait_event_timeout(*q, dev->cmds[seqno].signalled,
+                               (HZ * waitsecs));
+                       r = time_before(jiffies, stamp + (HZ * waitsecs));
+                       if (r)
+                               ret = SAA_OK;
+                       else
+                               saa7164_cmd_timeout_seqno(dev, seqno);
+
+                       dprintk(DBGLVL_CMD, "%s(seqno=%d) Waiting res = %d "
+                               "(signalled=%d)\n", __func__, seqno, r,
+                               dev->cmds[seqno].signalled);
+               } else
+                       ret = SAA_OK;
+       } else
+               printk(KERN_ERR "%s(seqno=%d) seqno is invalid\n",
+                       __func__, seqno);
+
+       return ret;
+}
+
+void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno)
+{
+       int i;
+       dprintk(DBGLVL_CMD, "%s()\n", __func__);
+
+       mutex_lock(&dev->lock);
+       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
+               if (dev->cmds[i].inuse == 1) {
+                       dprintk(DBGLVL_CMD,
+                               "seqno %d inuse, sig = %d, t/out = %d\n",
+                               dev->cmds[i].seqno,
+                               dev->cmds[i].signalled,
+                               dev->cmds[i].timeout);
+               }
+       }
+
+       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
+               if ((dev->cmds[i].inuse == 1) && ((i == 0) ||
+                       (dev->cmds[i].signalled) || (dev->cmds[i].timeout))) {
+                       dprintk(DBGLVL_CMD, "%s(seqno=%d) calling wake_up\n",
+                               __func__, i);
+                       dev->cmds[i].signalled = 1;
+                       wake_up(&dev->cmds[i].wait);
+               }
+       }
+       mutex_unlock(&dev->lock);
+}
+
+int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command,
+       u16 controlselector, u16 size, void *buf)
+{
+       struct tmComResInfo command_t, *pcommand_t;
+       struct tmComResInfo response_t, *presponse_t;
+       u8 errdata[256];
+       u16 resp_dsize;
+       u16 data_recd;
+       u32 loop;
+       int ret;
+       int safety = 0;
+
+       dprintk(DBGLVL_CMD, "%s(unitid = %s (%d) , command = 0x%x, "
+               "sel = 0x%x)\n", __func__, saa7164_unitid_name(dev, id), id,
+               command, controlselector);
+
+       if ((size == 0) || (buf == NULL)) {
+               printk(KERN_ERR "%s() Invalid param\n", __func__);
+               return SAA_ERR_BAD_PARAMETER;
+       }
+
+       /* Prepare some basic command/response structures */
+       memset(&command_t, 0, sizeof(command_t));
+       memset(&response_t, 0, sizeof(response_t));
+       pcommand_t = &command_t;
+       presponse_t = &response_t;
+       command_t.id = id;
+       command_t.command = command;
+       command_t.controlselector = controlselector;
+       command_t.size = size;
+
+       /* Allocate a unique sequence number */
+       ret = saa7164_cmd_alloc_seqno(dev);
+       if (ret < 0) {
+               printk(KERN_ERR "%s() No free sequences\n", __func__);
+               ret = SAA_ERR_NO_RESOURCES;
+               goto out;
+       }
+
+       command_t.seqno = (u8)ret;
+
+       /* Send Command */
+       resp_dsize = size;
+       pcommand_t->size = size;
+
+       dprintk(DBGLVL_CMD, "%s() pcommand_t.seqno = %d\n",
+               __func__, pcommand_t->seqno);
+
+       dprintk(DBGLVL_CMD, "%s() pcommand_t.size = %d\n",
+               __func__, pcommand_t->size);
+
+       ret = saa7164_cmd_set(dev, pcommand_t, buf);
+       if (ret != SAA_OK) {
+               printk(KERN_ERR "%s() set command failed %d\n", __func__, ret);
+
+               if (ret != SAA_ERR_BUSY)
+                       saa7164_cmd_free_seqno(dev, pcommand_t->seqno);
+               else
+                       /* Flag a timeout, because at least one
+                        * command was sent */
+                       saa7164_cmd_timeout_seqno(dev, pcommand_t->seqno);
+
+               goto out;
+       }
+
+       /* With split responses we have to collect the msgs piece by piece */
+       data_recd = 0;
+       loop = 1;
+       while (loop) {
+               dprintk(DBGLVL_CMD, "%s() loop\n", __func__);
+
+               ret = saa7164_cmd_wait(dev, pcommand_t->seqno);
+               dprintk(DBGLVL_CMD, "%s() loop ret = %d\n", __func__, ret);
+
+               /* if power is down and this is not a power command ... */
+
+               if (ret == SAA_BUS_TIMEOUT) {
+                       printk(KERN_ERR "Event timed out\n");
+                       saa7164_cmd_timeout_seqno(dev, pcommand_t->seqno);
+                       return ret;
+               }
+
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "spurious error\n");
+                       return ret;
+               }
+
+               /* Peek response */
+               ret = saa7164_bus_get(dev, presponse_t, NULL, 1);
+               if (ret == SAA_ERR_EMPTY) {
+                       dprintk(4, "%s() SAA_ERR_EMPTY\n", __func__);
+                       continue;
+               }
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "peek failed\n");
+                       return ret;
+               }
+
+               dprintk(DBGLVL_CMD, "%s() presponse_t->seqno = %d\n",
+                       __func__, presponse_t->seqno);
+
+               dprintk(DBGLVL_CMD, "%s() presponse_t->flags = 0x%x\n",
+                       __func__, presponse_t->flags);
+
+               dprintk(DBGLVL_CMD, "%s() presponse_t->size = %d\n",
+                       __func__, presponse_t->size);
+
+               /* Check if the response was for our command */
+               if (presponse_t->seqno != pcommand_t->seqno) {
+
+                       dprintk(DBGLVL_CMD,
+                               "wrong event: seqno = %d, "
+                               "expected seqno = %d, "
+                               "will dequeue regardless\n",
+                               presponse_t->seqno, pcommand_t->seqno);
+
+                       ret = saa7164_cmd_dequeue(dev);
+                       if (ret != SAA_OK) {
+                               printk(KERN_ERR "dequeue failed, ret = %d\n",
+                                       ret);
+                               if (safety++ > 16) {
+                                       printk(KERN_ERR
+                                       "dequeue exceeded, safety exit\n");
+                                       return SAA_ERR_BUSY;
+                               }
+                       }
+
+                       continue;
+               }
+
+               if ((presponse_t->flags & PVC_RESPONSEFLAG_ERROR) != 0) {
+
+                       memset(&errdata[0], 0, sizeof(errdata));
+
+                       ret = saa7164_bus_get(dev, presponse_t, &errdata[0], 0);
+                       if (ret != SAA_OK) {
+                               printk(KERN_ERR "get error(2)\n");
+                               return ret;
+                       }
+
+                       saa7164_cmd_free_seqno(dev, pcommand_t->seqno);
+
+                       dprintk(DBGLVL_CMD, "%s() errdata %02x%02x%02x%02x\n",
+                               __func__, errdata[0], errdata[1], errdata[2],
+                               errdata[3]);
+
+                       /* Map error codes */
+                       dprintk(DBGLVL_CMD, "%s() cmd, error code  = 0x%x\n",
+                               __func__, errdata[0]);
+
+                       switch (errdata[0]) {
+                       case PVC_ERRORCODE_INVALID_COMMAND:
+                               dprintk(DBGLVL_CMD, "%s() INVALID_COMMAND\n",
+                                       __func__);
+                               ret = SAA_ERR_INVALID_COMMAND;
+                               break;
+                       case PVC_ERRORCODE_INVALID_DATA:
+                               dprintk(DBGLVL_CMD, "%s() INVALID_DATA\n",
+                                       __func__);
+                               ret = SAA_ERR_BAD_PARAMETER;
+                               break;
+                       case PVC_ERRORCODE_TIMEOUT:
+                               dprintk(DBGLVL_CMD, "%s() TIMEOUT\n", __func__);
+                               ret = SAA_ERR_TIMEOUT;
+                               break;
+                       case PVC_ERRORCODE_NAK:
+                               dprintk(DBGLVL_CMD, "%s() NAK\n", __func__);
+                               ret = SAA_ERR_NULL_PACKET;
+                               break;
+                       case PVC_ERRORCODE_UNKNOWN:
+                       case PVC_ERRORCODE_INVALID_CONTROL:
+                               dprintk(DBGLVL_CMD,
+                                       "%s() UNKNOWN OR INVALID CONTROL\n",
+                                       __func__);
+                       default:
+                               dprintk(DBGLVL_CMD, "%s() UNKNOWN\n", __func__);
+                               ret = SAA_ERR_NOT_SUPPORTED;
+                       }
+
+                       /* See of other commands are on the bus */
+                       if (saa7164_cmd_dequeue(dev) != SAA_OK)
+                               printk(KERN_ERR "dequeue(2) failed\n");
+
+                       return ret;
+               }
+
+               /* If response is invalid */
+               if ((presponse_t->id != pcommand_t->id) ||
+                       (presponse_t->command != pcommand_t->command) ||
+                       (presponse_t->controlselector !=
+                               pcommand_t->controlselector) ||
+                       (((resp_dsize - data_recd) != presponse_t->size) &&
+                               !(presponse_t->flags & PVC_CMDFLAG_CONTINUE)) ||
+                       ((resp_dsize - data_recd) < presponse_t->size)) {
+
+                       /* Invalid */
+                       dprintk(DBGLVL_CMD, "%s() Invalid\n", __func__);
+                       ret = saa7164_bus_get(dev, presponse_t, NULL, 0);
+                       if (ret != SAA_OK) {
+                               printk(KERN_ERR "get failed\n");
+                               return ret;
+                       }
+
+                       /* See of other commands are on the bus */
+                       if (saa7164_cmd_dequeue(dev) != SAA_OK)
+                               printk(KERN_ERR "dequeue(3) failed\n");
+                       continue;
+               }
+
+               /* OK, now we're actually getting out correct response */
+               ret = saa7164_bus_get(dev, presponse_t, buf + data_recd, 0);
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "get failed\n");
+                       return ret;
+               }
+
+               data_recd = presponse_t->size + data_recd;
+               if (resp_dsize == data_recd) {
+                       dprintk(DBGLVL_CMD, "%s() Resp recd\n", __func__);
+                       break;
+               }
+
+               /* See of other commands are on the bus */
+               if (saa7164_cmd_dequeue(dev) != SAA_OK)
+                       printk(KERN_ERR "dequeue(3) failed\n");
+
+               continue;
+
+       } /* (loop) */
+
+       /* Release the sequence number allocation */
+       saa7164_cmd_free_seqno(dev, pcommand_t->seqno);
+
+       /* if powerdown signal all pending commands */
+
+       dprintk(DBGLVL_CMD, "%s() Calling dequeue then exit\n", __func__);
+
+       /* See of other commands are on the bus */
+       if (saa7164_cmd_dequeue(dev) != SAA_OK)
+               printk(KERN_ERR "dequeue(4) failed\n");
+
+       ret = SAA_OK;
+out:
+       return ret;
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
new file mode 100644 (file)
index 0000000..2c9ad87
--- /dev/null
@@ -0,0 +1,1488 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
+#include "saa7164.h"
+
+MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@kernellabs.com>");
+MODULE_LICENSE("GPL");
+
+/*
+ *  1 Basic
+ *  2
+ *  4 i2c
+ *  8 api
+ * 16 cmd
+ * 32 bus
+ */
+
+unsigned int saa_debug;
+module_param_named(debug, saa_debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+unsigned int fw_debug;
+module_param(fw_debug, int, 0644);
+MODULE_PARM_DESC(fw_debug, "Firware debug level def:2");
+
+unsigned int encoder_buffers = SAA7164_MAX_ENCODER_BUFFERS;
+module_param(encoder_buffers, int, 0644);
+MODULE_PARM_DESC(encoder_buffers, "Total buffers in read queue 16-512 def:64");
+
+unsigned int vbi_buffers = SAA7164_MAX_VBI_BUFFERS;
+module_param(vbi_buffers, int, 0644);
+MODULE_PARM_DESC(vbi_buffers, "Total buffers in read queue 16-512 def:64");
+
+unsigned int waitsecs = 10;
+module_param(waitsecs, int, 0644);
+MODULE_PARM_DESC(waitsecs, "timeout on firmware messages");
+
+static unsigned int card[]  = {[0 ... (SAA7164_MAXBOARDS - 1)] = UNSET };
+module_param_array(card,  int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+unsigned int print_histogram = 64;
+module_param(print_histogram, int, 0644);
+MODULE_PARM_DESC(print_histogram, "print histogram values once");
+
+unsigned int crc_checking = 1;
+module_param(crc_checking, int, 0644);
+MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers");
+
+unsigned int guard_checking = 1;
+module_param(guard_checking, int, 0644);
+MODULE_PARM_DESC(guard_checking,
+       "enable dma sanity checking for buffer overruns");
+
+static unsigned int saa7164_devcount;
+
+static DEFINE_MUTEX(devlist);
+LIST_HEAD(saa7164_devlist);
+
+#define INT_SIZE 16
+
+static void saa7164_pack_verifier(struct saa7164_buffer *buf)
+{
+       u8 *p = (u8 *)buf->cpu;
+       int i;
+
+       for (i = 0; i < buf->actual_size; i += 2048) {
+
+               if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) ||
+                       (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) {
+                       printk(KERN_ERR "No pack at 0x%x\n", i);
+#if 0
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                                      p + 1, 32, false);
+#endif
+               }
+       }
+}
+
+#define FIXED_VIDEO_PID 0xf1
+#define FIXED_AUDIO_PID 0xf2
+
+static void saa7164_ts_verifier(struct saa7164_buffer *buf)
+{
+       struct saa7164_port *port = buf->port;
+       u32 i;
+       u8 cc, a;
+       u16 pid;
+       u8 __iomem *bufcpu = (u8 *)buf->cpu;
+
+       port->sync_errors = 0;
+       port->v_cc_errors = 0;
+       port->a_cc_errors = 0;
+
+       for (i = 0; i < buf->actual_size; i += 188) {
+               if (*(bufcpu + i) != 0x47)
+                       port->sync_errors++;
+
+               /* TODO: Query pid lower 8 bits, ignoring upper bits intensionally */
+               pid = ((*(bufcpu + i + 1) & 0x1f) << 8) | *(bufcpu + i + 2);
+               cc = *(bufcpu + i + 3) & 0x0f;
+
+               if (pid == FIXED_VIDEO_PID) {
+                       a = ((port->last_v_cc + 1) & 0x0f);
+                       if (a != cc) {
+                               printk(KERN_ERR "video cc last = %x current = %x i = %d\n",
+                                       port->last_v_cc, cc, i);
+                               port->v_cc_errors++;
+                       }
+
+                       port->last_v_cc = cc;
+               } else
+               if (pid == FIXED_AUDIO_PID) {
+                       a = ((port->last_a_cc + 1) & 0x0f);
+                       if (a != cc) {
+                               printk(KERN_ERR "audio cc last = %x current = %x i = %d\n",
+                                       port->last_a_cc, cc, i);
+                               port->a_cc_errors++;
+                       }
+
+                       port->last_a_cc = cc;
+               }
+
+       }
+
+       /* Only report errors if we've been through this function atleast
+        * once already and the cached cc values are primed. First time through
+        * always generates errors.
+        */
+       if (port->v_cc_errors && (port->done_first_interrupt > 1))
+               printk(KERN_ERR "video pid cc, %d errors\n", port->v_cc_errors);
+
+       if (port->a_cc_errors && (port->done_first_interrupt > 1))
+               printk(KERN_ERR "audio pid cc, %d errors\n", port->a_cc_errors);
+
+       if (port->sync_errors && (port->done_first_interrupt > 1))
+               printk(KERN_ERR "sync_errors = %d\n", port->sync_errors);
+
+       if (port->done_first_interrupt == 1)
+               port->done_first_interrupt++;
+}
+
+static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name)
+{
+       int i;
+
+       memset(hg, 0, sizeof(struct saa7164_histogram));
+       strcpy(hg->name, name);
+
+       /* First 30ms x 1ms */
+       for (i = 0; i < 30; i++)
+               hg->counter1[0 + i].val = i;
+
+       /* 30 - 200ms x 10ms  */
+       for (i = 0; i < 18; i++)
+               hg->counter1[30 + i].val = 30 + (i * 10);
+
+       /* 200 - 2000ms x 100ms  */
+       for (i = 0; i < 15; i++)
+               hg->counter1[48 + i].val = 200 + (i * 200);
+
+       /* Catch all massive value (2secs) */
+       hg->counter1[55].val = 2000;
+
+       /* Catch all massive value (4secs) */
+       hg->counter1[56].val = 4000;
+
+       /* Catch all massive value (8secs) */
+       hg->counter1[57].val = 8000;
+
+       /* Catch all massive value (15secs) */
+       hg->counter1[58].val = 15000;
+
+       /* Catch all massive value (30secs) */
+       hg->counter1[59].val = 30000;
+
+       /* Catch all massive value (60secs) */
+       hg->counter1[60].val = 60000;
+
+       /* Catch all massive value (5mins) */
+       hg->counter1[61].val = 300000;
+
+       /* Catch all massive value (15mins) */
+       hg->counter1[62].val = 900000;
+
+       /* Catch all massive values (1hr) */
+       hg->counter1[63].val = 3600000;
+}
+
+void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val)
+{
+       int i;
+       for (i = 0; i < 64; i++) {
+               if (val <= hg->counter1[i].val) {
+                       hg->counter1[i].count++;
+                       hg->counter1[i].update_time = jiffies;
+                       break;
+               }
+       }
+}
+
+static void saa7164_histogram_print(struct saa7164_port *port,
+       struct saa7164_histogram *hg)
+{
+       u32 entries = 0;
+       int i;
+
+       printk(KERN_ERR "Histogram named %s (ms, count, last_update_jiffy)\n", hg->name);
+       for (i = 0; i < 64; i++) {
+               if (hg->counter1[i].count == 0)
+                       continue;
+
+               printk(KERN_ERR " %4d %12d %Ld\n",
+                       hg->counter1[i].val,
+                       hg->counter1[i].count,
+                       hg->counter1[i].update_time);
+
+               entries++;
+       }
+       printk(KERN_ERR "Total: %d\n", entries);
+}
+
+static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf = NULL;
+       struct saa7164_user_buffer *ubuf = NULL;
+       struct list_head *c, *n;
+       int i = 0;
+       u8 __iomem *p;
+
+       mutex_lock(&port->dmaqueue_lock);
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+
+               buf = list_entry(c, struct saa7164_buffer, list);
+               if (i++ > port->hwcfg.buffercount) {
+                       printk(KERN_ERR "%s() illegal i count %d\n",
+                               __func__, i);
+                       break;
+               }
+
+               if (buf->idx == bufnr) {
+
+                       /* Found the buffer, deal with it */
+                       dprintk(DBGLVL_IRQ, "%s() bufnr: %d\n", __func__, bufnr);
+
+                       if (crc_checking) {
+                               /* Throw a new checksum on the dma buffer */
+                               buf->crc = crc32(0, buf->cpu, buf->actual_size);
+                       }
+
+                       if (guard_checking) {
+                               p = (u8 *)buf->cpu;
+                               if ((*(p + buf->actual_size + 0) != 0xff) ||
+                                       (*(p + buf->actual_size + 1) != 0xff) ||
+                                       (*(p + buf->actual_size + 2) != 0xff) ||
+                                       (*(p + buf->actual_size + 3) != 0xff) ||
+                                       (*(p + buf->actual_size + 0x10) != 0xff) ||
+                                       (*(p + buf->actual_size + 0x11) != 0xff) ||
+                                       (*(p + buf->actual_size + 0x12) != 0xff) ||
+                                       (*(p + buf->actual_size + 0x13) != 0xff)) {
+                                               printk(KERN_ERR "%s() buf %p guard buffer breach\n",
+                                                       __func__, buf);
+#if 0
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                                      p + buf->actual_size - 32, 64, false);
+#endif
+                               }
+                       }
+
+                       if ((port->nr != SAA7164_PORT_VBI1) && (port->nr != SAA7164_PORT_VBI2)) {
+                               /* Validate the incoming buffer content */
+                               if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
+                                       saa7164_ts_verifier(buf);
+                               else if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
+                                       saa7164_pack_verifier(buf);
+                       }
+
+                       /* find a free user buffer and clone to it */
+                       if (!list_empty(&port->list_buf_free.list)) {
+
+                               /* Pull the first buffer from the used list */
+                               ubuf = list_first_entry(&port->list_buf_free.list,
+                                       struct saa7164_user_buffer, list);
+
+                               if (buf->actual_size <= ubuf->actual_size) {
+
+                                       memcpy_fromio(ubuf->data, buf->cpu,
+                                               ubuf->actual_size);
+
+                                       if (crc_checking) {
+                                               /* Throw a new checksum on the read buffer */
+                                               ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
+                                       }
+
+                                       /* Requeue the buffer on the free list */
+                                       ubuf->pos = 0;
+
+                                       list_move_tail(&ubuf->list,
+                                               &port->list_buf_used.list);
+
+                                       /* Flag any userland waiters */
+                                       wake_up_interruptible(&port->wait_read);
+
+                               } else {
+                                       printk(KERN_ERR "buf %p bufsize fails match\n", buf);
+                               }
+
+                       } else
+                               printk(KERN_ERR "encirq no free buffers, increase param encoder_buffers\n");
+
+                       /* Ensure offset into buffer remains 0, fill buffer
+                        * with known bad data. We check for this data at a later point
+                        * in time. */
+                       saa7164_buffer_zero_offsets(port, bufnr);
+                       memset_io(buf->cpu, 0xff, buf->pci_size);
+                       if (crc_checking) {
+                               /* Throw yet aanother new checksum on the dma buffer */
+                               buf->crc = crc32(0, buf->cpu, buf->actual_size);
+                       }
+
+                       break;
+               }
+       }
+       mutex_unlock(&port->dmaqueue_lock);
+}
+
+static void saa7164_work_enchandler(struct work_struct *w)
+{
+       struct saa7164_port *port =
+               container_of(w, struct saa7164_port, workenc);
+       struct saa7164_dev *dev = port->dev;
+
+       u32 wp, mcb, rp, cnt = 0;
+
+       port->last_svc_msecs_diff = port->last_svc_msecs;
+       port->last_svc_msecs = jiffies_to_msecs(jiffies);
+
+       port->last_svc_msecs_diff = port->last_svc_msecs -
+               port->last_svc_msecs_diff;
+
+       saa7164_histogram_update(&port->svc_interval,
+               port->last_svc_msecs_diff);
+
+       port->last_irq_svc_msecs_diff = port->last_svc_msecs -
+               port->last_irq_msecs;
+
+       saa7164_histogram_update(&port->irq_svc_interval,
+               port->last_irq_svc_msecs_diff);
+
+       dprintk(DBGLVL_IRQ,
+               "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
+               __func__,
+               port->last_svc_msecs_diff,
+               port->last_irq_svc_msecs_diff,
+               port->last_svc_wp,
+               port->last_svc_rp
+               );
+
+       /* Current write position */
+       wp = saa7164_readl(port->bufcounter);
+       if (wp > (port->hwcfg.buffercount - 1)) {
+               printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
+               return;
+       }
+
+       /* Most current complete buffer */
+       if (wp == 0)
+               mcb = (port->hwcfg.buffercount - 1);
+       else
+               mcb = wp - 1;
+
+       while (1) {
+               if (port->done_first_interrupt == 0) {
+                       port->done_first_interrupt++;
+                       rp = mcb;
+               } else
+                       rp = (port->last_svc_rp + 1) % 8;
+
+               if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
+                       printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
+                       break;
+               }
+
+               saa7164_work_enchandler_helper(port, rp);
+               port->last_svc_rp = rp;
+               cnt++;
+
+               if (rp == mcb)
+                       break;
+       }
+
+       /* TODO: Convert this into a /proc/saa7164 style readable file */
+       if (print_histogram == port->nr) {
+               saa7164_histogram_print(port, &port->irq_interval);
+               saa7164_histogram_print(port, &port->svc_interval);
+               saa7164_histogram_print(port, &port->irq_svc_interval);
+               saa7164_histogram_print(port, &port->read_interval);
+               saa7164_histogram_print(port, &port->poll_interval);
+               /* TODO: fix this to preserve any previous state */
+               print_histogram = 64 + port->nr;
+       }
+}
+
+static void saa7164_work_vbihandler(struct work_struct *w)
+{
+       struct saa7164_port *port =
+               container_of(w, struct saa7164_port, workenc);
+       struct saa7164_dev *dev = port->dev;
+
+       u32 wp, mcb, rp, cnt = 0;
+
+       port->last_svc_msecs_diff = port->last_svc_msecs;
+       port->last_svc_msecs = jiffies_to_msecs(jiffies);
+       port->last_svc_msecs_diff = port->last_svc_msecs -
+               port->last_svc_msecs_diff;
+
+       saa7164_histogram_update(&port->svc_interval,
+               port->last_svc_msecs_diff);
+
+       port->last_irq_svc_msecs_diff = port->last_svc_msecs -
+               port->last_irq_msecs;
+
+       saa7164_histogram_update(&port->irq_svc_interval,
+               port->last_irq_svc_msecs_diff);
+
+       dprintk(DBGLVL_IRQ,
+               "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
+               __func__,
+               port->last_svc_msecs_diff,
+               port->last_irq_svc_msecs_diff,
+               port->last_svc_wp,
+               port->last_svc_rp
+               );
+
+       /* Current write position */
+       wp = saa7164_readl(port->bufcounter);
+       if (wp > (port->hwcfg.buffercount - 1)) {
+               printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
+               return;
+       }
+
+       /* Most current complete buffer */
+       if (wp == 0)
+               mcb = (port->hwcfg.buffercount - 1);
+       else
+               mcb = wp - 1;
+
+       while (1) {
+               if (port->done_first_interrupt == 0) {
+                       port->done_first_interrupt++;
+                       rp = mcb;
+               } else
+                       rp = (port->last_svc_rp + 1) % 8;
+
+               if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
+                       printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
+                       break;
+               }
+
+               saa7164_work_enchandler_helper(port, rp);
+               port->last_svc_rp = rp;
+               cnt++;
+
+               if (rp == mcb)
+                       break;
+       }
+
+       /* TODO: Convert this into a /proc/saa7164 style readable file */
+       if (print_histogram == port->nr) {
+               saa7164_histogram_print(port, &port->irq_interval);
+               saa7164_histogram_print(port, &port->svc_interval);
+               saa7164_histogram_print(port, &port->irq_svc_interval);
+               saa7164_histogram_print(port, &port->read_interval);
+               saa7164_histogram_print(port, &port->poll_interval);
+               /* TODO: fix this to preserve any previous state */
+               print_histogram = 64 + port->nr;
+       }
+}
+
+static void saa7164_work_cmdhandler(struct work_struct *w)
+{
+       struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
+
+       /* Wake up any complete commands */
+       saa7164_irq_dequeue(dev);
+}
+
+static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
+{
+       struct saa7164_port *port = buf->port;
+
+       /* Feed the transport payload into the kernel demux */
+       dvb_dmx_swfilter_packets(&port->dvb.demux, (u8 *)buf->cpu,
+               SAA7164_TS_NUMBER_OF_LINES);
+
+}
+
+static irqreturn_t saa7164_irq_vbi(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       /* Store old time */
+       port->last_irq_msecs_diff = port->last_irq_msecs;
+
+       /* Collect new stats */
+       port->last_irq_msecs = jiffies_to_msecs(jiffies);
+
+       /* Calculate stats */
+       port->last_irq_msecs_diff = port->last_irq_msecs -
+               port->last_irq_msecs_diff;
+
+       saa7164_histogram_update(&port->irq_interval,
+               port->last_irq_msecs_diff);
+
+       dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
+               port->last_irq_msecs_diff);
+
+       /* Tis calls the vbi irq handler */
+       schedule_work(&port->workenc);
+       return 0;
+}
+
+static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       /* Store old time */
+       port->last_irq_msecs_diff = port->last_irq_msecs;
+
+       /* Collect new stats */
+       port->last_irq_msecs = jiffies_to_msecs(jiffies);
+
+       /* Calculate stats */
+       port->last_irq_msecs_diff = port->last_irq_msecs -
+               port->last_irq_msecs_diff;
+
+       saa7164_histogram_update(&port->irq_interval,
+               port->last_irq_msecs_diff);
+
+       dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
+               port->last_irq_msecs_diff);
+
+       schedule_work(&port->workenc);
+       return 0;
+}
+
+static irqreturn_t saa7164_irq_ts(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct list_head *c, *n;
+       int wp, i = 0, rp;
+
+       /* Find the current write point from the hardware */
+       wp = saa7164_readl(port->bufcounter);
+       if (wp > (port->hwcfg.buffercount - 1))
+               BUG();
+
+       /* Find the previous buffer to the current write point */
+       if (wp == 0)
+               rp = (port->hwcfg.buffercount - 1);
+       else
+               rp = wp - 1;
+
+       /* Lookup the WP in the buffer list */
+       /* TODO: turn this into a worker thread */
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               buf = list_entry(c, struct saa7164_buffer, list);
+               if (i++ > port->hwcfg.buffercount)
+                       BUG();
+
+               if (buf->idx == rp) {
+                       /* Found the buffer, deal with it */
+                       dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n",
+                               __func__, wp, rp);
+                       saa7164_buffer_deliver(buf);
+                       break;
+               }
+
+       }
+       return 0;
+}
+
+/* Primary IRQ handler and dispatch mechanism */
+static irqreturn_t saa7164_irq(int irq, void *dev_id)
+{
+       struct saa7164_dev *dev = dev_id;
+       struct saa7164_port *porta = &dev->ports[SAA7164_PORT_TS1];
+       struct saa7164_port *portb = &dev->ports[SAA7164_PORT_TS2];
+       struct saa7164_port *portc = &dev->ports[SAA7164_PORT_ENC1];
+       struct saa7164_port *portd = &dev->ports[SAA7164_PORT_ENC2];
+       struct saa7164_port *porte = &dev->ports[SAA7164_PORT_VBI1];
+       struct saa7164_port *portf = &dev->ports[SAA7164_PORT_VBI2];
+
+       u32 intid, intstat[INT_SIZE/4];
+       int i, handled = 0, bit;
+
+       if (dev == NULL) {
+               printk(KERN_ERR "%s() No device specified\n", __func__);
+               handled = 0;
+               goto out;
+       }
+
+       /* Check that the hardware is accessible. If the status bytes are
+        * 0xFF then the device is not accessible, the the IRQ belongs
+        * to another driver.
+        * 4 x u32 interrupt registers.
+        */
+       for (i = 0; i < INT_SIZE/4; i++) {
+
+               /* TODO: Convert into saa7164_readl() */
+               /* Read the 4 hardware interrupt registers */
+               intstat[i] = saa7164_readl(dev->int_status + (i * 4));
+
+               if (intstat[i])
+                       handled = 1;
+       }
+       if (handled == 0)
+               goto out;
+
+       /* For each of the HW interrupt registers */
+       for (i = 0; i < INT_SIZE/4; i++) {
+
+               if (intstat[i]) {
+                       /* Each function of the board has it's own interruptid.
+                        * Find the function that triggered then call
+                        * it's handler.
+                        */
+                       for (bit = 0; bit < 32; bit++) {
+
+                               if (((intstat[i] >> bit) & 0x00000001) == 0)
+                                       continue;
+
+                               /* Calculate the interrupt id (0x00 to 0x7f) */
+
+                               intid = (i * 32) + bit;
+                               if (intid == dev->intfdesc.bInterruptId) {
+                                       /* A response to an cmd/api call */
+                                       schedule_work(&dev->workcmd);
+                               } else if (intid == porta->hwcfg.interruptid) {
+
+                                       /* Transport path 1 */
+                                       saa7164_irq_ts(porta);
+
+                               } else if (intid == portb->hwcfg.interruptid) {
+
+                                       /* Transport path 2 */
+                                       saa7164_irq_ts(portb);
+
+                               } else if (intid == portc->hwcfg.interruptid) {
+
+                                       /* Encoder path 1 */
+                                       saa7164_irq_encoder(portc);
+
+                               } else if (intid == portd->hwcfg.interruptid) {
+
+                                       /* Encoder path 2 */
+                                       saa7164_irq_encoder(portd);
+
+                               } else if (intid == porte->hwcfg.interruptid) {
+
+                                       /* VBI path 1 */
+                                       saa7164_irq_vbi(porte);
+
+                               } else if (intid == portf->hwcfg.interruptid) {
+
+                                       /* VBI path 2 */
+                                       saa7164_irq_vbi(portf);
+
+                               } else {
+                                       /* Find the function */
+                                       dprintk(DBGLVL_IRQ,
+                                               "%s() unhandled interrupt "
+                                               "reg 0x%x bit 0x%x "
+                                               "intid = 0x%x\n",
+                                               __func__, i, bit, intid);
+                               }
+                       }
+
+                       /* Ack it */
+                       saa7164_writel(dev->int_ack + (i * 4), intstat[i]);
+
+               }
+       }
+out:
+       return IRQ_RETVAL(handled);
+}
+
+void saa7164_getfirmwarestatus(struct saa7164_dev *dev)
+{
+       struct saa7164_fw_status *s = &dev->fw_status;
+
+       dev->fw_status.status = saa7164_readl(SAA_DEVICE_SYSINIT_STATUS);
+       dev->fw_status.mode = saa7164_readl(SAA_DEVICE_SYSINIT_MODE);
+       dev->fw_status.spec = saa7164_readl(SAA_DEVICE_SYSINIT_SPEC);
+       dev->fw_status.inst = saa7164_readl(SAA_DEVICE_SYSINIT_INST);
+       dev->fw_status.cpuload = saa7164_readl(SAA_DEVICE_SYSINIT_CPULOAD);
+       dev->fw_status.remainheap =
+               saa7164_readl(SAA_DEVICE_SYSINIT_REMAINHEAP);
+
+       dprintk(1, "Firmware status:\n");
+       dprintk(1, " .status     = 0x%08x\n", s->status);
+       dprintk(1, " .mode       = 0x%08x\n", s->mode);
+       dprintk(1, " .spec       = 0x%08x\n", s->spec);
+       dprintk(1, " .inst       = 0x%08x\n", s->inst);
+       dprintk(1, " .cpuload    = 0x%08x\n", s->cpuload);
+       dprintk(1, " .remainheap = 0x%08x\n", s->remainheap);
+}
+
+u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev)
+{
+       u32 reg;
+
+       reg = saa7164_readl(SAA_DEVICE_VERSION);
+       dprintk(1, "Device running firmware version %d.%d.%d.%d (0x%x)\n",
+               (reg & 0x0000fc00) >> 10,
+               (reg & 0x000003e0) >> 5,
+               (reg & 0x0000001f),
+               (reg & 0xffff0000) >> 16,
+               reg);
+
+       return reg;
+}
+
+/* TODO: Debugging func, remove */
+void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr)
+{
+       int i;
+
+       dprintk(1, "--------------------> "
+               "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
+
+       for (i = 0; i < 0x100; i += 16)
+               dprintk(1, "region0[0x%08x] = "
+                       "%02x %02x %02x %02x %02x %02x %02x %02x"
+                       " %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
+                       (u8)saa7164_readb(addr + i + 0),
+                       (u8)saa7164_readb(addr + i + 1),
+                       (u8)saa7164_readb(addr + i + 2),
+                       (u8)saa7164_readb(addr + i + 3),
+                       (u8)saa7164_readb(addr + i + 4),
+                       (u8)saa7164_readb(addr + i + 5),
+                       (u8)saa7164_readb(addr + i + 6),
+                       (u8)saa7164_readb(addr + i + 7),
+                       (u8)saa7164_readb(addr + i + 8),
+                       (u8)saa7164_readb(addr + i + 9),
+                       (u8)saa7164_readb(addr + i + 10),
+                       (u8)saa7164_readb(addr + i + 11),
+                       (u8)saa7164_readb(addr + i + 12),
+                       (u8)saa7164_readb(addr + i + 13),
+                       (u8)saa7164_readb(addr + i + 14),
+                       (u8)saa7164_readb(addr + i + 15)
+                       );
+}
+
+static void saa7164_dump_hwdesc(struct saa7164_dev *dev)
+{
+       dprintk(1, "@0x%p hwdesc sizeof(struct tmComResHWDescr) = %d bytes\n",
+               &dev->hwdesc, (u32)sizeof(struct tmComResHWDescr));
+
+       dprintk(1, " .bLength = 0x%x\n", dev->hwdesc.bLength);
+       dprintk(1, " .bDescriptorType = 0x%x\n", dev->hwdesc.bDescriptorType);
+       dprintk(1, " .bDescriptorSubtype = 0x%x\n",
+               dev->hwdesc.bDescriptorSubtype);
+
+       dprintk(1, " .bcdSpecVersion = 0x%x\n", dev->hwdesc.bcdSpecVersion);
+       dprintk(1, " .dwClockFrequency = 0x%x\n", dev->hwdesc.dwClockFrequency);
+       dprintk(1, " .dwClockUpdateRes = 0x%x\n", dev->hwdesc.dwClockUpdateRes);
+       dprintk(1, " .bCapabilities = 0x%x\n", dev->hwdesc.bCapabilities);
+       dprintk(1, " .dwDeviceRegistersLocation = 0x%x\n",
+               dev->hwdesc.dwDeviceRegistersLocation);
+
+       dprintk(1, " .dwHostMemoryRegion = 0x%x\n",
+               dev->hwdesc.dwHostMemoryRegion);
+
+       dprintk(1, " .dwHostMemoryRegionSize = 0x%x\n",
+               dev->hwdesc.dwHostMemoryRegionSize);
+
+       dprintk(1, " .dwHostHibernatMemRegion = 0x%x\n",
+               dev->hwdesc.dwHostHibernatMemRegion);
+
+       dprintk(1, " .dwHostHibernatMemRegionSize = 0x%x\n",
+               dev->hwdesc.dwHostHibernatMemRegionSize);
+}
+
+static void saa7164_dump_intfdesc(struct saa7164_dev *dev)
+{
+       dprintk(1, "@0x%p intfdesc "
+               "sizeof(struct tmComResInterfaceDescr) = %d bytes\n",
+               &dev->intfdesc, (u32)sizeof(struct tmComResInterfaceDescr));
+
+       dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength);
+       dprintk(1, " .bDescriptorType = 0x%x\n", dev->intfdesc.bDescriptorType);
+       dprintk(1, " .bDescriptorSubtype = 0x%x\n",
+               dev->intfdesc.bDescriptorSubtype);
+
+       dprintk(1, " .bFlags = 0x%x\n", dev->intfdesc.bFlags);
+       dprintk(1, " .bInterfaceType = 0x%x\n", dev->intfdesc.bInterfaceType);
+       dprintk(1, " .bInterfaceId = 0x%x\n", dev->intfdesc.bInterfaceId);
+       dprintk(1, " .bBaseInterface = 0x%x\n", dev->intfdesc.bBaseInterface);
+       dprintk(1, " .bInterruptId = 0x%x\n", dev->intfdesc.bInterruptId);
+       dprintk(1, " .bDebugInterruptId = 0x%x\n",
+               dev->intfdesc.bDebugInterruptId);
+
+       dprintk(1, " .BARLocation = 0x%x\n", dev->intfdesc.BARLocation);
+}
+
+static void saa7164_dump_busdesc(struct saa7164_dev *dev)
+{
+       dprintk(1, "@0x%p busdesc sizeof(struct tmComResBusDescr) = %d bytes\n",
+               &dev->busdesc, (u32)sizeof(struct tmComResBusDescr));
+
+       dprintk(1, " .CommandRing   = 0x%016Lx\n", dev->busdesc.CommandRing);
+       dprintk(1, " .ResponseRing  = 0x%016Lx\n", dev->busdesc.ResponseRing);
+       dprintk(1, " .CommandWrite  = 0x%x\n", dev->busdesc.CommandWrite);
+       dprintk(1, " .CommandRead   = 0x%x\n", dev->busdesc.CommandRead);
+       dprintk(1, " .ResponseWrite = 0x%x\n", dev->busdesc.ResponseWrite);
+       dprintk(1, " .ResponseRead  = 0x%x\n", dev->busdesc.ResponseRead);
+}
+
+/* Much of the hardware configuration and PCI registers are configured
+ * dynamically depending on firmware. We have to cache some initial
+ * structures then use these to locate other important structures
+ * from PCI space.
+ */
+static void saa7164_get_descriptors(struct saa7164_dev *dev)
+{
+       memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(struct tmComResHWDescr));
+       memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(struct tmComResHWDescr),
+               sizeof(struct tmComResInterfaceDescr));
+       memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
+               sizeof(struct tmComResBusDescr));
+
+       if (dev->hwdesc.bLength != sizeof(struct tmComResHWDescr)) {
+               printk(KERN_ERR "Structure struct tmComResHWDescr is mangled\n");
+               printk(KERN_ERR "Need %x got %d\n", dev->hwdesc.bLength,
+                       (u32)sizeof(struct tmComResHWDescr));
+       } else
+               saa7164_dump_hwdesc(dev);
+
+       if (dev->intfdesc.bLength != sizeof(struct tmComResInterfaceDescr)) {
+               printk(KERN_ERR "struct struct tmComResInterfaceDescr is mangled\n");
+               printk(KERN_ERR "Need %x got %d\n", dev->intfdesc.bLength,
+                       (u32)sizeof(struct tmComResInterfaceDescr));
+       } else
+               saa7164_dump_intfdesc(dev);
+
+       saa7164_dump_busdesc(dev);
+}
+
+static int saa7164_pci_quirks(struct saa7164_dev *dev)
+{
+       return 0;
+}
+
+static int get_resources(struct saa7164_dev *dev)
+{
+       if (request_mem_region(pci_resource_start(dev->pci, 0),
+               pci_resource_len(dev->pci, 0), dev->name)) {
+
+               if (request_mem_region(pci_resource_start(dev->pci, 2),
+                       pci_resource_len(dev->pci, 2), dev->name))
+                       return 0;
+       }
+
+       printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx or 0x%llx\n",
+               dev->name,
+               (u64)pci_resource_start(dev->pci, 0),
+               (u64)pci_resource_start(dev->pci, 2));
+
+       return -EBUSY;
+}
+
+static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
+{
+       struct saa7164_port *port = NULL;
+
+       if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
+               BUG();
+
+       port = &dev->ports[portnr];
+
+       port->dev = dev;
+       port->nr = portnr;
+
+       if ((portnr == SAA7164_PORT_TS1) || (portnr == SAA7164_PORT_TS2))
+               port->type = SAA7164_MPEG_DVB;
+       else
+       if ((portnr == SAA7164_PORT_ENC1) || (portnr == SAA7164_PORT_ENC2)) {
+               port->type = SAA7164_MPEG_ENCODER;
+
+               /* We need a deferred interrupt handler for cmd handling */
+               INIT_WORK(&port->workenc, saa7164_work_enchandler);
+       } else if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) {
+               port->type = SAA7164_MPEG_VBI;
+
+               /* We need a deferred interrupt handler for cmd handling */
+               INIT_WORK(&port->workenc, saa7164_work_vbihandler);
+       } else
+               BUG();
+
+       /* Init all the critical resources */
+       mutex_init(&port->dvb.lock);
+       INIT_LIST_HEAD(&port->dmaqueue.list);
+       mutex_init(&port->dmaqueue_lock);
+
+       INIT_LIST_HEAD(&port->list_buf_used.list);
+       INIT_LIST_HEAD(&port->list_buf_free.list);
+       init_waitqueue_head(&port->wait_read);
+
+
+       saa7164_histogram_reset(&port->irq_interval, "irq intervals");
+       saa7164_histogram_reset(&port->svc_interval, "deferred intervals");
+       saa7164_histogram_reset(&port->irq_svc_interval,
+               "irq to deferred intervals");
+       saa7164_histogram_reset(&port->read_interval,
+               "encoder/vbi read() intervals");
+       saa7164_histogram_reset(&port->poll_interval,
+               "encoder/vbi poll() intervals");
+
+       return 0;
+}
+
+static int saa7164_dev_setup(struct saa7164_dev *dev)
+{
+       int i;
+
+       mutex_init(&dev->lock);
+       atomic_inc(&dev->refcount);
+       dev->nr = saa7164_devcount++;
+
+       snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr);
+
+       mutex_lock(&devlist);
+       list_add_tail(&dev->devlist, &saa7164_devlist);
+       mutex_unlock(&devlist);
+
+       /* board config */
+       dev->board = UNSET;
+       if (card[dev->nr] < saa7164_bcount)
+               dev->board = card[dev->nr];
+
+       for (i = 0; UNSET == dev->board  &&  i < saa7164_idcount; i++)
+               if (dev->pci->subsystem_vendor == saa7164_subids[i].subvendor &&
+                       dev->pci->subsystem_device ==
+                               saa7164_subids[i].subdevice)
+                               dev->board = saa7164_subids[i].card;
+
+       if (UNSET == dev->board) {
+               dev->board = SAA7164_BOARD_UNKNOWN;
+               saa7164_card_list(dev);
+       }
+
+       dev->pci_bus  = dev->pci->bus->number;
+       dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+
+       /* I2C Defaults / setup */
+       dev->i2c_bus[0].dev = dev;
+       dev->i2c_bus[0].nr = 0;
+       dev->i2c_bus[1].dev = dev;
+       dev->i2c_bus[1].nr = 1;
+       dev->i2c_bus[2].dev = dev;
+       dev->i2c_bus[2].nr = 2;
+
+       /* Transport + Encoder ports 1, 2, 3, 4 - Defaults / setup */
+       saa7164_port_init(dev, SAA7164_PORT_TS1);
+       saa7164_port_init(dev, SAA7164_PORT_TS2);
+       saa7164_port_init(dev, SAA7164_PORT_ENC1);
+       saa7164_port_init(dev, SAA7164_PORT_ENC2);
+       saa7164_port_init(dev, SAA7164_PORT_VBI1);
+       saa7164_port_init(dev, SAA7164_PORT_VBI2);
+
+       if (get_resources(dev) < 0) {
+               printk(KERN_ERR "CORE %s No more PCIe resources for "
+                      "subsystem: %04x:%04x\n",
+                      dev->name, dev->pci->subsystem_vendor,
+                      dev->pci->subsystem_device);
+
+               saa7164_devcount--;
+               return -ENODEV;
+       }
+
+       /* PCI/e allocations */
+       dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
+                            pci_resource_len(dev->pci, 0));
+
+       dev->lmmio2 = ioremap(pci_resource_start(dev->pci, 2),
+                            pci_resource_len(dev->pci, 2));
+
+       dev->bmmio = (u8 __iomem *)dev->lmmio;
+       dev->bmmio2 = (u8 __iomem *)dev->lmmio2;
+
+       /* Inerrupt and ack register locations offset of bmmio */
+       dev->int_status = 0x183000 + 0xf80;
+       dev->int_ack = 0x183000 + 0xf90;
+
+       printk(KERN_INFO
+               "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+              dev->name, dev->pci->subsystem_vendor,
+              dev->pci->subsystem_device, saa7164_boards[dev->board].name,
+              dev->board, card[dev->nr] == dev->board ?
+              "insmod option" : "autodetected");
+
+       saa7164_pci_quirks(dev);
+
+       return 0;
+}
+
+static void saa7164_dev_unregister(struct saa7164_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       release_mem_region(pci_resource_start(dev->pci, 0),
+               pci_resource_len(dev->pci, 0));
+
+       release_mem_region(pci_resource_start(dev->pci, 2),
+               pci_resource_len(dev->pci, 2));
+
+       if (!atomic_dec_and_test(&dev->refcount))
+               return;
+
+       iounmap(dev->lmmio);
+       iounmap(dev->lmmio2);
+
+       return;
+}
+
+#ifdef CONFIG_PROC_FS
+static int saa7164_proc_show(struct seq_file *m, void *v)
+{
+       struct saa7164_dev *dev;
+       struct tmComResBusInfo *b;
+       struct list_head *list;
+       int i, c;
+
+       if (saa7164_devcount == 0)
+               return 0;
+
+       list_for_each(list, &saa7164_devlist) {
+               dev = list_entry(list, struct saa7164_dev, devlist);
+               seq_printf(m, "%s = %p\n", dev->name, dev);
+
+               /* Lock the bus from any other access */
+               b = &dev->bus;
+               mutex_lock(&b->lock);
+
+               seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n",
+                       b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
+
+               seq_printf(m, " .m_pdwSetReadPos  = 0x%x (0x%08x)\n",
+                       b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
+
+               seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n",
+                       b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
+
+               seq_printf(m, " .m_pdwGetReadPos  = 0x%x (0x%08x)\n",
+                       b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
+               c = 0;
+               seq_printf(m, "\n  Set Ring:\n");
+               seq_printf(m, "\n addr  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
+               for (i = 0; i < b->m_dwSizeSetRing; i++) {
+                       if (c == 0)
+                               seq_printf(m, " %04x:", i);
+
+                       seq_printf(m, " %02x", *(b->m_pdwSetRing + i));
+
+                       if (++c == 16) {
+                               seq_printf(m, "\n");
+                               c = 0;
+                       }
+               }
+
+               c = 0;
+               seq_printf(m, "\n  Get Ring:\n");
+               seq_printf(m, "\n addr  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
+               for (i = 0; i < b->m_dwSizeGetRing; i++) {
+                       if (c == 0)
+                               seq_printf(m, " %04x:", i);
+
+                       seq_printf(m, " %02x", *(b->m_pdwGetRing + i));
+
+                       if (++c == 16) {
+                               seq_printf(m, "\n");
+                               c = 0;
+                       }
+               }
+
+               mutex_unlock(&b->lock);
+
+       }
+
+       return 0;
+}
+
+static int saa7164_proc_open(struct inode *inode, struct file *filp)
+{
+       return single_open(filp, saa7164_proc_show, NULL);
+}
+
+static const struct file_operations saa7164_proc_fops = {
+       .open           = saa7164_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int saa7164_proc_create(void)
+{
+       struct proc_dir_entry *pe;
+
+       pe = proc_create("saa7164", S_IRUGO, NULL, &saa7164_proc_fops);
+       if (!pe)
+               return -ENOMEM;
+
+       return 0;
+}
+#endif
+
+static int saa7164_thread_function(void *data)
+{
+       struct saa7164_dev *dev = data;
+       struct tmFwInfoStruct fwinfo;
+       u64 last_poll_time = 0;
+
+       dprintk(DBGLVL_THR, "thread started\n");
+
+       set_freezable();
+
+       while (1) {
+               msleep_interruptible(100);
+               if (kthread_should_stop())
+                       break;
+               try_to_freeze();
+
+               dprintk(DBGLVL_THR, "thread running\n");
+
+               /* Dump the firmware debug message to console */
+               /* Polling this costs us 1-2% of the arm CPU */
+               /* convert this into a respnde to interrupt 0x7a */
+               saa7164_api_collect_debug(dev);
+
+               /* Monitor CPU load every 1 second */
+               if ((last_poll_time + 1000 /* ms */) < jiffies_to_msecs(jiffies)) {
+                       saa7164_api_get_load_info(dev, &fwinfo);
+                       last_poll_time = jiffies_to_msecs(jiffies);
+               }
+
+       }
+
+       dprintk(DBGLVL_THR, "thread exiting\n");
+       return 0;
+}
+
+static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
+                                    const struct pci_device_id *pci_id)
+{
+       struct saa7164_dev *dev;
+       int err, i;
+       u32 version;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (NULL == dev)
+               return -ENOMEM;
+
+       /* pci init */
+       dev->pci = pci_dev;
+       if (pci_enable_device(pci_dev)) {
+               err = -EIO;
+               goto fail_free;
+       }
+
+       if (saa7164_dev_setup(dev) < 0) {
+               err = -EINVAL;
+               goto fail_free;
+       }
+
+       /* print pci info */
+       dev->pci_rev = pci_dev->revision;
+       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+       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));
+
+       pci_set_master(pci_dev);
+       /* TODO */
+       if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+               printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+               err = -EIO;
+               goto fail_irq;
+       }
+
+       err = request_irq(pci_dev->irq, saa7164_irq,
+               IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+       if (err < 0) {
+               printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
+                       pci_dev->irq);
+               err = -EIO;
+               goto fail_irq;
+       }
+
+       pci_set_drvdata(pci_dev, dev);
+
+       /* Init the internal command list */
+       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
+               dev->cmds[i].seqno = i;
+               dev->cmds[i].inuse = 0;
+               mutex_init(&dev->cmds[i].lock);
+               init_waitqueue_head(&dev->cmds[i].wait);
+       }
+
+       /* We need a deferred interrupt handler for cmd handling */
+       INIT_WORK(&dev->workcmd, saa7164_work_cmdhandler);
+
+       /* Only load the firmware if we know the board */
+       if (dev->board != SAA7164_BOARD_UNKNOWN) {
+
+               err = saa7164_downloadfirmware(dev);
+               if (err < 0) {
+                       printk(KERN_ERR
+                               "Failed to boot firmware, no features "
+                               "registered\n");
+                       goto fail_fw;
+               }
+
+               saa7164_get_descriptors(dev);
+               saa7164_dumpregs(dev, 0);
+               saa7164_getcurrentfirmwareversion(dev);
+               saa7164_getfirmwarestatus(dev);
+               err = saa7164_bus_setup(dev);
+               if (err < 0)
+                       printk(KERN_ERR
+                               "Failed to setup the bus, will continue\n");
+               saa7164_bus_dump(dev);
+
+               /* Ping the running firmware via the command bus and get the
+                * firmware version, this checks the bus is running OK.
+                */
+               version = 0;
+               if (saa7164_api_get_fw_version(dev, &version) == SAA_OK)
+                       dprintk(1, "Bus is operating correctly using "
+                               "version %d.%d.%d.%d (0x%x)\n",
+                               (version & 0x0000fc00) >> 10,
+                               (version & 0x000003e0) >> 5,
+                               (version & 0x0000001f),
+                               (version & 0xffff0000) >> 16,
+                               version);
+               else
+                       printk(KERN_ERR
+                               "Failed to communicate with the firmware\n");
+
+               /* Bring up the I2C buses */
+               saa7164_i2c_register(&dev->i2c_bus[0]);
+               saa7164_i2c_register(&dev->i2c_bus[1]);
+               saa7164_i2c_register(&dev->i2c_bus[2]);
+               saa7164_gpio_setup(dev);
+               saa7164_card_setup(dev);
+
+               /* Parse the dynamic device configuration, find various
+                * media endpoints (MPEG, WMV, PS, TS) and cache their
+                * configuration details into the driver, so we can
+                * reference them later during simething_register() func,
+                * interrupt handlers, deferred work handlers etc.
+                */
+               saa7164_api_enum_subdevs(dev);
+
+               /* Begin to create the video sub-systems and register funcs */
+               if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) {
+                       if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS1]) < 0) {
+                               printk(KERN_ERR "%s() Failed to register "
+                                       "dvb adapters on porta\n",
+                                       __func__);
+                       }
+               }
+
+               if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) {
+                       if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS2]) < 0) {
+                               printk(KERN_ERR"%s() Failed to register "
+                                       "dvb adapters on portb\n",
+                                       __func__);
+                       }
+               }
+
+               if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) {
+                       if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC1]) < 0) {
+                               printk(KERN_ERR"%s() Failed to register "
+                                       "mpeg encoder\n", __func__);
+                       }
+               }
+
+               if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) {
+                       if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC2]) < 0) {
+                               printk(KERN_ERR"%s() Failed to register "
+                                       "mpeg encoder\n", __func__);
+                       }
+               }
+
+               if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI) {
+                       if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI1]) < 0) {
+                               printk(KERN_ERR"%s() Failed to register "
+                                       "vbi device\n", __func__);
+                       }
+               }
+
+               if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI) {
+                       if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI2]) < 0) {
+                               printk(KERN_ERR"%s() Failed to register "
+                                       "vbi device\n", __func__);
+                       }
+               }
+               saa7164_api_set_debug(dev, fw_debug);
+
+               if (fw_debug) {
+                       dev->kthread = kthread_run(saa7164_thread_function, dev,
+                               "saa7164 debug");
+                       if (!dev->kthread)
+                               printk(KERN_ERR "%s() Failed to create "
+                                       "debug kernel thread\n", __func__);
+               }
+
+       } /* != BOARD_UNKNOWN */
+       else
+               printk(KERN_ERR "%s() Unsupported board detected, "
+                       "registering without firmware\n", __func__);
+
+       dprintk(1, "%s() parameter debug = %d\n", __func__, saa_debug);
+       dprintk(1, "%s() parameter waitsecs = %d\n", __func__, waitsecs);
+
+fail_fw:
+       return 0;
+
+fail_irq:
+       saa7164_dev_unregister(dev);
+fail_free:
+       kfree(dev);
+       return err;
+}
+
+static void saa7164_shutdown(struct saa7164_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+}
+
+static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
+{
+       struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
+
+       if (dev->board != SAA7164_BOARD_UNKNOWN) {
+               if (fw_debug && dev->kthread) {
+                       kthread_stop(dev->kthread);
+                       dev->kthread = NULL;
+               }
+               if (dev->firmwareloaded)
+                       saa7164_api_set_debug(dev, 0x00);
+       }
+
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
+               &dev->ports[SAA7164_PORT_ENC1].irq_interval);
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
+               &dev->ports[SAA7164_PORT_ENC1].svc_interval);
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
+               &dev->ports[SAA7164_PORT_ENC1].irq_svc_interval);
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
+               &dev->ports[SAA7164_PORT_ENC1].read_interval);
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
+               &dev->ports[SAA7164_PORT_ENC1].poll_interval);
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI1],
+               &dev->ports[SAA7164_PORT_VBI1].read_interval);
+       saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI2],
+               &dev->ports[SAA7164_PORT_VBI2].poll_interval);
+
+       saa7164_shutdown(dev);
+
+       if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
+               saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS1]);
+
+       if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB)
+               saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS2]);
+
+       if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER)
+               saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC1]);
+
+       if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER)
+               saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC2]);
+
+       if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI)
+               saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI1]);
+
+       if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI)
+               saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI2]);
+
+       saa7164_i2c_unregister(&dev->i2c_bus[0]);
+       saa7164_i2c_unregister(&dev->i2c_bus[1]);
+       saa7164_i2c_unregister(&dev->i2c_bus[2]);
+
+       pci_disable_device(pci_dev);
+
+       /* unregister stuff */
+       free_irq(pci_dev->irq, dev);
+       pci_set_drvdata(pci_dev, NULL);
+
+       mutex_lock(&devlist);
+       list_del(&dev->devlist);
+       mutex_unlock(&devlist);
+
+       saa7164_dev_unregister(dev);
+       kfree(dev);
+}
+
+static struct pci_device_id saa7164_pci_tbl[] = {
+       {
+               /* SAA7164 */
+               .vendor       = 0x1131,
+               .device       = 0x7164,
+               .subvendor    = PCI_ANY_ID,
+               .subdevice    = PCI_ANY_ID,
+       }, {
+               /* --- end of list --- */
+       }
+};
+MODULE_DEVICE_TABLE(pci, saa7164_pci_tbl);
+
+static struct pci_driver saa7164_pci_driver = {
+       .name     = "saa7164",
+       .id_table = saa7164_pci_tbl,
+       .probe    = saa7164_initdev,
+       .remove   = __devexit_p(saa7164_finidev),
+       /* TODO */
+       .suspend  = NULL,
+       .resume   = NULL,
+};
+
+static int __init saa7164_init(void)
+{
+       printk(KERN_INFO "saa7164 driver loaded\n");
+
+#ifdef CONFIG_PROC_FS
+       saa7164_proc_create();
+#endif
+       return pci_register_driver(&saa7164_pci_driver);
+}
+
+static void __exit saa7164_fini(void)
+{
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("saa7164", NULL);
+#endif
+       pci_unregister_driver(&saa7164_pci_driver);
+}
+
+module_init(saa7164_init);
+module_exit(saa7164_fini);
+
diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c
new file mode 100644 (file)
index 0000000..5c5cc3e
--- /dev/null
@@ -0,0 +1,556 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 "saa7164.h"
+
+#include "tda10048.h"
+#include "tda18271.h"
+#include "s5h1411.h"
+
+#define DRIVER_NAME "saa7164"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* addr is in the card struct, get it from there */
+static struct tda10048_config hauppauge_hvr2200_1_config = {
+       .demod_address    = 0x10 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+};
+static struct tda10048_config hauppauge_hvr2200_2_config = {
+       .demod_address    = 0x12 >> 1,
+       .output_mode      = TDA10048_SERIAL_OUTPUT,
+       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
+       .inversion        = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3500,
+       .dtv8_if_freq_khz = TDA10048_IF_4000,
+       .clk_freq_khz     = TDA10048_CLK_16000,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 3250, .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_hvr22x0_tuner_config = {
+       .std_map        = &hauppauge_tda18271_std_map,
+       .gate           = TDA18271_GATE_ANALOG,
+       .role           = TDA18271_MASTER,
+};
+
+static struct tda18271_config hauppauge_hvr22x0s_tuner_config = {
+       .std_map        = &hauppauge_tda18271_std_map,
+       .gate           = TDA18271_GATE_ANALOG,
+       .role           = TDA18271_SLAVE,
+       .output_opt     = TDA18271_OUTPUT_LT_OFF,
+       .rf_cal_on_startup = 1
+};
+
+static struct s5h1411_config hauppauge_s5h1411_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_ON,
+       .qam_if        = S5H1411_IF_4000,
+       .vsb_if        = S5H1411_IF_3250,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static int saa7164_dvb_stop_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_DVB, "%s()    Stopped\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int saa7164_dvb_acquire_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_DVB, "%s() Acquired\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int saa7164_dvb_pause_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/* Firmware is very windows centric, meaning you have to transition
+ * the part through AVStream / KS Windows stages, forwards or backwards.
+ * States are: stopped, acquired (h/w), paused, started.
+ */
+static int saa7164_dvb_stop_streaming(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct list_head *p, *q;
+       int ret;
+
+       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
+
+       ret = saa7164_dvb_pause_port(port);
+       ret = saa7164_dvb_acquire_port(port);
+       ret = saa7164_dvb_stop_port(port);
+
+       /* Mark the hardware buffers as free */
+       mutex_lock(&port->dmaqueue_lock);
+       list_for_each_safe(p, q, &port->dmaqueue.list) {
+               buf = list_entry(p, struct saa7164_buffer, list);
+               buf->flags = SAA7164_BUFFER_FREE;
+       }
+       mutex_unlock(&port->dmaqueue_lock);
+
+       return ret;
+}
+
+static int saa7164_dvb_start_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0, result;
+
+       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
+
+       saa7164_buffer_cfg_port(port);
+
+       /* Acquire the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
+                       __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+                       printk(KERN_ERR "%s() acquire/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+               ret = -EIO;
+               goto out;
+       } else
+               dprintk(DBGLVL_DVB, "%s()   Acquired\n", __func__);
+
+       /* Pause the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
+                               __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+                       printk(KERN_ERR "%s() pause/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+
+               ret = -EIO;
+               goto out;
+       } else
+               dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
+
+       /* Start the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
+                               __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+                       printk(KERN_ERR "%s() run/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+
+               ret = -EIO;
+       } else
+               dprintk(DBGLVL_DVB, "%s()   Running\n", __func__);
+
+out:
+       return ret;
+}
+
+static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct saa7164_port *port = (struct saa7164_port *) demux->priv;
+       struct saa7164_dvb *dvb = &port->dvb;
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+
+       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (dvb->feeding++ == 0) {
+                       /* Start transport */
+                       ret = saa7164_dvb_start_port(port);
+               }
+               mutex_unlock(&dvb->lock);
+               dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+                       __func__, port->nr, dvb->feeding);
+       }
+
+       return ret;
+}
+
+static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct saa7164_port *port = (struct saa7164_port *) demux->priv;
+       struct saa7164_dvb *dvb = &port->dvb;
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+
+       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (--dvb->feeding == 0) {
+                       /* Stop transport */
+                       ret = saa7164_dvb_stop_streaming(port);
+               }
+               mutex_unlock(&dvb->lock);
+               dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+                       __func__, port->nr, dvb->feeding);
+       }
+
+       return ret;
+}
+
+static int dvb_register(struct saa7164_port *port)
+{
+       struct saa7164_dvb *dvb = &port->dvb;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       int result, i;
+
+       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
+
+       if (port->type != SAA7164_MPEG_DVB)
+               BUG();
+
+       /* Sanity check that the PCI configuration space is active */
+       if (port->hwcfg.BARLocation == 0) {
+               result = -ENOMEM;
+               printk(KERN_ERR "%s: dvb_register_adapter failed "
+                      "(errno = %d), NO PCI configuration\n",
+                       DRIVER_NAME, result);
+               goto fail_adapter;
+       }
+
+       /* Init and establish defaults */
+       port->hw_streamingparams.bitspersample = 8;
+       port->hw_streamingparams.samplesperline = 188;
+       port->hw_streamingparams.numberoflines =
+               (SAA7164_TS_NUMBER_OF_LINES * 188) / 188;
+
+       port->hw_streamingparams.pitch = 188;
+       port->hw_streamingparams.linethreshold = 0;
+       port->hw_streamingparams.pagetablelistvirt = NULL;
+       port->hw_streamingparams.pagetablelistphys = NULL;
+       port->hw_streamingparams.numpagetables = 2 +
+               ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
+
+       port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount;
+
+       /* Allocate the PCI resources */
+       for (i = 0; i < port->hwcfg.buffercount; i++) {
+               buf = saa7164_buffer_alloc(port,
+                       port->hw_streamingparams.numberoflines *
+                       port->hw_streamingparams.pitch);
+
+               if (!buf) {
+                       result = -ENOMEM;
+                       printk(KERN_ERR "%s: dvb_register_adapter failed "
+                              "(errno = %d), unable to allocate buffers\n",
+                               DRIVER_NAME, result);
+                       goto fail_adapter;
+               }
+
+               mutex_lock(&port->dmaqueue_lock);
+               list_add_tail(&buf->list, &port->dmaqueue.list);
+               mutex_unlock(&port->dmaqueue_lock);
+       }
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
+                       &dev->pci->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 = port;
+
+       /* 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       = port;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = saa7164_dvb_start_feed;
+       dvb->demux.stop_feed  = saa7164_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;
+}
+
+int saa7164_dvb_unregister(struct saa7164_port *port)
+{
+       struct saa7164_dvb *dvb = &port->dvb;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *b;
+       struct list_head *c, *n;
+
+       dprintk(DBGLVL_DVB, "%s()\n", __func__);
+
+       if (port->type != SAA7164_MPEG_DVB)
+               BUG();
+
+       /* Remove any allocated buffers */
+       mutex_lock(&port->dmaqueue_lock);
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               b = list_entry(c, struct saa7164_buffer, list);
+               list_del(c);
+               saa7164_buffer_dealloc(b);
+       }
+       mutex_unlock(&port->dmaqueue_lock);
+
+       if (dvb->frontend == NULL)
+               return 0;
+
+       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);
+       return 0;
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card.
+ */
+int saa7164_dvb_register(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_dvb *dvb = &port->dvb;
+       struct saa7164_i2c *i2c_bus = NULL;
+       int ret;
+
+       dprintk(DBGLVL_DVB, "%s()\n", __func__);
+
+       /* init frontend */
+       switch (dev->board) {
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
+               i2c_bus = &dev->i2c_bus[port->nr + 1];
+               switch (port->nr) {
+               case 0:
+                       port->dvb.frontend = dvb_attach(tda10048_attach,
+                               &hauppauge_hvr2200_1_config,
+                               &i2c_bus->i2c_adap);
+
+                       if (port->dvb.frontend != NULL) {
+                               /* TODO: addr is in the card struct */
+                               dvb_attach(tda18271_attach, port->dvb.frontend,
+                                       0xc0 >> 1, &i2c_bus->i2c_adap,
+                                       &hauppauge_hvr22x0_tuner_config);
+                       }
+
+                       break;
+               case 1:
+                       port->dvb.frontend = dvb_attach(tda10048_attach,
+                               &hauppauge_hvr2200_2_config,
+                               &i2c_bus->i2c_adap);
+
+                       if (port->dvb.frontend != NULL) {
+                               /* TODO: addr is in the card struct */
+                               dvb_attach(tda18271_attach, port->dvb.frontend,
+                                       0xc0 >> 1, &i2c_bus->i2c_adap,
+                                       &hauppauge_hvr22x0s_tuner_config);
+                       }
+
+                       break;
+               }
+               break;
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
+       case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
+               i2c_bus = &dev->i2c_bus[port->nr + 1];
+
+               port->dvb.frontend = dvb_attach(s5h1411_attach,
+                       &hauppauge_s5h1411_config,
+                       &i2c_bus->i2c_adap);
+
+               if (port->dvb.frontend != NULL) {
+                       if (port->nr == 0) {
+                               /* Master TDA18271 */
+                               /* TODO: addr is in the card struct */
+                               dvb_attach(tda18271_attach, port->dvb.frontend,
+                                       0xc0 >> 1, &i2c_bus->i2c_adap,
+                                       &hauppauge_hvr22x0_tuner_config);
+                       } else {
+                               /* Slave TDA18271 */
+                               dvb_attach(tda18271_attach, port->dvb.frontend,
+                                       0xc0 >> 1, &i2c_bus->i2c_adap,
+                                       &hauppauge_hvr22x0s_tuner_config);
+                       }
+               }
+
+               break;
+       default:
+               printk(KERN_ERR "%s: The frontend isn't supported\n",
+                      dev->name);
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR "%s() Frontend initialization failed\n",
+                      __func__);
+               return -1;
+       }
+
+       /* register everything */
+       ret = dvb_register(port);
+       if (ret < 0) {
+               if (dvb->frontend->ops.release)
+                       dvb->frontend->ops.release(dvb->frontend);
+               return ret;
+       }
+
+       return 0;
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-encoder.c b/drivers/media/pci/saa7164/saa7164-encoder.c
new file mode 100644 (file)
index 0000000..a9ed686
--- /dev/null
@@ -0,0 +1,1500 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 "saa7164.h"
+
+#define ENCODER_MAX_BITRATE 6500000
+#define ENCODER_MIN_BITRATE 1000000
+#define ENCODER_DEF_BITRATE 5000000
+
+static struct saa7164_tvnorm saa7164_tvnorms[] = {
+       {
+               .name      = "NTSC-M",
+               .id        = V4L2_STD_NTSC_M,
+       }, {
+               .name      = "NTSC-JP",
+               .id        = V4L2_STD_NTSC_M_JP,
+       }
+};
+
+static const u32 saa7164_v4l2_ctrls[] = {
+       V4L2_CID_BRIGHTNESS,
+       V4L2_CID_CONTRAST,
+       V4L2_CID_SATURATION,
+       V4L2_CID_HUE,
+       V4L2_CID_AUDIO_VOLUME,
+       V4L2_CID_SHARPNESS,
+       V4L2_CID_MPEG_STREAM_TYPE,
+       V4L2_CID_MPEG_VIDEO_ASPECT,
+       V4L2_CID_MPEG_VIDEO_B_FRAMES,
+       V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+       V4L2_CID_MPEG_AUDIO_MUTE,
+       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+       V4L2_CID_MPEG_VIDEO_BITRATE,
+       V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+       0
+};
+
+/* Take the encoder configuration form the port struct and
+ * flush it to the hardware.
+ */
+static void saa7164_encoder_configure(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       port->encoder_params.width = port->width;
+       port->encoder_params.height = port->height;
+       port->encoder_params.is_50hz =
+               (port->encodernorm.id & V4L2_STD_625_50) != 0;
+
+       /* Set up the DIF (enable it) for analog mode by default */
+       saa7164_api_initialize_dif(port);
+
+       /* Configure the correct video standard */
+       saa7164_api_configure_dif(port, port->encodernorm.id);
+
+       /* Ensure the audio decoder is correct configured */
+       saa7164_api_set_audio_std(port);
+}
+
+static int saa7164_encoder_buffers_dealloc(struct saa7164_port *port)
+{
+       struct list_head *c, *n, *p, *q, *l, *v;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct saa7164_user_buffer *ubuf;
+
+       /* Remove any allocated buffers */
+       mutex_lock(&port->dmaqueue_lock);
+
+       dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr);
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               buf = list_entry(c, struct saa7164_buffer, list);
+               list_del(c);
+               saa7164_buffer_dealloc(buf);
+       }
+
+       dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr);
+       list_for_each_safe(p, q, &port->list_buf_used.list) {
+               ubuf = list_entry(p, struct saa7164_user_buffer, list);
+               list_del(p);
+               saa7164_buffer_dealloc_user(ubuf);
+       }
+
+       dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr);
+       list_for_each_safe(l, v, &port->list_buf_free.list) {
+               ubuf = list_entry(l, struct saa7164_user_buffer, list);
+               list_del(l);
+               saa7164_buffer_dealloc_user(ubuf);
+       }
+
+       mutex_unlock(&port->dmaqueue_lock);
+       dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
+
+       return 0;
+}
+
+/* Dynamic buffer switch at encoder start time */
+static int saa7164_encoder_buffers_alloc(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct saa7164_user_buffer *ubuf;
+       struct tmHWStreamParameters *params = &port->hw_streamingparams;
+       int result = -ENODEV, i;
+       int len = 0;
+
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       if (port->encoder_params.stream_type ==
+               V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
+               dprintk(DBGLVL_ENC,
+                       "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n",
+                       __func__);
+               params->samplesperline = 128;
+               params->numberoflines = 256;
+               params->pitch = 128;
+               params->numpagetables = 2 +
+                       ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE);
+       } else
+       if (port->encoder_params.stream_type ==
+               V4L2_MPEG_STREAM_TYPE_MPEG2_TS) {
+               dprintk(DBGLVL_ENC,
+                       "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n",
+                       __func__);
+               params->samplesperline = 188;
+               params->numberoflines = 312;
+               params->pitch = 188;
+               params->numpagetables = 2 +
+                       ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
+       } else
+               BUG();
+
+       /* Init and establish defaults */
+       params->bitspersample = 8;
+       params->linethreshold = 0;
+       params->pagetablelistvirt = NULL;
+       params->pagetablelistphys = NULL;
+       params->numpagetableentries = port->hwcfg.buffercount;
+
+       /* Allocate the PCI resources, buffers (hard) */
+       for (i = 0; i < port->hwcfg.buffercount; i++) {
+               buf = saa7164_buffer_alloc(port,
+                       params->numberoflines *
+                       params->pitch);
+
+               if (!buf) {
+                       printk(KERN_ERR "%s() failed "
+                              "(errno = %d), unable to allocate buffer\n",
+                               __func__, result);
+                       result = -ENOMEM;
+                       goto failed;
+               } else {
+
+                       mutex_lock(&port->dmaqueue_lock);
+                       list_add_tail(&buf->list, &port->dmaqueue.list);
+                       mutex_unlock(&port->dmaqueue_lock);
+
+               }
+       }
+
+       /* Allocate some kernel buffers for copying
+        * to userpsace.
+        */
+       len = params->numberoflines * params->pitch;
+
+       if (encoder_buffers < 16)
+               encoder_buffers = 16;
+       if (encoder_buffers > 512)
+               encoder_buffers = 512;
+
+       for (i = 0; i < encoder_buffers; i++) {
+
+               ubuf = saa7164_buffer_alloc_user(dev, len);
+               if (ubuf) {
+                       mutex_lock(&port->dmaqueue_lock);
+                       list_add_tail(&ubuf->list, &port->list_buf_free.list);
+                       mutex_unlock(&port->dmaqueue_lock);
+               }
+
+       }
+
+       result = 0;
+
+failed:
+       return result;
+}
+
+static int saa7164_encoder_initialize(struct saa7164_port *port)
+{
+       saa7164_encoder_configure(port);
+       return 0;
+}
+
+/* -- V4L2 --------------------------------------------------------- */
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+       unsigned int i;
+
+       dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)*id);
+
+       for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
+               if (*id & saa7164_tvnorms[i].id)
+                       break;
+       }
+       if (i == ARRAY_SIZE(saa7164_tvnorms))
+               return -EINVAL;
+
+       port->encodernorm = saa7164_tvnorms[i];
+
+       /* Update the audio decoder while is not running in
+        * auto detect mode.
+        */
+       saa7164_api_set_audio_std(port);
+
+       dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)*id);
+
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+       struct v4l2_input *i)
+{
+       int n;
+
+       char *inputs[] = { "tuner", "composite", "svideo", "aux",
+               "composite 2", "svideo 2", "aux 2" };
+
+       if (i->index >= 7)
+               return -EINVAL;
+
+       strcpy(i->name, inputs[i->index]);
+
+       if (i->index == 0)
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       else
+               i->type  = V4L2_INPUT_TYPE_CAMERA;
+
+       for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
+               i->std |= saa7164_tvnorms[n].id;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       if (saa7164_api_get_videomux(port) != SAA_OK)
+               return -EIO;
+
+       *i = (port->mux_input - 1);
+
+       dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, *i);
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
+
+       if (i >= 7)
+               return -EINVAL;
+
+       port->mux_input = i + 1;
+
+       if (saa7164_api_set_videomux(port) != SAA_OK)
+               return -EIO;
+
+       return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+       struct v4l2_tuner *t)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "tuner");
+       t->type = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
+
+       dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+       struct v4l2_tuner *t)
+{
+       /* Update the A/V core */
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+
+       f->type = V4L2_TUNER_ANALOG_TV;
+       f->frequency = port->freq;
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_port *tsport;
+       struct dvb_frontend *fe;
+
+       /* TODO: Pull this for the std */
+       struct analog_parameters params = {
+               .mode      = V4L2_TUNER_ANALOG_TV,
+               .audmode   = V4L2_TUNER_MODE_STEREO,
+               .std       = port->encodernorm.id,
+               .frequency = f->frequency
+       };
+
+       /* Stop the encoder */
+       dprintk(DBGLVL_ENC, "%s() frequency=%d tuner=%d\n", __func__,
+               f->frequency, f->tuner);
+
+       if (f->tuner != 0)
+               return -EINVAL;
+
+       if (f->type != V4L2_TUNER_ANALOG_TV)
+               return -EINVAL;
+
+       port->freq = f->frequency;
+
+       /* Update the hardware */
+       if (port->nr == SAA7164_PORT_ENC1)
+               tsport = &dev->ports[SAA7164_PORT_TS1];
+       else
+       if (port->nr == SAA7164_PORT_ENC2)
+               tsport = &dev->ports[SAA7164_PORT_TS2];
+       else
+               BUG();
+
+       fe = tsport->dvb.frontend;
+
+       if (fe && fe->ops.tuner_ops.set_analog_params)
+               fe->ops.tuner_ops.set_analog_params(fe, &params);
+       else
+               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+
+       saa7164_encoder_initialize(port);
+
+       return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
+               ctl->id, ctl->value);
+
+       switch (ctl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctl->value = port->ctl_brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctl->value = port->ctl_contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               ctl->value = port->ctl_saturation;
+               break;
+       case V4L2_CID_HUE:
+               ctl->value = port->ctl_hue;
+               break;
+       case V4L2_CID_SHARPNESS:
+               ctl->value = port->ctl_sharpness;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               ctl->value = port->ctl_volume;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+
+       dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
+               ctl->id, ctl->value);
+
+       switch (ctl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_brightness = ctl->value;
+                       saa7164_api_set_usercontrol(port,
+                               PU_BRIGHTNESS_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_CONTRAST:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_contrast = ctl->value;
+                       saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_SATURATION:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_saturation = ctl->value;
+                       saa7164_api_set_usercontrol(port,
+                               PU_SATURATION_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_HUE:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_hue = ctl->value;
+                       saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_SHARPNESS:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_sharpness = ctl->value;
+                       saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               if ((ctl->value >= -83) && (ctl->value <= 24)) {
+                       port->ctl_volume = ctl->value;
+                       saa7164_api_set_audio_volume(port, port->ctl_volume);
+               } else
+                       ret = -EINVAL;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int saa7164_get_ctrl(struct saa7164_port *port,
+       struct v4l2_ext_control *ctrl)
+{
+       struct saa7164_encoder_params *params = &port->encoder_params;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               ctrl->value = params->bitrate;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               ctrl->value = params->stream_type;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               ctrl->value = params->ctl_mute;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               ctrl->value = params->ctl_aspect;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               ctrl->value = params->bitrate_mode;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               ctrl->value = params->refdist;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               ctrl->value = params->bitrate_peak;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               ctrl->value = params->gop_size;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = saa7164_get_ctrl(port, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+
+       }
+
+       return -EINVAL;
+}
+
+static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
+{
+       int ret = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
+                       (ctrl->value <= ENCODER_MAX_BITRATE))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
+                       (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               if ((ctrl->value >= 0) &&
+                       (ctrl->value <= 1))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
+                       (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               if ((ctrl->value >= 0) &&
+                       (ctrl->value <= 255))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ||
+                       (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               if ((ctrl->value >= 1) &&
+                       (ctrl->value <= 3))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
+                       (ctrl->value <= ENCODER_MAX_BITRATE))
+                       ret = 0;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = saa7164_try_ctrl(ctrl, 0);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+       }
+
+       return -EINVAL;
+}
+
+static int saa7164_set_ctrl(struct saa7164_port *port,
+       struct v4l2_ext_control *ctrl)
+{
+       struct saa7164_encoder_params *params = &port->encoder_params;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               params->bitrate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               params->stream_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               params->ctl_mute = ctrl->value;
+               ret = saa7164_api_audio_mute(port, params->ctl_mute);
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
+                               ret);
+                       ret = -EIO;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               params->ctl_aspect = ctrl->value;
+               ret = saa7164_api_set_aspect_ratio(port);
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
+                               ret);
+                       ret = -EIO;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               params->bitrate_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               params->refdist = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               params->bitrate_peak = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               params->gop_size = ctrl->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* TODO: Update the hardware */
+
+       return ret;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = saa7164_try_ctrl(ctrl, 0);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+                       err = saa7164_set_ctrl(port, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+       struct v4l2_capability *cap)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       strcpy(cap->driver, dev->name);
+       strlcpy(cap->card, saa7164_boards[dev->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+
+       cap->capabilities =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_READWRITE     |
+               0;
+
+       cap->capabilities |= V4L2_CAP_TUNER;
+       cap->version = 0;
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+       struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "MPEG", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               port->ts_packet_size * port->ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+       f->fmt.pix.width        = port->width;
+       f->fmt.pix.height       = port->height;
+
+       dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n",
+               port->width, port->height);
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               port->ts_packet_size * port->ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+       dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
+               port->width, port->height);
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               port->ts_packet_size * port->ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+
+       dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+
+       return 0;
+}
+
+static int fill_queryctrl(struct saa7164_encoder_params *params,
+       struct v4l2_queryctrl *c)
+{
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
+       case V4L2_CID_CONTRAST:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
+       case V4L2_CID_SATURATION:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
+       case V4L2_CID_HUE:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
+       case V4L2_CID_SHARPNESS:
+               return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
+       case V4L2_CID_AUDIO_VOLUME:
+               return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               return v4l2_ctrl_query_fill(c,
+                       ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
+                       100000, ENCODER_DEF_BITRATE);
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               return v4l2_ctrl_query_fill(c,
+                       V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+                       V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+                       1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               return v4l2_ctrl_query_fill(c,
+                       V4L2_MPEG_VIDEO_ASPECT_1x1,
+                       V4L2_MPEG_VIDEO_ASPECT_221x100,
+                       1, V4L2_MPEG_VIDEO_ASPECT_4x3);
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               return v4l2_ctrl_query_fill(c,
+                       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
+                       1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               return v4l2_ctrl_query_fill(c,
+                       1, 3, 1, 1);
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               return v4l2_ctrl_query_fill(c,
+                       ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
+                       100000, ENCODER_DEF_BITRATE);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+       struct v4l2_queryctrl *c)
+{
+       struct saa7164_encoder_fh *fh = priv;
+       struct saa7164_port *port = fh->port;
+       int i, next;
+       u32 id = c->id;
+
+       memset(c, 0, sizeof(*c));
+
+       next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
+       c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
+
+       for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
+               if (next) {
+                       if (c->id < saa7164_v4l2_ctrls[i])
+                               c->id = saa7164_v4l2_ctrls[i];
+                       else
+                               continue;
+               }
+
+               if (c->id == saa7164_v4l2_ctrls[i])
+                       return fill_queryctrl(&port->encoder_params, c);
+
+               if (c->id < saa7164_v4l2_ctrls[i])
+                       break;
+       }
+
+       return -EINVAL;
+}
+
+static int saa7164_encoder_stop_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_ENC, "%s()    Stopped\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int saa7164_encoder_acquire_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int saa7164_encoder_pause_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_ENC, "%s()   Paused\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/* Firmware is very windows centric, meaning you have to transition
+ * the part through AVStream / KS Windows stages, forwards or backwards.
+ * States are: stopped, acquired (h/w), paused, started.
+ * We have to leave here will all of the soft buffers on the free list,
+ * else the cfg_post() func won't have soft buffers to correctly configure.
+ */
+static int saa7164_encoder_stop_streaming(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct saa7164_user_buffer *ubuf;
+       struct list_head *c, *n;
+       int ret;
+
+       dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
+
+       ret = saa7164_encoder_pause_port(port);
+       ret = saa7164_encoder_acquire_port(port);
+       ret = saa7164_encoder_stop_port(port);
+
+       dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__,
+               port->nr);
+
+       /* Reset the state of any allocated buffer resources */
+       mutex_lock(&port->dmaqueue_lock);
+
+       /* Reset the hard and soft buffer state */
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               buf = list_entry(c, struct saa7164_buffer, list);
+               buf->flags = SAA7164_BUFFER_FREE;
+               buf->pos = 0;
+       }
+
+       list_for_each_safe(c, n, &port->list_buf_used.list) {
+               ubuf = list_entry(c, struct saa7164_user_buffer, list);
+               ubuf->pos = 0;
+               list_move_tail(&ubuf->list, &port->list_buf_free.list);
+       }
+
+       mutex_unlock(&port->dmaqueue_lock);
+
+       /* Free any allocated resources */
+       saa7164_encoder_buffers_dealloc(port);
+
+       dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr);
+
+       return ret;
+}
+
+static int saa7164_encoder_start_streaming(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int result, ret = 0;
+
+       dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
+
+       port->done_first_interrupt = 0;
+
+       /* allocate all of the PCIe DMA buffer resources on the fly,
+        * allowing switching between TS and PS payloads without
+        * requiring a complete driver reload.
+        */
+       saa7164_encoder_buffers_alloc(port);
+
+       /* Configure the encoder with any cache values */
+       saa7164_api_set_encoder(port);
+       saa7164_api_get_encoder(port);
+
+       /* Place the empty buffers on the hardware */
+       saa7164_buffer_cfg_port(port);
+
+       /* Acquire the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
+                       __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+                       printk(KERN_ERR "%s() acquire/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+               ret = -EIO;
+               goto out;
+       } else
+               dprintk(DBGLVL_ENC, "%s()   Acquired\n", __func__);
+
+       /* Pause the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
+                               __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+                       printk(KERN_ERR "%s() pause/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+
+               ret = -EIO;
+               goto out;
+       } else
+               dprintk(DBGLVL_ENC, "%s()   Paused\n", __func__);
+
+       /* Start the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
+                               __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+                       printk(KERN_ERR "%s() run/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+
+               ret = -EIO;
+       } else
+               dprintk(DBGLVL_ENC, "%s()   Running\n", __func__);
+
+out:
+       return ret;
+}
+
+static int fops_open(struct file *file)
+{
+       struct saa7164_dev *dev;
+       struct saa7164_port *port;
+       struct saa7164_encoder_fh *fh;
+
+       port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
+       if (!port)
+               return -ENODEV;
+
+       dev = port->dev;
+
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       file->private_data = fh;
+       fh->port = port;
+
+       return 0;
+}
+
+static int fops_release(struct file *file)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       /* Shut device down on last close */
+       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+               if (atomic_dec_return(&port->v4l_reader_count) == 0) {
+                       /* stop mpeg capture then cancel buffers */
+                       saa7164_encoder_stop_streaming(port);
+               }
+       }
+
+       file->private_data = NULL;
+       kfree(fh);
+
+       return 0;
+}
+
+struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
+{
+       struct saa7164_user_buffer *ubuf = NULL;
+       struct saa7164_dev *dev = port->dev;
+       u32 crc;
+
+       mutex_lock(&port->dmaqueue_lock);
+       if (!list_empty(&port->list_buf_used.list)) {
+               ubuf = list_first_entry(&port->list_buf_used.list,
+                       struct saa7164_user_buffer, list);
+
+               if (crc_checking) {
+                       crc = crc32(0, ubuf->data, ubuf->actual_size);
+                       if (crc != ubuf->crc) {
+                               printk(KERN_ERR
+               "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
+                                       __func__,
+                                       ubuf, ubuf->crc, crc);
+                       }
+               }
+
+       }
+       mutex_unlock(&port->dmaqueue_lock);
+
+       dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf);
+
+       return ubuf;
+}
+
+static ssize_t fops_read(struct file *file, char __user *buffer,
+       size_t count, loff_t *pos)
+{
+       struct saa7164_encoder_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_user_buffer *ubuf = NULL;
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+       int rem, cnt;
+       u8 *p;
+
+       port->last_read_msecs_diff = port->last_read_msecs;
+       port->last_read_msecs = jiffies_to_msecs(jiffies);
+       port->last_read_msecs_diff = port->last_read_msecs -
+               port->last_read_msecs_diff;
+
+       saa7164_histogram_update(&port->read_interval,
+               port->last_read_msecs_diff);
+
+       if (*pos) {
+               printk(KERN_ERR "%s() ESPIPE\n", __func__);
+               return -ESPIPE;
+       }
+
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
+
+                       if (saa7164_encoder_initialize(port) < 0) {
+                               printk(KERN_ERR "%s() EINVAL\n", __func__);
+                               return -EINVAL;
+                       }
+
+                       saa7164_encoder_start_streaming(port);
+                       msleep(200);
+               }
+       }
+
+       /* blocking wait for buffer */
+       if ((file->f_flags & O_NONBLOCK) == 0) {
+               if (wait_event_interruptible(port->wait_read,
+                       saa7164_enc_next_buf(port))) {
+                               printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
+                               return -ERESTARTSYS;
+               }
+       }
+
+       /* Pull the first buffer from the used list */
+       ubuf = saa7164_enc_next_buf(port);
+
+       while ((count > 0) && ubuf) {
+
+               /* set remaining bytes to copy */
+               rem = ubuf->actual_size - ubuf->pos;
+               cnt = rem > count ? count : rem;
+
+               p = ubuf->data + ubuf->pos;
+
+               dprintk(DBGLVL_ENC,
+                       "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
+                       __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
+
+               if (copy_to_user(buffer, p, cnt)) {
+                       printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
+                       if (!ret) {
+                               printk(KERN_ERR "%s() EFAULT\n", __func__);
+                               ret = -EFAULT;
+                       }
+                       goto err;
+               }
+
+               ubuf->pos += cnt;
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+
+               if (ubuf->pos > ubuf->actual_size)
+                       printk(KERN_ERR "read() pos > actual, huh?\n");
+
+               if (ubuf->pos == ubuf->actual_size) {
+
+                       /* finished with current buffer, take next buffer */
+
+                       /* Requeue the buffer on the free list */
+                       ubuf->pos = 0;
+
+                       mutex_lock(&port->dmaqueue_lock);
+                       list_move_tail(&ubuf->list, &port->list_buf_free.list);
+                       mutex_unlock(&port->dmaqueue_lock);
+
+                       /* Dequeue next */
+                       if ((file->f_flags & O_NONBLOCK) == 0) {
+                               if (wait_event_interruptible(port->wait_read,
+                                       saa7164_enc_next_buf(port))) {
+                                               break;
+                               }
+                       }
+                       ubuf = saa7164_enc_next_buf(port);
+               }
+       }
+err:
+       if (!ret && !ubuf)
+               ret = -EAGAIN;
+
+       return ret;
+}
+
+static unsigned int fops_poll(struct file *file, poll_table *wait)
+{
+       struct saa7164_encoder_fh *fh =
+               (struct saa7164_encoder_fh *)file->private_data;
+       struct saa7164_port *port = fh->port;
+       unsigned int mask = 0;
+
+       port->last_poll_msecs_diff = port->last_poll_msecs;
+       port->last_poll_msecs = jiffies_to_msecs(jiffies);
+       port->last_poll_msecs_diff = port->last_poll_msecs -
+               port->last_poll_msecs_diff;
+
+       saa7164_histogram_update(&port->poll_interval,
+               port->last_poll_msecs_diff);
+
+       if (!video_is_registered(port->v4l_device))
+               return -EIO;
+
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
+                       if (saa7164_encoder_initialize(port) < 0)
+                               return -EINVAL;
+                       saa7164_encoder_start_streaming(port);
+                       msleep(200);
+               }
+       }
+
+       /* blocking wait for buffer */
+       if ((file->f_flags & O_NONBLOCK) == 0) {
+               if (wait_event_interruptible(port->wait_read,
+                       saa7164_enc_next_buf(port))) {
+                               return -ERESTARTSYS;
+               }
+       }
+
+       /* Pull the first buffer from the used list */
+       if (!list_empty(&port->list_buf_used.list))
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+static const struct v4l2_file_operations mpeg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fops_open,
+       .release        = fops_release,
+       .read           = fops_read,
+       .poll           = fops_poll,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+int saa7164_g_chip_ident(struct file *file, void *fh,
+       struct v4l2_dbg_chip_ident *chip)
+{
+       struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
+       struct saa7164_dev *dev = port->dev;
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       return 0;
+}
+
+int saa7164_g_register(struct file *file, void *fh,
+       struct v4l2_dbg_register *reg)
+{
+       struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
+       struct saa7164_dev *dev = port->dev;
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       return 0;
+}
+
+int saa7164_s_register(struct file *file, void *fh,
+       struct v4l2_dbg_register *reg)
+{
+       struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
+       struct saa7164_dev *dev = port->dev;
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+       .vidioc_s_std            = vidioc_s_std,
+       .vidioc_enum_input       = vidioc_enum_input,
+       .vidioc_g_input          = vidioc_g_input,
+       .vidioc_s_input          = vidioc_s_input,
+       .vidioc_g_tuner          = vidioc_g_tuner,
+       .vidioc_s_tuner          = vidioc_s_tuner,
+       .vidioc_g_frequency      = vidioc_g_frequency,
+       .vidioc_s_frequency      = vidioc_s_frequency,
+       .vidioc_s_ctrl           = vidioc_s_ctrl,
+       .vidioc_g_ctrl           = vidioc_g_ctrl,
+       .vidioc_querycap         = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
+       .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
+       .vidioc_queryctrl        = vidioc_queryctrl,
+       .vidioc_g_chip_ident     = saa7164_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register       = saa7164_g_register,
+       .vidioc_s_register       = saa7164_s_register,
+#endif
+};
+
+static struct video_device saa7164_mpeg_template = {
+       .name          = "saa7164",
+       .fops          = &mpeg_fops,
+       .ioctl_ops     = &mpeg_ioctl_ops,
+       .minor         = -1,
+       .tvnorms       = SAA7164_NORMS,
+       .current_norm  = V4L2_STD_NTSC_M,
+};
+
+static struct video_device *saa7164_encoder_alloc(
+       struct saa7164_port *port,
+       struct pci_dev *pci,
+       struct video_device *template,
+       char *type)
+{
+       struct video_device *vfd;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+
+       *vfd = *template;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
+               type, saa7164_boards[dev->board].name);
+
+       vfd->parent  = &pci->dev;
+       vfd->release = video_device_release;
+       return vfd;
+}
+
+int saa7164_encoder_register(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int result = -ENODEV;
+
+       dprintk(DBGLVL_ENC, "%s()\n", __func__);
+
+       if (port->type != SAA7164_MPEG_ENCODER)
+               BUG();
+
+       /* Sanity check that the PCI configuration space is active */
+       if (port->hwcfg.BARLocation == 0) {
+               printk(KERN_ERR "%s() failed "
+                      "(errno = %d), NO PCI configuration\n",
+                       __func__, result);
+               result = -ENOMEM;
+               goto failed;
+       }
+
+       /* Establish encoder defaults here */
+       /* Set default TV standard */
+       port->encodernorm = saa7164_tvnorms[0];
+       port->width = 720;
+       port->mux_input = 1; /* Composite */
+       port->video_format = EU_VIDEO_FORMAT_MPEG_2;
+       port->audio_format = 0;
+       port->video_resolution = 0;
+       port->ctl_brightness = 127;
+       port->ctl_contrast = 66;
+       port->ctl_hue = 128;
+       port->ctl_saturation = 62;
+       port->ctl_sharpness = 8;
+       port->encoder_params.bitrate = ENCODER_DEF_BITRATE;
+       port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE;
+       port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+       port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
+       port->encoder_params.ctl_mute = 0;
+       port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
+       port->encoder_params.refdist = 1;
+       port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE;
+
+       if (port->encodernorm.id & V4L2_STD_525_60)
+               port->height = 480;
+       else
+               port->height = 576;
+
+       /* Allocate and register the video device node */
+       port->v4l_device = saa7164_encoder_alloc(port,
+               dev->pci, &saa7164_mpeg_template, "mpeg");
+
+       if (!port->v4l_device) {
+               printk(KERN_INFO "%s: can't allocate mpeg device\n",
+                       dev->name);
+               result = -ENOMEM;
+               goto failed;
+       }
+
+       video_set_drvdata(port->v4l_device, port);
+       result = video_register_device(port->v4l_device,
+               VFL_TYPE_GRABBER, -1);
+       if (result < 0) {
+               printk(KERN_INFO "%s: can't register mpeg device\n",
+                       dev->name);
+               /* TODO: We're going to leak here if we don't dealloc
+                The buffers above. The unreg function can't deal wit it.
+               */
+               goto failed;
+       }
+
+       printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
+               dev->name, port->v4l_device->num);
+
+       /* Configure the hardware defaults */
+       saa7164_api_set_videomux(port);
+       saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
+       saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
+       saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
+       saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
+       saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
+       saa7164_api_audio_mute(port, 0);
+       saa7164_api_set_audio_volume(port, 20);
+       saa7164_api_set_aspect_ratio(port);
+
+       /* Disable audio standard detection, it's buggy */
+       saa7164_api_set_audio_detection(port, 0);
+
+       saa7164_api_set_encoder(port);
+       saa7164_api_get_encoder(port);
+
+       result = 0;
+failed:
+       return result;
+}
+
+void saa7164_encoder_unregister(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
+
+       if (port->type != SAA7164_MPEG_ENCODER)
+               BUG();
+
+       if (port->v4l_device) {
+               if (port->v4l_device->minor != -1)
+                       video_unregister_device(port->v4l_device);
+               else
+                       video_device_release(port->v4l_device);
+
+               port->v4l_device = NULL;
+       }
+
+       dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
+}
+
diff --git a/drivers/media/pci/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c
new file mode 100644 (file)
index 0000000..a266bf0
--- /dev/null
@@ -0,0 +1,613 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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/firmware.h>
+#include <linux/slab.h>
+
+#include "saa7164.h"
+
+#define SAA7164_REV2_FIRMWARE          "NXP7164-2010-03-10.1.fw"
+#define SAA7164_REV2_FIRMWARE_SIZE     4019072
+
+#define SAA7164_REV3_FIRMWARE          "NXP7164-2010-03-10.1.fw"
+#define SAA7164_REV3_FIRMWARE_SIZE     4019072
+
+struct fw_header {
+       u32     firmwaresize;
+       u32     bslsize;
+       u32     reserved;
+       u32     version;
+};
+
+int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
+{
+       u32 timeout = SAA_DEVICE_TIMEOUT;
+       while ((saa7164_readl(reg) & 0x01) == 0) {
+               timeout -= 10;
+               if (timeout == 0) {
+                       printk(KERN_ERR "%s() timeout (no d/l ack)\n",
+                               __func__);
+                       return -EBUSY;
+               }
+               msleep(100);
+       }
+
+       return 0;
+}
+
+int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
+{
+       u32 timeout = SAA_DEVICE_TIMEOUT;
+       while (saa7164_readl(reg) & 0x01) {
+               timeout -= 10;
+               if (timeout == 0) {
+                       printk(KERN_ERR "%s() timeout (no d/l clr)\n",
+                               __func__);
+                       return -EBUSY;
+               }
+               msleep(100);
+       }
+
+       return 0;
+}
+
+/* TODO: move dlflags into dev-> and change to write/readl/b */
+/* TODO: Excessive levels of debug */
+int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
+       u32 dlflags, u8 *dst, u32 dstsize)
+{
+       u32 reg, timeout, offset;
+       u8 *srcbuf = NULL;
+       int ret;
+
+       u32 dlflag = dlflags;
+       u32 dlflag_ack = dlflag + 4;
+       u32 drflag = dlflag_ack + 4;
+       u32 drflag_ack = drflag + 4;
+       u32 bleflag = drflag_ack + 4;
+
+       dprintk(DBGLVL_FW,
+               "%s(image=%p, size=%d, flags=0x%x, dst=%p, dstsize=0x%x)\n",
+               __func__, src, srcsize, dlflags, dst, dstsize);
+
+       if ((src == NULL) || (dst == NULL)) {
+               ret = -EIO;
+               goto out;
+       }
+
+       srcbuf = kzalloc(4 * 1048576, GFP_KERNEL);
+       if (NULL == srcbuf) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       if (srcsize > (4*1048576)) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       memcpy(srcbuf, src, srcsize);
+
+       dprintk(DBGLVL_FW, "%s() dlflag = 0x%x\n", __func__, dlflag);
+       dprintk(DBGLVL_FW, "%s() dlflag_ack = 0x%x\n", __func__, dlflag_ack);
+       dprintk(DBGLVL_FW, "%s() drflag = 0x%x\n", __func__, drflag);
+       dprintk(DBGLVL_FW, "%s() drflag_ack = 0x%x\n", __func__, drflag_ack);
+       dprintk(DBGLVL_FW, "%s() bleflag = 0x%x\n", __func__, bleflag);
+
+       reg = saa7164_readl(dlflag);
+       dprintk(DBGLVL_FW, "%s() dlflag (0x%x)= 0x%x\n", __func__, dlflag, reg);
+       if (reg == 1)
+               dprintk(DBGLVL_FW,
+                       "%s() Download flag already set, please reboot\n",
+                       __func__);
+
+       /* Indicate download start */
+       saa7164_writel(dlflag, 1);
+       ret = saa7164_dl_wait_ack(dev, dlflag_ack);
+       if (ret < 0)
+               goto out;
+
+       /* Ack download start, then wait for wait */
+       saa7164_writel(dlflag, 0);
+       ret = saa7164_dl_wait_clr(dev, dlflag_ack);
+       if (ret < 0)
+               goto out;
+
+       /* Deal with the raw firmware, in the appropriate chunk size */
+       for (offset = 0; srcsize > dstsize;
+               srcsize -= dstsize, offset += dstsize) {
+
+               dprintk(DBGLVL_FW, "%s() memcpy %d\n", __func__, dstsize);
+               memcpy(dst, srcbuf + offset, dstsize);
+
+               /* Flag the data as ready */
+               saa7164_writel(drflag, 1);
+               ret = saa7164_dl_wait_ack(dev, drflag_ack);
+               if (ret < 0)
+                       goto out;
+
+               /* Wait for indication data was received */
+               saa7164_writel(drflag, 0);
+               ret = saa7164_dl_wait_clr(dev, drflag_ack);
+               if (ret < 0)
+                       goto out;
+
+       }
+
+       dprintk(DBGLVL_FW, "%s() memcpy(l) %d\n", __func__, dstsize);
+       /* Write last block to the device */
+       memcpy(dst, srcbuf+offset, srcsize);
+
+       /* Flag the data as ready */
+       saa7164_writel(drflag, 1);
+       ret = saa7164_dl_wait_ack(dev, drflag_ack);
+       if (ret < 0)
+               goto out;
+
+       saa7164_writel(drflag, 0);
+       timeout = 0;
+       while (saa7164_readl(bleflag) != SAA_DEVICE_IMAGE_BOOTING) {
+               if (saa7164_readl(bleflag) & SAA_DEVICE_IMAGE_CORRUPT) {
+                       printk(KERN_ERR "%s() image corrupt\n", __func__);
+                       ret = -EBUSY;
+                       goto out;
+               }
+
+               if (saa7164_readl(bleflag) & SAA_DEVICE_MEMORY_CORRUPT) {
+                       printk(KERN_ERR "%s() device memory corrupt\n",
+                               __func__);
+                       ret = -EBUSY;
+                       goto out;
+               }
+
+               msleep(10); /* Checkpatch throws a < 20ms warning */
+               if (timeout++ > 60)
+                       break;
+       }
+
+       printk(KERN_INFO "%s() Image downloaded, booting...\n", __func__);
+
+       ret = saa7164_dl_wait_clr(dev, drflag_ack);
+       if (ret < 0)
+               goto out;
+
+       printk(KERN_INFO "%s() Image booted successfully.\n", __func__);
+       ret = 0;
+
+out:
+       kfree(srcbuf);
+       return ret;
+}
+
+/* TODO: Excessive debug */
+/* Load the firmware. Optionally it can be in ROM or newer versions
+ * can be on disk, saving the expense of the ROM hardware. */
+int saa7164_downloadfirmware(struct saa7164_dev *dev)
+{
+       /* u32 second_timeout = 60 * SAA_DEVICE_TIMEOUT; */
+       u32 tmp, filesize, version, err_flags, first_timeout, fwlength;
+       u32 second_timeout, updatebootloader = 1, bootloadersize = 0;
+       const struct firmware *fw = NULL;
+       struct fw_header *hdr, *boothdr = NULL, *fwhdr;
+       u32 bootloaderversion = 0, fwloadersize;
+       u8 *bootloaderoffset = NULL, *fwloaderoffset;
+       char *fwname;
+       int ret;
+
+       dprintk(DBGLVL_FW, "%s()\n", __func__);
+
+       if (saa7164_boards[dev->board].chiprev == SAA7164_CHIP_REV2) {
+               fwname = SAA7164_REV2_FIRMWARE;
+               fwlength = SAA7164_REV2_FIRMWARE_SIZE;
+       } else {
+               fwname = SAA7164_REV3_FIRMWARE;
+               fwlength = SAA7164_REV3_FIRMWARE_SIZE;
+       }
+
+       version = saa7164_getcurrentfirmwareversion(dev);
+
+       if (version == 0x00) {
+
+               second_timeout = 100;
+               first_timeout = 100;
+               err_flags = saa7164_readl(SAA_BOOTLOADERERROR_FLAGS);
+               dprintk(DBGLVL_FW, "%s() err_flags = %x\n",
+                       __func__, err_flags);
+
+               while (err_flags != SAA_DEVICE_IMAGE_BOOTING) {
+                       dprintk(DBGLVL_FW, "%s() err_flags = %x\n",
+                               __func__, err_flags);
+                       msleep(10); /* Checkpatch throws a < 20ms warning */
+
+                       if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) {
+                               printk(KERN_ERR "%s() firmware corrupt\n",
+                                       __func__);
+                               break;
+                       }
+                       if (err_flags & SAA_DEVICE_MEMORY_CORRUPT) {
+                               printk(KERN_ERR "%s() device memory corrupt\n",
+                                       __func__);
+                               break;
+                       }
+                       if (err_flags & SAA_DEVICE_NO_IMAGE) {
+                               printk(KERN_ERR "%s() no first image\n",
+                               __func__);
+                               break;
+                       }
+                       if (err_flags & SAA_DEVICE_IMAGE_SEARCHING) {
+                               first_timeout -= 10;
+                               if (first_timeout == 0) {
+                                       printk(KERN_ERR
+                                               "%s() no first image\n",
+                                               __func__);
+                                       break;
+                               }
+                       } else if (err_flags & SAA_DEVICE_IMAGE_LOADING) {
+                               second_timeout -= 10;
+                               if (second_timeout == 0) {
+                                       printk(KERN_ERR
+                                       "%s() FW load time exceeded\n",
+                                               __func__);
+                                       break;
+                               }
+                       } else {
+                               second_timeout -= 10;
+                               if (second_timeout == 0) {
+                                       printk(KERN_ERR
+                                       "%s() Unknown bootloader flags 0x%x\n",
+                                               __func__, err_flags);
+                                       break;
+                               }
+                       }
+
+                       err_flags = saa7164_readl(SAA_BOOTLOADERERROR_FLAGS);
+               } /* While != Booting */
+
+               if (err_flags == SAA_DEVICE_IMAGE_BOOTING) {
+                       dprintk(DBGLVL_FW, "%s() Loader 1 has loaded.\n",
+                               __func__);
+                       first_timeout = SAA_DEVICE_TIMEOUT;
+                       second_timeout = 60 * SAA_DEVICE_TIMEOUT;
+                       second_timeout = 100;
+
+                       err_flags = saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS);
+                       dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n",
+                               __func__, err_flags);
+                       while (err_flags != SAA_DEVICE_IMAGE_BOOTING) {
+                               dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n",
+                                       __func__, err_flags);
+                               msleep(10); /* Checkpatch throws a < 20ms warning */
+
+                               if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) {
+                                       printk(KERN_ERR
+                                               "%s() firmware corrupt\n",
+                                               __func__);
+                                       break;
+                               }
+                               if (err_flags & SAA_DEVICE_MEMORY_CORRUPT) {
+                                       printk(KERN_ERR
+                                               "%s() device memory corrupt\n",
+                                               __func__);
+                                       break;
+                               }
+                               if (err_flags & SAA_DEVICE_NO_IMAGE) {
+                                       printk(KERN_ERR "%s() no first image\n",
+                                               __func__);
+                                       break;
+                               }
+                               if (err_flags & SAA_DEVICE_IMAGE_SEARCHING) {
+                                       first_timeout -= 10;
+                                       if (first_timeout == 0) {
+                                               printk(KERN_ERR
+                                               "%s() no second image\n",
+                                                       __func__);
+                                               break;
+                                       }
+                               } else if (err_flags &
+                                       SAA_DEVICE_IMAGE_LOADING) {
+                                       second_timeout -= 10;
+                                       if (second_timeout == 0) {
+                                               printk(KERN_ERR
+                                               "%s() FW load time exceeded\n",
+                                                       __func__);
+                                               break;
+                                       }
+                               } else {
+                                       second_timeout -= 10;
+                                       if (second_timeout == 0) {
+                                               printk(KERN_ERR
+                                       "%s() Unknown bootloader flags 0x%x\n",
+                                                       __func__, err_flags);
+                                               break;
+                                       }
+                               }
+
+                               err_flags =
+                               saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS);
+                       } /* err_flags != SAA_DEVICE_IMAGE_BOOTING */
+
+                       dprintk(DBGLVL_FW, "%s() Loader flags 1:0x%x 2:0x%x.\n",
+                               __func__,
+                               saa7164_readl(SAA_BOOTLOADERERROR_FLAGS),
+                               saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS));
+
+               } /* err_flags == SAA_DEVICE_IMAGE_BOOTING */
+
+               /* It's possible for both firmwares to have booted,
+                * but that doesn't mean they've finished booting yet.
+                */
+               if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) ==
+                       SAA_DEVICE_IMAGE_BOOTING) &&
+                       (saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS) ==
+                       SAA_DEVICE_IMAGE_BOOTING)) {
+
+
+                       dprintk(DBGLVL_FW, "%s() Loader 2 has loaded.\n",
+                               __func__);
+
+                       first_timeout = SAA_DEVICE_TIMEOUT;
+                       while (first_timeout) {
+                               msleep(10); /* Checkpatch throws a < 20ms warning */
+
+                               version =
+                                       saa7164_getcurrentfirmwareversion(dev);
+                               if (version) {
+                                       dprintk(DBGLVL_FW,
+                                       "%s() All f/w loaded successfully\n",
+                                               __func__);
+                                       break;
+                               } else {
+                                       first_timeout -= 10;
+                                       if (first_timeout == 0) {
+                                               printk(KERN_ERR
+                                               "%s() FW did not boot\n",
+                                                       __func__);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               version = saa7164_getcurrentfirmwareversion(dev);
+       } /* version == 0 */
+
+       /* Has the firmware really booted? */
+       if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) ==
+               SAA_DEVICE_IMAGE_BOOTING) &&
+               (saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS) ==
+               SAA_DEVICE_IMAGE_BOOTING) && (version == 0)) {
+
+               printk(KERN_ERR
+                       "%s() The firmware hung, probably bad firmware\n",
+                       __func__);
+
+               /* Tell the second stage loader we have a deadlock */
+               saa7164_writel(SAA_DEVICE_DEADLOCK_DETECTED_OFFSET,
+                       SAA_DEVICE_DEADLOCK_DETECTED);
+
+               saa7164_getfirmwarestatus(dev);
+
+               return -ENOMEM;
+       }
+
+       dprintk(DBGLVL_FW, "Device has Firmware Version %d.%d.%d.%d\n",
+               (version & 0x0000fc00) >> 10,
+               (version & 0x000003e0) >> 5,
+               (version & 0x0000001f),
+               (version & 0xffff0000) >> 16);
+
+       /* Load the firmwware from the disk if required */
+       if (version == 0) {
+
+               printk(KERN_INFO "%s() Waiting for firmware upload (%s)\n",
+                       __func__, fwname);
+
+               ret = request_firmware(&fw, fwname, &dev->pci->dev);
+               if (ret) {
+                       printk(KERN_ERR "%s() Upload failed. "
+                               "(file not found?)\n", __func__);
+                       return -ENOMEM;
+               }
+
+               printk(KERN_INFO "%s() firmware read %Zu bytes.\n",
+                       __func__, fw->size);
+
+               if (fw->size != fwlength) {
+                       printk(KERN_ERR "xc5000: firmware incorrect size\n");
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               printk(KERN_INFO "%s() firmware loaded.\n", __func__);
+
+               hdr = (struct fw_header *)fw->data;
+               printk(KERN_INFO "Firmware file header part 1:\n");
+               printk(KERN_INFO " .FirmwareSize = 0x%x\n", hdr->firmwaresize);
+               printk(KERN_INFO " .BSLSize = 0x%x\n", hdr->bslsize);
+               printk(KERN_INFO " .Reserved = 0x%x\n", hdr->reserved);
+               printk(KERN_INFO " .Version = 0x%x\n", hdr->version);
+
+               /* Retrieve bootloader if reqd */
+               if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0))
+                       /* Second bootloader in the firmware file */
+                       filesize = hdr->reserved * 16;
+               else
+                       filesize = (hdr->firmwaresize + hdr->bslsize) *
+                               16 + sizeof(struct fw_header);
+
+               printk(KERN_INFO "%s() SecBootLoader.FileSize = %d\n",
+                       __func__, filesize);
+
+               /* Get bootloader (if reqd) and firmware header */
+               if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) {
+                       /* Second boot loader is required */
+
+                       /* Get the loader header */
+                       boothdr = (struct fw_header *)(fw->data +
+                               sizeof(struct fw_header));
+
+                       bootloaderversion =
+                               saa7164_readl(SAA_DEVICE_2ND_VERSION);
+                       dprintk(DBGLVL_FW, "Onboard BootLoader:\n");
+                       dprintk(DBGLVL_FW, "->Flag 0x%x\n",
+                               saa7164_readl(SAA_BOOTLOADERERROR_FLAGS));
+                       dprintk(DBGLVL_FW, "->Ack 0x%x\n",
+                               saa7164_readl(SAA_DATAREADY_FLAG_ACK));
+                       dprintk(DBGLVL_FW, "->FW Version 0x%x\n", version);
+                       dprintk(DBGLVL_FW, "->Loader Version 0x%x\n",
+                               bootloaderversion);
+
+                       if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) ==
+                               0x03) && (saa7164_readl(SAA_DATAREADY_FLAG_ACK)
+                               == 0x00) && (version == 0x00)) {
+
+                               dprintk(DBGLVL_FW, "BootLoader version in  "
+                                       "rom %d.%d.%d.%d\n",
+                                       (bootloaderversion & 0x0000fc00) >> 10,
+                                       (bootloaderversion & 0x000003e0) >> 5,
+                                       (bootloaderversion & 0x0000001f),
+                                       (bootloaderversion & 0xffff0000) >> 16
+                                       );
+                               dprintk(DBGLVL_FW, "BootLoader version "
+                                       "in file %d.%d.%d.%d\n",
+                                       (boothdr->version & 0x0000fc00) >> 10,
+                                       (boothdr->version & 0x000003e0) >> 5,
+                                       (boothdr->version & 0x0000001f),
+                                       (boothdr->version & 0xffff0000) >> 16
+                                       );
+
+                               if (bootloaderversion == boothdr->version)
+                                       updatebootloader = 0;
+                       }
+
+                       /* Calculate offset to firmware header */
+                       tmp = (boothdr->firmwaresize + boothdr->bslsize) * 16 +
+                               (sizeof(struct fw_header) +
+                               sizeof(struct fw_header));
+
+                       fwhdr = (struct fw_header *)(fw->data+tmp);
+               } else {
+                       /* No second boot loader */
+                       fwhdr = hdr;
+               }
+
+               dprintk(DBGLVL_FW, "Firmware version in file %d.%d.%d.%d\n",
+                       (fwhdr->version & 0x0000fc00) >> 10,
+                       (fwhdr->version & 0x000003e0) >> 5,
+                       (fwhdr->version & 0x0000001f),
+                       (fwhdr->version & 0xffff0000) >> 16
+                       );
+
+               if (version == fwhdr->version) {
+                       /* No download, firmware already on board */
+                       ret = 0;
+                       goto out;
+               }
+
+               if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) {
+                       if (updatebootloader) {
+                               /* Get ready to upload the bootloader */
+                               bootloadersize = (boothdr->firmwaresize +
+                                       boothdr->bslsize) * 16 +
+                                       sizeof(struct fw_header);
+
+                               bootloaderoffset = (u8 *)(fw->data +
+                                       sizeof(struct fw_header));
+
+                               dprintk(DBGLVL_FW, "bootloader d/l starts.\n");
+                               printk(KERN_INFO "%s() FirmwareSize = 0x%x\n",
+                                       __func__, boothdr->firmwaresize);
+                               printk(KERN_INFO "%s() BSLSize = 0x%x\n",
+                                       __func__, boothdr->bslsize);
+                               printk(KERN_INFO "%s() Reserved = 0x%x\n",
+                                       __func__, boothdr->reserved);
+                               printk(KERN_INFO "%s() Version = 0x%x\n",
+                                       __func__, boothdr->version);
+                               ret = saa7164_downloadimage(
+                                       dev,
+                                       bootloaderoffset,
+                                       bootloadersize,
+                                       SAA_DOWNLOAD_FLAGS,
+                                       dev->bmmio + SAA_DEVICE_DOWNLOAD_OFFSET,
+                                       SAA_DEVICE_BUFFERBLOCKSIZE);
+                               if (ret < 0) {
+                                       printk(KERN_ERR
+                                               "bootloader d/l has failed\n");
+                                       goto out;
+                               }
+                               dprintk(DBGLVL_FW,
+                                       "bootloader download complete.\n");
+
+                       }
+
+                       printk(KERN_ERR "starting firmware download(2)\n");
+                       bootloadersize = (boothdr->firmwaresize +
+                               boothdr->bslsize) * 16 +
+                               sizeof(struct fw_header);
+
+                       bootloaderoffset =
+                               (u8 *)(fw->data + sizeof(struct fw_header));
+
+                       fwloaderoffset = bootloaderoffset + bootloadersize;
+
+                       /* TODO: fix this bounds overrun here with old f/ws */
+                       fwloadersize = (fwhdr->firmwaresize + fwhdr->bslsize) *
+                               16 + sizeof(struct fw_header);
+
+                       ret = saa7164_downloadimage(
+                               dev,
+                               fwloaderoffset,
+                               fwloadersize,
+                               SAA_DEVICE_2ND_DOWNLOADFLAG_OFFSET,
+                               dev->bmmio + SAA_DEVICE_2ND_DOWNLOAD_OFFSET,
+                               SAA_DEVICE_2ND_BUFFERBLOCKSIZE);
+                       if (ret < 0) {
+                               printk(KERN_ERR "firmware download failed\n");
+                               goto out;
+                       }
+                       printk(KERN_ERR "firmware download complete.\n");
+
+               } else {
+
+                       /* No bootloader update reqd, download firmware only */
+                       printk(KERN_ERR "starting firmware download(3)\n");
+
+                       ret = saa7164_downloadimage(
+                               dev,
+                               (u8 *)fw->data,
+                               fw->size,
+                               SAA_DOWNLOAD_FLAGS,
+                               dev->bmmio + SAA_DEVICE_DOWNLOAD_OFFSET,
+                               SAA_DEVICE_BUFFERBLOCKSIZE);
+                       if (ret < 0) {
+                               printk(KERN_ERR "firmware download failed\n");
+                               goto out;
+                       }
+                       printk(KERN_ERR "firmware download complete.\n");
+               }
+       }
+
+       dev->firmwareloaded = 1;
+       ret = 0;
+
+out:
+       release_firmware(fw);
+       return ret;
+}
diff --git a/drivers/media/pci/saa7164/saa7164-i2c.c b/drivers/media/pci/saa7164/saa7164-i2c.c
new file mode 100644 (file)
index 0000000..4f7e3b4
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 "saa7164.h"
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+       struct saa7164_i2c *bus = i2c_adap->algo_data;
+       struct saa7164_dev *dev = bus->dev;
+       int i, retval = 0;
+
+       dprintk(DBGLVL_I2C, "%s(num = %d)\n", __func__, num);
+
+       for (i = 0 ; i < num; i++) {
+               dprintk(DBGLVL_I2C, "%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) {
+                       /* Unsupported - Yet*/
+                       printk(KERN_ERR "%s() Unsupported - Yet\n", __func__);
+                       continue;
+               } 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 = saa7164_api_i2c_read(bus, msgs[i].addr,
+                               msgs[i].len, msgs[i].buf,
+                               msgs[i+1].len, msgs[i+1].buf
+                               );
+
+                       i++;
+
+                       if (retval < 0)
+                               goto err;
+               } else {
+                       /* write */
+                       retval = saa7164_api_i2c_write(bus, msgs[i].addr,
+                               msgs[i].len, msgs[i].buf);
+               }
+               if (retval < 0)
+                       goto err;
+       }
+       return num;
+
+err:
+       return retval;
+}
+
+static u32 saa7164_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm saa7164_i2c_algo_template = {
+       .master_xfer    = i2c_xfer,
+       .functionality  = saa7164_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter saa7164_i2c_adap_template = {
+       .name              = "saa7164",
+       .owner             = THIS_MODULE,
+       .algo              = &saa7164_i2c_algo_template,
+};
+
+static struct i2c_client saa7164_i2c_client_template = {
+       .name   = "saa7164 internal",
+};
+
+int saa7164_i2c_register(struct saa7164_i2c *bus)
+{
+       struct saa7164_dev *dev = bus->dev;
+
+       dprintk(DBGLVL_I2C, "%s(bus = %d)\n", __func__, bus->nr);
+
+       bus->i2c_adap = saa7164_i2c_adap_template;
+       bus->i2c_client = saa7164_i2c_client_template;
+
+       bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+       strlcpy(bus->i2c_adap.name, bus->dev->name,
+               sizeof(bus->i2c_adap.name));
+
+       bus->i2c_adap.algo_data = bus;
+       i2c_set_adapdata(&bus->i2c_adap, bus);
+       i2c_add_adapter(&bus->i2c_adap);
+
+       bus->i2c_client.adapter = &bus->i2c_adap;
+
+       if (0 != bus->i2c_rc)
+               printk(KERN_ERR "%s: i2c bus %d register FAILED\n",
+                       dev->name, bus->nr);
+
+       return bus->i2c_rc;
+}
+
+int saa7164_i2c_unregister(struct saa7164_i2c *bus)
+{
+       i2c_del_adapter(&bus->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/pci/saa7164/saa7164-reg.h b/drivers/media/pci/saa7164/saa7164-reg.h
new file mode 100644 (file)
index 0000000..2bbf815
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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.
+ */
+
+/* TODO: Retest the driver with errors expressed as negatives */
+
+/* Result codes */
+#define SAA_OK                         0
+#define SAA_ERR_BAD_PARAMETER          0x09
+#define SAA_ERR_NO_RESOURCES           0x0c
+#define SAA_ERR_NOT_SUPPORTED          0x13
+#define SAA_ERR_BUSY                   0x15
+#define SAA_ERR_READ                   0x17
+#define SAA_ERR_TIMEOUT                        0x1f
+#define SAA_ERR_OVERFLOW               0x20
+#define SAA_ERR_EMPTY                  0x22
+#define SAA_ERR_NOT_STARTED            0x23
+#define SAA_ERR_ALREADY_STARTED                0x24
+#define SAA_ERR_NOT_STOPPED            0x25
+#define SAA_ERR_ALREADY_STOPPED                0x26
+#define SAA_ERR_INVALID_COMMAND                0x3e
+#define SAA_ERR_NULL_PACKET            0x59
+
+/* Errors and flags from the silicon */
+#define PVC_ERRORCODE_UNKNOWN          0x00
+#define PVC_ERRORCODE_INVALID_COMMAND  0x01
+#define PVC_ERRORCODE_INVALID_CONTROL  0x02
+#define PVC_ERRORCODE_INVALID_DATA     0x03
+#define PVC_ERRORCODE_TIMEOUT          0x04
+#define PVC_ERRORCODE_NAK              0x05
+#define PVC_RESPONSEFLAG_ERROR         0x01
+#define PVC_RESPONSEFLAG_OVERFLOW      0x02
+#define PVC_RESPONSEFLAG_RESET         0x04
+#define PVC_RESPONSEFLAG_INTERFACE     0x08
+#define PVC_RESPONSEFLAG_CONTINUED     0x10
+#define PVC_CMDFLAG_INTERRUPT          0x02
+#define PVC_CMDFLAG_INTERFACE          0x04
+#define PVC_CMDFLAG_SERIALIZE          0x08
+#define PVC_CMDFLAG_CONTINUE           0x10
+
+/* Silicon Commands */
+#define GET_DESCRIPTORS_CONTROL                0x01
+#define GET_STRING_CONTROL             0x03
+#define GET_LANGUAGE_CONTROL           0x05
+#define SET_POWER_CONTROL              0x07
+#define GET_FW_STATUS_CONTROL          0x08
+#define GET_FW_VERSION_CONTROL         0x09
+#define SET_DEBUG_LEVEL_CONTROL                0x0B
+#define GET_DEBUG_DATA_CONTROL         0x0C
+#define GET_PRODUCTION_INFO_CONTROL    0x0D
+
+/* cmd defines */
+#define SAA_CMDFLAG_CONTINUE           0x10
+#define SAA_CMD_MAX_MSG_UNITS          256
+
+/* Some defines */
+#define SAA_BUS_TIMEOUT                        50
+#define SAA_DEVICE_TIMEOUT             5000
+#define SAA_DEVICE_MAXREQUESTSIZE      256
+
+/* Register addresses */
+#define SAA_DEVICE_VERSION             0x30
+#define SAA_DOWNLOAD_FLAGS             0x34
+#define SAA_DOWNLOAD_FLAG              0x34
+#define SAA_DOWNLOAD_FLAG_ACK          0x38
+#define SAA_DATAREADY_FLAG             0x3C
+#define SAA_DATAREADY_FLAG_ACK         0x40
+
+/* Boot loader register and bit definitions */
+#define SAA_BOOTLOADERERROR_FLAGS      0x44
+#define SAA_DEVICE_IMAGE_SEARCHING     0x01
+#define SAA_DEVICE_IMAGE_LOADING       0x02
+#define SAA_DEVICE_IMAGE_BOOTING       0x03
+#define SAA_DEVICE_IMAGE_CORRUPT       0x04
+#define SAA_DEVICE_MEMORY_CORRUPT      0x08
+#define SAA_DEVICE_NO_IMAGE            0x10
+
+/* Register addresses */
+#define SAA_DEVICE_2ND_VERSION                 0x50
+#define SAA_DEVICE_2ND_DOWNLOADFLAG_OFFSET     0x54
+
+/* Register addresses */
+#define SAA_SECONDSTAGEERROR_FLAGS             0x64
+
+/* Bootloader regs and flags */
+#define SAA_DEVICE_DEADLOCK_DETECTED_OFFSET    0x6C
+#define SAA_DEVICE_DEADLOCK_DETECTED           0xDEADDEAD
+
+/* Basic firmware status registers */
+#define SAA_DEVICE_SYSINIT_STATUS_OFFSET       0x70
+#define SAA_DEVICE_SYSINIT_STATUS              0x70
+#define SAA_DEVICE_SYSINIT_MODE                        0x74
+#define SAA_DEVICE_SYSINIT_SPEC                        0x78
+#define SAA_DEVICE_SYSINIT_INST                        0x7C
+#define SAA_DEVICE_SYSINIT_CPULOAD             0x80
+#define SAA_DEVICE_SYSINIT_REMAINHEAP          0x84
+
+#define SAA_DEVICE_DOWNLOAD_OFFSET             0x1000
+#define SAA_DEVICE_BUFFERBLOCKSIZE             0x1000
+
+#define SAA_DEVICE_2ND_BUFFERBLOCKSIZE         0x100000
+#define SAA_DEVICE_2ND_DOWNLOAD_OFFSET         0x200000
+
+/* Descriptors */
+#define CS_INTERFACE   0x24
+
+/* Descriptor subtypes */
+#define VC_INPUT_TERMINAL              0x02
+#define VC_OUTPUT_TERMINAL             0x03
+#define VC_SELECTOR_UNIT               0x04
+#define VC_PROCESSING_UNIT             0x05
+#define FEATURE_UNIT                   0x06
+#define TUNER_UNIT                     0x09
+#define ENCODER_UNIT                   0x0A
+#define EXTENSION_UNIT                 0x0B
+#define VC_TUNER_PATH                  0xF0
+#define PVC_HARDWARE_DESCRIPTOR                0xF1
+#define PVC_INTERFACE_DESCRIPTOR       0xF2
+#define PVC_INFRARED_UNIT              0xF3
+#define DRM_UNIT                       0xF4
+#define GENERAL_REQUEST                        0xF5
+
+/* Format Types */
+#define VS_FORMAT_TYPE         0x02
+#define VS_FORMAT_TYPE_I       0x01
+#define VS_FORMAT_UNCOMPRESSED 0x04
+#define VS_FRAME_UNCOMPRESSED  0x05
+#define VS_FORMAT_MPEG2PS      0x09
+#define VS_FORMAT_MPEG2TS      0x0A
+#define VS_FORMAT_MPEG4SL      0x0B
+#define VS_FORMAT_WM9          0x0C
+#define VS_FORMAT_DIVX         0x0D
+#define VS_FORMAT_VBI          0x0E
+#define VS_FORMAT_RDS          0x0F
+
+/* Device extension commands */
+#define EXU_REGISTER_ACCESS_CONTROL    0x00
+#define EXU_GPIO_CONTROL               0x01
+#define EXU_GPIO_GROUP_CONTROL         0x02
+#define EXU_INTERRUPT_CONTROL          0x03
+
+/* State Transition and args */
+#define SAA_PROBE_CONTROL      0x01
+#define SAA_COMMIT_CONTROL     0x02
+#define SAA_STATE_CONTROL      0x03
+#define SAA_DMASTATE_STOP      0x00
+#define SAA_DMASTATE_ACQUIRE   0x01
+#define SAA_DMASTATE_PAUSE     0x02
+#define SAA_DMASTATE_RUN       0x03
+
+/* A/V Mux Input Selector */
+#define SU_INPUT_SELECT_CONTROL 0x01
+
+/* Encoder Profiles */
+#define EU_PROFILE_PS_DVD      0x06
+#define EU_PROFILE_TS_HQ       0x09
+#define EU_VIDEO_FORMAT_MPEG_2 0x02
+
+/* Tuner */
+#define TU_AUDIO_MODE_CONTROL  0x17
+
+/* Video Formats */
+#define TU_STANDARD_CONTROL            0x00
+#define TU_STANDARD_AUTO_CONTROL       0x01
+#define TU_STANDARD_NONE               0x00
+#define TU_STANDARD_NTSC_M             0x01
+#define TU_STANDARD_PAL_I              0x08
+#define TU_STANDARD_MANUAL             0x00
+#define TU_STANDARD_AUTO               0x01
+
+/* Video Controls */
+#define PU_BRIGHTNESS_CONTROL  0x02
+#define PU_CONTRAST_CONTROL    0x03
+#define PU_HUE_CONTROL         0x06
+#define PU_SATURATION_CONTROL  0x07
+#define PU_SHARPNESS_CONTROL   0x08
+
+/* Audio Controls */
+#define MUTE_CONTROL           0x01
+#define VOLUME_CONTROL         0x02
+#define AUDIO_DEFAULT_CONTROL  0x0D
+
+/* Default Volume Levels */
+#define TMHW_LEV_ADJ_DECLEV_DEFAULT     0x00
+#define TMHW_LEV_ADJ_MONOLEV_DEFAULT    0x00
+#define TMHW_LEV_ADJ_NICLEV_DEFAULT     0x00
+#define TMHW_LEV_ADJ_SAPLEV_DEFAULT     0x00
+#define TMHW_LEV_ADJ_ADCLEV_DEFAULT     0x00
+
+/* Encoder Related Commands */
+#define EU_PROFILE_CONTROL             0x00
+#define EU_VIDEO_FORMAT_CONTROL                0x01
+#define EU_VIDEO_BIT_RATE_CONTROL      0x02
+#define EU_VIDEO_RESOLUTION_CONTROL    0x03
+#define EU_VIDEO_GOP_STRUCTURE_CONTROL 0x04
+#define EU_VIDEO_INPUT_ASPECT_CONTROL  0x0A
+#define EU_AUDIO_FORMAT_CONTROL                0x0C
+#define EU_AUDIO_BIT_RATE_CONTROL      0x0D
+
+/* Firmware Debugging */
+#define SET_DEBUG_LEVEL_CONTROL        0x0B
+#define GET_DEBUG_DATA_CONTROL 0x0C
diff --git a/drivers/media/pci/saa7164/saa7164-types.h b/drivers/media/pci/saa7164/saa7164-types.h
new file mode 100644 (file)
index 0000000..1d2140a
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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.
+ */
+
+/* TODO: Cleanup and shorten the namespace */
+
+/* Some structues are passed directly to/from the firmware and
+ * have strict alignment requirements. This is one of them.
+ */
+struct tmComResHWDescr {
+       u8      bLength;
+       u8      bDescriptorType;
+       u8      bDescriptorSubtype;
+       u16     bcdSpecVersion;
+       u32     dwClockFrequency;
+       u32     dwClockUpdateRes;
+       u8      bCapabilities;
+       u32     dwDeviceRegistersLocation;
+       u32     dwHostMemoryRegion;
+       u32     dwHostMemoryRegionSize;
+       u32     dwHostHibernatMemRegion;
+       u32     dwHostHibernatMemRegionSize;
+} __attribute__((packed));
+
+/* This is DWORD aligned on windows but I can't find the right
+ * gcc syntax to match the binary data from the device.
+ * I've manually padded with Reserved[3] bytes to match the hardware,
+ * but this could break if GCC decies to pack in a different way.
+ */
+struct tmComResInterfaceDescr {
+       u8      bLength;
+       u8      bDescriptorType;
+       u8      bDescriptorSubtype;
+       u8      bFlags;
+       u8      bInterfaceType;
+       u8      bInterfaceId;
+       u8      bBaseInterface;
+       u8      bInterruptId;
+       u8      bDebugInterruptId;
+       u8      BARLocation;
+       u8      Reserved[3];
+};
+
+struct tmComResBusDescr {
+       u64     CommandRing;
+       u64     ResponseRing;
+       u32     CommandWrite;
+       u32     CommandRead;
+       u32     ResponseWrite;
+       u32     ResponseRead;
+};
+
+enum tmBusType {
+       NONE            = 0,
+       TYPE_BUS_PCI    = 1,
+       TYPE_BUS_PCIe   = 2,
+       TYPE_BUS_USB    = 3,
+       TYPE_BUS_I2C    = 4
+};
+
+struct tmComResBusInfo {
+       enum tmBusType Type;
+       u16     m_wMaxReqSize;
+       u8      *m_pdwSetRing;
+       u32     m_dwSizeSetRing;
+       u8      *m_pdwGetRing;
+       u32     m_dwSizeGetRing;
+       u32     m_dwSetWritePos;
+       u32     m_dwSetReadPos;
+       u32     m_dwGetWritePos;
+       u32     m_dwGetReadPos;
+
+       /* All access is protected */
+       struct mutex lock;
+
+};
+
+struct tmComResInfo {
+       u8      id;
+       u8      flags;
+       u16     size;
+       u32     command;
+       u16     controlselector;
+       u8      seqno;
+} __attribute__((packed));
+
+enum tmComResCmd {
+       SET_CUR  = 0x01,
+       GET_CUR  = 0x81,
+       GET_MIN  = 0x82,
+       GET_MAX  = 0x83,
+       GET_RES  = 0x84,
+       GET_LEN  = 0x85,
+       GET_INFO = 0x86,
+       GET_DEF  = 0x87
+};
+
+struct cmd {
+       u8 seqno;
+       u32 inuse;
+       u32 timeout;
+       u32 signalled;
+       struct mutex lock;
+       wait_queue_head_t wait;
+};
+
+struct tmDescriptor {
+       u32     pathid;
+       u32     size;
+       void    *descriptor;
+};
+
+struct tmComResDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+} __attribute__((packed));
+
+struct tmComResExtDevDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+       u32     devicetype;
+       u16     deviceid;
+       u32     numgpiopins;
+       u8      numgpiogroups;
+       u8      controlsize;
+} __attribute__((packed));
+
+struct tmComResGPIO {
+       u32     pin;
+       u8      state;
+} __attribute__((packed));
+
+struct tmComResPathDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      pathid;
+} __attribute__((packed));
+
+/* terminaltype */
+enum tmComResTermType {
+       ITT_ANTENNA              = 0x0203,
+       LINE_CONNECTOR           = 0x0603,
+       SPDIF_CONNECTOR          = 0x0605,
+       COMPOSITE_CONNECTOR      = 0x0401,
+       SVIDEO_CONNECTOR         = 0x0402,
+       COMPONENT_CONNECTOR      = 0x0403,
+       STANDARD_DMA             = 0xF101
+};
+
+struct tmComResAntTermDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      terminalid;
+       u16     terminaltype;
+       u8      assocterminal;
+       u8      iterminal;
+       u8      controlsize;
+} __attribute__((packed));
+
+struct tmComResTunerDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+       u8      sourceid;
+       u8      iunit;
+       u32     tuningstandards;
+       u8      controlsize;
+       u32     controls;
+} __attribute__((packed));
+
+enum tmBufferFlag {
+       /* the buffer does not contain any valid data */
+       TM_BUFFER_FLAG_EMPTY,
+
+       /* the buffer is filled with valid data */
+       TM_BUFFER_FLAG_DONE,
+
+       /* the buffer is the dummy buffer - TODO??? */
+       TM_BUFFER_FLAG_DUMMY_BUFFER
+};
+
+struct tmBuffer {
+       u64             *pagetablevirt;
+       u64             pagetablephys;
+       u16             offset;
+       u8              *context;
+       u64             timestamp;
+       enum tmBufferFlag BufferFlag;
+       u32             lostbuffers;
+       u32             validbuffers;
+       u64             *dummypagevirt;
+       u64             dummypagephys;
+       u64             *addressvirt;
+};
+
+struct tmHWStreamParameters {
+       u32     bitspersample;
+       u32     samplesperline;
+       u32     numberoflines;
+       u32     pitch;
+       u32     linethreshold;
+       u64     **pagetablelistvirt;
+       u64     *pagetablelistphys;
+       u32     numpagetables;
+       u32     numpagetableentries;
+};
+
+struct tmStreamParameters {
+       struct tmHWStreamParameters     HWStreamParameters;
+       u64                             qwDummyPageTablePhys;
+       u64                             *pDummyPageTableVirt;
+};
+
+struct tmComResDMATermDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtyle;
+       u8      unitid;
+       u16     terminaltype;
+       u8      assocterminal;
+       u8      sourceid;
+       u8      iterminal;
+       u32     BARLocation;
+       u8      flags;
+       u8      interruptid;
+       u8      buffercount;
+       u8      metadatasize;
+       u8      numformats;
+       u8      controlsize;
+} __attribute__((packed));
+
+/*
+ *
+ * Description:
+ *  This is the transport stream format header.
+ *
+ * Settings:
+ *  bLength                 - The size of this descriptor in bytes.
+ *  bDescriptorType         - CS_INTERFACE.
+ *  bDescriptorSubtype      - VS_FORMAT_MPEG2TS descriptor subtype.
+ *  bFormatIndex            - A non-zero constant that uniquely identifies the
+ *                            format.
+ *  bDataOffset             - Offset to TSP packet within MPEG-2 TS transport
+ *                            stride, in bytes.
+ *  bPacketLength           - Length of TSP packet, in bytes (typically 188).
+ *  bStrideLength           - Length of MPEG-2 TS transport stride.
+ *  guidStrideFormat        - A Globally Unique Identifier indicating the
+ *                            format of the stride data (if any). Set to zeros
+ *                            if there is no Stride Data, or if the Stride
+ *                            Data is to be ignored by the application.
+ *
+ */
+struct tmComResTSFormatDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      bFormatIndex;
+       u8      bDataOffset;
+       u8      bPacketLength;
+       u8      bStrideLength;
+       u8      guidStrideFormat[16];
+} __attribute__((packed));
+
+/* Encoder related structures */
+
+/* A/V Mux Selector */
+struct tmComResSelDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+       u8      nrinpins;
+       u8      sourceid;
+} __attribute__((packed));
+
+/* A/V Audio processor definitions */
+struct tmComResProcDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+       u8      sourceid;
+       u16     wreserved;
+       u8      controlsize;
+} __attribute__((packed));
+
+/* Video bitrate control message */
+#define EU_VIDEO_BIT_RATE_MODE_CONSTANT                (0)
+#define EU_VIDEO_BIT_RATE_MODE_VARIABLE_AVERAGE (1)
+#define EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK   (2)
+struct tmComResEncVideoBitRate {
+       u8      ucVideoBitRateMode;
+       u32     dwVideoBitRate;
+       u32     dwVideoBitRatePeak;
+} __attribute__((packed));
+
+/* Video Encoder Aspect Ratio message */
+struct tmComResEncVideoInputAspectRatio {
+       u8      width;
+       u8      height;
+} __attribute__((packed));
+
+/* Video Encoder GOP IBP message */
+/* 1. IPPPPPPPPPPPPPP */
+/* 2. IBPBPBPBPBPBPBP */
+/* 3. IBBPBBPBBPBBP   */
+#define SAA7164_ENCODER_DEFAULT_GOP_DIST (1)
+#define SAA7164_ENCODER_DEFAULT_GOP_SIZE (15)
+struct tmComResEncVideoGopStructure {
+       u8      ucGOPSize;      /* GOP Size 12, 15 */
+       u8      ucRefFrameDist; /* Reference Frame Distance */
+} __attribute__((packed));
+
+/* Encoder processor definition */
+struct tmComResEncoderDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+       u8      vsourceid;
+       u8      asourceid;
+       u8      iunit;
+       u32     dwmControlCap;
+       u32     dwmProfileCap;
+       u32     dwmVidFormatCap;
+       u8      bmVidBitrateCap;
+       u16     wmVidResolutionsCap;
+       u16     wmVidFrmRateCap;
+       u32     dwmAudFormatCap;
+       u8      bmAudBitrateCap;
+} __attribute__((packed));
+
+/* Audio processor definition */
+struct tmComResAFeatureDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      unitid;
+       u8      sourceid;
+       u8      controlsize;
+} __attribute__((packed));
+
+/* Audio control messages */
+struct tmComResAudioDefaults {
+       u8      ucDecoderLevel;
+       u8      ucDecoderFM_Level;
+       u8      ucMonoLevel;
+       u8      ucNICAM_Level;
+       u8      ucSAP_Level;
+       u8      ucADC_Level;
+} __attribute__((packed));
+
+/* Audio bitrate control message */
+struct tmComResEncAudioBitRate {
+       u8      ucAudioBitRateMode;
+       u32     dwAudioBitRate;
+       u32     dwAudioBitRatePeak;
+} __attribute__((packed));
+
+/* Tuner / AV Decoder messages */
+struct tmComResTunerStandard {
+       u8      std;
+       u32     country;
+} __attribute__((packed));
+
+struct tmComResTunerStandardAuto {
+       u8      mode;
+} __attribute__((packed));
+
+/* EEPROM definition for PS stream types */
+struct tmComResPSFormatDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype;
+       u8      bFormatIndex;
+       u16     wPacketLength;
+       u16     wPackLength;
+       u8      bPackDataType;
+} __attribute__((packed));
+
+/* VBI control structure */
+struct tmComResVBIFormatDescrHeader {
+       u8      len;
+       u8      type;
+       u8      subtype; /* VS_FORMAT_VBI */
+       u8      bFormatIndex;
+       u32     VideoStandard; /* See KS_AnalogVideoStandard, NTSC = 1 */
+       u8      StartLine; /* NTSC Start = 10 */
+       u8      EndLine; /* NTSC = 21 */
+       u8      FieldRate; /* 60 for NTSC */
+       u8      bNumLines; /* Unused - scheduled for removal */
+} __attribute__((packed));
+
+struct tmComResProbeCommit {
+       u16     bmHint;
+       u8      bFormatIndex;
+       u8      bFrameIndex;
+} __attribute__((packed));
+
+struct tmComResDebugSetLevel {
+       u32     dwDebugLevel;
+} __attribute__((packed));
+
+struct tmComResDebugGetData {
+       u32     dwResult;
+       u8      ucDebugData[256];
+} __attribute__((packed));
+
+struct tmFwInfoStruct {
+       u32     status;
+       u32     mode;
+       u32     devicespec;
+       u32     deviceinst;
+       u32     CPULoad;
+       u32     RemainHeap;
+       u32     CPUClock;
+       u32     RAMSpeed;
+} __attribute__((packed));
diff --git a/drivers/media/pci/saa7164/saa7164-vbi.c b/drivers/media/pci/saa7164/saa7164-vbi.c
new file mode 100644 (file)
index 0000000..d8e6c8f
--- /dev/null
@@ -0,0 +1,1374 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 "saa7164.h"
+
+static struct saa7164_tvnorm saa7164_tvnorms[] = {
+       {
+               .name      = "NTSC-M",
+               .id        = V4L2_STD_NTSC_M,
+       }, {
+               .name      = "NTSC-JP",
+               .id        = V4L2_STD_NTSC_M_JP,
+       }
+};
+
+static const u32 saa7164_v4l2_ctrls[] = {
+       0
+};
+
+/* Take the encoder configuration from the port struct and
+ * flush it to the hardware.
+ */
+static void saa7164_vbi_configure(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       dprintk(DBGLVL_VBI, "%s()\n", __func__);
+
+       port->vbi_params.width = port->width;
+       port->vbi_params.height = port->height;
+       port->vbi_params.is_50hz =
+               (port->encodernorm.id & V4L2_STD_625_50) != 0;
+
+       /* Set up the DIF (enable it) for analog mode by default */
+       saa7164_api_initialize_dif(port);
+
+       /* Configure the correct video standard */
+#if 0
+       saa7164_api_configure_dif(port, port->encodernorm.id);
+#endif
+
+#if 0
+       /* Ensure the audio decoder is correct configured */
+       saa7164_api_set_audio_std(port);
+#endif
+       dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
+}
+
+static int saa7164_vbi_buffers_dealloc(struct saa7164_port *port)
+{
+       struct list_head *c, *n, *p, *q, *l, *v;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct saa7164_user_buffer *ubuf;
+
+       /* Remove any allocated buffers */
+       mutex_lock(&port->dmaqueue_lock);
+
+       dprintk(DBGLVL_VBI, "%s(port=%d) dmaqueue\n", __func__, port->nr);
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               buf = list_entry(c, struct saa7164_buffer, list);
+               list_del(c);
+               saa7164_buffer_dealloc(buf);
+       }
+
+       dprintk(DBGLVL_VBI, "%s(port=%d) used\n", __func__, port->nr);
+       list_for_each_safe(p, q, &port->list_buf_used.list) {
+               ubuf = list_entry(p, struct saa7164_user_buffer, list);
+               list_del(p);
+               saa7164_buffer_dealloc_user(ubuf);
+       }
+
+       dprintk(DBGLVL_VBI, "%s(port=%d) free\n", __func__, port->nr);
+       list_for_each_safe(l, v, &port->list_buf_free.list) {
+               ubuf = list_entry(l, struct saa7164_user_buffer, list);
+               list_del(l);
+               saa7164_buffer_dealloc_user(ubuf);
+       }
+
+       mutex_unlock(&port->dmaqueue_lock);
+       dprintk(DBGLVL_VBI, "%s(port=%d) done\n", __func__, port->nr);
+
+       return 0;
+}
+
+/* Dynamic buffer switch at vbi start time */
+static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct saa7164_user_buffer *ubuf;
+       struct tmHWStreamParameters *params = &port->hw_streamingparams;
+       int result = -ENODEV, i;
+       int len = 0;
+
+       dprintk(DBGLVL_VBI, "%s()\n", __func__);
+
+       /* TODO: NTSC SPECIFIC */
+       /* Init and establish defaults */
+       params->samplesperline = 1440;
+       params->numberoflines = 12;
+       params->numberoflines = 18;
+       params->pitch = 1600;
+       params->pitch = 1440;
+       params->numpagetables = 2 +
+               ((params->numberoflines * params->pitch) / PAGE_SIZE);
+       params->bitspersample = 8;
+       params->linethreshold = 0;
+       params->pagetablelistvirt = NULL;
+       params->pagetablelistphys = NULL;
+       params->numpagetableentries = port->hwcfg.buffercount;
+
+       /* Allocate the PCI resources, buffers (hard) */
+       for (i = 0; i < port->hwcfg.buffercount; i++) {
+               buf = saa7164_buffer_alloc(port,
+                       params->numberoflines *
+                       params->pitch);
+
+               if (!buf) {
+                       printk(KERN_ERR "%s() failed "
+                              "(errno = %d), unable to allocate buffer\n",
+                               __func__, result);
+                       result = -ENOMEM;
+                       goto failed;
+               } else {
+
+                       mutex_lock(&port->dmaqueue_lock);
+                       list_add_tail(&buf->list, &port->dmaqueue.list);
+                       mutex_unlock(&port->dmaqueue_lock);
+
+               }
+       }
+
+       /* Allocate some kernel buffers for copying
+        * to userpsace.
+        */
+       len = params->numberoflines * params->pitch;
+
+       if (vbi_buffers < 16)
+               vbi_buffers = 16;
+       if (vbi_buffers > 512)
+               vbi_buffers = 512;
+
+       for (i = 0; i < vbi_buffers; i++) {
+
+               ubuf = saa7164_buffer_alloc_user(dev, len);
+               if (ubuf) {
+                       mutex_lock(&port->dmaqueue_lock);
+                       list_add_tail(&ubuf->list, &port->list_buf_free.list);
+                       mutex_unlock(&port->dmaqueue_lock);
+               }
+
+       }
+
+       result = 0;
+
+failed:
+       return result;
+}
+
+
+static int saa7164_vbi_initialize(struct saa7164_port *port)
+{
+       saa7164_vbi_configure(port);
+       return 0;
+}
+
+/* -- V4L2 --------------------------------------------------------- */
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+       unsigned int i;
+
+       dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)*id);
+
+       for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
+               if (*id & saa7164_tvnorms[i].id)
+                       break;
+       }
+       if (i == ARRAY_SIZE(saa7164_tvnorms))
+               return -EINVAL;
+
+       port->encodernorm = saa7164_tvnorms[i];
+
+       /* Update the audio decoder while is not running in
+        * auto detect mode.
+        */
+       saa7164_api_set_audio_std(port);
+
+       dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)*id);
+
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+       struct v4l2_input *i)
+{
+       int n;
+
+       char *inputs[] = { "tuner", "composite", "svideo", "aux",
+               "composite 2", "svideo 2", "aux 2" };
+
+       if (i->index >= 7)
+               return -EINVAL;
+
+       strcpy(i->name, inputs[i->index]);
+
+       if (i->index == 0)
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       else
+               i->type  = V4L2_INPUT_TYPE_CAMERA;
+
+       for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
+               i->std |= saa7164_tvnorms[n].id;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       if (saa7164_api_get_videomux(port) != SAA_OK)
+               return -EIO;
+
+       *i = (port->mux_input - 1);
+
+       dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i);
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i);
+
+       if (i >= 7)
+               return -EINVAL;
+
+       port->mux_input = i + 1;
+
+       if (saa7164_api_set_videomux(port) != SAA_OK)
+               return -EIO;
+
+       return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+       struct v4l2_tuner *t)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "tuner");
+       t->type = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
+
+       dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+       struct v4l2_tuner *t)
+{
+       /* Update the A/V core */
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+
+       f->type = V4L2_TUNER_ANALOG_TV;
+       f->frequency = port->freq;
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+       struct v4l2_frequency *f)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_port *tsport;
+       struct dvb_frontend *fe;
+
+       /* TODO: Pull this for the std */
+       struct analog_parameters params = {
+               .mode      = V4L2_TUNER_ANALOG_TV,
+               .audmode   = V4L2_TUNER_MODE_STEREO,
+               .std       = port->encodernorm.id,
+               .frequency = f->frequency
+       };
+
+       /* Stop the encoder */
+       dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__,
+               f->frequency, f->tuner);
+
+       if (f->tuner != 0)
+               return -EINVAL;
+
+       if (f->type != V4L2_TUNER_ANALOG_TV)
+               return -EINVAL;
+
+       port->freq = f->frequency;
+
+       /* Update the hardware */
+       if (port->nr == SAA7164_PORT_VBI1)
+               tsport = &dev->ports[SAA7164_PORT_TS1];
+       else
+       if (port->nr == SAA7164_PORT_VBI2)
+               tsport = &dev->ports[SAA7164_PORT_TS2];
+       else
+               BUG();
+
+       fe = tsport->dvb.frontend;
+
+       if (fe && fe->ops.tuner_ops.set_analog_params)
+               fe->ops.tuner_ops.set_analog_params(fe, &params);
+       else
+               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+
+       saa7164_vbi_initialize(port);
+
+       return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
+               ctl->id, ctl->value);
+
+       switch (ctl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctl->value = port->ctl_brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctl->value = port->ctl_contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               ctl->value = port->ctl_saturation;
+               break;
+       case V4L2_CID_HUE:
+               ctl->value = port->ctl_hue;
+               break;
+       case V4L2_CID_SHARPNESS:
+               ctl->value = port->ctl_sharpness;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               ctl->value = port->ctl_volume;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+       struct v4l2_control *ctl)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+
+       dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
+               ctl->id, ctl->value);
+
+       switch (ctl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_brightness = ctl->value;
+                       saa7164_api_set_usercontrol(port,
+                               PU_BRIGHTNESS_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_CONTRAST:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_contrast = ctl->value;
+                       saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_SATURATION:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_saturation = ctl->value;
+                       saa7164_api_set_usercontrol(port,
+                               PU_SATURATION_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_HUE:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_hue = ctl->value;
+                       saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_SHARPNESS:
+               if ((ctl->value >= 0) && (ctl->value <= 255)) {
+                       port->ctl_sharpness = ctl->value;
+                       saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
+               } else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               if ((ctl->value >= -83) && (ctl->value <= 24)) {
+                       port->ctl_volume = ctl->value;
+                       saa7164_api_set_audio_volume(port, port->ctl_volume);
+               } else
+                       ret = -EINVAL;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int saa7164_get_ctrl(struct saa7164_port *port,
+       struct v4l2_ext_control *ctrl)
+{
+       struct saa7164_vbi_params *params = &port->vbi_params;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               ctrl->value = params->stream_type;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               ctrl->value = params->ctl_mute;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               ctrl->value = params->ctl_aspect;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               ctrl->value = params->refdist;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               ctrl->value = params->gop_size;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = saa7164_get_ctrl(port, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+
+       }
+
+       return -EINVAL;
+}
+
+static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
+{
+       int ret = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
+                       (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               if ((ctrl->value >= 0) &&
+                       (ctrl->value <= 1))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
+                       (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               if ((ctrl->value >= 0) &&
+                       (ctrl->value <= 255))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               if ((ctrl->value >= 1) &&
+                       (ctrl->value <= 3))
+                       ret = 0;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = saa7164_try_ctrl(ctrl, 0);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+       }
+
+       return -EINVAL;
+}
+
+static int saa7164_set_ctrl(struct saa7164_port *port,
+       struct v4l2_ext_control *ctrl)
+{
+       struct saa7164_vbi_params *params = &port->vbi_params;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               params->stream_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               params->ctl_mute = ctrl->value;
+               ret = saa7164_api_audio_mute(port, params->ctl_mute);
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
+                               ret);
+                       ret = -EIO;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               params->ctl_aspect = ctrl->value;
+               ret = saa7164_api_set_aspect_ratio(port);
+               if (ret != SAA_OK) {
+                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
+                               ret);
+                       ret = -EIO;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               params->refdist = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               params->gop_size = ctrl->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* TODO: Update the hardware */
+
+       return ret;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+       struct v4l2_ext_controls *ctrls)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = saa7164_try_ctrl(ctrl, 0);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+                       err = saa7164_set_ctrl(port, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+       struct v4l2_capability *cap)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       strcpy(cap->driver, dev->name);
+       strlcpy(cap->card, saa7164_boards[dev->board].name,
+               sizeof(cap->card));
+       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+
+       cap->capabilities =
+               V4L2_CAP_VBI_CAPTURE |
+               V4L2_CAP_READWRITE     |
+               0;
+
+       cap->capabilities |= V4L2_CAP_TUNER;
+       cap->version = 0;
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+       struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "VBI", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               port->ts_packet_size * port->ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+       f->fmt.pix.width        = port->width;
+       f->fmt.pix.height       = port->height;
+
+       dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n",
+               port->width, port->height);
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               port->ts_packet_size * port->ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+       dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
+               port->width, port->height);
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               port->ts_packet_size * port->ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+
+       dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+
+       return 0;
+}
+
+static int fill_queryctrl(struct saa7164_vbi_params *params,
+       struct v4l2_queryctrl *c)
+{
+       switch (c->id) {
+       case V4L2_CID_BRIGHTNESS:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
+       case V4L2_CID_CONTRAST:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
+       case V4L2_CID_SATURATION:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
+       case V4L2_CID_HUE:
+               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
+       case V4L2_CID_SHARPNESS:
+               return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
+       case V4L2_CID_MPEG_AUDIO_MUTE:
+               return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
+       case V4L2_CID_AUDIO_VOLUME:
+               return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               return v4l2_ctrl_query_fill(c,
+                       V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+                       V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+                       1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+       case V4L2_CID_MPEG_VIDEO_ASPECT:
+               return v4l2_ctrl_query_fill(c,
+                       V4L2_MPEG_VIDEO_ASPECT_1x1,
+                       V4L2_MPEG_VIDEO_ASPECT_221x100,
+                       1, V4L2_MPEG_VIDEO_ASPECT_4x3);
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               return v4l2_ctrl_query_fill(c,
+                       1, 3, 1, 1);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+       struct v4l2_queryctrl *c)
+{
+       struct saa7164_vbi_fh *fh = priv;
+       struct saa7164_port *port = fh->port;
+       int i, next;
+       u32 id = c->id;
+
+       memset(c, 0, sizeof(*c));
+
+       next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
+       c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
+
+       for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
+               if (next) {
+                       if (c->id < saa7164_v4l2_ctrls[i])
+                               c->id = saa7164_v4l2_ctrls[i];
+                       else
+                               continue;
+               }
+
+               if (c->id == saa7164_v4l2_ctrls[i])
+                       return fill_queryctrl(&port->vbi_params, c);
+
+               if (c->id < saa7164_v4l2_ctrls[i])
+                       break;
+       }
+
+       return -EINVAL;
+}
+
+static int saa7164_vbi_stop_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_VBI, "%s()    Stopped\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int saa7164_vbi_acquire_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+static int saa7164_vbi_pause_port(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int ret;
+
+       ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
+       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
+                       __func__, ret);
+               ret = -EIO;
+       } else {
+               dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
+               ret = 0;
+       }
+
+       return ret;
+}
+
+/* Firmware is very windows centric, meaning you have to transition
+ * the part through AVStream / KS Windows stages, forwards or backwards.
+ * States are: stopped, acquired (h/w), paused, started.
+ * We have to leave here will all of the soft buffers on the free list,
+ * else the cfg_post() func won't have soft buffers to correctly configure.
+ */
+static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       struct saa7164_buffer *buf;
+       struct saa7164_user_buffer *ubuf;
+       struct list_head *c, *n;
+       int ret;
+
+       dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
+
+       ret = saa7164_vbi_pause_port(port);
+       ret = saa7164_vbi_acquire_port(port);
+       ret = saa7164_vbi_stop_port(port);
+
+       dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
+               port->nr);
+
+       /* Reset the state of any allocated buffer resources */
+       mutex_lock(&port->dmaqueue_lock);
+
+       /* Reset the hard and soft buffer state */
+       list_for_each_safe(c, n, &port->dmaqueue.list) {
+               buf = list_entry(c, struct saa7164_buffer, list);
+               buf->flags = SAA7164_BUFFER_FREE;
+               buf->pos = 0;
+       }
+
+       list_for_each_safe(c, n, &port->list_buf_used.list) {
+               ubuf = list_entry(c, struct saa7164_user_buffer, list);
+               ubuf->pos = 0;
+               list_move_tail(&ubuf->list, &port->list_buf_free.list);
+       }
+
+       mutex_unlock(&port->dmaqueue_lock);
+
+       /* Free any allocated resources */
+       saa7164_vbi_buffers_dealloc(port);
+
+       dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
+
+       return ret;
+}
+
+static int saa7164_vbi_start_streaming(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int result, ret = 0;
+
+       dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
+
+       port->done_first_interrupt = 0;
+
+       /* allocate all of the PCIe DMA buffer resources on the fly,
+        * allowing switching between TS and PS payloads without
+        * requiring a complete driver reload.
+        */
+       saa7164_vbi_buffers_alloc(port);
+
+       /* Configure the encoder with any cache values */
+#if 0
+       saa7164_api_set_encoder(port);
+       saa7164_api_get_encoder(port);
+#endif
+
+       /* Place the empty buffers on the hardware */
+       saa7164_buffer_cfg_port(port);
+
+       /* Negotiate format */
+       if (saa7164_api_set_vbi_format(port) != SAA_OK) {
+               printk(KERN_ERR "%s() No supported VBI format\n", __func__);
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Acquire the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
+                       __func__, result);
+
+               ret = -EIO;
+               goto out;
+       } else
+               dprintk(DBGLVL_VBI, "%s()   Acquired\n", __func__);
+
+       /* Pause the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
+                               __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_vbi_stop_port(port);
+               if (result != SAA_OK) {
+                       printk(KERN_ERR "%s() pause/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+
+               ret = -EIO;
+               goto out;
+       } else
+               dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
+
+       /* Start the hardware */
+       result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
+       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
+               printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
+                               __func__, result);
+
+               /* Stop the hardware, regardless */
+               result = saa7164_vbi_acquire_port(port);
+               result = saa7164_vbi_stop_port(port);
+               if (result != SAA_OK) {
+                       printk(KERN_ERR "%s() run/forced stop transition "
+                               "failed, res = 0x%x\n", __func__, result);
+               }
+
+               ret = -EIO;
+       } else
+               dprintk(DBGLVL_VBI, "%s()   Running\n", __func__);
+
+out:
+       return ret;
+}
+
+int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       /* ntsc */
+       f->fmt.vbi.samples_per_line = 1600;
+       f->fmt.vbi.samples_per_line = 1440;
+       f->fmt.vbi.sampling_rate = 27000000;
+       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       f->fmt.vbi.offset = 0;
+       f->fmt.vbi.flags = 0;
+       f->fmt.vbi.start[0] = 10;
+       f->fmt.vbi.count[0] = 18;
+       f->fmt.vbi.start[1] = 263 + 10 + 1;
+       f->fmt.vbi.count[1] = 18;
+       return 0;
+}
+
+static int fops_open(struct file *file)
+{
+       struct saa7164_dev *dev;
+       struct saa7164_port *port;
+       struct saa7164_vbi_fh *fh;
+
+       port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
+       if (!port)
+               return -ENODEV;
+
+       dev = port->dev;
+
+       dprintk(DBGLVL_VBI, "%s()\n", __func__);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh)
+               return -ENOMEM;
+
+       file->private_data = fh;
+       fh->port = port;
+
+       return 0;
+}
+
+static int fops_release(struct file *file)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_VBI, "%s()\n", __func__);
+
+       /* Shut device down on last close */
+       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+               if (atomic_dec_return(&port->v4l_reader_count) == 0) {
+                       /* stop vbi capture then cancel buffers */
+                       saa7164_vbi_stop_streaming(port);
+               }
+       }
+
+       file->private_data = NULL;
+       kfree(fh);
+
+       return 0;
+}
+
+struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
+{
+       struct saa7164_user_buffer *ubuf = NULL;
+       struct saa7164_dev *dev = port->dev;
+       u32 crc;
+
+       mutex_lock(&port->dmaqueue_lock);
+       if (!list_empty(&port->list_buf_used.list)) {
+               ubuf = list_first_entry(&port->list_buf_used.list,
+                       struct saa7164_user_buffer, list);
+
+               if (crc_checking) {
+                       crc = crc32(0, ubuf->data, ubuf->actual_size);
+                       if (crc != ubuf->crc) {
+                               printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
+                                       __func__,
+                                       ubuf, ubuf->crc, crc);
+                       }
+               }
+
+       }
+       mutex_unlock(&port->dmaqueue_lock);
+
+       dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
+
+       return ubuf;
+}
+
+static ssize_t fops_read(struct file *file, char __user *buffer,
+       size_t count, loff_t *pos)
+{
+       struct saa7164_vbi_fh *fh = file->private_data;
+       struct saa7164_port *port = fh->port;
+       struct saa7164_user_buffer *ubuf = NULL;
+       struct saa7164_dev *dev = port->dev;
+       int ret = 0;
+       int rem, cnt;
+       u8 *p;
+
+       port->last_read_msecs_diff = port->last_read_msecs;
+       port->last_read_msecs = jiffies_to_msecs(jiffies);
+       port->last_read_msecs_diff = port->last_read_msecs -
+               port->last_read_msecs_diff;
+
+       saa7164_histogram_update(&port->read_interval,
+               port->last_read_msecs_diff);
+
+       if (*pos) {
+               printk(KERN_ERR "%s() ESPIPE\n", __func__);
+               return -ESPIPE;
+       }
+
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
+
+                       if (saa7164_vbi_initialize(port) < 0) {
+                               printk(KERN_ERR "%s() EINVAL\n", __func__);
+                               return -EINVAL;
+                       }
+
+                       saa7164_vbi_start_streaming(port);
+                       msleep(200);
+               }
+       }
+
+       /* blocking wait for buffer */
+       if ((file->f_flags & O_NONBLOCK) == 0) {
+               if (wait_event_interruptible(port->wait_read,
+                       saa7164_vbi_next_buf(port))) {
+                               printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
+                               return -ERESTARTSYS;
+               }
+       }
+
+       /* Pull the first buffer from the used list */
+       ubuf = saa7164_vbi_next_buf(port);
+
+       while ((count > 0) && ubuf) {
+
+               /* set remaining bytes to copy */
+               rem = ubuf->actual_size - ubuf->pos;
+               cnt = rem > count ? count : rem;
+
+               p = ubuf->data + ubuf->pos;
+
+               dprintk(DBGLVL_VBI,
+                       "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
+                       __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
+
+               if (copy_to_user(buffer, p, cnt)) {
+                       printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
+                       if (!ret) {
+                               printk(KERN_ERR "%s() EFAULT\n", __func__);
+                               ret = -EFAULT;
+                       }
+                       goto err;
+               }
+
+               ubuf->pos += cnt;
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+
+               if (ubuf->pos > ubuf->actual_size)
+                       printk(KERN_ERR "read() pos > actual, huh?\n");
+
+               if (ubuf->pos == ubuf->actual_size) {
+
+                       /* finished with current buffer, take next buffer */
+
+                       /* Requeue the buffer on the free list */
+                       ubuf->pos = 0;
+
+                       mutex_lock(&port->dmaqueue_lock);
+                       list_move_tail(&ubuf->list, &port->list_buf_free.list);
+                       mutex_unlock(&port->dmaqueue_lock);
+
+                       /* Dequeue next */
+                       if ((file->f_flags & O_NONBLOCK) == 0) {
+                               if (wait_event_interruptible(port->wait_read,
+                                       saa7164_vbi_next_buf(port))) {
+                                               break;
+                               }
+                       }
+                       ubuf = saa7164_vbi_next_buf(port);
+               }
+       }
+err:
+       if (!ret && !ubuf) {
+               printk(KERN_ERR "%s() EAGAIN\n", __func__);
+               ret = -EAGAIN;
+       }
+
+       return ret;
+}
+
+static unsigned int fops_poll(struct file *file, poll_table *wait)
+{
+       struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
+       struct saa7164_port *port = fh->port;
+       unsigned int mask = 0;
+
+       port->last_poll_msecs_diff = port->last_poll_msecs;
+       port->last_poll_msecs = jiffies_to_msecs(jiffies);
+       port->last_poll_msecs_diff = port->last_poll_msecs -
+               port->last_poll_msecs_diff;
+
+       saa7164_histogram_update(&port->poll_interval,
+               port->last_poll_msecs_diff);
+
+       if (!video_is_registered(port->v4l_device))
+               return -EIO;
+
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
+                       if (saa7164_vbi_initialize(port) < 0)
+                               return -EINVAL;
+                       saa7164_vbi_start_streaming(port);
+                       msleep(200);
+               }
+       }
+
+       /* blocking wait for buffer */
+       if ((file->f_flags & O_NONBLOCK) == 0) {
+               if (wait_event_interruptible(port->wait_read,
+                       saa7164_vbi_next_buf(port))) {
+                               return -ERESTARTSYS;
+               }
+       }
+
+       /* Pull the first buffer from the used list */
+       if (!list_empty(&port->list_buf_used.list))
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+static const struct v4l2_file_operations vbi_fops = {
+       .owner          = THIS_MODULE,
+       .open           = fops_open,
+       .release        = fops_release,
+       .read           = fops_read,
+       .poll           = fops_poll,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
+       .vidioc_s_std            = vidioc_s_std,
+       .vidioc_enum_input       = vidioc_enum_input,
+       .vidioc_g_input          = vidioc_g_input,
+       .vidioc_s_input          = vidioc_s_input,
+       .vidioc_g_tuner          = vidioc_g_tuner,
+       .vidioc_s_tuner          = vidioc_s_tuner,
+       .vidioc_g_frequency      = vidioc_g_frequency,
+       .vidioc_s_frequency      = vidioc_s_frequency,
+       .vidioc_s_ctrl           = vidioc_s_ctrl,
+       .vidioc_g_ctrl           = vidioc_g_ctrl,
+       .vidioc_querycap         = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
+       .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
+       .vidioc_queryctrl        = vidioc_queryctrl,
+#if 0
+       .vidioc_g_chip_ident     = saa7164_g_chip_ident,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+#if 0
+       .vidioc_g_register       = saa7164_g_register,
+       .vidioc_s_register       = saa7164_s_register,
+#endif
+#endif
+       .vidioc_g_fmt_vbi_cap    = saa7164_vbi_fmt,
+       .vidioc_try_fmt_vbi_cap  = saa7164_vbi_fmt,
+       .vidioc_s_fmt_vbi_cap    = saa7164_vbi_fmt,
+};
+
+static struct video_device saa7164_vbi_template = {
+       .name          = "saa7164",
+       .fops          = &vbi_fops,
+       .ioctl_ops     = &vbi_ioctl_ops,
+       .minor         = -1,
+       .tvnorms       = SAA7164_NORMS,
+       .current_norm  = V4L2_STD_NTSC_M,
+};
+
+static struct video_device *saa7164_vbi_alloc(
+       struct saa7164_port *port,
+       struct pci_dev *pci,
+       struct video_device *template,
+       char *type)
+{
+       struct video_device *vfd;
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_VBI, "%s()\n", __func__);
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+
+       *vfd = *template;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
+               type, saa7164_boards[dev->board].name);
+
+       vfd->parent  = &pci->dev;
+       vfd->release = video_device_release;
+       return vfd;
+}
+
+int saa7164_vbi_register(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+       int result = -ENODEV;
+
+       dprintk(DBGLVL_VBI, "%s()\n", __func__);
+
+       if (port->type != SAA7164_MPEG_VBI)
+               BUG();
+
+       /* Sanity check that the PCI configuration space is active */
+       if (port->hwcfg.BARLocation == 0) {
+               printk(KERN_ERR "%s() failed "
+                      "(errno = %d), NO PCI configuration\n",
+                       __func__, result);
+               result = -ENOMEM;
+               goto failed;
+       }
+
+       /* Establish VBI defaults here */
+
+       /* Allocate and register the video device node */
+       port->v4l_device = saa7164_vbi_alloc(port,
+               dev->pci, &saa7164_vbi_template, "vbi");
+
+       if (!port->v4l_device) {
+               printk(KERN_INFO "%s: can't allocate vbi device\n",
+                       dev->name);
+               result = -ENOMEM;
+               goto failed;
+       }
+
+       video_set_drvdata(port->v4l_device, port);
+       result = video_register_device(port->v4l_device,
+               VFL_TYPE_VBI, -1);
+       if (result < 0) {
+               printk(KERN_INFO "%s: can't register vbi device\n",
+                       dev->name);
+               /* TODO: We're going to leak here if we don't dealloc
+                The buffers above. The unreg function can't deal wit it.
+               */
+               goto failed;
+       }
+
+       printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
+               dev->name, port->v4l_device->num);
+
+       /* Configure the hardware defaults */
+
+       result = 0;
+failed:
+       return result;
+}
+
+void saa7164_vbi_unregister(struct saa7164_port *port)
+{
+       struct saa7164_dev *dev = port->dev;
+
+       dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
+
+       if (port->type != SAA7164_MPEG_VBI)
+               BUG();
+
+       if (port->v4l_device) {
+               if (port->v4l_device->minor != -1)
+                       video_unregister_device(port->v4l_device);
+               else
+                       video_device_release(port->v4l_device);
+
+               port->v4l_device = NULL;
+       }
+
+}
diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h
new file mode 100644 (file)
index 0000000..437284e
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ *  Driver for the NXP SAA7164 PCIe bridge
+ *
+ *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 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 architecture
+       *******************
+
+       saa7164_core.c/buffer.c/cards.c/i2c.c/dvb.c
+               |       : Standard Linux driver framework for creating
+               |       : exposing and managing interfaces to the rest
+               |       : of the kernel or userland. Also uses _fw.c to load
+               |       : firmware direct into the PCIe bus, bypassing layers.
+               V
+       saa7164_api..() : Translate kernel specific functions/features
+               |       : into command buffers.
+               V
+       saa7164_cmd..() : Manages the flow of command packets on/off,
+               |       : the bus. Deal with bus errors, timeouts etc.
+               V
+       saa7164_bus..() : Manage a read/write memory ring buffer in the
+               |       : PCIe Address space.
+               |
+               |               saa7164_fw...() : Load any frimware
+               |                       |       : direct into the device
+               V                       V
+       <- ----------------- PCIe address space -------------------- ->
+*/
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/kdev_t.h>
+#include <linux/mutex.h>
+#include <linux/crc32.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+#include <dvb_demux.h>
+#include <dvb_frontend.h>
+#include <dvb_net.h>
+#include <dvbdev.h>
+#include <dmxdev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+
+#include "saa7164-reg.h"
+#include "saa7164-types.h"
+
+#define SAA7164_MAXBOARDS 8
+
+#define UNSET (-1U)
+#define SAA7164_BOARD_NOAUTO                   UNSET
+#define SAA7164_BOARD_UNKNOWN                  0
+#define SAA7164_BOARD_UNKNOWN_REV2             1
+#define SAA7164_BOARD_UNKNOWN_REV3             2
+#define SAA7164_BOARD_HAUPPAUGE_HVR2250                3
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200                4
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_2      5
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_3      6
+#define SAA7164_BOARD_HAUPPAUGE_HVR2250_2      7
+#define SAA7164_BOARD_HAUPPAUGE_HVR2250_3      8
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4      9
+#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5      10
+
+#define SAA7164_MAX_UNITS              8
+#define SAA7164_TS_NUMBER_OF_LINES     312
+#define SAA7164_PS_NUMBER_OF_LINES     256
+#define SAA7164_PT_ENTRIES             16 /* (312 * 188) / 4096 */
+#define SAA7164_MAX_ENCODER_BUFFERS    64 /* max 5secs of latency at 6Mbps */
+#define SAA7164_MAX_VBI_BUFFERS                64
+
+/* Port related defines */
+#define SAA7164_PORT_TS1       (0)
+#define SAA7164_PORT_TS2       (SAA7164_PORT_TS1 + 1)
+#define SAA7164_PORT_ENC1      (SAA7164_PORT_TS2 + 1)
+#define SAA7164_PORT_ENC2      (SAA7164_PORT_ENC1 + 1)
+#define SAA7164_PORT_VBI1      (SAA7164_PORT_ENC2 + 1)
+#define SAA7164_PORT_VBI2      (SAA7164_PORT_VBI1 + 1)
+#define SAA7164_MAX_PORTS      (SAA7164_PORT_VBI2 + 1)
+
+#define DBGLVL_FW    4
+#define DBGLVL_DVB   8
+#define DBGLVL_I2C  16
+#define DBGLVL_API  32
+#define DBGLVL_CMD  64
+#define DBGLVL_BUS 128
+#define DBGLVL_IRQ 256
+#define DBGLVL_BUF 512
+#define DBGLVL_ENC 1024
+#define DBGLVL_VBI 2048
+#define DBGLVL_THR 4096
+#define DBGLVL_CPU 8192
+
+#define SAA7164_NORMS \
+       (V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443)
+
+enum port_t {
+       SAA7164_MPEG_UNDEFINED = 0,
+       SAA7164_MPEG_DVB,
+       SAA7164_MPEG_ENCODER,
+       SAA7164_MPEG_VBI,
+};
+
+enum saa7164_i2c_bus_nr {
+       SAA7164_I2C_BUS_0 = 0,
+       SAA7164_I2C_BUS_1,
+       SAA7164_I2C_BUS_2,
+};
+
+enum saa7164_buffer_flags {
+       SAA7164_BUFFER_UNDEFINED = 0,
+       SAA7164_BUFFER_FREE,
+       SAA7164_BUFFER_BUSY,
+       SAA7164_BUFFER_FULL
+};
+
+enum saa7164_unit_type {
+       SAA7164_UNIT_UNDEFINED = 0,
+       SAA7164_UNIT_DIGITAL_DEMODULATOR,
+       SAA7164_UNIT_ANALOG_DEMODULATOR,
+       SAA7164_UNIT_TUNER,
+       SAA7164_UNIT_EEPROM,
+       SAA7164_UNIT_ZILOG_IRBLASTER,
+       SAA7164_UNIT_ENCODER,
+};
+
+/* The PCIe bridge doesn't grant direct access to i2c.
+ * Instead, you address i2c devices using a uniqely
+ * allocated 'unitid' value via a messaging API. This
+ * is a problem. The kernel and existing demod/tuner
+ * drivers expect to talk 'i2c', so we have to maintain
+ * a translation layer, and a series of functions to
+ * convert i2c bus + device address into a unit id.
+ */
+struct saa7164_unit {
+       enum saa7164_unit_type type;
+       u8      id;
+       char    *name;
+       enum saa7164_i2c_bus_nr i2c_bus_nr;
+       u8      i2c_bus_addr;
+       u8      i2c_reg_len;
+};
+
+struct saa7164_board {
+       char    *name;
+       enum port_t porta, portb, portc,
+               portd, porte, portf;
+       enum {
+               SAA7164_CHIP_UNDEFINED = 0,
+               SAA7164_CHIP_REV2,
+               SAA7164_CHIP_REV3,
+       } chiprev;
+       struct  saa7164_unit unit[SAA7164_MAX_UNITS];
+};
+
+struct saa7164_subid {
+       u16     subvendor;
+       u16     subdevice;
+       u32     card;
+};
+
+struct saa7164_encoder_fh {
+       struct saa7164_port *port;
+       atomic_t v4l_reading;
+};
+
+struct saa7164_vbi_fh {
+       struct saa7164_port *port;
+       atomic_t v4l_reading;
+};
+
+struct saa7164_histogram_bucket {
+       u32 val;
+       u32 count;
+       u64 update_time;
+};
+
+struct saa7164_histogram {
+       char name[32];
+       struct saa7164_histogram_bucket counter1[64];
+};
+
+struct saa7164_user_buffer {
+       struct list_head list;
+
+       /* Attributes */
+       u8  *data;
+       u32 pos;
+       u32 actual_size;
+
+       u32 crc;
+};
+
+struct saa7164_fw_status {
+
+       /* RISC Core details */
+       u32     status;
+       u32     mode;
+       u32     spec;
+       u32     inst;
+       u32     cpuload;
+       u32     remainheap;
+
+       /* Firmware version */
+       u32     version;
+       u32     major;
+       u32     sub;
+       u32     rel;
+       u32     buildnr;
+};
+
+struct saa7164_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 saa7164_i2c {
+       struct saa7164_dev              *dev;
+
+       enum saa7164_i2c_bus_nr         nr;
+
+       /* I2C I/O */
+       struct i2c_adapter              i2c_adap;
+       struct i2c_client               i2c_client;
+       u32                             i2c_rc;
+};
+
+struct saa7164_ctrl {
+       struct v4l2_queryctrl v;
+};
+
+struct saa7164_tvnorm {
+       char            *name;
+       v4l2_std_id     id;
+};
+
+struct saa7164_encoder_params {
+       struct saa7164_tvnorm encodernorm;
+       u32 height;
+       u32 width;
+       u32 is_50hz;
+       u32 bitrate; /* bps */
+       u32 bitrate_peak; /* bps */
+       u32 bitrate_mode;
+       u32 stream_type; /* V4L2_MPEG_STREAM_TYPE_MPEG2_TS */
+
+       u32 audio_sampling_freq;
+       u32 ctl_mute;
+       u32 ctl_aspect;
+       u32 refdist;
+       u32 gop_size;
+};
+
+struct saa7164_vbi_params {
+       struct saa7164_tvnorm encodernorm;
+       u32 height;
+       u32 width;
+       u32 is_50hz;
+       u32 bitrate; /* bps */
+       u32 bitrate_peak; /* bps */
+       u32 bitrate_mode;
+       u32 stream_type; /* V4L2_MPEG_STREAM_TYPE_MPEG2_TS */
+
+       u32 audio_sampling_freq;
+       u32 ctl_mute;
+       u32 ctl_aspect;
+       u32 refdist;
+       u32 gop_size;
+};
+
+struct saa7164_port;
+
+struct saa7164_buffer {
+       struct list_head list;
+
+       /* Note of which h/w buffer list index position we occupy */
+       int idx;
+
+       struct saa7164_port *port;
+
+       /* Hardware Specific */
+       /* PCI Memory allocations */
+       enum saa7164_buffer_flags flags; /* Free, Busy, Full */
+
+       /* A block of page align PCI memory */
+       u32 pci_size;   /* PCI allocation size in bytes */
+       u64 __iomem *cpu;       /* Virtual address */
+       dma_addr_t dma; /* Physical address */
+       u32 crc;        /* Checksum for the entire buffer data */
+
+       /* A page table that splits the block into a number of entries */
+       u32 pt_size;            /* PCI allocation size in bytes */
+       u64 __iomem *pt_cpu;            /* Virtual address */
+       dma_addr_t pt_dma;      /* Physical address */
+
+       /* Encoder fops */
+       u32 pos;
+       u32 actual_size;
+};
+
+struct saa7164_port {
+
+       struct saa7164_dev *dev;
+       enum port_t type;
+       int nr;
+
+       /* --- Generic port attributes --- */
+
+       /* HW stream parameters */
+       struct tmHWStreamParameters hw_streamingparams;
+
+       /* DMA configuration values, is seeded during initialization */
+       struct tmComResDMATermDescrHeader hwcfg;
+
+       /* hardware specific registers */
+       u32 bufcounter;
+       u32 pitch;
+       u32 bufsize;
+       u32 bufoffset;
+       u32 bufptr32l;
+       u32 bufptr32h;
+       u64 bufptr64;
+
+       u32 numpte;     /* Number of entries in array, only valid in head */
+
+       struct mutex dmaqueue_lock;
+       struct saa7164_buffer dmaqueue;
+
+       u64 last_irq_msecs, last_svc_msecs;
+       u64 last_irq_msecs_diff, last_svc_msecs_diff;
+       u32 last_svc_wp;
+       u32 last_svc_rp;
+       u64 last_irq_svc_msecs_diff;
+       u64 last_read_msecs, last_read_msecs_diff;
+       u64 last_poll_msecs, last_poll_msecs_diff;
+
+       struct saa7164_histogram irq_interval;
+       struct saa7164_histogram svc_interval;
+       struct saa7164_histogram irq_svc_interval;
+       struct saa7164_histogram read_interval;
+       struct saa7164_histogram poll_interval;
+
+       /* --- DVB Transport Specific --- */
+       struct saa7164_dvb dvb;
+
+       /* --- Encoder/V4L related attributes --- */
+       /* Encoder */
+       /* Defaults established in saa7164-encoder.c */
+       struct saa7164_tvnorm encodernorm;
+       u32 height;
+       u32 width;
+       u32 freq;
+       u32 ts_packet_size;
+       u32 ts_packet_count;
+       u8 mux_input;
+       u8 encoder_profile;
+       u8 video_format;
+       u8 audio_format;
+       u8 video_resolution;
+       u16 ctl_brightness;
+       u16 ctl_contrast;
+       u16 ctl_hue;
+       u16 ctl_saturation;
+       u16 ctl_sharpness;
+       s8 ctl_volume;
+
+       struct tmComResAFeatureDescrHeader audfeat;
+       struct tmComResEncoderDescrHeader encunit;
+       struct tmComResProcDescrHeader vidproc;
+       struct tmComResExtDevDescrHeader ifunit;
+       struct tmComResTunerDescrHeader tunerunit;
+
+       struct work_struct workenc;
+
+       /* V4L Encoder Video */
+       struct saa7164_encoder_params encoder_params;
+       struct video_device *v4l_device;
+       atomic_t v4l_reader_count;
+
+       struct saa7164_buffer list_buf_used;
+       struct saa7164_buffer list_buf_free;
+       wait_queue_head_t wait_read;
+
+       /* V4L VBI */
+       struct tmComResVBIFormatDescrHeader vbi_fmt_ntsc;
+       struct saa7164_vbi_params vbi_params;
+
+       /* Debug */
+       u32 sync_errors;
+       u32 v_cc_errors;
+       u32 a_cc_errors;
+       u8 last_v_cc;
+       u8 last_a_cc;
+       u32 done_first_interrupt;
+};
+
+struct saa7164_dev {
+       struct list_head        devlist;
+       atomic_t                refcount;
+
+       /* pci stuff */
+       struct pci_dev  *pci;
+       unsigned char   pci_rev, pci_lat;
+       int             pci_bus, pci_slot;
+       u32             __iomem *lmmio;
+       u8              __iomem *bmmio;
+       u32             __iomem *lmmio2;
+       u8              __iomem *bmmio2;
+       int             pci_irqmask;
+
+       /* board details */
+       int     nr;
+       int     hwrevision;
+       u32     board;
+       char    name[16];
+
+       /* firmware status */
+       struct saa7164_fw_status        fw_status;
+       u32                             firmwareloaded;
+
+       struct tmComResHWDescr          hwdesc;
+       struct tmComResInterfaceDescr   intfdesc;
+       struct tmComResBusDescr         busdesc;
+
+       struct tmComResBusInfo          bus;
+
+       /* Interrupt status and ack registers */
+       u32 int_status;
+       u32 int_ack;
+
+       struct cmd                      cmds[SAA_CMD_MAX_MSG_UNITS];
+       struct mutex                    lock;
+
+       /* I2c related */
+       struct saa7164_i2c i2c_bus[3];
+
+       /* Transport related */
+       struct saa7164_port ports[SAA7164_MAX_PORTS];
+
+       /* Deferred command/api interrupts handling */
+       struct work_struct workcmd;
+
+       /* A kernel thread to monitor the firmware log, used
+        * only in debug mode.
+        */
+       struct task_struct *kthread;
+
+};
+
+extern struct list_head saa7164_devlist;
+extern unsigned int waitsecs;
+extern unsigned int encoder_buffers;
+extern unsigned int vbi_buffers;
+
+/* ----------------------------------------------------------- */
+/* saa7164-core.c                                              */
+void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr);
+void saa7164_getfirmwarestatus(struct saa7164_dev *dev);
+u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev);
+void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val);
+
+/* ----------------------------------------------------------- */
+/* saa7164-fw.c                                                */
+int saa7164_downloadfirmware(struct saa7164_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* saa7164-i2c.c                                               */
+extern int saa7164_i2c_register(struct saa7164_i2c *bus);
+extern int saa7164_i2c_unregister(struct saa7164_i2c *bus);
+extern void saa7164_call_i2c_clients(struct saa7164_i2c *bus,
+       unsigned int cmd, void *arg);
+
+/* ----------------------------------------------------------- */
+/* saa7164-bus.c                                               */
+int saa7164_bus_setup(struct saa7164_dev *dev);
+void saa7164_bus_dump(struct saa7164_dev *dev);
+int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
+       void *buf);
+int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
+       void *buf, int peekonly);
+
+/* ----------------------------------------------------------- */
+/* saa7164-cmd.c                                               */
+int saa7164_cmd_send(struct saa7164_dev *dev,
+       u8 id, enum tmComResCmd command, u16 controlselector,
+       u16 size, void *buf);
+void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno);
+int saa7164_irq_dequeue(struct saa7164_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* saa7164-api.c                                               */
+int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version);
+int saa7164_api_enum_subdevs(struct saa7164_dev *dev);
+int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
+       u32 datalen, u8 *data);
+int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr,
+       u32 datalen, u8 *data);
+int saa7164_api_dif_write(struct saa7164_i2c *bus, u8 addr,
+       u32 datalen, u8 *data);
+int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen);
+int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin);
+int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin);
+int saa7164_api_transition_port(struct saa7164_port *port, u8 mode);
+int saa7164_api_initialize_dif(struct saa7164_port *port);
+int saa7164_api_configure_dif(struct saa7164_port *port, u32 std);
+int saa7164_api_set_encoder(struct saa7164_port *port);
+int saa7164_api_get_encoder(struct saa7164_port *port);
+int saa7164_api_set_aspect_ratio(struct saa7164_port *port);
+int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl);
+int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl);
+int saa7164_api_set_videomux(struct saa7164_port *port);
+int saa7164_api_audio_mute(struct saa7164_port *port, int mute);
+int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level);
+int saa7164_api_set_audio_std(struct saa7164_port *port);
+int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect);
+int saa7164_api_get_videomux(struct saa7164_port *port);
+int saa7164_api_set_vbi_format(struct saa7164_port *port);
+int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level);
+int saa7164_api_collect_debug(struct saa7164_dev *dev);
+int saa7164_api_get_load_info(struct saa7164_dev *dev,
+       struct tmFwInfoStruct *i);
+
+/* ----------------------------------------------------------- */
+/* saa7164-cards.c                                             */
+extern struct saa7164_board saa7164_boards[];
+extern const unsigned int saa7164_bcount;
+
+extern struct saa7164_subid saa7164_subids[];
+extern const unsigned int saa7164_idcount;
+
+extern void saa7164_card_list(struct saa7164_dev *dev);
+extern void saa7164_gpio_setup(struct saa7164_dev *dev);
+extern void saa7164_card_setup(struct saa7164_dev *dev);
+
+extern int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr);
+extern int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr);
+extern char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid);
+
+/* ----------------------------------------------------------- */
+/* saa7164-dvb.c                                               */
+extern int saa7164_dvb_register(struct saa7164_port *port);
+extern int saa7164_dvb_unregister(struct saa7164_port *port);
+
+/* ----------------------------------------------------------- */
+/* saa7164-buffer.c                                            */
+extern struct saa7164_buffer *saa7164_buffer_alloc(
+       struct saa7164_port *port, u32 len);
+extern int saa7164_buffer_dealloc(struct saa7164_buffer *buf);
+extern void saa7164_buffer_display(struct saa7164_buffer *buf);
+extern int saa7164_buffer_activate(struct saa7164_buffer *buf, int i);
+extern int saa7164_buffer_cfg_port(struct saa7164_port *port);
+extern struct saa7164_user_buffer *saa7164_buffer_alloc_user(
+       struct saa7164_dev *dev, u32 len);
+extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf);
+extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
+
+/* ----------------------------------------------------------- */
+/* saa7164-encoder.c                                            */
+int saa7164_encoder_register(struct saa7164_port *port);
+void saa7164_encoder_unregister(struct saa7164_port *port);
+
+/* ----------------------------------------------------------- */
+/* saa7164-vbi.c                                            */
+int saa7164_vbi_register(struct saa7164_port *port);
+void saa7164_vbi_unregister(struct saa7164_port *port);
+
+/* ----------------------------------------------------------- */
+
+extern unsigned int crc_checking;
+
+extern unsigned int saa_debug;
+#define dprintk(level, fmt, arg...)\
+       do { if (saa_debug & level)\
+               printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+       } while (0)
+
+#define log_warn(fmt, arg...)\
+       do { \
+               printk(KERN_WARNING "%s: " fmt, dev->name, ## arg);\
+       } while (0)
+
+#define saa7164_readl(reg) readl(dev->lmmio + ((reg) >> 2))
+#define saa7164_writel(reg, value) writel((value), dev->lmmio + ((reg) >> 2))
+
+#define saa7164_readb(reg)             readl(dev->bmmio + (reg))
+#define saa7164_writeb(reg, value)     writel((value), dev->bmmio + (reg))
+
diff --git a/drivers/media/pci/zoran/Kconfig b/drivers/media/pci/zoran/Kconfig
new file mode 100644 (file)
index 0000000..fd4120e
--- /dev/null
@@ -0,0 +1,74 @@
+config VIDEO_ZORAN
+       tristate "Zoran ZR36057/36067 Video For Linux"
+       depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS
+       help
+         Say Y for support for MJPEG capture cards based on the Zoran
+         36057/36067 PCI controller chipset. This includes the Iomega
+         Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
+         a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
+         more information, check <file:Documentation/video4linux/Zoran>.
+
+         To compile this driver as a module, choose M here: the
+         module will be called zr36067.
+
+config VIDEO_ZORAN_DC30
+       tristate "Pinnacle/Miro DC30(+) support"
+       depends on VIDEO_ZORAN
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
+         card. This also supports really old DC10 cards based on the
+         zr36050 MJPEG codec and zr36016 VFE.
+
+config VIDEO_ZORAN_ZR36060
+       tristate "Zoran ZR36060"
+       depends on VIDEO_ZORAN
+       help
+         Say Y to support Zoran boards based on 36060 chips.
+         This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
+         and 33 R10 and AverMedia 6 boards.
+
+config VIDEO_ZORAN_BUZ
+       tristate "Iomega Buz support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Iomega Buz MJPEG capture/playback card.
+
+config VIDEO_ZORAN_DC10
+       tristate "Pinnacle/Miro DC10(+) support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
+         card.
+
+config VIDEO_ZORAN_LML33
+       tristate "Linux Media Labs LML33 support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the Linux Media Labs LML33 MJPEG capture/playback
+         card.
+
+config VIDEO_ZORAN_LML33R10
+       tristate "Linux Media Labs LML33R10 support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         support for the Linux Media Labs LML33R10 MJPEG capture/playback
+         card.
+
+config VIDEO_ZORAN_AVS6EYES
+       tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
+       depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL
+       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
+       help
+         Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/media/pci/zoran/Makefile b/drivers/media/pci/zoran/Makefile
new file mode 100644 (file)
index 0000000..44cc133
--- /dev/null
@@ -0,0 +1,6 @@
+zr36067-objs   :=      zoran_procfs.o zoran_device.o \
+                       zoran_driver.o zoran_card.o
+
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
+obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
+obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
diff --git a/drivers/media/pci/zoran/videocodec.c b/drivers/media/pci/zoran/videocodec.c
new file mode 100644 (file)
index 0000000..c010716
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * VIDEO MOTION CODECs internal API for video devices
+ *
+ * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
+ * bound to a master device.
+ *
+ * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 VIDEOCODEC_VERSION "v0.2"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+
+// kernel config is here (procfs flag)
+
+#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;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+struct attached_list {
+       struct videocodec *codec;
+       struct attached_list *next;
+};
+
+struct codec_list {
+       const struct videocodec *codec;
+       int attached;
+       struct attached_list *list;
+       struct codec_list *next;
+};
+
+static struct codec_list *codeclist_top = NULL;
+
+/* ================================================= */
+/* function prototypes of the master/slave interface */
+/* ================================================= */
+
+struct videocodec *
+videocodec_attach (struct videocodec_master *master)
+{
+       struct codec_list *h = codeclist_top;
+       struct attached_list *a, *ptr;
+       struct videocodec *codec;
+       int res;
+
+       if (!master) {
+               dprintk(1, KERN_ERR "videocodec_attach: no data\n");
+               return NULL;
+       }
+
+       dprintk(2,
+               "videocodec_attach: '%s', flags %lx, magic %lx\n",
+               master->name, master->flags, master->magic);
+
+       if (!h) {
+               dprintk(1,
+                       KERN_ERR
+                       "videocodec_attach: no device available\n");
+               return NULL;
+       }
+
+       while (h) {
+               // attach only if the slave has at least the flags
+               // expected by the master
+               if ((master->flags & h->codec->flags) == master->flags) {
+                       dprintk(4, "videocodec_attach: try '%s'\n",
+                               h->codec->name);
+
+                       if (!try_module_get(h->codec->owner))
+                               return NULL;
+
+                       codec = kmemdup(h->codec, sizeof(struct videocodec),
+                                       GFP_KERNEL);
+                       if (!codec) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "videocodec_attach: no mem\n");
+                               goto out_module_put;
+                       }
+
+                       snprintf(codec->name, sizeof(codec->name),
+                                "%s[%d]", codec->name, h->attached);
+                       codec->master_data = master;
+                       res = codec->setup(codec);
+                       if (res == 0) {
+                               dprintk(3, "videocodec_attach '%s'\n",
+                                       codec->name);
+                               ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
+                               if (!ptr) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "videocodec_attach: no memory\n");
+                                       goto out_kfree;
+                               }
+                               ptr->codec = codec;
+
+                               a = h->list;
+                               if (!a) {
+                                       h->list = ptr;
+                                       dprintk(4,
+                                               "videocodec: first element\n");
+                               } else {
+                                       while (a->next)
+                                               a = a->next;    // find end
+                                       a->next = ptr;
+                                       dprintk(4,
+                                               "videocodec: in after '%s'\n",
+                                               h->codec->name);
+                               }
+
+                               h->attached += 1;
+                               return codec;
+                       } else {
+                               kfree(codec);
+                       }
+               }
+               h = h->next;
+       }
+
+       dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
+       return NULL;
+
+ out_module_put:
+       module_put(h->codec->owner);
+ out_kfree:
+       kfree(codec);
+       return NULL;
+}
+
+int
+videocodec_detach (struct videocodec *codec)
+{
+       struct codec_list *h = codeclist_top;
+       struct attached_list *a, *prev;
+       int res;
+
+       if (!codec) {
+               dprintk(1, KERN_ERR "videocodec_detach: no data\n");
+               return -EINVAL;
+       }
+
+       dprintk(2,
+               "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n",
+               codec->name, codec->type, codec->flags, codec->magic);
+
+       if (!h) {
+               dprintk(1,
+                       KERN_ERR "videocodec_detach: no device left...\n");
+               return -ENXIO;
+       }
+
+       while (h) {
+               a = h->list;
+               prev = NULL;
+               while (a) {
+                       if (codec == a->codec) {
+                               res = a->codec->unset(a->codec);
+                               if (res >= 0) {
+                                       dprintk(3,
+                                               "videocodec_detach: '%s'\n",
+                                               a->codec->name);
+                                       a->codec->master_data = NULL;
+                               } else {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "videocodec_detach: '%s'\n",
+                                               a->codec->name);
+                                       a->codec->master_data = NULL;
+                               }
+                               if (prev == NULL) {
+                                       h->list = a->next;
+                                       dprintk(4,
+                                               "videocodec: delete first\n");
+                               } else {
+                                       prev->next = a->next;
+                                       dprintk(4,
+                                               "videocodec: delete middle\n");
+                               }
+                               module_put(a->codec->owner);
+                               kfree(a->codec);
+                               kfree(a);
+                               h->attached -= 1;
+                               return 0;
+                       }
+                       prev = a;
+                       a = a->next;
+               }
+               h = h->next;
+       }
+
+       dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n");
+       return -EINVAL;
+}
+
+int
+videocodec_register (const struct videocodec *codec)
+{
+       struct codec_list *ptr, *h = codeclist_top;
+
+       if (!codec) {
+               dprintk(1, KERN_ERR "videocodec_register: no data!\n");
+               return -EINVAL;
+       }
+
+       dprintk(2,
+               "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
+               codec->name, codec->type, codec->flags, codec->magic);
+
+       ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
+       if (!ptr) {
+               dprintk(1, KERN_ERR "videocodec_register: no memory\n");
+               return -ENOMEM;
+       }
+       ptr->codec = codec;
+
+       if (!h) {
+               codeclist_top = ptr;
+               dprintk(4, "videocodec: hooked in as first element\n");
+       } else {
+               while (h->next)
+                       h = h->next;    // find the end
+               h->next = ptr;
+               dprintk(4, "videocodec: hooked in after '%s'\n",
+                       h->codec->name);
+       }
+
+       return 0;
+}
+
+int
+videocodec_unregister (const struct videocodec *codec)
+{
+       struct codec_list *prev = NULL, *h = codeclist_top;
+
+       if (!codec) {
+               dprintk(1, KERN_ERR "videocodec_unregister: no data!\n");
+               return -EINVAL;
+       }
+
+       dprintk(2,
+               "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
+               codec->name, codec->type, codec->flags, codec->magic);
+
+       if (!h) {
+               dprintk(1,
+                       KERN_ERR
+                       "videocodec_unregister: no device left...\n");
+               return -ENXIO;
+       }
+
+       while (h) {
+               if (codec == h->codec) {
+                       if (h->attached) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "videocodec: '%s' is used\n",
+                                       h->codec->name);
+                               return -EBUSY;
+                       }
+                       dprintk(3, "videocodec: unregister '%s' is ok.\n",
+                               h->codec->name);
+                       if (prev == NULL) {
+                               codeclist_top = h->next;
+                               dprintk(4,
+                                       "videocodec: delete first element\n");
+                       } else {
+                               prev->next = h->next;
+                               dprintk(4,
+                                       "videocodec: delete middle element\n");
+                       }
+                       kfree(h);
+                       return 0;
+               }
+               prev = h;
+               h = h->next;
+       }
+
+       dprintk(1,
+               KERN_ERR
+               "videocodec_unregister: given codec not found!\n");
+       return -EINVAL;
+}
+
+#ifdef CONFIG_PROC_FS
+static int proc_videocodecs_show(struct seq_file *m, void *v)
+{
+       struct codec_list *h = codeclist_top;
+       struct attached_list *a;
+
+       seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
+       seq_printf(m, "(connected as)\n");
+
+       h = codeclist_top;
+       while (h) {
+               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) {
+                       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,
+                                     a->codec->master_data->magic,
+                                     a->codec->name);
+                       a = a->next;
+               }
+               h = h->next;
+       }
+
+       return 0;
+}
+
+static int proc_videocodecs_open(struct inode *inode, struct file *file)
+{
+       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
+
+/* ===================== */
+/* hook in driver module */
+/* ===================== */
+static int __init
+videocodec_init (void)
+{
+#ifdef CONFIG_PROC_FS
+       static struct proc_dir_entry *videocodec_proc_entry;
+#endif
+
+       printk(KERN_INFO "Linux video codec intermediate layer: %s\n",
+              VIDEOCODEC_VERSION);
+
+#ifdef CONFIG_PROC_FS
+       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
+       return 0;
+}
+
+static void __exit
+videocodec_exit (void)
+{
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("videocodecs", NULL);
+#endif
+}
+
+EXPORT_SYMBOL(videocodec_attach);
+EXPORT_SYMBOL(videocodec_detach);
+EXPORT_SYMBOL(videocodec_register);
+EXPORT_SYMBOL(videocodec_unregister);
+
+module_init(videocodec_init);
+module_exit(videocodec_exit);
+
+MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
+MODULE_DESCRIPTION("Intermediate API module for video codecs "
+                  VIDEOCODEC_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/zoran/videocodec.h b/drivers/media/pci/zoran/videocodec.h
new file mode 100644 (file)
index 0000000..def5558
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * VIDEO MOTION CODECs internal API for video devices
+ *
+ * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
+ * bound to a master device.
+ *
+ * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: videocodec.h,v 1.1.2.4 2003/01/14 21:15:03 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+/* =================== */
+/* general description */
+/* =================== */
+
+/* Should ease the (re-)usage of drivers supporting cards with (different)
+   video codecs. The codecs register to this module their functionality,
+   and the processors (masters) can attach to them if they fit.
+
+   The codecs are typically have a "strong" binding to their master - so I
+   don't think it makes sense to have a full blown interfacing as with e.g.
+   i2c. If you have an other opinion, let's discuss & implement it :-)))
+
+   Usage:
+
+   The slave has just to setup the videocodec structure and use two functions:
+   videocodec_register(codecdata);
+   videocodec_unregister(codecdata);
+   The best is just calling them at module (de-)initialisation.
+
+   The master sets up the structure videocodec_master and calls:
+   codecdata=videocodec_attach(master_codecdata);
+   videocodec_detach(codecdata);
+
+   The slave is called during attach/detach via functions setup previously
+   during register. At that time, the master_data pointer is set up
+   and the slave can access any io registers of the master device (in the case
+   the slave is bound to it). Otherwise it doesn't need this functions and
+   therfor they may not be initialized.
+
+   The other functions are just for convenience, as they are for sure used by
+   most/all of the codecs. The last ones may be omitted, too.
+
+   See the structure declaration below for more information and which data has
+   to be set up for the master and the slave.
+
+   ----------------------------------------------------------------------------
+   The master should have "knowledge" of the slave and vice versa.  So the data
+   structures sent to/from slave via set_data/get_data set_image/get_image are
+   device dependent and vary between MJPEG/MPEG/WAVELET/... devices. (!!!!)
+   ----------------------------------------------------------------------------
+*/
+\f
+
+/* ========================================== */
+/* description of the videocodec_io structure */
+/* ========================================== */
+
+/*
+   ==== master setup ====
+   name -> name of the device structure for reference and debugging
+   master_data ->  data ref. for the master (e.g. the zr36055,57,67)
+   readreg -> ref. to read-fn from register (setup by master, used by slave)
+   writereg -> ref. to write-fn to register (setup by master, used by slave)
+              this two functions do the lowlevel I/O job
+
+   ==== slave functionality setup ====
+   slave_data -> data ref. for the slave (e.g. the zr36050,60)
+   check -> fn-ref. checks availability of an device, returns -EIO on failure or
+           the type on success
+           this makes espcecially sense if a driver module supports more than
+           one codec which may be quite similar to access, nevertheless it
+           is good for a first functionality check
+
+   -- main functions you always need for compression/decompression --
+
+   set_mode -> this fn-ref. resets the entire codec, and sets up the mode
+              with the last defined norm/size (or device default if not
+              available) - it returns 0 if the mode is possible
+   set_size -> this fn-ref. sets the norm and image size for
+              compression/decompression (returns 0 on success)
+              the norm param is defined in videodev2.h (V4L2_STD_*)
+
+   additional setup may be available, too - but the codec should work with
+   some default values even without this
+
+   set_data -> sets device-specific data (tables, quality etc.)
+   get_data -> query device-specific data (tables, quality etc.)
+
+   if the device delivers interrupts, they may be setup/handled here
+   setup_interrupt -> codec irq setup (not needed for 36050/60)
+   handle_interrupt -> codec irq handling (not needed for 36050/60)
+
+   if the device delivers pictures, they may be handled here
+   put_image -> puts image data to the codec (not needed for 36050/60)
+   get_image -> gets image data from the codec (not needed for 36050/60)
+               the calls include frame numbers and flags (even/odd/...)
+               if needed and a flag which allows blocking until its ready
+*/
+\f
+/* ============== */
+/* user interface */
+/* ============== */
+
+/*
+   Currently there is only a information display planned, as the layer
+   is not visible for the user space at all.
+
+   Information is available via procfs. The current entry is "/proc/videocodecs"
+   but it makes sense to "hide" it in the /proc/video tree of v4l(2) --TODO--.
+
+A example for such an output is:
+
+<S>lave or attached <M>aster name  type flags    magic    (connected as)
+S                          zr36050 0002 0000d001 00000000 (TEMPLATE)
+M                       zr36055[0] 0001 0000c001 00000000 (zr36050[0])
+M                       zr36055[1] 0001 0000c001 00000000 (zr36050[1])
+
+*/
+\f
+
+/* =============================================== */
+/* special defines for the videocodec_io structure */
+/* =============================================== */
+
+#ifndef __LINUX_VIDEOCODEC_H
+#define __LINUX_VIDEOCODEC_H
+
+#include <linux/videodev2.h>
+
+#define CODEC_DO_COMPRESSION 0
+#define CODEC_DO_EXPANSION   1
+
+/* this are the current codec flags I think they are needed */
+/*  -> type value in structure */
+#define CODEC_FLAG_JPEG      0x00000001L       // JPEG codec
+#define CODEC_FLAG_MPEG      0x00000002L       // MPEG1/2/4 codec
+#define CODEC_FLAG_DIVX      0x00000004L       // DIVX codec
+#define CODEC_FLAG_WAVELET   0x00000008L       // WAVELET codec
+                                         // room for other types
+
+#define CODEC_FLAG_MAGIC     0x00000800L       // magic key must match
+#define CODEC_FLAG_HARDWARE  0x00001000L       // is a hardware codec
+#define CODEC_FLAG_VFE       0x00002000L       // has direct video frontend
+#define CODEC_FLAG_ENCODER   0x00004000L       // compression capability
+#define CODEC_FLAG_DECODER   0x00008000L       // decompression capability
+#define CODEC_FLAG_NEEDIRQ   0x00010000L       // needs irq handling
+#define CODEC_FLAG_RDWRPIC   0x00020000L       // handles picture I/O
+
+/* a list of modes, some are just examples (is there any HW?) */
+#define CODEC_MODE_BJPG      0x0001    // Baseline JPEG
+#define CODEC_MODE_LJPG      0x0002    // Lossless JPEG
+#define CODEC_MODE_MPEG1     0x0003    // MPEG 1
+#define CODEC_MODE_MPEG2     0x0004    // MPEG 2
+#define CODEC_MODE_MPEG4     0x0005    // MPEG 4
+#define CODEC_MODE_MSDIVX    0x0006    // MS DivX
+#define CODEC_MODE_ODIVX     0x0007    // Open DivX
+#define CODEC_MODE_WAVELET   0x0008    // Wavelet
+
+/* this are the current codec types I want to implement */
+/*  -> type value in structure */
+#define CODEC_TYPE_NONE    0
+#define CODEC_TYPE_L64702  1
+#define CODEC_TYPE_ZR36050 2
+#define CODEC_TYPE_ZR36016 3
+#define CODEC_TYPE_ZR36060 4
+
+/* the type of data may be enhanced by future implementations (data-fn.'s) */
+/*  -> used in command                                                     */
+#define CODEC_G_STATUS         0x0000  /* codec status (query only) */
+#define CODEC_S_CODEC_MODE     0x0001  /* codec mode (baseline JPEG, MPEG1,... */
+#define CODEC_G_CODEC_MODE     0x8001
+#define CODEC_S_VFE            0x0002  /* additional video frontend setup */
+#define CODEC_G_VFE            0x8002
+#define CODEC_S_MMAP           0x0003  /* MMAP setup (if available) */
+
+#define CODEC_S_JPEG_TDS_BYTE  0x0010  /* target data size in bytes */
+#define CODEC_G_JPEG_TDS_BYTE  0x8010
+#define CODEC_S_JPEG_SCALE     0x0011  /* scaling factor for quant. tables */
+#define CODEC_G_JPEG_SCALE     0x8011
+#define CODEC_S_JPEG_HDT_DATA  0x0018  /* huffman-tables */
+#define CODEC_G_JPEG_HDT_DATA  0x8018
+#define CODEC_S_JPEG_QDT_DATA  0x0019  /* quantizing-tables */
+#define CODEC_G_JPEG_QDT_DATA  0x8019
+#define CODEC_S_JPEG_APP_DATA  0x001A  /* APP marker */
+#define CODEC_G_JPEG_APP_DATA  0x801A
+#define CODEC_S_JPEG_COM_DATA  0x001B  /* COM marker */
+#define CODEC_G_JPEG_COM_DATA  0x801B
+
+#define CODEC_S_PRIVATE        0x1000  /* "private" commands start here */
+#define CODEC_G_PRIVATE        0x9000
+
+#define CODEC_G_FLAG           0x8000  /* this is how 'get' is detected */
+
+/* types of transfer, directly user space or a kernel buffer (image-fn.'s) */
+/*  -> used in get_image, put_image                                        */
+#define CODEC_TRANSFER_KERNEL 0        /* use "memcopy" */
+#define CODEC_TRANSFER_USER   1        /* use "to/from_user" */
+\f
+
+/* ========================= */
+/* the structures itself ... */
+/* ========================= */
+
+struct vfe_polarity {
+       unsigned int vsync_pol:1;
+       unsigned int hsync_pol:1;
+       unsigned int field_pol:1;
+       unsigned int blank_pol:1;
+       unsigned int subimg_pol:1;
+       unsigned int poe_pol:1;
+       unsigned int pvalid_pol:1;
+       unsigned int vclk_pol:1;
+};
+
+struct vfe_settings {
+       __u32 x, y;             /* Offsets into image */
+       __u32 width, height;    /* Area to capture */
+       __u16 decimation;       /* Decimation divider */
+       __u16 flags;            /* Flags for capture */
+       __u16 quality;          /* quality of the video */
+};
+
+struct tvnorm {
+       u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
+};
+
+struct jpeg_com_marker {
+       int len; /* number of usable bytes in data */
+       char data[60];
+};
+
+struct jpeg_app_marker {
+       int appn; /* number app segment */
+       int len; /* number of usable bytes in data */
+       char data[60];
+};
+
+struct videocodec {
+       struct module *owner;
+       /* -- filled in by slave device during register -- */
+       char name[32];
+       unsigned long magic;    /* may be used for client<->master attaching */
+       unsigned long flags;    /* functionality flags */
+       unsigned int type;      /* codec type */
+
+       /* -- these is filled in later during master device attach -- */
+
+       struct videocodec_master *master_data;
+
+       /* -- these are filled in by the slave device during register -- */
+
+       void *data;             /* private slave data */
+
+       /* attach/detach client functions (indirect call) */
+       int (*setup) (struct videocodec * codec);
+       int (*unset) (struct videocodec * codec);
+
+       /* main functions, every client needs them for sure! */
+       // set compression or decompression (or freeze, stop, standby, etc)
+       int (*set_mode) (struct videocodec * codec,
+                        int mode);
+       // setup picture size and norm (for the codec's video frontend)
+       int (*set_video) (struct videocodec * codec,
+                         struct tvnorm * norm,
+                         struct vfe_settings * cap,
+                         struct vfe_polarity * pol);
+       // other control commands, also mmap setup etc.
+       int (*control) (struct videocodec * codec,
+                       int type,
+                       int size,
+                       void *data);
+
+       /* additional setup/query/processing (may be NULL pointer) */
+       // interrupt setup / handling (for irq's delivered by master)
+       int (*setup_interrupt) (struct videocodec * codec,
+                               long mode);
+       int (*handle_interrupt) (struct videocodec * codec,
+                                int source,
+                                long flag);
+       // picture interface (if any)
+       long (*put_image) (struct videocodec * codec,
+                          int tr_type,
+                          int block,
+                          long *fr_num,
+                          long *flag,
+                          long size,
+                          void *buf);
+       long (*get_image) (struct videocodec * codec,
+                          int tr_type,
+                          int block,
+                          long *fr_num,
+                          long *flag,
+                          long size,
+                          void *buf);
+};
+
+struct videocodec_master {
+       /* -- filled in by master device for registration -- */
+       char name[32];
+       unsigned long magic;    /* may be used for client<->master attaching */
+       unsigned long flags;    /* functionality flags */
+       unsigned int type;      /* master type */
+
+       void *data;             /* private master data */
+
+        __u32(*readreg) (struct videocodec * codec,
+                         __u16 reg);
+       void (*writereg) (struct videocodec * codec,
+                         __u16 reg,
+                         __u32 value);
+};
+\f
+
+/* ================================================= */
+/* function prototypes of the master/slave interface */
+/* ================================================= */
+
+/* attach and detach commands for the master */
+// * master structure needs to be kmalloc'ed before calling attach
+//   and free'd after calling detach
+// * returns pointer on success, NULL on failure
+extern struct videocodec *videocodec_attach(struct videocodec_master *);
+// * 0 on success, <0 (errno) on failure
+extern int videocodec_detach(struct videocodec *);
+
+/* register and unregister commands for the slaves */
+// * 0 on success, <0 (errno) on failure
+extern int videocodec_register(const struct videocodec *);
+// * 0 on success, <0 (errno) on failure
+extern int videocodec_unregister(const struct videocodec *);
+
+/* the other calls are directly done via the videocodec structure! */
+
+#endif                         /*ifndef __LINUX_VIDEOCODEC_H */
diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h
new file mode 100644 (file)
index 0000000..ca2754a
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * zoran - Iomega Buz driver
+ *
+ * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
+ *
+ * based on
+ *
+ * zoran.0.0.3 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * and
+ *
+ * bttv - Bt848 frame grabber driver
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+ *                        & Marcus Metzler (mocm@thp.uni-koeln.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.
+ *
+ * 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 _BUZ_H_
+#define _BUZ_H_
+
+#include <media/v4l2-device.h>
+
+struct zoran_sync {
+       unsigned long frame;    /* number of buffer that has been free'd */
+       unsigned long length;   /* number of code bytes in buffer (capture only) */
+       unsigned long seq;      /* frame sequence number */
+       struct timeval timestamp;       /* timestamp */
+};
+
+
+#define ZORAN_NAME    "ZORAN"  /* name of the device */
+
+#define ZR_DEVNAME(zr) ((zr)->name)
+
+#define   BUZ_MAX_WIDTH   (zr->timing->Wa)
+#define   BUZ_MAX_HEIGHT  (zr->timing->Ha)
+#define   BUZ_MIN_WIDTH    32  /* never display less than 32 pixels */
+#define   BUZ_MIN_HEIGHT   24  /* never display less than 24 rows */
+
+#define BUZ_NUM_STAT_COM    4
+#define BUZ_MASK_STAT_COM   3
+
+#define BUZ_MAX_FRAME     256  /* Must be a power of 2 */
+#define BUZ_MASK_FRAME    255  /* Must be BUZ_MAX_FRAME-1 */
+
+#define BUZ_MAX_INPUT       16
+
+#if VIDEO_MAX_FRAME <= 32
+#   define   V4L_MAX_FRAME   32
+#elif VIDEO_MAX_FRAME <= 64
+#   define   V4L_MAX_FRAME   64
+#else
+#   error   "Too many video frame buffers to handle"
+#endif
+#define   V4L_MASK_FRAME   (V4L_MAX_FRAME - 1)
+
+#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME)
+
+#include "zr36057.h"
+
+enum card_type {
+       UNKNOWN = -1,
+
+       /* Pinnacle/Miro */
+       DC10_old,               /* DC30 like */
+       DC10_new,               /* DC10plus like */
+       DC10plus,
+       DC30,
+       DC30plus,
+
+       /* Linux Media Labs */
+       LML33,
+       LML33R10,
+
+       /* Iomega */
+       BUZ,
+
+       /* AverMedia */
+       AVS6EYES,
+
+       /* total number of cards */
+       NUM_CARDS
+};
+
+enum zoran_codec_mode {
+       BUZ_MODE_IDLE,          /* nothing going on */
+       BUZ_MODE_MOTION_COMPRESS,       /* grabbing frames */
+       BUZ_MODE_MOTION_DECOMPRESS,     /* playing frames */
+       BUZ_MODE_STILL_COMPRESS,        /* still frame conversion */
+       BUZ_MODE_STILL_DECOMPRESS       /* still frame conversion */
+};
+
+enum zoran_buffer_state {
+       BUZ_STATE_USER,         /* buffer is owned by application */
+       BUZ_STATE_PEND,         /* buffer is queued in pend[] ready to feed to I/O */
+       BUZ_STATE_DMA,          /* buffer is queued in dma[] for I/O */
+       BUZ_STATE_DONE          /* buffer is ready to return to application */
+};
+
+enum zoran_map_mode {
+       ZORAN_MAP_MODE_RAW,
+       ZORAN_MAP_MODE_JPG_REC,
+#define ZORAN_MAP_MODE_JPG ZORAN_MAP_MODE_JPG_REC
+       ZORAN_MAP_MODE_JPG_PLAY,
+};
+
+enum gpio_type {
+       ZR_GPIO_JPEG_SLEEP = 0,
+       ZR_GPIO_JPEG_RESET,
+       ZR_GPIO_JPEG_FRAME,
+       ZR_GPIO_VID_DIR,
+       ZR_GPIO_VID_EN,
+       ZR_GPIO_VID_RESET,
+       ZR_GPIO_CLK_SEL1,
+       ZR_GPIO_CLK_SEL2,
+       ZR_GPIO_MAX,
+};
+
+enum gpcs_type {
+       GPCS_JPEG_RESET = 0,
+       GPCS_JPEG_START,
+       GPCS_MAX,
+};
+
+struct zoran_format {
+       char *name;
+       __u32 fourcc;
+       int colorspace;
+       int depth;
+       __u32 flags;
+       __u32 vfespfr;
+};
+/* flags */
+#define ZORAN_FORMAT_COMPRESSED 1<<0
+#define ZORAN_FORMAT_OVERLAY    1<<1
+#define ZORAN_FORMAT_CAPTURE   1<<2
+#define ZORAN_FORMAT_PLAYBACK  1<<3
+
+/* overlay-settings */
+struct zoran_overlay_settings {
+       int is_set;
+       int x, y, width, height;        /* position */
+       int clipcount;          /* position and number of clips */
+       const struct zoran_format *format;      /* overlay format */
+};
+
+/* v4l-capture settings */
+struct zoran_v4l_settings {
+       int width, height, bytesperline;        /* capture size */
+       const struct zoran_format *format;      /* capture format */
+};
+
+/* jpg-capture/-playback settings */
+struct zoran_jpg_settings {
+       int decimation;         /* this bit is used to set everything to default */
+       int HorDcm, VerDcm, TmpDcm;     /* capture decimation settings (TmpDcm=1 means both fields) */
+       int field_per_buff, odd_even;   /* field-settings (odd_even=1 (+TmpDcm=1) means top-field-first) */
+       int img_x, img_y, img_width, img_height;        /* crop settings (subframe capture) */
+       struct v4l2_jpegcompression jpg_comp;   /* JPEG-specific capture settings */
+};
+
+struct zoran_fh;
+
+struct zoran_mapping {
+       struct zoran_fh *fh;
+       int count;
+};
+
+struct zoran_buffer {
+       struct zoran_mapping *map;
+       enum zoran_buffer_state state;  /* state: unused/pending/dma/done */
+       struct zoran_sync bs;           /* DONE: info to return to application */
+       union {
+               struct {
+                       __le32 *frag_tab;       /* addresses of frag table */
+                       u32 frag_tab_bus;       /* same value cached to save time in ISR */
+               } jpg;
+               struct {
+                       char *fbuffer;          /* virtual address of frame buffer */
+                       unsigned long fbuffer_phys;/* physical address of frame buffer */
+                       unsigned long fbuffer_bus;/* bus address of frame buffer */
+               } v4l;
+       };
+};
+
+enum zoran_lock_activity {
+       ZORAN_FREE,             /* free for use */
+       ZORAN_ACTIVE,           /* active but unlocked */
+       ZORAN_LOCKED,           /* locked */
+};
+
+/* buffer collections */
+struct zoran_buffer_col {
+       enum zoran_lock_activity active;        /* feature currently in use? */
+       unsigned int num_buffers, buffer_size;
+       struct zoran_buffer buffer[MAX_FRAME];  /* buffers */
+       u8 allocated;           /* Flag if buffers are allocated  */
+       u8 need_contiguous;     /* Flag if contiguous buffers are needed */
+       /* only applies to jpg buffers, raw buffers are always contiguous */
+};
+
+struct zoran;
+
+/* zoran_fh contains per-open() settings */
+struct zoran_fh {
+       struct zoran *zr;
+
+       enum zoran_map_mode map_mode;           /* Flag which bufferset will map by next mmap() */
+
+       struct zoran_overlay_settings overlay_settings;
+       u32 *overlay_mask;                      /* overlay mask */
+       enum zoran_lock_activity overlay_active;/* feature currently in use? */
+
+       struct zoran_buffer_col buffers;        /* buffers' info */
+
+       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
+       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
+};
+
+struct card_info {
+       enum card_type type;
+       char name[32];
+       const char *i2c_decoder;        /* i2c decoder device */
+       const unsigned short *addrs_decoder;
+       const char *i2c_encoder;        /* i2c encoder device */
+       const unsigned short *addrs_encoder;
+       u16 video_vfe, video_codec;                     /* videocodec types */
+       u16 audio_chip;                                 /* audio type */
+
+       int inputs;             /* number of video inputs */
+       struct input {
+               int muxsel;
+               char name[32];
+       } input[BUZ_MAX_INPUT];
+
+       v4l2_std_id norms;
+       struct tvnorm *tvn[3];  /* supported TV norms */
+
+       u32 jpeg_int;           /* JPEG interrupt */
+       u32 vsync_int;          /* VSYNC interrupt */
+       s8 gpio[ZR_GPIO_MAX];
+       u8 gpcs[GPCS_MAX];
+
+       struct vfe_polarity vfe_pol;
+       u8 gpio_pol[ZR_GPIO_MAX];
+
+       /* is the /GWS line connected? */
+       u8 gws_not_connected;
+
+       /* avs6eyes mux setting */
+       u8 input_mux;
+
+       void (*init) (struct zoran * zr);
+};
+
+struct zoran {
+       struct v4l2_device v4l2_dev;
+       struct video_device *video_dev;
+
+       struct i2c_adapter i2c_adapter; /* */
+       struct i2c_algo_bit_data i2c_algo;      /* */
+       u32 i2cbr;
+
+       struct v4l2_subdev *decoder;    /* video decoder sub-device */
+       struct v4l2_subdev *encoder;    /* video encoder sub-device */
+
+       struct videocodec *codec;       /* video codec */
+       struct videocodec *vfe; /* video front end */
+
+       struct mutex resource_lock;     /* prevent evil stuff */
+       struct mutex other_lock;        /* please merge with above */
+
+       u8 initialized;         /* flag if zoran has been correctly initialized */
+       int user;               /* number of current users */
+       struct card_info card;
+       struct tvnorm *timing;
+
+       unsigned short id;      /* number of this device */
+       char name[32];          /* name of this device */
+       struct pci_dev *pci_dev;        /* PCI device */
+       unsigned char revision; /* revision of zr36057 */
+       unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
+
+       spinlock_t spinlock;    /* Spinlock */
+
+       /* Video for Linux parameters */
+       int input;      /* card's norm and input */
+       v4l2_std_id norm;
+
+       /* Current buffer params */
+       void    *vbuf_base;
+       int     vbuf_height, vbuf_width;
+       int     vbuf_depth;
+       int     vbuf_bytesperline;
+
+       struct zoran_overlay_settings overlay_settings;
+       u32 *overlay_mask;      /* overlay mask */
+       enum zoran_lock_activity overlay_active;        /* feature currently in use? */
+
+       wait_queue_head_t v4l_capq;
+
+       int v4l_overlay_active; /* Overlay grab is activated */
+       int v4l_memgrab_active; /* Memory grab is activated */
+
+       int v4l_grab_frame;     /* Frame number being currently grabbed */
+#define NO_GRAB_ACTIVE (-1)
+       unsigned long v4l_grab_seq;     /* Number of frames grabbed */
+       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
+
+       /* V4L grab queue of frames pending */
+       unsigned long v4l_pend_head;
+       unsigned long v4l_pend_tail;
+       unsigned long v4l_sync_tail;
+       int v4l_pend[V4L_MAX_FRAME];
+       struct zoran_buffer_col v4l_buffers;    /* V4L buffers' info */
+
+       /* Buz MJPEG parameters */
+       enum zoran_codec_mode codec_mode;       /* status of codec */
+       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
+
+       wait_queue_head_t jpg_capq;     /* wait here for grab to finish */
+
+       /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */
+       /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */
+       /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */
+       unsigned long jpg_que_head;     /* Index where to put next buffer which is queued */
+       unsigned long jpg_dma_head;     /* Index of next buffer which goes into stat_com  */
+       unsigned long jpg_dma_tail;     /* Index of last buffer in stat_com               */
+       unsigned long jpg_que_tail;     /* Index of last buffer in queue                  */
+       unsigned long jpg_seq_num;      /* count of frames since grab/play started        */
+       unsigned long jpg_err_seq;      /* last seq_num before error                      */
+       unsigned long jpg_err_shift;
+       unsigned long jpg_queued_num;   /* count of frames queued since grab/play started */
+
+       /* zr36057's code buffer table */
+       __le32 *stat_com;               /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+
+       /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
+       int jpg_pend[BUZ_MAX_FRAME];
+
+       /* array indexed by frame number */
+       struct zoran_buffer_col jpg_buffers;    /* MJPEG buffers' info */
+
+       /* Additional stuff for testing */
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *zoran_proc;
+#else
+       void *zoran_proc;
+#endif
+       int testing;
+       int jpeg_error;
+       int intr_counter_GIRQ1;
+       int intr_counter_GIRQ0;
+       int intr_counter_CodRepIRQ;
+       int intr_counter_JPEGRepIRQ;
+       int field_counter;
+       int IRQ1_in;
+       int IRQ1_out;
+       int JPEG_in;
+       int JPEG_out;
+       int JPEG_0;
+       int JPEG_1;
+       int END_event_missed;
+       int JPEG_missed;
+       int JPEG_error;
+       int num_errors;
+       int JPEG_max_missed;
+       int JPEG_min_missed;
+
+       u32 last_isr;
+       unsigned long frame_num;
+
+       wait_queue_head_t test_q;
+};
+
+static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct zoran, v4l2_dev);
+}
+
+/* There was something called _ALPHA_BUZ that used the PCI address instead of
+ * the kernel iomapped address for btread/btwrite.  */
+#define btwrite(dat,adr)    writel((dat), zr->zr36057_mem+(adr))
+#define btread(adr)         readl(zr->zr36057_mem+(adr))
+
+#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
+#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
+#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
+
+#endif
diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c
new file mode 100644 (file)
index 0000000..c3602d6
--- /dev/null
@@ -0,0 +1,1524 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.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/delay.h>
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include <linux/proc_fs.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/kmod.h>
+#include <linux/wait.h>
+
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <media/v4l2-common.h>
+#include <media/bt819.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_card.h"
+#include "zoran_device.h"
+#include "zoran_procfs.h"
+
+extern const struct zoran_format zoran_formats[];
+
+static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "Card type");
+
+/*
+   The video mem address of the video card.
+   The driver has a little database for some videocards
+   to determine it from there. If your video card is not in there
+   you have either to give it to the driver as a parameter
+   or set in in a VIDIOCSFBUF ioctl
+ */
+
+static unsigned long vidmem;   /* default = 0 - Video memory base address */
+module_param(vidmem, ulong, 0444);
+MODULE_PARM_DESC(vidmem, "Default video memory base address");
+
+/*
+   Default input and video norm at startup of the driver.
+*/
+
+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)");
+
+static int default_mux = 1;    /* 6 Eyes input selection */
+module_param(default_mux, int, 0644);
+MODULE_PARM_DESC(default_mux,
+                "Default 6 Eyes mux setting (Input selection)");
+
+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)");
+
+/* /dev/videoN, -1 for autodetect */
+static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
+
+int v4l_nbufs = 4;
+int v4l_bufsize = 864;         /* Everybody should be able to work with this setting */
+module_param(v4l_nbufs, int, 0644);
+MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
+module_param(v4l_bufsize, int, 0644);
+MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)");
+
+int jpg_nbufs = 32;
+int jpg_bufsize = 512;         /* max size for 100% quality full-PAL frame */
+module_param(jpg_nbufs, int, 0644);
+MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
+module_param(jpg_bufsize, int, 0644);
+MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)");
+
+int pass_through = 0;          /* 1=Pass through TV signal when device is not used */
+                               /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
+module_param(pass_through, int, 0644);
+MODULE_PARM_DESC(pass_through,
+                "Pass TV signal through to TV-out when idling");
+
+int zr36067_debug = 1;
+module_param_named(debug, zr36067_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-5)");
+
+#define ZORAN_VERSION "0.10.1"
+
+MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
+MODULE_AUTHOR("Serguei Miridonov");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(ZORAN_VERSION);
+
+#define ZR_DEVICE(subven, subdev, data)        { \
+       .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
+       .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) }
+
+static struct pci_device_id zr36067_pci_tbl[] = {
+       ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus),
+       ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus),
+       ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10),
+       ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ),
+       ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS),
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
+
+static unsigned int zoran_num;         /* number of cards found */
+
+/* videocodec bus functions ZR36060 */
+static u32
+zr36060_read (struct videocodec *codec,
+             u16                reg)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+       __u32 data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 0, 1, reg >> 8)
+           || post_office_write(zr, 0, 2, reg & 0xff)) {
+               return -1;
+       }
+
+       data = post_office_read(zr, 0, 3) & 0xff;
+       return data;
+}
+
+static void
+zr36060_write (struct videocodec *codec,
+              u16                reg,
+              u32                val)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 0, 1, reg >> 8)
+           || post_office_write(zr, 0, 2, reg & 0xff)) {
+               return;
+       }
+
+       post_office_write(zr, 0, 3, val & 0xff);
+}
+
+/* videocodec bus functions ZR36050 */
+static u32
+zr36050_read (struct videocodec *codec,
+             u16                reg)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+       __u32 data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
+               return -1;
+       }
+
+       data = post_office_read(zr, 0, reg & 0x03) & 0xff;      // reg. LOWBYTES + read
+       return data;
+}
+
+static void
+zr36050_write (struct videocodec *codec,
+              u16                reg,
+              u32                val)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+
+       if (post_office_wait(zr)
+           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
+               return;
+       }
+
+       post_office_write(zr, 0, reg & 0x03, val & 0xff);       // reg. LOWBYTES + wr. data
+}
+
+/* videocodec bus functions ZR36016 */
+static u32
+zr36016_read (struct videocodec *codec,
+             u16                reg)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+       __u32 data;
+
+       if (post_office_wait(zr)) {
+               return -1;
+       }
+
+       data = post_office_read(zr, 2, reg & 0x03) & 0xff;      // read
+       return data;
+}
+
+/* hack for in zoran_device.c */
+void
+zr36016_write (struct videocodec *codec,
+              u16                reg,
+              u32                val)
+{
+       struct zoran *zr = (struct zoran *) codec->master_data->data;
+
+       if (post_office_wait(zr)) {
+               return;
+       }
+
+       post_office_write(zr, 2, reg & 0x03, val & 0x0ff);      // wr. data
+}
+
+/*
+ * Board specific information
+ */
+
+static void
+dc10_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
+
+       /* Pixel clock selection */
+       GPIO(zr, 4, 0);
+       GPIO(zr, 5, 1);
+       /* Enable the video bus sync signals */
+       GPIO(zr, 7, 0);
+}
+
+static void
+dc10plus_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
+}
+
+static void
+buz_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
+
+       /* some stuff from Iomega */
+       pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15);
+       pci_write_config_dword(zr->pci_dev, 0x0c, 0x00012020);
+       pci_write_config_dword(zr->pci_dev, 0xe8, 0xc0200000);
+}
+
+static void
+lml33_init (struct zoran *zr)
+{
+       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
+
+       GPIO(zr, 2, 1);         // Set Composite input/output
+}
+
+static void
+avs6eyes_init (struct zoran *zr)
+{
+       // AverMedia 6-Eyes original driver by Christer Weinigel
+
+       // Lifted straight from Christer's old driver and
+       // modified slightly by Martin Samuelsson.
+
+       int mux = default_mux; /* 1 = BT866, 7 = VID1 */
+
+       GPIO(zr, 4, 1); /* Bt866 SLEEP on */
+       udelay(2);
+
+       GPIO(zr, 0, 1); /* ZR36060 /RESET on */
+       GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
+       GPIO(zr, 2, mux & 1);   /* MUX S0 */
+       GPIO(zr, 3, 0); /* /FRAME on */
+       GPIO(zr, 4, 0); /* Bt866 SLEEP off */
+       GPIO(zr, 5, mux & 2);   /* MUX S1 */
+       GPIO(zr, 6, 0); /* ? */
+       GPIO(zr, 7, mux & 4);   /* MUX S2 */
+
+}
+
+static char *
+codecid_to_modulename (u16 codecid)
+{
+       char *name = NULL;
+
+       switch (codecid) {
+       case CODEC_TYPE_ZR36060:
+               name = "zr36060";
+               break;
+       case CODEC_TYPE_ZR36050:
+               name = "zr36050";
+               break;
+       case CODEC_TYPE_ZR36016:
+               name = "zr36016";
+               break;
+       }
+
+       return name;
+}
+
+// struct tvnorm {
+//      u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
+// };
+
+static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };
+static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };
+static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };
+
+static struct tvnorm f50ccir601_lml33 = { 864, 720, 75+34, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_lml33 = { 858, 720, 57+34, 788, 525, 480, 16 };
+
+/* The DC10 (57/16/50) uses VActive as HSync, so HStart must be 0 */
+static struct tvnorm f50sqpixel_dc10 = { 944, 768, 0, 880, 625, 576, 0 };
+static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 };
+
+/* FIXME: I cannot swap U and V in saa7114, so i do one
+ * pixel left shift in zoran (75 -> 74)
+ * (Maxim Yevtyushkin <max@linuxmedialabs.com>) */
+static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 };
+
+/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I
+ * copy Maxim's left shift hack for the 6 Eyes.
+ *
+ * Christer's driver used the unshifted norms, though...
+ * /Sam  */
+static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
+
+static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END };
+static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END };
+static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END };
+static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END };
+static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END };
+static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END };
+static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END };
+static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END };
+static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END };
+static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END };
+
+static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
+       {
+               .type = DC10_old,
+               .name = "DC10(old)",
+               .i2c_decoder = "vpx3220a",
+               .addrs_decoder = vpx3220_addrs,
+               .video_codec = CODEC_TYPE_ZR36050,
+               .video_vfe = CODEC_TYPE_ZR36016,
+
+               .inputs = 3,
+               .input = {
+                       { 1, "Composite" },
+                       { 2, "S-Video" },
+                       { 0, "Internal/comp" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
+               .tvn = {
+                       &f50sqpixel_dc10,
+                       &f60sqpixel_dc10,
+                       &f50sqpixel_dc10
+               },
+               .jpeg_int = 0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+               .gpcs = { -1, 0 },
+               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10_init,
+       }, {
+               .type = DC10_new,
+               .name = "DC10(new)",
+               .i2c_decoder = "saa7110",
+               .addrs_decoder = saa7110_addrs,
+               .i2c_encoder = "adv7175",
+               .addrs_encoder = adv717x_addrs,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 3,
+               .input = {
+                               { 0, "Composite" },
+                               { 7, "S-Video" },
+                               { 5, "Internal/comp" }
+                       },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
+               .tvn = {
+                               &f50sqpixel,
+                               &f60sqpixel,
+                               &f50sqpixel},
+               .jpeg_int = ZR36057_ISR_GIRQ0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gpcs = { -1, 1},
+               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10plus_init,
+       }, {
+               .type = DC10plus,
+               .name = "DC10plus",
+               .i2c_decoder = "saa7110",
+               .addrs_decoder = saa7110_addrs,
+               .i2c_encoder = "adv7175",
+               .addrs_encoder = adv717x_addrs,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 3,
+               .input = {
+                       { 0, "Composite" },
+                       { 7, "S-Video" },
+                       { 5, "Internal/comp" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
+               .tvn = {
+                       &f50sqpixel,
+                       &f60sqpixel,
+                       &f50sqpixel
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gpcs = { -1, 1 },
+               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10plus_init,
+       }, {
+               .type = DC30,
+               .name = "DC30",
+               .i2c_decoder = "vpx3220a",
+               .addrs_decoder = vpx3220_addrs,
+               .i2c_encoder = "adv7175",
+               .addrs_encoder = adv717x_addrs,
+               .video_codec = CODEC_TYPE_ZR36050,
+               .video_vfe = CODEC_TYPE_ZR36016,
+
+               .inputs = 3,
+               .input = {
+                       { 1, "Composite" },
+                       { 2, "S-Video" },
+                       { 0, "Internal/comp" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
+               .tvn = {
+                       &f50sqpixel_dc10,
+                       &f60sqpixel_dc10,
+                       &f50sqpixel_dc10
+               },
+               .jpeg_int = 0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+               .gpcs = { -1, 0 },
+               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10_init,
+       }, {
+               .type = DC30plus,
+               .name = "DC30plus",
+               .i2c_decoder = "vpx3220a",
+               .addrs_decoder = vpx3220_addrs,
+               .i2c_encoder = "adv7175",
+               .addrs_encoder = adv717x_addrs,
+               .video_codec = CODEC_TYPE_ZR36050,
+               .video_vfe = CODEC_TYPE_ZR36016,
+
+               .inputs = 3,
+               .input = {
+                       { 1, "Composite" },
+                       { 2, "S-Video" },
+                       { 0, "Internal/comp" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
+               .tvn = {
+                       &f50sqpixel_dc10,
+                       &f60sqpixel_dc10,
+                       &f50sqpixel_dc10
+               },
+               .jpeg_int = 0,
+               .vsync_int = ZR36057_ISR_GIRQ1,
+               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
+               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
+               .gpcs = { -1, 0 },
+               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gws_not_connected = 0,
+               .input_mux = 0,
+               .init = &dc10_init,
+       }, {
+               .type = LML33,
+               .name = "LML33",
+               .i2c_decoder = "bt819a",
+               .addrs_decoder = bt819_addrs,
+               .i2c_encoder = "bt856",
+               .addrs_encoder = bt856_addrs,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 2,
+               .input = {
+                       { 0, "Composite" },
+                       { 7, "S-Video" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL,
+               .tvn = {
+                       &f50ccir601_lml33,
+                       &f60ccir601_lml33,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
+               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
+               .gpcs = { 3, 1 },
+               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+               .gws_not_connected = 1,
+               .input_mux = 0,
+               .init = &lml33_init,
+       }, {
+               .type = LML33R10,
+               .name = "LML33R10",
+               .i2c_decoder = "saa7114",
+               .addrs_decoder = saa7114_addrs,
+               .i2c_encoder = "adv7170",
+               .addrs_encoder = adv717x_addrs,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 2,
+               .input = {
+                       { 0, "Composite" },
+                       { 7, "S-Video" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL,
+               .tvn = {
+                       &f50ccir601_lm33r10,
+                       &f60ccir601_lm33r10,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
+               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
+               .gpcs = { 3, 1 },
+               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+               .gws_not_connected = 1,
+               .input_mux = 0,
+               .init = &lml33_init,
+       }, {
+               .type = BUZ,
+               .name = "Buz",
+               .i2c_decoder = "saa7111",
+               .addrs_decoder = saa7111_addrs,
+               .i2c_encoder = "saa7185",
+               .addrs_encoder = saa7185_addrs,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 2,
+               .input = {
+                       { 3, "Composite" },
+                       { 7, "S-Video" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
+               .tvn = {
+                       &f50ccir601,
+                       &f60ccir601,
+                       &f50ccir601
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, -1, 3, -1, -1, -1, -1, -1 },
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
+               .gpcs = { 3, 1 },
+               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
+               .gws_not_connected = 1,
+               .input_mux = 0,
+               .init = &buz_init,
+       }, {
+               .type = AVS6EYES,
+               .name = "6-Eyes",
+               /* AverMedia chose not to brand the 6-Eyes. Thus it
+                  can't be autodetected, and requires card=x. */
+               .i2c_decoder = "ks0127",
+               .addrs_decoder = ks0127_addrs,
+               .i2c_encoder = "bt866",
+               .addrs_encoder = bt866_addrs,
+               .video_codec = CODEC_TYPE_ZR36060,
+
+               .inputs = 10,
+               .input = {
+                       { 0, "Composite 1" },
+                       { 1, "Composite 2" },
+                       { 2, "Composite 3" },
+                       { 4, "Composite 4" },
+                       { 5, "Composite 5" },
+                       { 6, "Composite 6" },
+                       { 8, "S-Video 1" },
+                       { 9, "S-Video 2" },
+                       {10, "S-Video 3" },
+                       {15, "YCbCr" }
+               },
+               .norms = V4L2_STD_NTSC|V4L2_STD_PAL,
+               .tvn = {
+                       &f50ccir601_avs6eyes,
+                       &f60ccir601_avs6eyes,
+                       NULL
+               },
+               .jpeg_int = ZR36057_ISR_GIRQ1,
+               .vsync_int = ZR36057_ISR_GIRQ0,
+               .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
+               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
+               .gpcs = { 3, 1 },                       // Validity unknown /Sam
+               .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 },  // Validity unknown /Sam
+               .gws_not_connected = 1,
+               .input_mux = 1,
+               .init = &avs6eyes_init,
+       }
+
+};
+
+/*
+ * I2C functions
+ */
+/* software I2C functions */
+static int
+zoran_i2c_getsda (void *data)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       return (btread(ZR36057_I2CBR) >> 1) & 1;
+}
+
+static int
+zoran_i2c_getscl (void *data)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       return btread(ZR36057_I2CBR) & 1;
+}
+
+static void
+zoran_i2c_setsda (void *data,
+                 int   state)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       if (state)
+               zr->i2cbr |= 2;
+       else
+               zr->i2cbr &= ~2;
+       btwrite(zr->i2cbr, ZR36057_I2CBR);
+}
+
+static void
+zoran_i2c_setscl (void *data,
+                 int   state)
+{
+       struct zoran *zr = (struct zoran *) data;
+
+       if (state)
+               zr->i2cbr |= 1;
+       else
+               zr->i2cbr &= ~1;
+       btwrite(zr->i2cbr, ZR36057_I2CBR);
+}
+
+static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
+       .setsda = zoran_i2c_setsda,
+       .setscl = zoran_i2c_setscl,
+       .getsda = zoran_i2c_getsda,
+       .getscl = zoran_i2c_getscl,
+       .udelay = 10,
+       .timeout = 100,
+};
+
+static int
+zoran_register_i2c (struct zoran *zr)
+{
+       memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
+              sizeof(struct i2c_algo_bit_data));
+       zr->i2c_algo.data = zr;
+       strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
+               sizeof(zr->i2c_adapter.name));
+       i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev);
+       zr->i2c_adapter.algo_data = &zr->i2c_algo;
+       zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
+       return i2c_bit_add_bus(&zr->i2c_adapter);
+}
+
+static void
+zoran_unregister_i2c (struct zoran *zr)
+{
+       i2c_del_adapter(&zr->i2c_adapter);
+}
+
+/* Check a zoran_params struct for correctness, insert default params */
+
+int
+zoran_check_jpg_settings (struct zoran              *zr,
+                         struct zoran_jpg_settings *settings,
+                         int try)
+{
+       int err = 0, err0 = 0;
+
+       dprintk(4,
+               KERN_DEBUG
+               "%s: %s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
+               ZR_DEVNAME(zr), __func__, settings->decimation, settings->HorDcm,
+               settings->VerDcm, settings->TmpDcm);
+       dprintk(4,
+               KERN_DEBUG
+               "%s: %s - x: %d, y: %d, w: %d, y: %d\n",
+               ZR_DEVNAME(zr), __func__, settings->img_x, settings->img_y,
+               settings->img_width, settings->img_height);
+       /* Check decimation, set default values for decimation = 1, 2, 4 */
+       switch (settings->decimation) {
+       case 1:
+
+               settings->HorDcm = 1;
+               settings->VerDcm = 1;
+               settings->TmpDcm = 1;
+               settings->field_per_buff = 2;
+               settings->img_x = 0;
+               settings->img_y = 0;
+               settings->img_width = BUZ_MAX_WIDTH;
+               settings->img_height = BUZ_MAX_HEIGHT / 2;
+               break;
+       case 2:
+
+               settings->HorDcm = 2;
+               settings->VerDcm = 1;
+               settings->TmpDcm = 2;
+               settings->field_per_buff = 1;
+               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+               settings->img_y = 0;
+               settings->img_width =
+                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+               settings->img_height = BUZ_MAX_HEIGHT / 2;
+               break;
+       case 4:
+
+               if (zr->card.type == DC10_new) {
+                       dprintk(1,
+                               KERN_DEBUG
+                               "%s: %s - HDec by 4 is not supported on the DC10\n",
+                               ZR_DEVNAME(zr), __func__);
+                       err0++;
+                       break;
+               }
+
+               settings->HorDcm = 4;
+               settings->VerDcm = 2;
+               settings->TmpDcm = 2;
+               settings->field_per_buff = 1;
+               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+               settings->img_y = 0;
+               settings->img_width =
+                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+               settings->img_height = BUZ_MAX_HEIGHT / 2;
+               break;
+       case 0:
+
+               /* We have to check the data the user has set */
+
+               if (settings->HorDcm != 1 && settings->HorDcm != 2 &&
+                   (zr->card.type == DC10_new || settings->HorDcm != 4)) {
+                       settings->HorDcm = clamp(settings->HorDcm, 1, 2);
+                       err0++;
+               }
+               if (settings->VerDcm != 1 && settings->VerDcm != 2) {
+                       settings->VerDcm = clamp(settings->VerDcm, 1, 2);
+                       err0++;
+               }
+               if (settings->TmpDcm != 1 && settings->TmpDcm != 2) {
+                       settings->TmpDcm = clamp(settings->TmpDcm, 1, 2);
+                       err0++;
+               }
+               if (settings->field_per_buff != 1 &&
+                   settings->field_per_buff != 2) {
+                       settings->field_per_buff = clamp(settings->field_per_buff, 1, 2);
+                       err0++;
+               }
+               if (settings->img_x < 0) {
+                       settings->img_x = 0;
+                       err0++;
+               }
+               if (settings->img_y < 0) {
+                       settings->img_y = 0;
+                       err0++;
+               }
+               if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) {
+                       settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH);
+                       err0++;
+               }
+               if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) {
+                       settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2);
+                       err0++;
+               }
+               if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) {
+                       settings->img_x = BUZ_MAX_WIDTH - settings->img_width;
+                       err0++;
+               }
+               if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) {
+                       settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height;
+                       err0++;
+               }
+               if (settings->img_width % (16 * settings->HorDcm) != 0) {
+                       settings->img_width -= settings->img_width % (16 * settings->HorDcm);
+                       if (settings->img_width == 0)
+                               settings->img_width = 16 * settings->HorDcm;
+                       err0++;
+               }
+               if (settings->img_height % (8 * settings->VerDcm) != 0) {
+                       settings->img_height -= settings->img_height % (8 * settings->VerDcm);
+                       if (settings->img_height == 0)
+                               settings->img_height = 8 * settings->VerDcm;
+                       err0++;
+               }
+
+               if (!try && err0) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - error in params for decimation = 0\n",
+                               ZR_DEVNAME(zr), __func__);
+                       err++;
+               }
+               break;
+       default:
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - decimation = %d, must be 0, 1, 2 or 4\n",
+                       ZR_DEVNAME(zr), __func__, settings->decimation);
+               err++;
+               break;
+       }
+
+       if (settings->jpg_comp.quality > 100)
+               settings->jpg_comp.quality = 100;
+       if (settings->jpg_comp.quality < 5)
+               settings->jpg_comp.quality = 5;
+       if (settings->jpg_comp.APPn < 0)
+               settings->jpg_comp.APPn = 0;
+       if (settings->jpg_comp.APPn > 15)
+               settings->jpg_comp.APPn = 15;
+       if (settings->jpg_comp.APP_len < 0)
+               settings->jpg_comp.APP_len = 0;
+       if (settings->jpg_comp.APP_len > 60)
+               settings->jpg_comp.APP_len = 60;
+       if (settings->jpg_comp.COM_len < 0)
+               settings->jpg_comp.COM_len = 0;
+       if (settings->jpg_comp.COM_len > 60)
+               settings->jpg_comp.COM_len = 60;
+       if (err)
+               return -EINVAL;
+       return 0;
+}
+
+void
+zoran_open_init_params (struct zoran *zr)
+{
+       int i;
+
+       /* User must explicitly set a window */
+       zr->overlay_settings.is_set = 0;
+       zr->overlay_mask = NULL;
+       zr->overlay_active = ZORAN_FREE;
+
+       zr->v4l_memgrab_active = 0;
+       zr->v4l_overlay_active = 0;
+       zr->v4l_grab_frame = NO_GRAB_ACTIVE;
+       zr->v4l_grab_seq = 0;
+       zr->v4l_settings.width = 192;
+       zr->v4l_settings.height = 144;
+       zr->v4l_settings.format = &zoran_formats[7];    /* YUY2 - YUV-4:2:2 packed */
+       zr->v4l_settings.bytesperline =
+           zr->v4l_settings.width *
+           ((zr->v4l_settings.format->depth + 7) / 8);
+
+       /* DMA ring stuff for V4L */
+       zr->v4l_pend_tail = 0;
+       zr->v4l_pend_head = 0;
+       zr->v4l_sync_tail = 0;
+       zr->v4l_buffers.active = ZORAN_FREE;
+       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+               zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+       }
+       zr->v4l_buffers.allocated = 0;
+
+       for (i = 0; i < BUZ_MAX_FRAME; i++) {
+               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+       }
+       zr->jpg_buffers.active = ZORAN_FREE;
+       zr->jpg_buffers.allocated = 0;
+       /* Set necessary params and call zoran_check_jpg_settings to set the defaults */
+       zr->jpg_settings.decimation = 1;
+       zr->jpg_settings.jpg_comp.quality = 50; /* default compression factor 8 */
+       if (zr->card.type != BUZ)
+               zr->jpg_settings.odd_even = 1;
+       else
+               zr->jpg_settings.odd_even = 0;
+       zr->jpg_settings.jpg_comp.APPn = 0;
+       zr->jpg_settings.jpg_comp.APP_len = 0;  /* No APPn marker */
+       memset(zr->jpg_settings.jpg_comp.APP_data, 0,
+              sizeof(zr->jpg_settings.jpg_comp.APP_data));
+       zr->jpg_settings.jpg_comp.COM_len = 0;  /* No COM marker */
+       memset(zr->jpg_settings.jpg_comp.COM_data, 0,
+              sizeof(zr->jpg_settings.jpg_comp.COM_data));
+       zr->jpg_settings.jpg_comp.jpeg_markers =
+           V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT;
+       i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0);
+       if (i)
+               dprintk(1, KERN_ERR "%s: %s internal error\n",
+                       ZR_DEVNAME(zr), __func__);
+
+       clear_interrupt_counters(zr);
+       zr->testing = 0;
+}
+
+static void __devinit
+test_interrupts (struct zoran *zr)
+{
+       DEFINE_WAIT(wait);
+       int timeout, icr;
+
+       clear_interrupt_counters(zr);
+
+       zr->testing = 1;
+       icr = btread(ZR36057_ICR);
+       btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR);
+       prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE);
+       timeout = schedule_timeout(HZ);
+       finish_wait(&zr->test_q, &wait);
+       btwrite(0, ZR36057_ICR);
+       btwrite(0x78000000, ZR36057_ISR);
+       zr->testing = 0;
+       dprintk(5, KERN_INFO "%s: Testing interrupts...\n", ZR_DEVNAME(zr));
+       if (timeout) {
+               dprintk(1, ": time spent: %d\n", 1 * HZ - timeout);
+       }
+       if (zr36067_debug > 1)
+               print_interrupts(zr);
+       btwrite(icr, ZR36057_ICR);
+}
+
+static int __devinit
+zr36057_init (struct zoran *zr)
+{
+       int j, err;
+
+       dprintk(1,
+               KERN_INFO
+               "%s: %s - initializing card[%d], zr=%p\n",
+               ZR_DEVNAME(zr), __func__, zr->id, zr);
+
+       /* default setup of all parameters which will persist between opens */
+       zr->user = 0;
+
+       init_waitqueue_head(&zr->v4l_capq);
+       init_waitqueue_head(&zr->jpg_capq);
+       init_waitqueue_head(&zr->test_q);
+       zr->jpg_buffers.allocated = 0;
+       zr->v4l_buffers.allocated = 0;
+
+       zr->vbuf_base = (void *) vidmem;
+       zr->vbuf_width = 0;
+       zr->vbuf_height = 0;
+       zr->vbuf_depth = 0;
+       zr->vbuf_bytesperline = 0;
+
+       /* Avoid nonsense settings from user for default input/norm */
+       if (default_norm < 0 || default_norm > 2)
+               default_norm = 0;
+       if (default_norm == 0) {
+               zr->norm = V4L2_STD_PAL;
+               zr->timing = zr->card.tvn[0];
+       } else if (default_norm == 1) {
+               zr->norm = V4L2_STD_NTSC;
+               zr->timing = zr->card.tvn[1];
+       } else {
+               zr->norm = V4L2_STD_SECAM;
+               zr->timing = zr->card.tvn[2];
+       }
+       if (zr->timing == NULL) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: %s - default TV standard not supported by hardware. PAL will be used.\n",
+                       ZR_DEVNAME(zr), __func__);
+               zr->norm = V4L2_STD_PAL;
+               zr->timing = zr->card.tvn[0];
+       }
+
+       if (default_input > zr->card.inputs-1) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: default_input value %d out of range (0-%d)\n",
+                       ZR_DEVNAME(zr), default_input, zr->card.inputs-1);
+               default_input = 0;
+       }
+       zr->input = default_input;
+
+       /* default setup (will be repeated at every open) */
+       zoran_open_init_params(zr);
+
+       /* allocate memory *before* doing anything to the hardware
+        * in case allocation fails */
+       zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
+       zr->video_dev = video_device_alloc();
+       if (!zr->stat_com || !zr->video_dev) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - kmalloc (STAT_COM) failed\n",
+                       ZR_DEVNAME(zr), __func__);
+               err = -ENOMEM;
+               goto exit_free;
+       }
+       for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+               zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
+       }
+
+       /*
+        *   Now add the template and register the device unit.
+        */
+       memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
+       zr->video_dev->parent = &zr->pci_dev->dev;
+       strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
+       err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
+       if (err < 0)
+               goto exit_free;
+       video_set_drvdata(zr->video_dev, zr);
+
+       zoran_init_hardware(zr);
+       if (zr36067_debug > 2)
+               detect_guest_activity(zr);
+       test_interrupts(zr);
+       if (!pass_through) {
+               decoder_call(zr, video, s_stream, 0);
+               encoder_call(zr, video, s_routing, 2, 0, 0);
+       }
+
+       zr->zoran_proc = NULL;
+       zr->initialized = 1;
+       return 0;
+
+exit_free:
+       kfree(zr->stat_com);
+       kfree(zr->video_dev);
+       return err;
+}
+
+static void __devexit zoran_remove(struct pci_dev *pdev)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
+       struct zoran *zr = to_zoran(v4l2_dev);
+
+       if (!zr->initialized)
+               goto exit_free;
+
+       /* unregister videocodec bus */
+       if (zr->codec) {
+               struct videocodec_master *master = zr->codec->master_data;
+
+               videocodec_detach(zr->codec);
+               kfree(master);
+       }
+       if (zr->vfe) {
+               struct videocodec_master *master = zr->vfe->master_data;
+
+               videocodec_detach(zr->vfe);
+               kfree(master);
+       }
+
+       /* unregister i2c bus */
+       zoran_unregister_i2c(zr);
+       /* disable PCI bus-mastering */
+       zoran_set_pci_master(zr, 0);
+       /* put chip into reset */
+       btwrite(0, ZR36057_SPGPPCR);
+       free_irq(zr->pci_dev->irq, zr);
+       /* unmap and free memory */
+       kfree(zr->stat_com);
+       zoran_proc_cleanup(zr);
+       iounmap(zr->zr36057_mem);
+       pci_disable_device(zr->pci_dev);
+       video_unregister_device(zr->video_dev);
+exit_free:
+       v4l2_device_unregister(&zr->v4l2_dev);
+       kfree(zr);
+}
+
+void
+zoran_vdev_release (struct video_device *vdev)
+{
+       kfree(vdev);
+}
+
+static struct videocodec_master * __devinit
+zoran_setup_videocodec (struct zoran *zr,
+                       int           type)
+{
+       struct videocodec_master *m = NULL;
+
+       m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL);
+       if (!m) {
+               dprintk(1, KERN_ERR "%s: %s - no memory\n",
+                       ZR_DEVNAME(zr), __func__);
+               return m;
+       }
+
+       /* magic and type are unused for master struct. Makes sense only at
+          codec structs.
+          In the past, .type were initialized to the old V4L1 .hardware
+          value, as VID_HARDWARE_ZR36067
+        */
+       m->magic = 0L;
+       m->type = 0;
+
+       m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
+       strlcpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
+       m->data = zr;
+
+       switch (type)
+       {
+       case CODEC_TYPE_ZR36060:
+               m->readreg = zr36060_read;
+               m->writereg = zr36060_write;
+               m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE;
+               break;
+       case CODEC_TYPE_ZR36050:
+               m->readreg = zr36050_read;
+               m->writereg = zr36050_write;
+               m->flags |= CODEC_FLAG_JPEG;
+               break;
+       case CODEC_TYPE_ZR36016:
+               m->readreg = zr36016_read;
+               m->writereg = zr36016_write;
+               m->flags |= CODEC_FLAG_VFE;
+               break;
+       }
+
+       return m;
+}
+
+static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+       struct zoran *zr = to_zoran(sd->v4l2_dev);
+
+       /* Bt819 needs to reset its FIFO buffer using #FRST pin and
+          LML33 card uses GPIO(7) for that. */
+       if (cmd == BT819_FIFO_RESET_LOW)
+               GPIO(zr, 7, 0);
+       else if (cmd == BT819_FIFO_RESET_HIGH)
+               GPIO(zr, 7, 1);
+}
+
+/*
+ *   Scan for a Buz card (actually for the PCI controller ZR36057),
+ *   request the irq and map the io memory
+ */
+static int __devinit zoran_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+       unsigned char latency, need_latency;
+       struct zoran *zr;
+       int result;
+       struct videocodec_master *master_vfe = NULL;
+       struct videocodec_master *master_codec = NULL;
+       int card_num;
+       char *codec_name, *vfe_name;
+       unsigned int nr;
+
+
+       nr = zoran_num++;
+       if (nr >= BUZ_MAX) {
+               dprintk(1, KERN_ERR "%s: driver limited to %d card(s) maximum\n",
+                       ZORAN_NAME, BUZ_MAX);
+               return -ENOENT;
+       }
+
+       zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
+       if (!zr) {
+               dprintk(1, KERN_ERR "%s: %s - kzalloc failed\n",
+                       ZORAN_NAME, __func__);
+               return -ENOMEM;
+       }
+       zr->v4l2_dev.notify = zoran_subdev_notify;
+       if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev))
+               goto zr_free_mem;
+       zr->pci_dev = pdev;
+       zr->id = nr;
+       snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
+       spin_lock_init(&zr->spinlock);
+       mutex_init(&zr->resource_lock);
+       mutex_init(&zr->other_lock);
+       if (pci_enable_device(pdev))
+               goto zr_unreg;
+       zr->revision = zr->pci_dev->revision;
+
+       dprintk(1,
+               KERN_INFO
+               "%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n",
+               ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision,
+               zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0));
+       if (zr->revision >= 2) {
+               dprintk(1,
+                       KERN_INFO
+                       "%s: Subsystem vendor=0x%04x id=0x%04x\n",
+                       ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor,
+                       zr->pci_dev->subsystem_device);
+       }
+
+       /* Use auto-detected card type? */
+       if (card[nr] == -1) {
+               if (zr->revision < 2) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: No card type specified, please use the card=X module parameter\n",
+                               ZR_DEVNAME(zr));
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: It is not possible to auto-detect ZR36057 based cards\n",
+                               ZR_DEVNAME(zr));
+                       goto zr_unreg;
+               }
+
+               card_num = ent->driver_data;
+               if (card_num >= NUM_CARDS) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: Unknown card, try specifying card=X module parameter\n",
+                               ZR_DEVNAME(zr));
+                       goto zr_unreg;
+               }
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() - card %s detected\n",
+                       ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name);
+       } else {
+               card_num = card[nr];
+               if (card_num >= NUM_CARDS || card_num < 0) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: User specified card type %d out of range (0 .. %d)\n",
+                               ZR_DEVNAME(zr), card_num, NUM_CARDS - 1);
+                       goto zr_unreg;
+               }
+       }
+
+       /* even though we make this a non pointer and thus
+        * theoretically allow for making changes to this struct
+        * on a per-individual card basis at runtime, this is
+        * strongly discouraged. This structure is intended to
+        * keep general card information, no settings or anything */
+       zr->card = zoran_cards[card_num];
+       snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
+                "%s[%u]", zr->card.name, zr->id);
+
+       zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0);
+       if (!zr->zr36057_mem) {
+               dprintk(1, KERN_ERR "%s: %s() - ioremap failed\n",
+                       ZR_DEVNAME(zr), __func__);
+               goto zr_unreg;
+       }
+
+       result = request_irq(zr->pci_dev->irq, zoran_irq,
+                            IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr);
+       if (result < 0) {
+               if (result == -EINVAL) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - bad irq number or handler\n",
+                               ZR_DEVNAME(zr), __func__);
+               } else if (result == -EBUSY) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - IRQ %d busy, change your PnP config in BIOS\n",
+                               ZR_DEVNAME(zr), __func__, zr->pci_dev->irq);
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - can't assign irq, error code %d\n",
+                               ZR_DEVNAME(zr), __func__, result);
+               }
+               goto zr_unmap;
+       }
+
+       /* set PCI latency timer */
+       pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
+                            &latency);
+       need_latency = zr->revision > 1 ? 32 : 48;
+       if (latency != need_latency) {
+               dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d\n",
+                       ZR_DEVNAME(zr), latency, need_latency);
+               pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
+                                     need_latency);
+       }
+
+       zr36057_restart(zr);
+       /* i2c */
+       dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
+               ZR_DEVNAME(zr));
+
+       if (zoran_register_i2c(zr) < 0) {
+               dprintk(1, KERN_ERR "%s: %s - can't initialize i2c bus\n",
+                       ZR_DEVNAME(zr), __func__);
+               goto zr_free_irq;
+       }
+
+       zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev,
+               &zr->i2c_adapter, zr->card.i2c_decoder,
+               0, zr->card.addrs_decoder);
+
+       if (zr->card.i2c_encoder)
+               zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev,
+                       &zr->i2c_adapter, zr->card.i2c_encoder,
+                       0, zr->card.addrs_encoder);
+
+       dprintk(2,
+               KERN_INFO "%s: Initializing videocodec bus...\n",
+               ZR_DEVNAME(zr));
+
+       if (zr->card.video_codec) {
+               codec_name = codecid_to_modulename(zr->card.video_codec);
+               if (codec_name) {
+                       result = request_module(codec_name);
+                       if (result) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: failed to load modules %s: %d\n",
+                                       ZR_DEVNAME(zr), codec_name, result);
+                       }
+               }
+       }
+       if (zr->card.video_vfe) {
+               vfe_name = codecid_to_modulename(zr->card.video_vfe);
+               if (vfe_name) {
+                       result = request_module(vfe_name);
+                       if (result < 0) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: failed to load modules %s: %d\n",
+                                       ZR_DEVNAME(zr), vfe_name, result);
+                       }
+               }
+       }
+
+       /* reset JPEG codec */
+       jpeg_codec_sleep(zr, 1);
+       jpeg_codec_reset(zr);
+       /* video bus enabled */
+       /* display codec revision */
+       if (zr->card.video_codec != 0) {
+               master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
+               if (!master_codec)
+                       goto zr_unreg_i2c;
+               zr->codec = videocodec_attach(master_codec);
+               if (!zr->codec) {
+                       dprintk(1, KERN_ERR "%s: %s - no codec found\n",
+                               ZR_DEVNAME(zr), __func__);
+                       goto zr_free_codec;
+               }
+               if (zr->codec->type != zr->card.video_codec) {
+                       dprintk(1, KERN_ERR "%s: %s - wrong codec\n",
+                               ZR_DEVNAME(zr), __func__);
+                       goto zr_detach_codec;
+               }
+       }
+       if (zr->card.video_vfe != 0) {
+               master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe);
+               if (!master_vfe)
+                       goto zr_detach_codec;
+               zr->vfe = videocodec_attach(master_vfe);
+               if (!zr->vfe) {
+                       dprintk(1, KERN_ERR "%s: %s - no VFE found\n",
+                               ZR_DEVNAME(zr), __func__);
+                       goto zr_free_vfe;
+               }
+               if (zr->vfe->type != zr->card.video_vfe) {
+                       dprintk(1, KERN_ERR "%s: %s = wrong VFE\n",
+                               ZR_DEVNAME(zr), __func__);
+                       goto zr_detach_vfe;
+               }
+       }
+
+       /* take care of Natoma chipset and a revision 1 zr36057 */
+       if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
+               zr->jpg_buffers.need_contiguous = 1;
+               dprintk(1, KERN_INFO
+                       "%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
+                       ZR_DEVNAME(zr));
+       }
+
+       if (zr36057_init(zr) < 0)
+               goto zr_detach_vfe;
+
+       zoran_proc_init(zr);
+
+       return 0;
+
+zr_detach_vfe:
+       videocodec_detach(zr->vfe);
+zr_free_vfe:
+       kfree(master_vfe);
+zr_detach_codec:
+       videocodec_detach(zr->codec);
+zr_free_codec:
+       kfree(master_codec);
+zr_unreg_i2c:
+       zoran_unregister_i2c(zr);
+zr_free_irq:
+       btwrite(0, ZR36057_SPGPPCR);
+       free_irq(zr->pci_dev->irq, zr);
+zr_unmap:
+       iounmap(zr->zr36057_mem);
+zr_unreg:
+       v4l2_device_unregister(&zr->v4l2_dev);
+zr_free_mem:
+       kfree(zr);
+
+       return -ENODEV;
+}
+
+static struct pci_driver zoran_driver = {
+       .name = "zr36067",
+       .id_table = zr36067_pci_tbl,
+       .probe = zoran_probe,
+       .remove = __devexit_p(zoran_remove),
+};
+
+static int __init zoran_init(void)
+{
+       int res;
+
+       printk(KERN_INFO "Zoran MJPEG board driver version %s\n",
+              ZORAN_VERSION);
+
+       /* check the parameters we have been given, adjust if necessary */
+       if (v4l_nbufs < 2)
+               v4l_nbufs = 2;
+       if (v4l_nbufs > VIDEO_MAX_FRAME)
+               v4l_nbufs = VIDEO_MAX_FRAME;
+       /* The user specfies the in KB, we want them in byte
+        * (and page aligned) */
+       v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
+       if (v4l_bufsize < 32768)
+               v4l_bufsize = 32768;
+       /* 2 MB is arbitrary but sufficient for the maximum possible images */
+       if (v4l_bufsize > 2048 * 1024)
+               v4l_bufsize = 2048 * 1024;
+       if (jpg_nbufs < 4)
+               jpg_nbufs = 4;
+       if (jpg_nbufs > BUZ_MAX_FRAME)
+               jpg_nbufs = BUZ_MAX_FRAME;
+       jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024);
+       if (jpg_bufsize < 8192)
+               jpg_bufsize = 8192;
+       if (jpg_bufsize > (512 * 1024))
+               jpg_bufsize = 512 * 1024;
+       /* Use parameter for vidmem or try to find a video card */
+       if (vidmem) {
+               dprintk(1,
+                       KERN_INFO
+                       "%s: Using supplied video memory base address @ 0x%lx\n",
+                       ZORAN_NAME, vidmem);
+       }
+
+       /* some mainboards might not do PCI-PCI data transfer well */
+       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: chipset does not support reliable PCI-PCI DMA\n",
+                       ZORAN_NAME);
+       }
+
+       res = pci_register_driver(&zoran_driver);
+       if (res) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: Unable to register ZR36057 driver\n",
+                       ZORAN_NAME);
+               return res;
+       }
+
+       return 0;
+}
+
+static void __exit zoran_exit(void)
+{
+       pci_unregister_driver(&zoran_driver);
+}
+
+module_init(zoran_init);
+module_exit(zoran_exit);
diff --git a/drivers/media/pci/zoran/zoran_card.h b/drivers/media/pci/zoran/zoran_card.h
new file mode 100644 (file)
index 0000000..4936fea
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.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.
+ */
+
+#ifndef __ZORAN_CARD_H__
+#define __ZORAN_CARD_H__
+
+extern int zr36067_debug;
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (zr36067_debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* Anybody who uses more than four? */
+#define BUZ_MAX 4
+
+extern struct video_device zoran_template;
+
+extern int zoran_check_jpg_settings(struct zoran *zr,
+                                   struct zoran_jpg_settings *settings,
+                                   int try);
+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__ */
diff --git a/drivers/media/pci/zoran/zoran_device.c b/drivers/media/pci/zoran/zoran_device.c
new file mode 100644 (file)
index 0000000..a4cd504
--- /dev/null
@@ -0,0 +1,1640 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles device access (PCI/I2C/codec/...)
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.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/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_device.h"
+#include "zoran_card.h"
+
+#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \
+                  ZR36057_ISR_GIRQ1 | \
+                  ZR36057_ISR_JPEGRepIRQ )
+
+static bool 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
+                                * on TV monitor connected to the output.
+                                * However, due to absence of 75 Ohm
+                                * load on Bt819 input, there will be
+                                * some image imperfections */
+
+module_param(lml33dpath, bool, 0644);
+MODULE_PARM_DESC(lml33dpath,
+                "Use digital path capture mode (on LML33 cards)");
+
+static void
+zr36057_init_vfe (struct zoran *zr);
+
+/*
+ * General Purpose I/O and Guest bus access
+ */
+
+/*
+ * This is a bit tricky. When a board lacks a GPIO function, the corresponding
+ * GPIO bit number in the card_info structure is set to 0.
+ */
+
+void
+GPIO (struct zoran *zr,
+      int           bit,
+      unsigned int  value)
+{
+       u32 reg;
+       u32 mask;
+
+       /* Make sure the bit number is legal
+        * A bit number of -1 (lacking) gives a mask of 0,
+        * making it harmless */
+       mask = (1 << (24 + bit)) & 0xff000000;
+       reg = btread(ZR36057_GPPGCR1) & ~mask;
+       if (value) {
+               reg |= mask;
+       }
+       btwrite(reg, ZR36057_GPPGCR1);
+       udelay(1);
+}
+
+/*
+ * Wait til post office is no longer busy
+ */
+
+int
+post_office_wait (struct zoran *zr)
+{
+       u32 por;
+
+//      while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) {
+       while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) {
+               /* wait for something to happen */
+       }
+       if ((por & ZR36057_POR_POTime) && !zr->card.gws_not_connected) {
+               /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */
+               dprintk(1, KERN_INFO "%s: pop timeout %08x\n", ZR_DEVNAME(zr),
+                       por);
+               return -1;
+       }
+
+       return 0;
+}
+
+int
+post_office_write (struct zoran *zr,
+                  unsigned int  guest,
+                  unsigned int  reg,
+                  unsigned int  value)
+{
+       u32 por;
+
+       por =
+           ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) |
+           ((reg & 7) << 16) | (value & 0xFF);
+       btwrite(por, ZR36057_POR);
+
+       return post_office_wait(zr);
+}
+
+int
+post_office_read (struct zoran *zr,
+                 unsigned int  guest,
+                 unsigned int  reg)
+{
+       u32 por;
+
+       por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16);
+       btwrite(por, ZR36057_POR);
+       if (post_office_wait(zr) < 0) {
+               return -1;
+       }
+
+       return btread(ZR36057_POR) & 0xFF;
+}
+
+/*
+ * detect guests
+ */
+
+static void
+dump_guests (struct zoran *zr)
+{
+       if (zr36067_debug > 2) {
+               int i, guest[8];
+
+               for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
+                       guest[i] = post_office_read(zr, i, 0);
+               }
+
+               printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
+
+               for (i = 1; i < 8; i++) {
+                       printk(" 0x%02x", guest[i]);
+               }
+               printk("\n");
+       }
+}
+
+static inline unsigned long
+get_time (void)
+{
+       struct timeval tv;
+
+       do_gettimeofday(&tv);
+       return (1000000 * tv.tv_sec + tv.tv_usec);
+}
+
+void
+detect_guest_activity (struct zoran *zr)
+{
+       int timeout, i, j, res, guest[8], guest0[8], change[8][3];
+       unsigned long t0, t1;
+
+       dump_guests(zr);
+       printk(KERN_INFO "%s: Detecting guests activity, please wait...\n",
+              ZR_DEVNAME(zr));
+       for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
+               guest0[i] = guest[i] = post_office_read(zr, i, 0);
+       }
+
+       timeout = 0;
+       j = 0;
+       t0 = get_time();
+       while (timeout < 10000) {
+               udelay(10);
+               timeout++;
+               for (i = 1; (i < 8) && (j < 8); i++) {
+                       res = post_office_read(zr, i, 0);
+                       if (res != guest[i]) {
+                               t1 = get_time();
+                               change[j][0] = (t1 - t0);
+                               t0 = t1;
+                               change[j][1] = i;
+                               change[j][2] = res;
+                               j++;
+                               guest[i] = res;
+                       }
+               }
+               if (j >= 8)
+                       break;
+       }
+       printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
+
+       for (i = 1; i < 8; i++) {
+               printk(" 0x%02x", guest0[i]);
+       }
+       printk("\n");
+       if (j == 0) {
+               printk(KERN_INFO "%s: No activity detected.\n", ZR_DEVNAME(zr));
+               return;
+       }
+       for (i = 0; i < j; i++) {
+               printk(KERN_INFO "%s: %6d: %d => 0x%02x\n", ZR_DEVNAME(zr),
+                      change[i][0], change[i][1], change[i][2]);
+       }
+}
+
+/*
+ * JPEG Codec access
+ */
+
+void
+jpeg_codec_sleep (struct zoran *zr,
+                 int           sleep)
+{
+       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep);
+       if (!sleep) {
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: jpeg_codec_sleep() - wake GPIO=0x%08x\n",
+                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
+               udelay(500);
+       } else {
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: jpeg_codec_sleep() - sleep GPIO=0x%08x\n",
+                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
+               udelay(2);
+       }
+}
+
+int
+jpeg_codec_reset (struct zoran *zr)
+{
+       /* Take the codec out of sleep */
+       jpeg_codec_sleep(zr, 0);
+
+       if (zr->card.gpcs[GPCS_JPEG_RESET] != 0xff) {
+               post_office_write(zr, zr->card.gpcs[GPCS_JPEG_RESET], 0,
+                                 0);
+               udelay(2);
+       } else {
+               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0);
+               udelay(2);
+               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1);
+               udelay(2);
+       }
+
+       return 0;
+}
+
+/*
+ *   Set the registers for the size we have specified. Don't bother
+ *   trying to understand this without the ZR36057 manual in front of
+ *   you [AC].
+ *
+ *   PS: The manual is free for download in .pdf format from
+ *   www.zoran.com - nicely done those folks.
+ */
+
+static void
+zr36057_adjust_vfe (struct zoran          *zr,
+                   enum zoran_codec_mode  mode)
+{
+       u32 reg;
+
+       switch (mode) {
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
+               reg = btread(ZR36057_VFEHCR);
+               if ((reg & (1 << 10)) && zr->card.type != LML33R10) {
+                       reg += ((1 << 10) | 1);
+               }
+               btwrite(reg, ZR36057_VFEHCR);
+               break;
+       case BUZ_MODE_MOTION_COMPRESS:
+       case BUZ_MODE_IDLE:
+       default:
+               if ((zr->norm & V4L2_STD_NTSC) ||
+                   (zr->card.type == LML33R10 &&
+                    (zr->norm & V4L2_STD_PAL)))
+                       btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
+               else
+                       btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
+               reg = btread(ZR36057_VFEHCR);
+               if (!(reg & (1 << 10)) && zr->card.type != LML33R10) {
+                       reg -= ((1 << 10) | 1);
+               }
+               btwrite(reg, ZR36057_VFEHCR);
+               break;
+       }
+}
+
+/*
+ * set geometry
+ */
+
+static void
+zr36057_set_vfe (struct zoran              *zr,
+                int                        video_width,
+                int                        video_height,
+                const struct zoran_format *format)
+{
+       struct tvnorm *tvn;
+       unsigned HStart, HEnd, VStart, VEnd;
+       unsigned DispMode;
+       unsigned VidWinWid, VidWinHt;
+       unsigned hcrop1, hcrop2, vcrop1, vcrop2;
+       unsigned Wa, We, Ha, He;
+       unsigned X, Y, HorDcm, VerDcm;
+       u32 reg;
+       unsigned mask_line_size;
+
+       tvn = zr->timing;
+
+       Wa = tvn->Wa;
+       Ha = tvn->Ha;
+
+       dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n",
+               ZR_DEVNAME(zr), video_width, video_height);
+
+       if (video_width < BUZ_MIN_WIDTH ||
+           video_height < BUZ_MIN_HEIGHT ||
+           video_width > Wa || video_height > Ha) {
+               dprintk(1, KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n",
+                       ZR_DEVNAME(zr), video_width, video_height);
+               return;
+       }
+
+       /**** zr36057 ****/
+
+       /* horizontal */
+       VidWinWid = video_width;
+       X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa);
+       We = (VidWinWid * 64) / X;
+       HorDcm = 64 - X;
+       hcrop1 = 2 * ((tvn->Wa - We) / 4);
+       hcrop2 = tvn->Wa - We - hcrop1;
+       HStart = tvn->HStart ? tvn->HStart : 1;
+       /* (Ronald) Original comment:
+        * "| 1 Doesn't have any effect, tested on both a DC10 and a DC10+"
+        * this is false. It inverses chroma values on the LML33R10 (so Cr
+        * suddenly is shown as Cb and reverse, really cool effect if you
+        * want to see blue faces, not useful otherwise). So don't use |1.
+        * However, the DC10 has '0' as HStart, but does need |1, so we
+        * use a dirty check...
+        */
+       HEnd = HStart + tvn->Wa - 1;
+       HStart += hcrop1;
+       HEnd -= hcrop2;
+       reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart)
+           | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd);
+       if (zr->card.vfe_pol.hsync_pol)
+               reg |= ZR36057_VFEHCR_HSPol;
+       btwrite(reg, ZR36057_VFEHCR);
+
+       /* Vertical */
+       DispMode = !(video_height > BUZ_MAX_HEIGHT / 2);
+       VidWinHt = DispMode ? video_height : video_height / 2;
+       Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha);
+       He = (VidWinHt * 64) / Y;
+       VerDcm = 64 - Y;
+       vcrop1 = (tvn->Ha / 2 - He) / 2;
+       vcrop2 = tvn->Ha / 2 - He - vcrop1;
+       VStart = tvn->VStart;
+       VEnd = VStart + tvn->Ha / 2;    // - 1; FIXME SnapShot times out with -1 in 768*576 on the DC10 - LP
+       VStart += vcrop1;
+       VEnd -= vcrop2;
+       reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart)
+           | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd);
+       if (zr->card.vfe_pol.vsync_pol)
+               reg |= ZR36057_VFEVCR_VSPol;
+       btwrite(reg, ZR36057_VFEVCR);
+
+       /* scaler and pixel format */
+       reg = 0;
+       reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
+       reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
+       reg |= (DispMode << ZR36057_VFESPFR_DispMode);
+       /* RJ: I don't know, why the following has to be the opposite
+        * of the corresponding ZR36060 setting, but only this way
+        * we get the correct colors when uncompressing to the screen  */
+       //reg |= ZR36057_VFESPFR_VCLKPol; /**/
+       /* RJ: Don't know if that is needed for NTSC also */
+       if (!(zr->norm & V4L2_STD_NTSC))
+               reg |= ZR36057_VFESPFR_ExtFl;   // NEEDED!!!!!!! Wolfgang
+       reg |= ZR36057_VFESPFR_TopField;
+       if (HorDcm >= 48) {
+               reg |= 3 << ZR36057_VFESPFR_HFilter;    /* 5 tap filter */
+       } else if (HorDcm >= 32) {
+               reg |= 2 << ZR36057_VFESPFR_HFilter;    /* 4 tap filter */
+       } else if (HorDcm >= 16) {
+               reg |= 1 << ZR36057_VFESPFR_HFilter;    /* 3 tap filter */
+       }
+       reg |= format->vfespfr;
+       btwrite(reg, ZR36057_VFESPFR);
+
+       /* display configuration */
+       reg = (16 << ZR36057_VDCR_MinPix)
+           | (VidWinHt << ZR36057_VDCR_VidWinHt)
+           | (VidWinWid << ZR36057_VDCR_VidWinWid);
+       if (pci_pci_problems & PCIPCI_TRITON)
+               // || zr->revision < 1) // Revision 1 has also Triton support
+               reg &= ~ZR36057_VDCR_Triton;
+       else
+               reg |= ZR36057_VDCR_Triton;
+       btwrite(reg, ZR36057_VDCR);
+
+       /* (Ronald) don't write this if overlay_mask = NULL */
+       if (zr->overlay_mask) {
+               /* Write overlay clipping mask data, but don't enable overlay clipping */
+               /* RJ: since this makes only sense on the screen, we use
+                * zr->overlay_settings.width instead of video_width */
+
+               mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
+               reg = virt_to_bus(zr->overlay_mask);
+               btwrite(reg, ZR36057_MMTR);
+               reg = virt_to_bus(zr->overlay_mask + mask_line_size);
+               btwrite(reg, ZR36057_MMBR);
+               reg =
+                   mask_line_size - (zr->overlay_settings.width +
+                                     31) / 32;
+               if (DispMode == 0)
+                       reg += mask_line_size;
+               reg <<= ZR36057_OCR_MaskStride;
+               btwrite(reg, ZR36057_OCR);
+       }
+
+       zr36057_adjust_vfe(zr, zr->codec_mode);
+}
+
+/*
+ * Switch overlay on or off
+ */
+
+void
+zr36057_overlay (struct zoran *zr,
+                int           on)
+{
+       u32 reg;
+
+       if (on) {
+               /* do the necessary settings ... */
+               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);       /* switch it off first */
+
+               zr36057_set_vfe(zr,
+                               zr->overlay_settings.width,
+                               zr->overlay_settings.height,
+                               zr->overlay_settings.format);
+
+               /* Start and length of each line MUST be 4-byte aligned.
+                * This should be already checked before the call to this routine.
+                * All error messages are internal driver checking only! */
+
+               /* video display top and bottom registers */
+               reg = (long) zr->vbuf_base +
+                   zr->overlay_settings.x *
+                   ((zr->overlay_settings.format->depth + 7) / 8) +
+                   zr->overlay_settings.y *
+                   zr->vbuf_bytesperline;
+               btwrite(reg, ZR36057_VDTR);
+               if (reg & 3)
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: zr36057_overlay() - video_address not aligned\n",
+                               ZR_DEVNAME(zr));
+               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
+                       reg += zr->vbuf_bytesperline;
+               btwrite(reg, ZR36057_VDBR);
+
+               /* video stride, status, and frame grab register */
+               reg = zr->vbuf_bytesperline -
+                   zr->overlay_settings.width *
+                   ((zr->overlay_settings.format->depth + 7) / 8);
+               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
+                       reg += zr->vbuf_bytesperline;
+               if (reg & 3)
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: zr36057_overlay() - video_stride not aligned\n",
+                               ZR_DEVNAME(zr));
+               reg = (reg << ZR36057_VSSFGR_DispStride);
+               reg |= ZR36057_VSSFGR_VidOvf;   /* clear overflow status */
+               btwrite(reg, ZR36057_VSSFGR);
+
+               /* Set overlay clipping */
+               if (zr->overlay_settings.clipcount > 0)
+                       btor(ZR36057_OCR_OvlEnable, ZR36057_OCR);
+
+               /* ... and switch it on */
+               btor(ZR36057_VDCR_VidEn, ZR36057_VDCR);
+       } else {
+               /* Switch it off */
+               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
+       }
+}
+
+/*
+ * The overlay mask has one bit for each pixel on a scan line,
+ *  and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels.
+ */
+
+void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count)
+{
+       struct zoran *zr = fh->zr;
+       unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
+       u32 *mask;
+       int x, y, width, height;
+       unsigned i, j, k;
+
+       /* fill mask with one bits */
+       memset(fh->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT);
+
+       for (i = 0; i < count; ++i) {
+               /* pick up local copy of clip */
+               x = vp[i].c.left;
+               y = vp[i].c.top;
+               width = vp[i].c.width;
+               height = vp[i].c.height;
+
+               /* trim clips that extend beyond the window */
+               if (x < 0) {
+                       width += x;
+                       x = 0;
+               }
+               if (y < 0) {
+                       height += y;
+                       y = 0;
+               }
+               if (x + width > fh->overlay_settings.width) {
+                       width = fh->overlay_settings.width - x;
+               }
+               if (y + height > fh->overlay_settings.height) {
+                       height = fh->overlay_settings.height - y;
+               }
+
+               /* ignore degenerate clips */
+               if (height <= 0) {
+                       continue;
+               }
+               if (width <= 0) {
+                       continue;
+               }
+
+               /* apply clip for each scan line */
+               for (j = 0; j < height; ++j) {
+                       /* reset bit for each pixel */
+                       /* this can be optimized later if need be */
+                       mask = fh->overlay_mask + (y + j) * mask_line_size;
+                       for (k = 0; k < width; ++k) {
+                               mask[(x + k) / 32] &=
+                                   ~((u32) 1 << (x + k) % 32);
+                       }
+               }
+       }
+}
+
+/* Enable/Disable uncompressed memory grabbing of the 36057 */
+
+void
+zr36057_set_memgrab (struct zoran *zr,
+                    int           mode)
+{
+       if (mode) {
+               /* We only check SnapShot and not FrameGrab here.  SnapShot==1
+                * means a capture is already in progress, but FrameGrab==1
+                * doesn't necessary mean that.  It's more correct to say a 1
+                * to 0 transition indicates a capture completed.  If a
+                * capture is pending when capturing is tuned off, FrameGrab
+                * will be stuck at 1 until capturing is turned back on.
+                */
+               if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot)
+                       dprintk(1,
+                               KERN_WARNING
+                               "%s: zr36057_set_memgrab(1) with SnapShot on!?\n",
+                               ZR_DEVNAME(zr));
+
+               /* switch on VSync interrupts */
+               btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts
+               btor(zr->card.vsync_int, ZR36057_ICR);  // SW
+
+               /* enable SnapShot */
+               btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
+
+               /* Set zr36057 video front end  and enable video */
+               zr36057_set_vfe(zr, zr->v4l_settings.width,
+                               zr->v4l_settings.height,
+                               zr->v4l_settings.format);
+
+               zr->v4l_memgrab_active = 1;
+       } else {
+               /* switch off VSync interrupts */
+               btand(~zr->card.vsync_int, ZR36057_ICR);        // SW
+
+               zr->v4l_memgrab_active = 0;
+               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
+
+               /* reenable grabbing to screen if it was running */
+               if (zr->v4l_overlay_active) {
+                       zr36057_overlay(zr, 1);
+               } else {
+                       btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
+                       btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
+               }
+       }
+}
+
+int
+wait_grab_pending (struct zoran *zr)
+{
+       unsigned long flags;
+
+       /* wait until all pending grabs are finished */
+
+       if (!zr->v4l_memgrab_active)
+               return 0;
+
+       wait_event_interruptible(zr->v4l_capq,
+                       (zr->v4l_pend_tail == zr->v4l_pend_head));
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+       zr36057_set_memgrab(zr, 0);
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return 0;
+}
+
+/*****************************************************************************
+ *                                                                           *
+ *  Set up the Buz-specific MJPEG part                                       *
+ *                                                                           *
+ *****************************************************************************/
+
+static inline void
+set_frame (struct zoran *zr,
+          int           val)
+{
+       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val);
+}
+
+static void
+set_videobus_dir (struct zoran *zr,
+                 int           val)
+{
+       switch (zr->card.type) {
+       case LML33:
+       case LML33R10:
+               if (lml33dpath == 0)
+                       GPIO(zr, 5, val);
+               else
+                       GPIO(zr, 5, 1);
+               break;
+       default:
+               GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR],
+                    zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val);
+               break;
+       }
+}
+
+static void
+init_jpeg_queue (struct zoran *zr)
+{
+       int i;
+
+       /* re-initialize DMA ring stuff */
+       zr->jpg_que_head = 0;
+       zr->jpg_dma_head = 0;
+       zr->jpg_dma_tail = 0;
+       zr->jpg_que_tail = 0;
+       zr->jpg_seq_num = 0;
+       zr->JPEG_error = 0;
+       zr->num_errors = 0;
+       zr->jpg_err_seq = 0;
+       zr->jpg_err_shift = 0;
+       zr->jpg_queued_num = 0;
+       for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
+               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
+       }
+       for (i = 0; i < BUZ_NUM_STAT_COM; i++) {
+               zr->stat_com[i] = cpu_to_le32(1);       /* mark as unavailable to zr36057 */
+       }
+}
+
+static void
+zr36057_set_jpg (struct zoran          *zr,
+                enum zoran_codec_mode  mode)
+{
+       struct tvnorm *tvn;
+       u32 reg;
+
+       tvn = zr->timing;
+
+       /* assert P_Reset, disable code transfer, deassert Active */
+       btwrite(0, ZR36057_JPC);
+
+       /* MJPEG compression mode */
+       switch (mode) {
+
+       case BUZ_MODE_MOTION_COMPRESS:
+       default:
+               reg = ZR36057_JMC_MJPGCmpMode;
+               break;
+
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               reg = ZR36057_JMC_MJPGExpMode;
+               reg |= ZR36057_JMC_SyncMstr;
+               /* RJ: The following is experimental - improves the output to screen */
+               //if(zr->jpg_settings.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM
+               break;
+
+       case BUZ_MODE_STILL_COMPRESS:
+               reg = ZR36057_JMC_JPGCmpMode;
+               break;
+
+       case BUZ_MODE_STILL_DECOMPRESS:
+               reg = ZR36057_JMC_JPGExpMode;
+               break;
+
+       }
+       reg |= ZR36057_JMC_JPG;
+       if (zr->jpg_settings.field_per_buff == 1)
+               reg |= ZR36057_JMC_Fld_per_buff;
+       btwrite(reg, ZR36057_JMC);
+
+       /* vertical */
+       btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR);
+       reg = (6 << ZR36057_VSP_VsyncSize) |
+             (tvn->Ht << ZR36057_VSP_FrmTot);
+       btwrite(reg, ZR36057_VSP);
+       reg = ((zr->jpg_settings.img_y + tvn->VStart) << ZR36057_FVAP_NAY) |
+             (zr->jpg_settings.img_height << ZR36057_FVAP_PAY);
+       btwrite(reg, ZR36057_FVAP);
+
+       /* horizontal */
+       if (zr->card.vfe_pol.hsync_pol)
+               btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
+       else
+               btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
+       reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) |
+             (tvn->Wt << ZR36057_HSP_LineTot);
+       btwrite(reg, ZR36057_HSP);
+       reg = ((zr->jpg_settings.img_x +
+               tvn->HStart + 4) << ZR36057_FHAP_NAX) |
+             (zr->jpg_settings.img_width << ZR36057_FHAP_PAX);
+       btwrite(reg, ZR36057_FHAP);
+
+       /* field process parameters */
+       if (zr->jpg_settings.odd_even)
+               reg = ZR36057_FPP_Odd_Even;
+       else
+               reg = 0;
+
+       btwrite(reg, ZR36057_FPP);
+
+       /* Set proper VCLK Polarity, else colors will be wrong during playback */
+       //btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
+
+       /* code base address */
+       reg = virt_to_bus(zr->stat_com);
+       btwrite(reg, ZR36057_JCBA);
+
+       /* FIFO threshold (FIFO is 160. double words) */
+       /* NOTE: decimal values here */
+       switch (mode) {
+
+       case BUZ_MODE_STILL_COMPRESS:
+       case BUZ_MODE_MOTION_COMPRESS:
+               if (zr->card.type != BUZ)
+                       reg = 140;
+               else
+                       reg = 60;
+               break;
+
+       case BUZ_MODE_STILL_DECOMPRESS:
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               reg = 20;
+               break;
+
+       default:
+               reg = 80;
+               break;
+
+       }
+       btwrite(reg, ZR36057_JCFT);
+       zr36057_adjust_vfe(zr, mode);
+
+}
+
+void
+print_interrupts (struct zoran *zr)
+{
+       int res, noerr = 0;
+
+       printk(KERN_INFO "%s: interrupts received:", ZR_DEVNAME(zr));
+       if ((res = zr->field_counter) < -1 || res > 1) {
+               printk(" FD:%d", res);
+       }
+       if ((res = zr->intr_counter_GIRQ1) != 0) {
+               printk(" GIRQ1:%d", res);
+               noerr++;
+       }
+       if ((res = zr->intr_counter_GIRQ0) != 0) {
+               printk(" GIRQ0:%d", res);
+               noerr++;
+       }
+       if ((res = zr->intr_counter_CodRepIRQ) != 0) {
+               printk(" CodRepIRQ:%d", res);
+               noerr++;
+       }
+       if ((res = zr->intr_counter_JPEGRepIRQ) != 0) {
+               printk(" JPEGRepIRQ:%d", res);
+               noerr++;
+       }
+       if (zr->JPEG_max_missed) {
+               printk(" JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
+                      zr->JPEG_min_missed);
+       }
+       if (zr->END_event_missed) {
+               printk(" ENDs missed: %d", zr->END_event_missed);
+       }
+       //if (zr->jpg_queued_num) {
+       printk(" queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
+              zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head);
+       //}
+       if (!noerr) {
+               printk(": no interrupts detected.");
+       }
+       printk("\n");
+}
+
+void
+clear_interrupt_counters (struct zoran *zr)
+{
+       zr->intr_counter_GIRQ1 = 0;
+       zr->intr_counter_GIRQ0 = 0;
+       zr->intr_counter_CodRepIRQ = 0;
+       zr->intr_counter_JPEGRepIRQ = 0;
+       zr->field_counter = 0;
+       zr->IRQ1_in = 0;
+       zr->IRQ1_out = 0;
+       zr->JPEG_in = 0;
+       zr->JPEG_out = 0;
+       zr->JPEG_0 = 0;
+       zr->JPEG_1 = 0;
+       zr->END_event_missed = 0;
+       zr->JPEG_missed = 0;
+       zr->JPEG_max_missed = 0;
+       zr->JPEG_min_missed = 0x7fffffff;
+}
+
+static u32
+count_reset_interrupt (struct zoran *zr)
+{
+       u32 isr;
+
+       if ((isr = btread(ZR36057_ISR) & 0x78000000)) {
+               if (isr & ZR36057_ISR_GIRQ1) {
+                       btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR);
+                       zr->intr_counter_GIRQ1++;
+               }
+               if (isr & ZR36057_ISR_GIRQ0) {
+                       btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR);
+                       zr->intr_counter_GIRQ0++;
+               }
+               if (isr & ZR36057_ISR_CodRepIRQ) {
+                       btwrite(ZR36057_ISR_CodRepIRQ, ZR36057_ISR);
+                       zr->intr_counter_CodRepIRQ++;
+               }
+               if (isr & ZR36057_ISR_JPEGRepIRQ) {
+                       btwrite(ZR36057_ISR_JPEGRepIRQ, ZR36057_ISR);
+                       zr->intr_counter_JPEGRepIRQ++;
+               }
+       }
+       return isr;
+}
+
+void
+jpeg_start (struct zoran *zr)
+{
+       int reg;
+
+       zr->frame_num = 0;
+
+       /* deassert P_reset, disable code transfer, deassert Active */
+       btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC);
+       /* stop flushing the internal code buffer */
+       btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
+       /* enable code transfer */
+       btor(ZR36057_JPC_CodTrnsEn, ZR36057_JPC);
+
+       /* clear IRQs */
+       btwrite(IRQ_MASK, ZR36057_ISR);
+       /* enable the JPEG IRQs */
+       btwrite(zr->card.jpeg_int |
+                       ZR36057_ICR_JPEGRepIRQ |
+                       ZR36057_ICR_IntPinEn,
+               ZR36057_ICR);
+
+       set_frame(zr, 0);       // \FRAME
+
+       /* set the JPEG codec guest ID */
+       reg = (zr->card.gpcs[1] << ZR36057_JCGI_JPEGuestID) |
+              (0 << ZR36057_JCGI_JPEGuestReg);
+       btwrite(reg, ZR36057_JCGI);
+
+       if (zr->card.video_vfe == CODEC_TYPE_ZR36016 &&
+           zr->card.video_codec == CODEC_TYPE_ZR36050) {
+               /* Enable processing on the ZR36016 */
+               if (zr->vfe)
+                       zr36016_write(zr->vfe, 0, 1);
+
+               /* load the address of the GO register in the ZR36050 latch */
+               post_office_write(zr, 0, 0, 0);
+       }
+
+       /* assert Active */
+       btor(ZR36057_JPC_Active, ZR36057_JPC);
+
+       /* enable the Go generation */
+       btor(ZR36057_JMC_Go_en, ZR36057_JMC);
+       udelay(30);
+
+       set_frame(zr, 1);       // /FRAME
+
+       dprintk(3, KERN_DEBUG "%s: jpeg_start\n", ZR_DEVNAME(zr));
+}
+
+void
+zr36057_enable_jpg (struct zoran          *zr,
+                   enum zoran_codec_mode  mode)
+{
+       struct vfe_settings cap;
+       int field_size =
+           zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff;
+
+       zr->codec_mode = mode;
+
+       cap.x = zr->jpg_settings.img_x;
+       cap.y = zr->jpg_settings.img_y;
+       cap.width = zr->jpg_settings.img_width;
+       cap.height = zr->jpg_settings.img_height;
+       cap.decimation =
+           zr->jpg_settings.HorDcm | (zr->jpg_settings.VerDcm << 8);
+       cap.quality = zr->jpg_settings.jpg_comp.quality;
+
+       switch (mode) {
+
+       case BUZ_MODE_MOTION_COMPRESS: {
+               struct jpeg_app_marker app;
+               struct jpeg_com_marker com;
+
+               /* In motion compress mode, the decoder output must be enabled, and
+                * the video bus direction set to input.
+                */
+               set_videobus_dir(zr, 0);
+               decoder_call(zr, video, s_stream, 1);
+               encoder_call(zr, video, s_routing, 0, 0, 0);
+
+               /* Take the JPEG codec and the VFE out of sleep */
+               jpeg_codec_sleep(zr, 0);
+
+               /* set JPEG app/com marker */
+               app.appn = zr->jpg_settings.jpg_comp.APPn;
+               app.len = zr->jpg_settings.jpg_comp.APP_len;
+               memcpy(app.data, zr->jpg_settings.jpg_comp.APP_data, 60);
+               zr->codec->control(zr->codec, CODEC_S_JPEG_APP_DATA,
+                                  sizeof(struct jpeg_app_marker), &app);
+
+               com.len = zr->jpg_settings.jpg_comp.COM_len;
+               memcpy(com.data, zr->jpg_settings.jpg_comp.COM_data, 60);
+               zr->codec->control(zr->codec, CODEC_S_JPEG_COM_DATA,
+                                  sizeof(struct jpeg_com_marker), &com);
+
+               /* Setup the JPEG codec */
+               zr->codec->control(zr->codec, CODEC_S_JPEG_TDS_BYTE,
+                                  sizeof(int), &field_size);
+               zr->codec->set_video(zr->codec, zr->timing, &cap,
+                                    &zr->card.vfe_pol);
+               zr->codec->set_mode(zr->codec, CODEC_DO_COMPRESSION);
+
+               /* Setup the VFE */
+               if (zr->vfe) {
+                       zr->vfe->control(zr->vfe, CODEC_S_JPEG_TDS_BYTE,
+                                        sizeof(int), &field_size);
+                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
+                                          &zr->card.vfe_pol);
+                       zr->vfe->set_mode(zr->vfe, CODEC_DO_COMPRESSION);
+               }
+
+               init_jpeg_queue(zr);
+               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
+
+               clear_interrupt_counters(zr);
+               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_COMPRESS)\n",
+                       ZR_DEVNAME(zr));
+               break;
+       }
+
+       case BUZ_MODE_MOTION_DECOMPRESS:
+               /* In motion decompression mode, the decoder output must be disabled, and
+                * the video bus direction set to output.
+                */
+               decoder_call(zr, video, s_stream, 0);
+               set_videobus_dir(zr, 1);
+               encoder_call(zr, video, s_routing, 1, 0, 0);
+
+               /* Take the JPEG codec and the VFE out of sleep */
+               jpeg_codec_sleep(zr, 0);
+               /* Setup the VFE */
+               if (zr->vfe) {
+                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
+                                          &zr->card.vfe_pol);
+                       zr->vfe->set_mode(zr->vfe, CODEC_DO_EXPANSION);
+               }
+               /* Setup the JPEG codec */
+               zr->codec->set_video(zr->codec, zr->timing, &cap,
+                                    &zr->card.vfe_pol);
+               zr->codec->set_mode(zr->codec, CODEC_DO_EXPANSION);
+
+               init_jpeg_queue(zr);
+               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
+
+               clear_interrupt_counters(zr);
+               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_DECOMPRESS)\n",
+                       ZR_DEVNAME(zr));
+               break;
+
+       case BUZ_MODE_IDLE:
+       default:
+               /* shut down processing */
+               btand(~(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ),
+                     ZR36057_ICR);
+               btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ,
+                       ZR36057_ISR);
+               btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en
+
+               msleep(50);
+
+               set_videobus_dir(zr, 0);
+               set_frame(zr, 1);       // /FRAME
+               btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);      // /CFlush
+               btwrite(0, ZR36057_JPC);        // \P_Reset,\CodTrnsEn,\Active
+               btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC);
+               btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC);
+               jpeg_codec_reset(zr);
+               jpeg_codec_sleep(zr, 1);
+               zr36057_adjust_vfe(zr, mode);
+
+               decoder_call(zr, video, s_stream, 1);
+               encoder_call(zr, video, s_routing, 0, 0, 0);
+
+               dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr));
+               break;
+
+       }
+}
+
+/* when this is called the spinlock must be held */
+void
+zoran_feed_stat_com (struct zoran *zr)
+{
+       /* move frames from pending queue to DMA */
+
+       int frame, i, max_stat_com;
+
+       max_stat_com =
+           (zr->jpg_settings.TmpDcm ==
+            1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1);
+
+       while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com &&
+              zr->jpg_dma_head < zr->jpg_que_head) {
+
+               frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME];
+               if (zr->jpg_settings.TmpDcm == 1) {
+                       /* fill 1 stat_com entry */
+                       i = (zr->jpg_dma_head -
+                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
+                               break;
+                       zr->stat_com[i] =
+                           cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
+               } else {
+                       /* fill 2 stat_com entries */
+                       i = ((zr->jpg_dma_head -
+                             zr->jpg_err_shift) & 1) * 2;
+                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
+                               break;
+                       zr->stat_com[i] =
+                           cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
+                       zr->stat_com[i + 1] =
+                           cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
+               }
+               zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
+               zr->jpg_dma_head++;
+
+       }
+       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
+               zr->jpg_queued_num++;
+}
+
+/* when this is called the spinlock must be held */
+static void
+zoran_reap_stat_com (struct zoran *zr)
+{
+       /* move frames from DMA queue to done queue */
+
+       int i;
+       u32 stat_com;
+       unsigned int seq;
+       unsigned int dif;
+       struct zoran_buffer *buffer;
+       int frame;
+
+       /* In motion decompress we don't have a hardware frame counter,
+        * we just count the interrupts here */
+
+       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
+               zr->jpg_seq_num++;
+       }
+       while (zr->jpg_dma_tail < zr->jpg_dma_head) {
+               if (zr->jpg_settings.TmpDcm == 1)
+                       i = (zr->jpg_dma_tail -
+                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+               else
+                       i = ((zr->jpg_dma_tail -
+                             zr->jpg_err_shift) & 1) * 2 + 1;
+
+               stat_com = le32_to_cpu(zr->stat_com[i]);
+
+               if ((stat_com & 1) == 0) {
+                       return;
+               }
+               frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
+               buffer = &zr->jpg_buffers.buffer[frame];
+               do_gettimeofday(&buffer->bs.timestamp);
+
+               if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+                       buffer->bs.length = (stat_com & 0x7fffff) >> 1;
+
+                       /* update sequence number with the help of the counter in stat_com */
+
+                       seq = ((stat_com >> 24) + zr->jpg_err_seq) & 0xff;
+                       dif = (seq - zr->jpg_seq_num) & 0xff;
+                       zr->jpg_seq_num += dif;
+               } else {
+                       buffer->bs.length = 0;
+               }
+               buffer->bs.seq =
+                   zr->jpg_settings.TmpDcm ==
+                   2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num;
+               buffer->state = BUZ_STATE_DONE;
+
+               zr->jpg_dma_tail++;
+       }
+}
+
+static void zoran_restart(struct zoran *zr)
+{
+       /* Now the stat_comm buffer is ready for restart */
+       unsigned int status = 0;
+       int mode;
+
+       if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+               decoder_call(zr, video, g_input_status, &status);
+               mode = CODEC_DO_COMPRESSION;
+       } else {
+               status = V4L2_IN_ST_NO_SIGNAL;
+               mode = CODEC_DO_EXPANSION;
+       }
+       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+           !(status & V4L2_IN_ST_NO_SIGNAL)) {
+               /********** RESTART code *************/
+               jpeg_codec_reset(zr);
+               zr->codec->set_mode(zr->codec, mode);
+               zr36057_set_jpg(zr, zr->codec_mode);
+               jpeg_start(zr);
+
+               if (zr->num_errors <= 8)
+                       dprintk(2, KERN_INFO "%s: Restart\n",
+                               ZR_DEVNAME(zr));
+
+               zr->JPEG_missed = 0;
+               zr->JPEG_error = 2;
+               /********** End RESTART code ***********/
+       }
+}
+
+static void
+error_handler (struct zoran *zr,
+              u32           astat,
+              u32           stat)
+{
+       int i;
+
+       /* This is JPEG error handling part */
+       if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS &&
+           zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS) {
+               return;
+       }
+
+       if ((stat & 1) == 0 &&
+           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS &&
+           zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_buffers.num_buffers) {
+               /* No free buffers... */
+               zoran_reap_stat_com(zr);
+               zoran_feed_stat_com(zr);
+               wake_up_interruptible(&zr->jpg_capq);
+               zr->JPEG_missed = 0;
+               return;
+       }
+
+       if (zr->JPEG_error == 1) {
+               zoran_restart(zr);
+               return;
+       }
+
+       /*
+        * First entry: error just happened during normal operation
+        *
+        * In BUZ_MODE_MOTION_COMPRESS:
+        *
+        * Possible glitch in TV signal. In this case we should
+        * stop the codec and wait for good quality signal before
+        * restarting it to avoid further problems
+        *
+        * In BUZ_MODE_MOTION_DECOMPRESS:
+        *
+        * Bad JPEG frame: we have to mark it as processed (codec crashed
+        * and was not able to do it itself), and to remove it from queue.
+        */
+       btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
+       udelay(1);
+       stat = stat | (post_office_read(zr, 7, 0) & 3) << 8;
+       btwrite(0, ZR36057_JPC);
+       btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
+       jpeg_codec_reset(zr);
+       jpeg_codec_sleep(zr, 1);
+       zr->JPEG_error = 1;
+       zr->num_errors++;
+
+       /* Report error */
+       if (zr36067_debug > 1 && zr->num_errors <= 8) {
+               long frame;
+               int j;
+
+               frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
+               printk(KERN_ERR
+                      "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
+                      ZR_DEVNAME(zr), stat, zr->last_isr,
+                      zr->jpg_que_tail, zr->jpg_dma_tail,
+                      zr->jpg_dma_head, zr->jpg_que_head,
+                      zr->jpg_seq_num, frame);
+               printk(KERN_INFO "stat_com frames:");
+               for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
+                       for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
+                               if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus)
+                                       printk(KERN_CONT "% d->%d", j, i);
+                       }
+               }
+               printk(KERN_CONT "\n");
+       }
+       /* Find an entry in stat_com and rotate contents */
+       if (zr->jpg_settings.TmpDcm == 1)
+               i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+       else
+               i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
+       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
+               /* Mimic zr36067 operation */
+               zr->stat_com[i] |= cpu_to_le32(1);
+               if (zr->jpg_settings.TmpDcm != 1)
+                       zr->stat_com[i + 1] |= cpu_to_le32(1);
+               /* Refill */
+               zoran_reap_stat_com(zr);
+               zoran_feed_stat_com(zr);
+               wake_up_interruptible(&zr->jpg_capq);
+               /* Find an entry in stat_com again after refill */
+               if (zr->jpg_settings.TmpDcm == 1)
+                       i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
+               else
+                       i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
+       }
+       if (i) {
+               /* Rotate stat_comm entries to make current entry first */
+               int j;
+               __le32 bus_addr[BUZ_NUM_STAT_COM];
+
+               /* Here we are copying the stat_com array, which
+                * is already in little endian format, so
+                * no endian conversions here
+                */
+               memcpy(bus_addr, zr->stat_com, sizeof(bus_addr));
+
+               for (j = 0; j < BUZ_NUM_STAT_COM; j++)
+                       zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM];
+
+               zr->jpg_err_shift += i;
+               zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
+       }
+       if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
+               zr->jpg_err_seq = zr->jpg_seq_num;      /* + 1; */
+       zoran_restart(zr);
+}
+
+irqreturn_t
+zoran_irq (int             irq,
+          void           *dev_id)
+{
+       u32 stat, astat;
+       int count;
+       struct zoran *zr;
+       unsigned long flags;
+
+       zr = dev_id;
+       count = 0;
+
+       if (zr->testing) {
+               /* Testing interrupts */
+               spin_lock_irqsave(&zr->spinlock, flags);
+               while ((stat = count_reset_interrupt(zr))) {
+                       if (count++ > 100) {
+                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: IRQ lockup while testing, isr=0x%08x, cleared int mask\n",
+                                       ZR_DEVNAME(zr), stat);
+                               wake_up_interruptible(&zr->test_q);
+                       }
+               }
+               zr->last_isr = stat;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+               return IRQ_HANDLED;
+       }
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+       while (1) {
+               /* get/clear interrupt status bits */
+               stat = count_reset_interrupt(zr);
+               astat = stat & IRQ_MASK;
+               if (!astat) {
+                       break;
+               }
+               dprintk(4,
+                       KERN_DEBUG
+                       "zoran_irq: astat: 0x%08x, mask: 0x%08x\n",
+                       astat, btread(ZR36057_ICR));
+               if (astat & zr->card.vsync_int) {       // SW
+
+                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+                           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+                               /* count missed interrupts */
+                               zr->JPEG_missed++;
+                       }
+                       //post_office_read(zr,1,0);
+                       /* Interrupts may still happen when
+                        * zr->v4l_memgrab_active is switched off.
+                        * We simply ignore them */
+
+                       if (zr->v4l_memgrab_active) {
+                               /* A lot more checks should be here ... */
+                               if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0)
+                                       dprintk(1,
+                                               KERN_WARNING
+                                               "%s: BuzIRQ with SnapShot off ???\n",
+                                               ZR_DEVNAME(zr));
+
+                               if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) {
+                                       /* There is a grab on a frame going on, check if it has finished */
+                                       if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) {
+                                               /* it is finished, notify the user */
+
+                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE;
+                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq;
+                                               do_gettimeofday(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp);
+                                               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
+                                               zr->v4l_pend_tail++;
+                                       }
+                               }
+
+                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE)
+                                       wake_up_interruptible(&zr->v4l_capq);
+
+                               /* Check if there is another grab queued */
+
+                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE &&
+                                   zr->v4l_pend_tail != zr->v4l_pend_head) {
+                                       int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME];
+                                       u32 reg;
+
+                                       zr->v4l_grab_frame = frame;
+
+                                       /* Set zr36057 video front end and enable video */
+
+                                       /* Buffer address */
+
+                                       reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus;
+                                       btwrite(reg, ZR36057_VDTR);
+                                       if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
+                                               reg += zr->v4l_settings.bytesperline;
+                                       btwrite(reg, ZR36057_VDBR);
+
+                                       /* video stride, status, and frame grab register */
+                                       reg = 0;
+                                       if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
+                                               reg += zr->v4l_settings.bytesperline;
+                                       reg = (reg << ZR36057_VSSFGR_DispStride);
+                                       reg |= ZR36057_VSSFGR_VidOvf;
+                                       reg |= ZR36057_VSSFGR_SnapShot;
+                                       reg |= ZR36057_VSSFGR_FrameGrab;
+                                       btwrite(reg, ZR36057_VSSFGR);
+
+                                       btor(ZR36057_VDCR_VidEn,
+                                            ZR36057_VDCR);
+                               }
+                       }
+
+                       /* even if we don't grab, we do want to increment
+                        * the sequence counter to see lost frames */
+                       zr->v4l_grab_seq++;
+               }
+#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ)
+               if (astat & ZR36057_ISR_CodRepIRQ) {
+                       zr->intr_counter_CodRepIRQ++;
+                       IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n",
+                               ZR_DEVNAME(zr)));
+                       btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR);
+               }
+#endif                         /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */
+
+#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ)
+               if ((astat & ZR36057_ISR_JPEGRepIRQ) &&
+                   (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
+                    zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) {
+                       if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) {
+                               char sv[BUZ_NUM_STAT_COM + 1];
+                               int i;
+
+                               printk(KERN_INFO
+                                      "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
+                                      ZR_DEVNAME(zr), stat,
+                                      zr->jpg_settings.odd_even,
+                                      zr->jpg_settings.field_per_buff,
+                                      zr->JPEG_missed);
+
+                               for (i = 0; i < BUZ_NUM_STAT_COM; i++)
+                                       sv[i] = le32_to_cpu(zr->stat_com[i]) & 1 ? '1' : '0';
+                               sv[BUZ_NUM_STAT_COM] = 0;
+                               printk(KERN_INFO
+                                      "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n",
+                                      ZR_DEVNAME(zr), sv,
+                                      zr->jpg_que_tail,
+                                      zr->jpg_dma_tail,
+                                      zr->jpg_dma_head,
+                                      zr->jpg_que_head);
+                       } else {
+                               /* Get statistics */
+                               if (zr->JPEG_missed > zr->JPEG_max_missed)
+                                       zr->JPEG_max_missed = zr->JPEG_missed;
+                               if (zr->JPEG_missed < zr->JPEG_min_missed)
+                                       zr->JPEG_min_missed = zr->JPEG_missed;
+                       }
+
+                       if (zr36067_debug > 2 && zr->frame_num < 6) {
+                               int i;
+
+                               printk(KERN_INFO "%s: seq=%ld stat_com:",
+                                      ZR_DEVNAME(zr), zr->jpg_seq_num);
+                               for (i = 0; i < 4; i++) {
+                                       printk(KERN_CONT " %08x",
+                                              le32_to_cpu(zr->stat_com[i]));
+                               }
+                               printk(KERN_CONT "\n");
+                       }
+                       zr->frame_num++;
+                       zr->JPEG_missed = 0;
+                       zr->JPEG_error = 0;
+                       zoran_reap_stat_com(zr);
+                       zoran_feed_stat_com(zr);
+                       wake_up_interruptible(&zr->jpg_capq);
+               }
+#endif                         /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */
+
+               /* DATERR, too many fields missed, error processing */
+               if ((astat & zr->card.jpeg_int) ||
+                   zr->JPEG_missed > 25 ||
+                   zr->JPEG_error == 1 ||
+                   ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) &&
+                    (zr->frame_num && (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) {
+                       error_handler(zr, astat, stat);
+               }
+
+               count++;
+               if (count > 10) {
+                       dprintk(2, KERN_WARNING "%s: irq loop %d\n",
+                               ZR_DEVNAME(zr), count);
+                       if (count > 20) {
+                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
+                               dprintk(2,
+                                       KERN_ERR
+                                       "%s: IRQ lockup, cleared int mask\n",
+                                       ZR_DEVNAME(zr));
+                               break;
+                       }
+               }
+               zr->last_isr = stat;
+       }
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return IRQ_HANDLED;
+}
+
+void
+zoran_set_pci_master (struct zoran *zr,
+                     int           set_master)
+{
+       if (set_master) {
+               pci_set_master(zr->pci_dev);
+       } else {
+               u16 command;
+
+               pci_read_config_word(zr->pci_dev, PCI_COMMAND, &command);
+               command &= ~PCI_COMMAND_MASTER;
+               pci_write_config_word(zr->pci_dev, PCI_COMMAND, command);
+       }
+}
+
+void
+zoran_init_hardware (struct zoran *zr)
+{
+       /* Enable bus-mastering */
+       zoran_set_pci_master(zr, 1);
+
+       /* Initialize the board */
+       if (zr->card.init) {
+               zr->card.init(zr);
+       }
+
+       decoder_call(zr, core, init, 0);
+       decoder_call(zr, core, s_std, zr->norm);
+       decoder_call(zr, video, s_routing,
+               zr->card.input[zr->input].muxsel, 0, 0);
+
+       encoder_call(zr, core, init, 0);
+       encoder_call(zr, video, s_std_output, zr->norm);
+       encoder_call(zr, video, s_routing, 0, 0, 0);
+
+       /* toggle JPEG codec sleep to sync PLL */
+       jpeg_codec_sleep(zr, 1);
+       jpeg_codec_sleep(zr, 0);
+
+       /* set individual interrupt enables (without GIRQ1)
+        * but don't global enable until zoran_open() */
+
+       //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR);  // SW
+       // It looks like using only JPEGRepIRQEn is not always reliable,
+       // may be when JPEG codec crashes it won't generate IRQ? So,
+        /*CP*/                 //        btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM    WHY ? LP
+           zr36057_init_vfe(zr);
+
+       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+
+       btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts
+}
+
+void
+zr36057_restart (struct zoran *zr)
+{
+       btwrite(0, ZR36057_SPGPPCR);
+       mdelay(1);
+       btor(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR);
+       mdelay(1);
+
+       /* assert P_Reset */
+       btwrite(0, ZR36057_JPC);
+       /* set up GPIO direction - all output */
+       btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR);
+
+       /* set up GPIO pins and guest bus timing */
+       btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1);
+}
+
+/*
+ * initialize video front end
+ */
+
+static void
+zr36057_init_vfe (struct zoran *zr)
+{
+       u32 reg;
+
+       reg = btread(ZR36057_VFESPFR);
+       reg |= ZR36057_VFESPFR_LittleEndian;
+       reg &= ~ZR36057_VFESPFR_VCLKPol;
+       reg |= ZR36057_VFESPFR_ExtFl;
+       reg |= ZR36057_VFESPFR_TopField;
+       btwrite(reg, ZR36057_VFESPFR);
+       reg = btread(ZR36057_VDCR);
+       if (pci_pci_problems & PCIPCI_TRITON)
+               // || zr->revision < 1) // Revision 1 has also Triton support
+               reg &= ~ZR36057_VDCR_Triton;
+       else
+               reg |= ZR36057_VDCR_Triton;
+       btwrite(reg, ZR36057_VDCR);
+}
diff --git a/drivers/media/pci/zoran/zoran_device.h b/drivers/media/pci/zoran/zoran_device.h
new file mode 100644 (file)
index 0000000..07f2c23
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.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.
+ */
+
+#ifndef __ZORAN_DEVICE_H__
+#define __ZORAN_DEVICE_H__
+
+/* general purpose I/O */
+extern void GPIO(struct zoran *zr,
+                int bit,
+                unsigned int value);
+
+/* codec (or actually: guest bus) access */
+extern int post_office_wait(struct zoran *zr);
+extern int post_office_write(struct zoran *zr,
+                            unsigned guest,
+                            unsigned reg,
+                            unsigned value);
+extern int post_office_read(struct zoran *zr,
+                           unsigned guest,
+                           unsigned reg);
+
+extern void detect_guest_activity(struct zoran *zr);
+
+extern void jpeg_codec_sleep(struct zoran *zr,
+                            int sleep);
+extern int jpeg_codec_reset(struct zoran *zr);
+
+/* zr360x7 access to raw capture */
+extern void zr36057_overlay(struct zoran *zr,
+                           int on);
+extern void write_overlay_mask(struct zoran_fh *fh,
+                              struct v4l2_clip *vp,
+                              int count);
+extern void zr36057_set_memgrab(struct zoran *zr,
+                               int mode);
+extern int wait_grab_pending(struct zoran *zr);
+
+/* interrupts */
+extern void print_interrupts(struct zoran *zr);
+extern void clear_interrupt_counters(struct zoran *zr);
+extern irqreturn_t zoran_irq(int irq, void *dev_id);
+
+/* JPEG codec access */
+extern void jpeg_start(struct zoran *zr);
+extern void zr36057_enable_jpg(struct zoran *zr,
+                              enum zoran_codec_mode mode);
+extern void zoran_feed_stat_com(struct zoran *zr);
+
+/* general */
+extern void zoran_set_pci_master(struct zoran *zr,
+                                int set_master);
+extern void zoran_init_hardware(struct zoran *zr);
+extern void zr36057_restart(struct zoran *zr);
+
+extern const struct zoran_format zoran_formats[];
+
+extern int v4l_nbufs;
+extern int v4l_bufsize;
+extern int jpg_nbufs;
+extern int jpg_bufsize;
+extern int pass_through;
+
+/* i2c */
+#define decoder_call(zr, o, f, args...) \
+       v4l2_subdev_call(zr->decoder, o, f, ##args)
+#define encoder_call(zr, o, f, args...) \
+       v4l2_subdev_call(zr->encoder, o, f, ##args)
+
+#endif                         /* __ZORAN_DEVICE_H__ */
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
new file mode 100644 (file)
index 0000000..c6ccdeb
--- /dev/null
@@ -0,0 +1,3090 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
+ *
+ * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * Based on
+ *
+ * Miro DC10 driver
+ * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Iomega Buz driver version 1.0
+ * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
+ *
+ * buz.0.0.3
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * bttv - Bt848 frame grabber driver
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+ *                        & Marcus Metzler (mocm@thp.uni-koeln.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.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include <linux/spinlock.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "videocodec.h"
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+
+#include <linux/mutex.h>
+#include "zoran.h"
+#include "zoran_device.h"
+#include "zoran_card.h"
+
+
+const struct zoran_format zoran_formats[] = {
+       {
+               .name = "15-bit RGB LE",
+               .fourcc = V4L2_PIX_FMT_RGB555,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 15,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif|
+                          ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "15-bit RGB BE",
+               .fourcc = V4L2_PIX_FMT_RGB555X,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 15,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
+       }, {
+               .name = "16-bit RGB LE",
+               .fourcc = V4L2_PIX_FMT_RGB565,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif|
+                          ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "16-bit RGB BE",
+               .fourcc = V4L2_PIX_FMT_RGB565X,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
+       }, {
+               .name = "24-bit RGB",
+               .fourcc = V4L2_PIX_FMT_BGR24,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 24,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
+       }, {
+               .name = "32-bit RGB LE",
+               .fourcc = V4L2_PIX_FMT_BGR32,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 32,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "32-bit RGB BE",
+               .fourcc = V4L2_PIX_FMT_RGB32,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .depth = 32,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_RGB888,
+       }, {
+               .name = "4:2:2, packed, YUYV",
+               .fourcc = V4L2_PIX_FMT_YUYV,
+               .colorspace = V4L2_COLORSPACE_SMPTE170M,
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_YUV422,
+       }, {
+               .name = "4:2:2, packed, UYVY",
+               .fourcc = V4L2_PIX_FMT_UYVY,
+               .colorspace = V4L2_COLORSPACE_SMPTE170M,
+               .depth = 16,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_OVERLAY,
+               .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
+       }, {
+               .name = "Hardware-encoded Motion-JPEG",
+               .fourcc = V4L2_PIX_FMT_MJPEG,
+               .colorspace = V4L2_COLORSPACE_SMPTE170M,
+               .depth = 0,
+               .flags = ZORAN_FORMAT_CAPTURE |
+                        ZORAN_FORMAT_PLAYBACK |
+                        ZORAN_FORMAT_COMPRESSED,
+       }
+};
+#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
+
+       /* small helper function for calculating buffersizes for v4l2
+        * we calculate the nearest higher power-of-two, which
+        * will be the recommended buffersize */
+static __u32
+zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
+{
+       __u8 div = settings->VerDcm * settings->HorDcm * settings->TmpDcm;
+       __u32 num = (1024 * 512) / (div);
+       __u32 result = 2;
+
+       num--;
+       while (num) {
+               num >>= 1;
+               result <<= 1;
+       }
+
+       if (result > jpg_bufsize)
+               return jpg_bufsize;
+       if (result < 8192)
+               return 8192;
+       return result;
+}
+
+/* forward references */
+static void v4l_fbuffer_free(struct zoran_fh *fh);
+static void jpg_fbuffer_free(struct zoran_fh *fh);
+
+/* Set mapping mode */
+static void map_mode_raw(struct zoran_fh *fh)
+{
+       fh->map_mode = ZORAN_MAP_MODE_RAW;
+       fh->buffers.buffer_size = v4l_bufsize;
+       fh->buffers.num_buffers = v4l_nbufs;
+}
+static void map_mode_jpg(struct zoran_fh *fh, int play)
+{
+       fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC;
+       fh->buffers.buffer_size = jpg_bufsize;
+       fh->buffers.num_buffers = jpg_nbufs;
+}
+static inline const char *mode_name(enum zoran_map_mode mode)
+{
+       return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG";
+}
+
+/*
+ *   Allocate the V4L grab buffers
+ *
+ *   These have to be pysically contiguous.
+ */
+
+static int v4l_fbuffer_alloc(struct zoran_fh *fh)
+{
+       struct zoran *zr = fh->zr;
+       int i, off;
+       unsigned char *mem;
+
+       for (i = 0; i < fh->buffers.num_buffers; i++) {
+               if (fh->buffers.buffer[i].v4l.fbuffer)
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: %s - buffer %d already allocated!?\n",
+                               ZR_DEVNAME(zr), __func__, i);
+
+               //udelay(20);
+               mem = kmalloc(fh->buffers.buffer_size,
+                             GFP_KERNEL | __GFP_NOWARN);
+               if (!mem) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - kmalloc for V4L buf %d failed\n",
+                               ZR_DEVNAME(zr), __func__, i);
+                       v4l_fbuffer_free(fh);
+                       return -ENOBUFS;
+               }
+               fh->buffers.buffer[i].v4l.fbuffer = mem;
+               fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
+               fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
+               for (off = 0; off < fh->buffers.buffer_size;
+                    off += PAGE_SIZE)
+                       SetPageReserved(virt_to_page(mem + off));
+               dprintk(4,
+                       KERN_INFO
+                       "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%llx)\n",
+                       ZR_DEVNAME(zr), __func__, i, (unsigned long) mem,
+                       (unsigned long long)virt_to_bus(mem));
+       }
+
+       fh->buffers.allocated = 1;
+
+       return 0;
+}
+
+/* free the V4L grab buffers */
+static void v4l_fbuffer_free(struct zoran_fh *fh)
+{
+       struct zoran *zr = fh->zr;
+       int i, off;
+       unsigned char *mem;
+
+       dprintk(4, KERN_INFO "%s: %s\n", ZR_DEVNAME(zr), __func__);
+
+       for (i = 0; i < fh->buffers.num_buffers; i++) {
+               if (!fh->buffers.buffer[i].v4l.fbuffer)
+                       continue;
+
+               mem = fh->buffers.buffer[i].v4l.fbuffer;
+               for (off = 0; off < fh->buffers.buffer_size;
+                    off += PAGE_SIZE)
+                       ClearPageReserved(virt_to_page(mem + off));
+               kfree(fh->buffers.buffer[i].v4l.fbuffer);
+               fh->buffers.buffer[i].v4l.fbuffer = NULL;
+       }
+
+       fh->buffers.allocated = 0;
+}
+
+/*
+ *   Allocate the MJPEG grab buffers.
+ *
+ *   If a Natoma chipset is present and this is a revision 1 zr36057,
+ *   each MJPEG buffer needs to be physically contiguous.
+ *   (RJ: This statement is from Dave Perks' original driver,
+ *   I could never check it because I have a zr36067)
+ *
+ *   RJ: The contents grab buffers needs never be accessed in the driver.
+ *       Therefore there is no need to allocate them with vmalloc in order
+ *       to get a contiguous virtual memory space.
+ *       I don't understand why many other drivers first allocate them with
+ *       vmalloc (which uses internally also get_zeroed_page, but delivers you
+ *       virtual addresses) and then again have to make a lot of efforts
+ *       to get the physical address.
+ *
+ *   Ben Capper:
+ *       On big-endian architectures (such as ppc) some extra steps
+ *       are needed. When reading and writing to the stat_com array
+ *       and fragment buffers, the device expects to see little-
+ *       endian values. The use of cpu_to_le32() and le32_to_cpu()
+ *       in this function (and one or two others in zoran_device.c)
+ *       ensure that these values are always stored in little-endian
+ *       form, regardless of architecture. The zr36057 does Very Bad
+ *       Things on big endian architectures if the stat_com array
+ *       and fragment buffers are not little-endian.
+ */
+
+static int jpg_fbuffer_alloc(struct zoran_fh *fh)
+{
+       struct zoran *zr = fh->zr;
+       int i, j, off;
+       u8 *mem;
+
+       for (i = 0; i < fh->buffers.num_buffers; i++) {
+               if (fh->buffers.buffer[i].jpg.frag_tab)
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: %s - buffer %d already allocated!?\n",
+                               ZR_DEVNAME(zr), __func__, i);
+
+               /* Allocate fragment table for this buffer */
+
+               mem = (void *)get_zeroed_page(GFP_KERNEL);
+               if (!mem) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n",
+                               ZR_DEVNAME(zr), __func__, i);
+                       jpg_fbuffer_free(fh);
+                       return -ENOBUFS;
+               }
+               fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem;
+               fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem);
+
+               if (fh->buffers.need_contiguous) {
+                       mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL);
+                       if (mem == NULL) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: %s - kmalloc failed for buffer %d\n",
+                                       ZR_DEVNAME(zr), __func__, i);
+                               jpg_fbuffer_free(fh);
+                               return -ENOBUFS;
+                       }
+                       fh->buffers.buffer[i].jpg.frag_tab[0] =
+                               cpu_to_le32(virt_to_bus(mem));
+                       fh->buffers.buffer[i].jpg.frag_tab[1] =
+                               cpu_to_le32((fh->buffers.buffer_size >> 1) | 1);
+                       for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
+                               SetPageReserved(virt_to_page(mem + off));
+               } else {
+                       /* jpg_bufsize is already page aligned */
+                       for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
+                               mem = (void *)get_zeroed_page(GFP_KERNEL);
+                               if (mem == NULL) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: %s - get_zeroed_page failed for buffer %d\n",
+                                               ZR_DEVNAME(zr), __func__, i);
+                                       jpg_fbuffer_free(fh);
+                                       return -ENOBUFS;
+                               }
+
+                               fh->buffers.buffer[i].jpg.frag_tab[2 * j] =
+                                       cpu_to_le32(virt_to_bus(mem));
+                               fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] =
+                                       cpu_to_le32((PAGE_SIZE >> 2) << 1);
+                               SetPageReserved(virt_to_page(mem));
+                       }
+
+                       fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1);
+               }
+       }
+
+       dprintk(4,
+               KERN_DEBUG "%s: %s - %d KB allocated\n",
+               ZR_DEVNAME(zr), __func__,
+               (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10);
+
+       fh->buffers.allocated = 1;
+
+       return 0;
+}
+
+/* free the MJPEG grab buffers */
+static void jpg_fbuffer_free(struct zoran_fh *fh)
+{
+       struct zoran *zr = fh->zr;
+       int i, j, off;
+       unsigned char *mem;
+       __le32 frag_tab;
+       struct zoran_buffer *buffer;
+
+       dprintk(4, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
+
+       for (i = 0, buffer = &fh->buffers.buffer[0];
+            i < fh->buffers.num_buffers; i++, buffer++) {
+               if (!buffer->jpg.frag_tab)
+                       continue;
+
+               if (fh->buffers.need_contiguous) {
+                       frag_tab = buffer->jpg.frag_tab[0];
+
+                       if (frag_tab) {
+                               mem = bus_to_virt(le32_to_cpu(frag_tab));
+                               for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
+                                       ClearPageReserved(virt_to_page(mem + off));
+                               kfree(mem);
+                               buffer->jpg.frag_tab[0] = 0;
+                               buffer->jpg.frag_tab[1] = 0;
+                       }
+               } else {
+                       for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
+                               frag_tab = buffer->jpg.frag_tab[2 * j];
+
+                               if (!frag_tab)
+                                       break;
+                               ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab))));
+                               free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab)));
+                               buffer->jpg.frag_tab[2 * j] = 0;
+                               buffer->jpg.frag_tab[2 * j + 1] = 0;
+                       }
+               }
+
+               free_page((unsigned long)buffer->jpg.frag_tab);
+               buffer->jpg.frag_tab = NULL;
+       }
+
+       fh->buffers.allocated = 0;
+}
+
+/*
+ *   V4L Buffer grabbing
+ */
+
+static int
+zoran_v4l_set_format (struct zoran_fh           *fh,
+                     int                        width,
+                     int                        height,
+                     const struct zoran_format *format)
+{
+       struct zoran *zr = fh->zr;
+       int bpp;
+
+       /* Check size and format of the grab wanted */
+
+       if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
+           height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - wrong frame size (%dx%d)\n",
+                       ZR_DEVNAME(zr), __func__, width, height);
+               return -EINVAL;
+       }
+
+       bpp = (format->depth + 7) / 8;
+
+       /* Check against available buffer size */
+       if (height * width * bpp > fh->buffers.buffer_size) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - video buffer size (%d kB) is too small\n",
+                       ZR_DEVNAME(zr), __func__, fh->buffers.buffer_size >> 10);
+               return -EINVAL;
+       }
+
+       /* The video front end needs 4-byte alinged line sizes */
+
+       if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - wrong frame alignment\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       fh->v4l_settings.width = width;
+       fh->v4l_settings.height = height;
+       fh->v4l_settings.format = format;
+       fh->v4l_settings.bytesperline = bpp * fh->v4l_settings.width;
+
+       return 0;
+}
+
+static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num)
+{
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+       int res = 0;
+
+       if (!fh->buffers.allocated) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - buffers not yet allocated\n",
+                       ZR_DEVNAME(zr), __func__);
+               res = -ENOMEM;
+       }
+
+       /* No grabbing outside the buffer range! */
+       if (num >= fh->buffers.num_buffers || num < 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - buffer %d is out of range\n",
+                       ZR_DEVNAME(zr), __func__, num);
+               res = -EINVAL;
+       }
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       if (fh->buffers.active == ZORAN_FREE) {
+               if (zr->v4l_buffers.active == ZORAN_FREE) {
+                       zr->v4l_buffers = fh->buffers;
+                       fh->buffers.active = ZORAN_ACTIVE;
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - another session is already capturing\n",
+                               ZR_DEVNAME(zr), __func__);
+                       res = -EBUSY;
+               }
+       }
+
+       /* make sure a grab isn't going on currently with this buffer */
+       if (!res) {
+               switch (zr->v4l_buffers.buffer[num].state) {
+               default:
+               case BUZ_STATE_PEND:
+                       if (zr->v4l_buffers.active == ZORAN_FREE) {
+                               fh->buffers.active = ZORAN_FREE;
+                               zr->v4l_buffers.allocated = 0;
+                       }
+                       res = -EBUSY;   /* what are you doing? */
+                       break;
+               case BUZ_STATE_DONE:
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: %s - queueing buffer %d in state DONE!?\n",
+                               ZR_DEVNAME(zr), __func__, num);
+               case BUZ_STATE_USER:
+                       /* since there is at least one unused buffer there's room for at least
+                        * one more pend[] entry */
+                       zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num;
+                       zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
+                       zr->v4l_buffers.buffer[num].bs.length =
+                           fh->v4l_settings.bytesperline *
+                           zr->v4l_settings.height;
+                       fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num];
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       if (!res && zr->v4l_buffers.active == ZORAN_FREE)
+               zr->v4l_buffers.active = fh->buffers.active;
+
+       return res;
+}
+
+/*
+ * Sync on a V4L buffer
+ */
+
+static int v4l_sync(struct zoran_fh *fh, int frame)
+{
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+
+       if (fh->buffers.active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - no grab active for this session\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       /* check passed-in frame number */
+       if (frame >= fh->buffers.num_buffers || frame < 0) {
+               dprintk(1,
+                       KERN_ERR "%s: %s - frame %d is invalid\n",
+                       ZR_DEVNAME(zr), __func__, frame);
+               return -EINVAL;
+       }
+
+       /* Check if is buffer was queued at all */
+       if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - attempt to sync on a buffer which was not queued?\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EPROTO;
+       }
+
+       /* wait on this buffer to get ready */
+       if (!wait_event_interruptible_timeout(zr->v4l_capq,
+               (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ))
+               return -ETIME;
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
+       /* buffer should now be in BUZ_STATE_DONE */
+       if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
+               dprintk(2,
+                       KERN_ERR "%s: %s - internal state error\n",
+                       ZR_DEVNAME(zr), __func__);
+
+       zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
+       fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       /* Check if streaming capture has finished */
+       if (zr->v4l_pend_tail == zr->v4l_pend_head) {
+               zr36057_set_memgrab(zr, 0);
+               if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
+                       fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE;
+                       zr->v4l_buffers.allocated = 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return 0;
+}
+
+/*
+ *   Queue a MJPEG buffer for capture/playback
+ */
+
+static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num,
+                                enum zoran_codec_mode mode)
+{
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+       int res = 0;
+
+       /* Check if buffers are allocated */
+       if (!fh->buffers.allocated) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - buffers not yet allocated\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -ENOMEM;
+       }
+
+       /* No grabbing outside the buffer range! */
+       if (num >= fh->buffers.num_buffers || num < 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - buffer %d out of range\n",
+                       ZR_DEVNAME(zr), __func__, num);
+               return -EINVAL;
+       }
+
+       /* what is the codec mode right now? */
+       if (zr->codec_mode == BUZ_MODE_IDLE) {
+               zr->jpg_settings = fh->jpg_settings;
+       } else if (zr->codec_mode != mode) {
+               /* wrong codec mode active - invalid */
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - codec in wrong mode\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       if (fh->buffers.active == ZORAN_FREE) {
+               if (zr->jpg_buffers.active == ZORAN_FREE) {
+                       zr->jpg_buffers = fh->buffers;
+                       fh->buffers.active = ZORAN_ACTIVE;
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - another session is already capturing\n",
+                               ZR_DEVNAME(zr), __func__);
+                       res = -EBUSY;
+               }
+       }
+
+       if (!res && zr->codec_mode == BUZ_MODE_IDLE) {
+               /* Ok load up the jpeg codec */
+               zr36057_enable_jpg(zr, mode);
+       }
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       if (!res) {
+               switch (zr->jpg_buffers.buffer[num].state) {
+               case BUZ_STATE_DONE:
+                       dprintk(2,
+                               KERN_WARNING
+                               "%s: %s - queing frame in BUZ_STATE_DONE state!?\n",
+                               ZR_DEVNAME(zr), __func__);
+               case BUZ_STATE_USER:
+                       /* since there is at least one unused buffer there's room for at
+                        *least one more pend[] entry */
+                       zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num;
+                       zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
+                       fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num];
+                       zoran_feed_stat_com(zr);
+                       break;
+               default:
+               case BUZ_STATE_DMA:
+               case BUZ_STATE_PEND:
+                       if (zr->jpg_buffers.active == ZORAN_FREE) {
+                               fh->buffers.active = ZORAN_FREE;
+                               zr->jpg_buffers.allocated = 0;
+                       }
+                       res = -EBUSY;   /* what are you doing? */
+                       break;
+               }
+       }
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       if (!res && zr->jpg_buffers.active == ZORAN_FREE)
+               zr->jpg_buffers.active = fh->buffers.active;
+
+       return res;
+}
+
+static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode)
+{
+       struct zoran *zr = fh->zr;
+       int res = 0;
+
+       /* Does the user want to stop streaming? */
+       if (frame < 0) {
+               if (zr->codec_mode == mode) {
+                       if (fh->buffers.active == ZORAN_FREE) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: %s(-1) - session not active\n",
+                                       ZR_DEVNAME(zr), __func__);
+                               return -EINVAL;
+                       }
+                       fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE;
+                       zr->jpg_buffers.allocated = 0;
+                       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+                       return 0;
+               } else {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - stop streaming but not in streaming mode\n",
+                               ZR_DEVNAME(zr), __func__);
+                       return -EINVAL;
+               }
+       }
+
+       if ((res = zoran_jpg_queue_frame(fh, frame, mode)))
+               return res;
+
+       /* Start the jpeg codec when the first frame is queued  */
+       if (!res && zr->jpg_que_head == 1)
+               jpeg_start(zr);
+
+       return res;
+}
+
+/*
+ *   Sync on a MJPEG buffer
+ */
+
+static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
+{
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+       int frame;
+
+       if (fh->buffers.active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - capture is not currently active\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+       if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
+           zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - codec not in streaming mode\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+       if (!wait_event_interruptible_timeout(zr->jpg_capq,
+                       (zr->jpg_que_tail != zr->jpg_dma_tail ||
+                        zr->jpg_dma_tail == zr->jpg_dma_head),
+                       10*HZ)) {
+               int isr;
+
+               btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
+               udelay(1);
+               zr->codec->control(zr->codec, CODEC_G_STATUS,
+                                          sizeof(isr), &isr);
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - timeout: codec isr=0x%02x\n",
+                       ZR_DEVNAME(zr), __func__, isr);
+
+               return -ETIME;
+
+       }
+       if (signal_pending(current))
+               return -ERESTARTSYS;
+
+       spin_lock_irqsave(&zr->spinlock, flags);
+
+       if (zr->jpg_dma_tail != zr->jpg_dma_head)
+               frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME];
+       else
+               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
+
+       /* buffer should now be in BUZ_STATE_DONE */
+       if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
+               dprintk(2,
+                       KERN_ERR "%s: %s - internal state error\n",
+                       ZR_DEVNAME(zr), __func__);
+
+       *bs = zr->jpg_buffers.buffer[frame].bs;
+       bs->frame = frame;
+       zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
+       fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
+
+       spin_unlock_irqrestore(&zr->spinlock, flags);
+
+       return 0;
+}
+
+static void zoran_open_init_session(struct zoran_fh *fh)
+{
+       int i;
+       struct zoran *zr = fh->zr;
+
+       /* Per default, map the V4L Buffers */
+       map_mode_raw(fh);
+
+       /* take over the card's current settings */
+       fh->overlay_settings = zr->overlay_settings;
+       fh->overlay_settings.is_set = 0;
+       fh->overlay_settings.format = zr->overlay_settings.format;
+       fh->overlay_active = ZORAN_FREE;
+
+       /* v4l settings */
+       fh->v4l_settings = zr->v4l_settings;
+       /* jpg settings */
+       fh->jpg_settings = zr->jpg_settings;
+
+       /* buffers */
+       memset(&fh->buffers, 0, sizeof(fh->buffers));
+       for (i = 0; i < MAX_FRAME; i++) {
+               fh->buffers.buffer[i].state = BUZ_STATE_USER;   /* nothing going on */
+               fh->buffers.buffer[i].bs.frame = i;
+       }
+       fh->buffers.allocated = 0;
+       fh->buffers.active = ZORAN_FREE;
+}
+
+static void zoran_close_end_session(struct zoran_fh *fh)
+{
+       struct zoran *zr = fh->zr;
+
+       /* overlay */
+       if (fh->overlay_active != ZORAN_FREE) {
+               fh->overlay_active = zr->overlay_active = ZORAN_FREE;
+               zr->v4l_overlay_active = 0;
+               if (!zr->v4l_memgrab_active)
+                       zr36057_overlay(zr, 0);
+               zr->overlay_mask = NULL;
+       }
+
+       if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+               /* v4l capture */
+               if (fh->buffers.active != ZORAN_FREE) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&zr->spinlock, flags);
+                       zr36057_set_memgrab(zr, 0);
+                       zr->v4l_buffers.allocated = 0;
+                       zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+                       spin_unlock_irqrestore(&zr->spinlock, flags);
+               }
+
+               /* v4l buffers */
+               if (fh->buffers.allocated)
+                       v4l_fbuffer_free(fh);
+       } else {
+               /* jpg capture */
+               if (fh->buffers.active != ZORAN_FREE) {
+                       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+                       zr->jpg_buffers.allocated = 0;
+                       zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
+               }
+
+               /* jpg buffers */
+               if (fh->buffers.allocated)
+                       jpg_fbuffer_free(fh);
+       }
+}
+
+/*
+ *   Open a zoran card. Right now the flags stuff is just playing
+ */
+
+static int zoran_open(struct file *file)
+{
+       struct zoran *zr = video_drvdata(file);
+       struct zoran_fh *fh;
+       int res, first_open = 0;
+
+       dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n",
+               ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1);
+
+       mutex_lock(&zr->other_lock);
+
+       if (zr->user >= 2048) {
+               dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
+                       ZR_DEVNAME(zr), zr->user);
+               res = -EBUSY;
+               goto fail_unlock;
+       }
+
+       /* now, create the open()-specific file_ops struct */
+       fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
+       if (!fh) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - allocation of zoran_fh failed\n",
+                       ZR_DEVNAME(zr), __func__);
+               res = -ENOMEM;
+               goto fail_unlock;
+       }
+       /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
+        * on norm-change! */
+       fh->overlay_mask =
+           kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
+       if (!fh->overlay_mask) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - allocation of overlay_mask failed\n",
+                       ZR_DEVNAME(zr), __func__);
+               res = -ENOMEM;
+               goto fail_fh;
+       }
+
+       if (zr->user++ == 0)
+               first_open = 1;
+
+       /*mutex_unlock(&zr->resource_lock);*/
+
+       /* default setup - TODO: look at flags */
+       if (first_open) {       /* First device open */
+               zr36057_restart(zr);
+               zoran_open_init_params(zr);
+               zoran_init_hardware(zr);
+
+               btor(ZR36057_ICR_IntPinEn, ZR36057_ICR);
+       }
+
+       /* set file_ops stuff */
+       file->private_data = fh;
+       fh->zr = zr;
+       zoran_open_init_session(fh);
+       mutex_unlock(&zr->other_lock);
+
+       return 0;
+
+fail_fh:
+       kfree(fh);
+fail_unlock:
+       mutex_unlock(&zr->other_lock);
+
+       dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n",
+               ZR_DEVNAME(zr), res, zr->user);
+
+       return res;
+}
+
+static int
+zoran_close(struct file  *file)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+
+       dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(+)=%d\n",
+               ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user - 1);
+
+       /* kernel locks (fs/device.c), so don't do that ourselves
+        * (prevents deadlocks) */
+       mutex_lock(&zr->other_lock);
+
+       zoran_close_end_session(fh);
+
+       if (zr->user-- == 1) {  /* Last process */
+               /* Clean up JPEG process */
+               wake_up_interruptible(&zr->jpg_capq);
+               zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
+               zr->jpg_buffers.allocated = 0;
+               zr->jpg_buffers.active = ZORAN_FREE;
+
+               /* disable interrupts */
+               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
+
+               if (zr36067_debug > 1)
+                       print_interrupts(zr);
+
+               /* Overlay off */
+               zr->v4l_overlay_active = 0;
+               zr36057_overlay(zr, 0);
+               zr->overlay_mask = NULL;
+
+               /* capture off */
+               wake_up_interruptible(&zr->v4l_capq);
+               zr36057_set_memgrab(zr, 0);
+               zr->v4l_buffers.allocated = 0;
+               zr->v4l_buffers.active = ZORAN_FREE;
+               zoran_set_pci_master(zr, 0);
+
+               if (!pass_through) {    /* Switch to color bar */
+                       decoder_call(zr, video, s_stream, 0);
+                       encoder_call(zr, video, s_routing, 2, 0, 0);
+               }
+       }
+       mutex_unlock(&zr->other_lock);
+
+       file->private_data = NULL;
+       kfree(fh->overlay_mask);
+       kfree(fh);
+
+       dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__);
+
+       return 0;
+}
+
+
+static ssize_t
+zoran_read (struct file *file,
+           char        __user *data,
+           size_t       count,
+           loff_t      *ppos)
+{
+       /* we simply don't support read() (yet)... */
+
+       return -EINVAL;
+}
+
+static ssize_t
+zoran_write (struct file *file,
+            const char  __user *data,
+            size_t       count,
+            loff_t      *ppos)
+{
+       /* ...and the same goes for write() */
+
+       return -EINVAL;
+}
+
+static int setup_fbuffer(struct zoran_fh *fh,
+              void                      *base,
+              const struct zoran_format *fmt,
+              int                        width,
+              int                        height,
+              int                        bytesperline)
+{
+       struct zoran *zr = fh->zr;
+
+       /* (Ronald) v4l/v4l2 guidelines */
+       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+               return -EPERM;
+
+       /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on
+          ALi Magik (that needs very low latency while the card needs a
+          higher value always) */
+
+       if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
+               return -ENXIO;
+
+       /* we need a bytesperline value, even if not given */
+       if (!bytesperline)
+               bytesperline = width * ((fmt->depth + 7) & ~7) / 8;
+
+#if 0
+       if (zr->overlay_active) {
+               /* dzjee... stupid users... don't even bother to turn off
+                * overlay before changing the memory location...
+                * normally, we would return errors here. However, one of
+                * the tools that does this is... xawtv! and since xawtv
+                * is used by +/- 99% of the users, we'd rather be user-
+                * friendly and silently do as if nothing went wrong */
+               dprintk(3,
+                       KERN_ERR
+                       "%s: %s - forced overlay turnoff because framebuffer changed\n",
+                       ZR_DEVNAME(zr), __func__);
+               zr36057_overlay(zr, 0);
+       }
+#endif
+
+       if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - no valid overlay format given\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+       if (height <= 0 || width <= 0 || bytesperline <= 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - invalid height/width/bpl value (%d|%d|%d)\n",
+                       ZR_DEVNAME(zr), __func__, width, height, bytesperline);
+               return -EINVAL;
+       }
+       if (bytesperline & 3) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - bytesperline (%d) must be 4-byte aligned\n",
+                       ZR_DEVNAME(zr), __func__, bytesperline);
+               return -EINVAL;
+       }
+
+       zr->vbuf_base = (void *) ((unsigned long) base & ~3);
+       zr->vbuf_height = height;
+       zr->vbuf_width = width;
+       zr->vbuf_depth = fmt->depth;
+       zr->overlay_settings.format = fmt;
+       zr->vbuf_bytesperline = bytesperline;
+
+       /* The user should set new window parameters */
+       zr->overlay_settings.is_set = 0;
+
+       return 0;
+}
+
+
+static int setup_window(struct zoran_fh *fh,
+                       int x,
+                       int y,
+                       int width,
+                       int height,
+                       struct v4l2_clip __user *clips,
+                       unsigned int clipcount,
+                       void __user *bitmap)
+{
+       struct zoran *zr = fh->zr;
+       struct v4l2_clip *vcp = NULL;
+       int on, end;
+
+
+       if (!zr->vbuf_base) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - frame buffer has to be set first\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       if (!fh->overlay_settings.format) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - no overlay format set\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       if (clipcount > 2048) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - invalid clipcount\n",
+                        ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       /*
+        * The video front end needs 4-byte alinged line sizes, we correct that
+        * silently here if necessary
+        */
+       if (zr->vbuf_depth == 15 || zr->vbuf_depth == 16) {
+               end = (x + width) & ~1; /* round down */
+               x = (x + 1) & ~1;       /* round up */
+               width = end - x;
+       }
+
+       if (zr->vbuf_depth == 24) {
+               end = (x + width) & ~3; /* round down */
+               x = (x + 3) & ~3;       /* round up */
+               width = end - x;
+       }
+
+       if (width > BUZ_MAX_WIDTH)
+               width = BUZ_MAX_WIDTH;
+       if (height > BUZ_MAX_HEIGHT)
+               height = BUZ_MAX_HEIGHT;
+
+       /* Check for invalid parameters */
+       if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||
+           width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - width = %d or height = %d invalid\n",
+                       ZR_DEVNAME(zr), __func__, width, height);
+               return -EINVAL;
+       }
+
+       fh->overlay_settings.x = x;
+       fh->overlay_settings.y = y;
+       fh->overlay_settings.width = width;
+       fh->overlay_settings.height = height;
+       fh->overlay_settings.clipcount = clipcount;
+
+       /*
+        * If an overlay is running, we have to switch it off
+        * and switch it on again in order to get the new settings in effect.
+        *
+        * We also want to avoid that the overlay mask is written
+        * when an overlay is running.
+        */
+
+       on = zr->v4l_overlay_active && !zr->v4l_memgrab_active &&
+           zr->overlay_active != ZORAN_FREE &&
+           fh->overlay_active != ZORAN_FREE;
+       if (on)
+               zr36057_overlay(zr, 0);
+
+       /*
+        *   Write the overlay mask if clips are wanted.
+        *   We prefer a bitmap.
+        */
+       if (bitmap) {
+               /* fake value - it just means we want clips */
+               fh->overlay_settings.clipcount = 1;
+
+               if (copy_from_user(fh->overlay_mask, bitmap,
+                                  (width * height + 7) / 8)) {
+                       return -EFAULT;
+               }
+       } else if (clipcount) {
+               /* write our own bitmap from the clips */
+               vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4));
+               if (vcp == NULL) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - Alloc of clip mask failed\n",
+                               ZR_DEVNAME(zr), __func__);
+                       return -ENOMEM;
+               }
+               if (copy_from_user
+                   (vcp, clips, sizeof(struct v4l2_clip) * clipcount)) {
+                       vfree(vcp);
+                       return -EFAULT;
+               }
+               write_overlay_mask(fh, vcp, clipcount);
+               vfree(vcp);
+       }
+
+       fh->overlay_settings.is_set = 1;
+       if (fh->overlay_active != ZORAN_FREE &&
+           zr->overlay_active != ZORAN_FREE)
+               zr->overlay_settings = fh->overlay_settings;
+
+       if (on)
+               zr36057_overlay(zr, 1);
+
+       /* Make sure the changes come into effect */
+       return wait_grab_pending(zr);
+}
+
+static int setup_overlay(struct zoran_fh *fh, int on)
+{
+       struct zoran *zr = fh->zr;
+
+       /* If there is nothing to do, return immediately */
+       if ((on && fh->overlay_active != ZORAN_FREE) ||
+           (!on && fh->overlay_active == ZORAN_FREE))
+               return 0;
+
+       /* check whether we're touching someone else's overlay */
+       if (on && zr->overlay_active != ZORAN_FREE &&
+           fh->overlay_active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - overlay is already active for another session\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EBUSY;
+       }
+       if (!on && zr->overlay_active != ZORAN_FREE &&
+           fh->overlay_active == ZORAN_FREE) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - you cannot cancel someone else's session\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EPERM;
+       }
+
+       if (on == 0) {
+               zr->overlay_active = fh->overlay_active = ZORAN_FREE;
+               zr->v4l_overlay_active = 0;
+               /* When a grab is running, the video simply
+                * won't be switched on any more */
+               if (!zr->v4l_memgrab_active)
+                       zr36057_overlay(zr, 0);
+               zr->overlay_mask = NULL;
+       } else {
+               if (!zr->vbuf_base || !fh->overlay_settings.is_set) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - buffer or window not set\n",
+                               ZR_DEVNAME(zr), __func__);
+                       return -EINVAL;
+               }
+               if (!fh->overlay_settings.format) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - no overlay format set\n",
+                               ZR_DEVNAME(zr), __func__);
+                       return -EINVAL;
+               }
+               zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
+               zr->v4l_overlay_active = 1;
+               zr->overlay_mask = fh->overlay_mask;
+               zr->overlay_settings = fh->overlay_settings;
+               if (!zr->v4l_memgrab_active)
+                       zr36057_overlay(zr, 1);
+               /* When a grab is running, the video will be
+                * switched on when grab is finished */
+       }
+
+       /* Make sure the changes come into effect */
+       return wait_grab_pending(zr);
+}
+
+/* get the status of a buffer in the clients buffer queue */
+static int zoran_v4l2_buffer_status(struct zoran_fh *fh,
+                                   struct v4l2_buffer *buf, int num)
+{
+       struct zoran *zr = fh->zr;
+       unsigned long flags;
+
+       buf->flags = V4L2_BUF_FLAG_MAPPED;
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:
+               /* check range */
+               if (num < 0 || num >= fh->buffers.num_buffers ||
+                   !fh->buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - wrong number or buffers not allocated\n",
+                               ZR_DEVNAME(zr), __func__);
+                       return -EINVAL;
+               }
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->buffers.active], num,
+                       "UPMD"[zr->v4l_buffers.buffer[num].state],
+                       fh->buffers.buffer[num].map ? 'Y' : 'N');
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
+               buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               buf->length = fh->buffers.buffer_size;
+
+               /* get buffer */
+               buf->bytesused = fh->buffers.buffer[num].bs.length;
+               if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
+                   fh->buffers.buffer[num].state == BUZ_STATE_USER) {
+                       buf->sequence = fh->buffers.buffer[num].bs.seq;
+                       buf->flags |= V4L2_BUF_FLAG_DONE;
+                       buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
+               } else {
+                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               }
+
+               if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2)
+                       buf->field = V4L2_FIELD_TOP;
+               else
+                       buf->field = V4L2_FIELD_INTERLACED;
+
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+
+               /* check range */
+               if (num < 0 || num >= fh->buffers.num_buffers ||
+                   !fh->buffers.allocated) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - wrong number or buffers not allocated\n",
+                               ZR_DEVNAME(zr), __func__);
+                       return -EINVAL;
+               }
+
+               buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
+                             V4L2_BUF_TYPE_VIDEO_CAPTURE :
+                             V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               buf->length = fh->buffers.buffer_size;
+
+               /* these variables are only written after frame has been captured */
+               if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
+                   fh->buffers.buffer[num].state == BUZ_STATE_USER) {
+                       buf->sequence = fh->buffers.buffer[num].bs.seq;
+                       buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
+                       buf->bytesused = fh->buffers.buffer[num].bs.length;
+                       buf->flags |= V4L2_BUF_FLAG_DONE;
+               } else {
+                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
+               }
+
+               /* which fields are these? */
+               if (fh->jpg_settings.TmpDcm != 1)
+                       buf->field = fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+               else
+                       buf->field = fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
+
+               break;
+
+       default:
+
+               dprintk(5,
+                       KERN_ERR
+                       "%s: %s - invalid buffer type|map_mode (%d|%d)\n",
+                       ZR_DEVNAME(zr), __func__, buf->type, fh->map_mode);
+               return -EINVAL;
+       }
+
+       buf->memory = V4L2_MEMORY_MMAP;
+       buf->index = num;
+       buf->m.offset = buf->length * num;
+
+       return 0;
+}
+
+static int
+zoran_set_norm (struct zoran *zr,
+               v4l2_std_id norm)
+{
+       int on;
+
+       if (zr->v4l_buffers.active != ZORAN_FREE ||
+           zr->jpg_buffers.active != ZORAN_FREE) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: %s called while in playback/capture mode\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EBUSY;
+       }
+
+       if (!(norm & zr->card.norms)) {
+               dprintk(1,
+                       KERN_ERR "%s: %s - unsupported norm %llx\n",
+                       ZR_DEVNAME(zr), __func__, norm);
+               return -EINVAL;
+       }
+
+       if (norm == V4L2_STD_ALL) {
+               unsigned int status = 0;
+               v4l2_std_id std = 0;
+
+               decoder_call(zr, video, querystd, &std);
+               decoder_call(zr, core, s_std, std);
+
+               /* let changes come into effect */
+               ssleep(2);
+
+               decoder_call(zr, video, g_input_status, &status);
+               if (status & V4L2_IN_ST_NO_SIGNAL) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s - no norm detected\n",
+                               ZR_DEVNAME(zr), __func__);
+                       /* reset norm */
+                       decoder_call(zr, core, s_std, zr->norm);
+                       return -EIO;
+               }
+
+               norm = std;
+       }
+       if (norm & V4L2_STD_SECAM)
+               zr->timing = zr->card.tvn[2];
+       else if (norm & V4L2_STD_NTSC)
+               zr->timing = zr->card.tvn[1];
+       else
+               zr->timing = zr->card.tvn[0];
+
+       /* We switch overlay off and on since a change in the
+        * norm needs different VFE settings */
+       on = zr->overlay_active && !zr->v4l_memgrab_active;
+       if (on)
+               zr36057_overlay(zr, 0);
+
+       decoder_call(zr, core, s_std, norm);
+       encoder_call(zr, video, s_std_output, norm);
+
+       if (on)
+               zr36057_overlay(zr, 1);
+
+       /* Make sure the changes come into effect */
+       zr->norm = norm;
+
+       return 0;
+}
+
+static int
+zoran_set_input (struct zoran *zr,
+                int           input)
+{
+       if (input == zr->input) {
+               return 0;
+       }
+
+       if (zr->v4l_buffers.active != ZORAN_FREE ||
+           zr->jpg_buffers.active != ZORAN_FREE) {
+               dprintk(1,
+                       KERN_WARNING
+                       "%s: %s called while in playback/capture mode\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EBUSY;
+       }
+
+       if (input < 0 || input >= zr->card.inputs) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - unnsupported input %d\n",
+                       ZR_DEVNAME(zr), __func__, input);
+               return -EINVAL;
+       }
+
+       zr->input = input;
+
+       decoder_call(zr, video, s_routing,
+                       zr->card.input[input].muxsel, 0, 0);
+
+       return 0;
+}
+
+/*
+ *   ioctl routine
+ */
+
+static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       memset(cap, 0, sizeof(*cap));
+       strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
+       strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
+                pci_name(zr->pci_dev));
+       cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
+                           V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
+       return 0;
+}
+
+static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
+{
+       unsigned int num, i;
+
+       for (num = i = 0; i < NUM_FORMATS; i++) {
+               if (zoran_formats[i].flags & flag && num++ == fmt->index) {
+                       strncpy(fmt->description, zoran_formats[i].name,
+                               sizeof(fmt->description) - 1);
+                       /* fmt struct pre-zeroed, so adding '\0' not needed */
+                       fmt->pixelformat = zoran_formats[i].fourcc;
+                       if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
+                               fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
+                                           struct v4l2_fmtdesc *f)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE);
+}
+
+static int zoran_enum_fmt_vid_out(struct file *file, void *__fh,
+                                           struct v4l2_fmtdesc *f)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK);
+}
+
+static int zoran_enum_fmt_vid_overlay(struct file *file, void *__fh,
+                                           struct v4l2_fmtdesc *f)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       return zoran_enum_fmt(zr, f, ZORAN_FORMAT_OVERLAY);
+}
+
+static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       mutex_lock(&zr->resource_lock);
+
+       fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm;
+       fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 /
+               (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm);
+       fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+       fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+       if (fh->jpg_settings.TmpDcm == 1)
+               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+       else
+               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+       fmt->fmt.pix.bytesperline = 0;
+       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       mutex_unlock(&zr->resource_lock);
+       return 0;
+}
+
+static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       if (fh->map_mode != ZORAN_MAP_MODE_RAW)
+               return zoran_g_fmt_vid_out(file, fh, fmt);
+
+       mutex_lock(&zr->resource_lock);
+       fmt->fmt.pix.width = fh->v4l_settings.width;
+       fmt->fmt.pix.height = fh->v4l_settings.height;
+       fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline *
+                                       fh->v4l_settings.height;
+       fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc;
+       fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
+       fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
+       if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2))
+               fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       else
+               fmt->fmt.pix.field = V4L2_FIELD_TOP;
+       mutex_unlock(&zr->resource_lock);
+       return 0;
+}
+
+static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       mutex_lock(&zr->resource_lock);
+
+       fmt->fmt.win.w.left = fh->overlay_settings.x;
+       fmt->fmt.win.w.top = fh->overlay_settings.y;
+       fmt->fmt.win.w.width = fh->overlay_settings.width;
+       fmt->fmt.win.w.height = fh->overlay_settings.height;
+       if (fh->overlay_settings.width * 2 > BUZ_MAX_HEIGHT)
+               fmt->fmt.win.field = V4L2_FIELD_INTERLACED;
+       else
+               fmt->fmt.win.field = V4L2_FIELD_TOP;
+
+       mutex_unlock(&zr->resource_lock);
+       return 0;
+}
+
+static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       mutex_lock(&zr->resource_lock);
+
+       if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
+               fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
+       if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
+               fmt->fmt.win.w.width = BUZ_MIN_WIDTH;
+       if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT)
+               fmt->fmt.win.w.height = BUZ_MAX_HEIGHT;
+       if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
+               fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
+
+       mutex_unlock(&zr->resource_lock);
+       return 0;
+}
+
+static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       struct zoran_jpg_settings settings;
+       int res = 0;
+
+       if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+               return -EINVAL;
+
+       mutex_lock(&zr->resource_lock);
+       settings = fh->jpg_settings;
+
+       /* we actually need to set 'real' parameters now */
+       if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT)
+               settings.TmpDcm = 1;
+       else
+               settings.TmpDcm = 2;
+       settings.decimation = 0;
+       if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2)
+               settings.VerDcm = 2;
+       else
+               settings.VerDcm = 1;
+       if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4)
+               settings.HorDcm = 4;
+       else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2)
+               settings.HorDcm = 2;
+       else
+               settings.HorDcm = 1;
+       if (settings.TmpDcm == 1)
+               settings.field_per_buff = 2;
+       else
+               settings.field_per_buff = 1;
+
+       if (settings.HorDcm > 1) {
+               settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+               settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+       } else {
+               settings.img_x = 0;
+               settings.img_width = BUZ_MAX_WIDTH;
+       }
+
+       /* check */
+       res = zoran_check_jpg_settings(zr, &settings, 1);
+       if (res)
+               goto tryfmt_unlock_and_return;
+
+       /* tell the user what we actually did */
+       fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
+       fmt->fmt.pix.height = settings.img_height * 2 /
+               (settings.TmpDcm * settings.VerDcm);
+       if (settings.TmpDcm == 1)
+               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+       else
+               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+
+       fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
+       fmt->fmt.pix.bytesperline = 0;
+       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+tryfmt_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int bpp;
+       int i;
+
+       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
+               return zoran_try_fmt_vid_out(file, fh, fmt);
+
+       mutex_lock(&zr->resource_lock);
+
+       for (i = 0; i < NUM_FORMATS; i++)
+               if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
+                       break;
+
+       if (i == NUM_FORMATS) {
+               mutex_unlock(&zr->resource_lock);
+               return -EINVAL;
+       }
+
+       bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
+       v4l_bound_align_image(
+               &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
+               &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
+       mutex_unlock(&zr->resource_lock);
+
+       return 0;
+}
+
+static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res;
+
+       dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
+                       fmt->fmt.win.w.left, fmt->fmt.win.w.top,
+                       fmt->fmt.win.w.width,
+                       fmt->fmt.win.w.height,
+                       fmt->fmt.win.clipcount,
+                       fmt->fmt.win.bitmap);
+       mutex_lock(&zr->resource_lock);
+       res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top,
+                          fmt->fmt.win.w.width, fmt->fmt.win.w.height,
+                          (struct v4l2_clip __user *)fmt->fmt.win.clips,
+                          fmt->fmt.win.clipcount, fmt->fmt.win.bitmap);
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
+       struct zoran_jpg_settings settings;
+       int res = 0;
+
+       dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n",
+                       fmt->fmt.pix.width, fmt->fmt.pix.height,
+                       fmt->fmt.pix.pixelformat,
+                       (char *) &printformat);
+       if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+               return -EINVAL;
+
+       mutex_lock(&zr->resource_lock);
+
+       if (fh->buffers.allocated) {
+               dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
+                       ZR_DEVNAME(zr));
+               res = -EBUSY;
+               goto sfmtjpg_unlock_and_return;
+       }
+
+       settings = fh->jpg_settings;
+
+       /* we actually need to set 'real' parameters now */
+       if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
+               settings.TmpDcm = 1;
+       else
+               settings.TmpDcm = 2;
+       settings.decimation = 0;
+       if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2)
+               settings.VerDcm = 2;
+       else
+               settings.VerDcm = 1;
+       if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4)
+               settings.HorDcm = 4;
+       else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2)
+               settings.HorDcm = 2;
+       else
+               settings.HorDcm = 1;
+       if (settings.TmpDcm == 1)
+               settings.field_per_buff = 2;
+       else
+               settings.field_per_buff = 1;
+
+       if (settings.HorDcm > 1) {
+               settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
+               settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
+       } else {
+               settings.img_x = 0;
+               settings.img_width = BUZ_MAX_WIDTH;
+       }
+
+       /* check */
+       res = zoran_check_jpg_settings(zr, &settings, 0);
+       if (res)
+               goto sfmtjpg_unlock_and_return;
+
+       /* it's ok, so set them */
+       fh->jpg_settings = settings;
+
+       map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
+       /* tell the user what we actually did */
+       fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
+       fmt->fmt.pix.height = settings.img_height * 2 /
+               (settings.TmpDcm * settings.VerDcm);
+       if (settings.TmpDcm == 1)
+               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
+       else
+               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
+                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
+       fmt->fmt.pix.bytesperline = 0;
+       fmt->fmt.pix.sizeimage = fh->buffers.buffer_size;
+       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+sfmtjpg_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
+                                       struct v4l2_format *fmt)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int i;
+       int res = 0;
+
+       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
+               return zoran_s_fmt_vid_out(file, fh, fmt);
+
+       for (i = 0; i < NUM_FORMATS; i++)
+               if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
+                       break;
+       if (i == NUM_FORMATS) {
+               dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
+                       ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       mutex_lock(&zr->resource_lock);
+
+       if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) ||
+           fh->buffers.active != ZORAN_FREE) {
+               dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
+                               ZR_DEVNAME(zr));
+               res = -EBUSY;
+               goto sfmtv4l_unlock_and_return;
+       }
+       if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
+               fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
+       if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
+               fmt->fmt.pix.width = BUZ_MAX_WIDTH;
+
+       map_mode_raw(fh);
+
+       res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height,
+                                  &zoran_formats[i]);
+       if (res)
+               goto sfmtv4l_unlock_and_return;
+
+       /* tell the user the results/missing stuff */
+       fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
+       fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline;
+       fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
+       if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2))
+               fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       else
+               fmt->fmt.pix.field = V4L2_FIELD_TOP;
+
+sfmtv4l_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_g_fbuf(struct file *file, void *__fh,
+               struct v4l2_framebuffer *fb)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       memset(fb, 0, sizeof(*fb));
+       mutex_lock(&zr->resource_lock);
+       fb->base = zr->vbuf_base;
+       fb->fmt.width = zr->vbuf_width;
+       fb->fmt.height = zr->vbuf_height;
+       if (zr->overlay_settings.format)
+               fb->fmt.pixelformat = fh->overlay_settings.format->fourcc;
+       fb->fmt.bytesperline = zr->vbuf_bytesperline;
+       mutex_unlock(&zr->resource_lock);
+       fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
+       fb->fmt.field = V4L2_FIELD_INTERLACED;
+       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+
+       return 0;
+}
+
+static int zoran_s_fbuf(struct file *file, void *__fh,
+               struct v4l2_framebuffer *fb)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int i, res = 0;
+       __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
+
+       for (i = 0; i < NUM_FORMATS; i++)
+               if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
+                       break;
+       if (i == NUM_FORMATS) {
+               dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
+                       ZR_DEVNAME(zr), fb->fmt.pixelformat,
+                       (char *)&printformat);
+               return -EINVAL;
+       }
+
+       mutex_lock(&zr->resource_lock);
+       res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width,
+                           fb->fmt.height, fb->fmt.bytesperline);
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_overlay(struct file *file, void *__fh, unsigned int on)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res;
+
+       mutex_lock(&zr->resource_lock);
+       res = setup_overlay(fh, on);
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type);
+
+static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0;
+
+       if (req->memory != V4L2_MEMORY_MMAP) {
+               dprintk(2,
+                               KERN_ERR
+                               "%s: only MEMORY_MMAP capture is supported, not %d\n",
+                               ZR_DEVNAME(zr), req->memory);
+               return -EINVAL;
+       }
+
+       if (req->count == 0)
+               return zoran_streamoff(file, fh, req->type);
+
+       mutex_lock(&zr->resource_lock);
+       if (fh->buffers.allocated) {
+               dprintk(2,
+                               KERN_ERR
+                               "%s: VIDIOC_REQBUFS - buffers already allocated\n",
+                               ZR_DEVNAME(zr));
+               res = -EBUSY;
+               goto v4l2reqbuf_unlock_and_return;
+       }
+
+       if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
+           req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               /* control user input */
+               if (req->count < 2)
+                       req->count = 2;
+               if (req->count > v4l_nbufs)
+                       req->count = v4l_nbufs;
+
+               /* The next mmap will map the V4L buffers */
+               map_mode_raw(fh);
+               fh->buffers.num_buffers = req->count;
+
+               if (v4l_fbuffer_alloc(fh)) {
+                       res = -ENOMEM;
+                       goto v4l2reqbuf_unlock_and_return;
+               }
+       } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
+                  fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
+               /* we need to calculate size ourselves now */
+               if (req->count < 4)
+                       req->count = 4;
+               if (req->count > jpg_nbufs)
+                       req->count = jpg_nbufs;
+
+               /* The next mmap will map the MJPEG buffers */
+               map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+               fh->buffers.num_buffers = req->count;
+               fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+
+               if (jpg_fbuffer_alloc(fh)) {
+                       res = -ENOMEM;
+                       goto v4l2reqbuf_unlock_and_return;
+               }
+       } else {
+               dprintk(1,
+                               KERN_ERR
+                               "%s: VIDIOC_REQBUFS - unknown type %d\n",
+                               ZR_DEVNAME(zr), req->type);
+               res = -EINVAL;
+               goto v4l2reqbuf_unlock_and_return;
+       }
+v4l2reqbuf_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res;
+
+       mutex_lock(&zr->resource_lock);
+       res = zoran_v4l2_buffer_status(fh, buf, buf->index);
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0, codec_mode, buf_type;
+
+       mutex_lock(&zr->resource_lock);
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:
+               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                       dprintk(1, KERN_ERR
+                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                       res = -EINVAL;
+                       goto qbuf_unlock_and_return;
+               }
+
+               res = zoran_v4l_queue_frame(fh, buf->index);
+               if (res)
+                       goto qbuf_unlock_and_return;
+               if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED)
+                       zr36057_set_memgrab(zr, 1);
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+               if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
+                       buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+                       codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
+               } else {
+                       buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+                       codec_mode = BUZ_MODE_MOTION_COMPRESS;
+               }
+
+               if (buf->type != buf_type) {
+                       dprintk(1, KERN_ERR
+                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                       res = -EINVAL;
+                       goto qbuf_unlock_and_return;
+               }
+
+               res = zoran_jpg_queue_frame(fh, buf->index, codec_mode);
+               if (res != 0)
+                       goto qbuf_unlock_and_return;
+               if (zr->codec_mode == BUZ_MODE_IDLE &&
+                   fh->buffers.active == ZORAN_LOCKED)
+                       zr36057_enable_jpg(zr, codec_mode);
+
+               break;
+
+       default:
+               dprintk(1, KERN_ERR
+                       "%s: VIDIOC_QBUF - unsupported type %d\n",
+                       ZR_DEVNAME(zr), buf->type);
+               res = -EINVAL;
+               break;
+       }
+qbuf_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0, buf_type, num = -1;        /* compiler borks here (?) */
+
+       mutex_lock(&zr->resource_lock);
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:
+               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+                       dprintk(1, KERN_ERR
+                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                       res = -EINVAL;
+                       goto dqbuf_unlock_and_return;
+               }
+
+               num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+               if (file->f_flags & O_NONBLOCK &&
+                   zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) {
+                       res = -EAGAIN;
+                       goto dqbuf_unlock_and_return;
+               }
+               res = v4l_sync(fh, num);
+               if (res)
+                       goto dqbuf_unlock_and_return;
+               zr->v4l_sync_tail++;
+               res = zoran_v4l2_buffer_status(fh, buf, num);
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+       {
+               struct zoran_sync bs;
+
+               if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
+                       buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               else
+                       buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+               if (buf->type != buf_type) {
+                       dprintk(1, KERN_ERR
+                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
+                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
+                       res = -EINVAL;
+                       goto dqbuf_unlock_and_return;
+               }
+
+               num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
+
+               if (file->f_flags & O_NONBLOCK &&
+                   zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) {
+                       res = -EAGAIN;
+                       goto dqbuf_unlock_and_return;
+               }
+               bs.frame = 0; /* suppress compiler warning */
+               res = jpg_sync(fh, &bs);
+               if (res)
+                       goto dqbuf_unlock_and_return;
+               res = zoran_v4l2_buffer_status(fh, buf, bs.frame);
+               break;
+       }
+
+       default:
+               dprintk(1, KERN_ERR
+                       "%s: VIDIOC_DQBUF - unsupported type %d\n",
+                       ZR_DEVNAME(zr), buf->type);
+               res = -EINVAL;
+               break;
+       }
+dqbuf_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0;
+
+       mutex_lock(&zr->resource_lock);
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:        /* raw capture */
+               if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
+                   fh->buffers.active != ZORAN_ACTIVE) {
+                       res = -EBUSY;
+                       goto strmon_unlock_and_return;
+               }
+
+               zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED;
+               zr->v4l_settings = fh->v4l_settings;
+
+               zr->v4l_sync_tail = zr->v4l_pend_tail;
+               if (!zr->v4l_memgrab_active &&
+                   zr->v4l_pend_head != zr->v4l_pend_tail) {
+                       zr36057_set_memgrab(zr, 1);
+               }
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+               /* what is the codec mode right now? */
+               if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
+                   fh->buffers.active != ZORAN_ACTIVE) {
+                       res = -EBUSY;
+                       goto strmon_unlock_and_return;
+               }
+
+               zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED;
+
+               if (zr->jpg_que_head != zr->jpg_que_tail) {
+                       /* Start the jpeg codec when the first frame is queued  */
+                       jpeg_start(zr);
+               }
+               break;
+
+       default:
+               dprintk(1,
+                       KERN_ERR
+                       "%s: VIDIOC_STREAMON - invalid map mode %d\n",
+                       ZR_DEVNAME(zr), fh->map_mode);
+               res = -EINVAL;
+               break;
+       }
+strmon_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int i, res = 0;
+       unsigned long flags;
+
+       mutex_lock(&zr->resource_lock);
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:        /* raw capture */
+               if (fh->buffers.active == ZORAN_FREE &&
+                   zr->v4l_buffers.active != ZORAN_FREE) {
+                       res = -EPERM;   /* stay off other's settings! */
+                       goto strmoff_unlock_and_return;
+               }
+               if (zr->v4l_buffers.active == ZORAN_FREE)
+                       goto strmoff_unlock_and_return;
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               /* unload capture */
+               if (zr->v4l_memgrab_active) {
+
+                       zr36057_set_memgrab(zr, 0);
+               }
+
+               for (i = 0; i < fh->buffers.num_buffers; i++)
+                       zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;
+               fh->buffers = zr->v4l_buffers;
+
+               zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+
+               zr->v4l_grab_seq = 0;
+               zr->v4l_pend_head = zr->v4l_pend_tail = 0;
+               zr->v4l_sync_tail = 0;
+
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+               if (fh->buffers.active == ZORAN_FREE &&
+                   zr->jpg_buffers.active != ZORAN_FREE) {
+                       res = -EPERM;   /* stay off other's settings! */
+                       goto strmoff_unlock_and_return;
+               }
+               if (zr->jpg_buffers.active == ZORAN_FREE)
+                       goto strmoff_unlock_and_return;
+
+               res = jpg_qbuf(fh, -1,
+                            (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
+                            BUZ_MODE_MOTION_COMPRESS :
+                            BUZ_MODE_MOTION_DECOMPRESS);
+               if (res)
+                       goto strmoff_unlock_and_return;
+               break;
+       default:
+               dprintk(1, KERN_ERR
+                       "%s: VIDIOC_STREAMOFF - invalid map mode %d\n",
+                       ZR_DEVNAME(zr), fh->map_mode);
+               res = -EINVAL;
+               break;
+       }
+strmoff_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_queryctrl(struct file *file, void *__fh,
+                                       struct v4l2_queryctrl *ctrl)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       /* we only support hue/saturation/contrast/brightness */
+       if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+           ctrl->id > V4L2_CID_HUE)
+               return -EINVAL;
+
+       decoder_call(zr, core, queryctrl, ctrl);
+
+       return 0;
+}
+
+static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       /* we only support hue/saturation/contrast/brightness */
+       if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+           ctrl->id > V4L2_CID_HUE)
+               return -EINVAL;
+
+       mutex_lock(&zr->resource_lock);
+       decoder_call(zr, core, g_ctrl, ctrl);
+       mutex_unlock(&zr->resource_lock);
+
+       return 0;
+}
+
+static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       /* we only support hue/saturation/contrast/brightness */
+       if (ctrl->id < V4L2_CID_BRIGHTNESS ||
+           ctrl->id > V4L2_CID_HUE)
+               return -EINVAL;
+
+       mutex_lock(&zr->resource_lock);
+       decoder_call(zr, core, s_ctrl, ctrl);
+       mutex_unlock(&zr->resource_lock);
+
+       return 0;
+}
+
+static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       mutex_lock(&zr->resource_lock);
+       *std = zr->norm;
+       mutex_unlock(&zr->resource_lock);
+       return 0;
+}
+
+static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0;
+
+       mutex_lock(&zr->resource_lock);
+       res = zoran_set_norm(zr, *std);
+       if (res)
+               goto sstd_unlock_and_return;
+
+       res = wait_grab_pending(zr);
+sstd_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_enum_input(struct file *file, void *__fh,
+                                struct v4l2_input *inp)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       if (inp->index >= zr->card.inputs)
+               return -EINVAL;
+
+       strncpy(inp->name, zr->card.input[inp->index].name,
+               sizeof(inp->name) - 1);
+       inp->type = V4L2_INPUT_TYPE_CAMERA;
+       inp->std = V4L2_STD_ALL;
+
+       /* Get status of video decoder */
+       mutex_lock(&zr->resource_lock);
+       decoder_call(zr, video, g_input_status, &inp->status);
+       mutex_unlock(&zr->resource_lock);
+       return 0;
+}
+
+static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+
+       mutex_lock(&zr->resource_lock);
+       *input = zr->input;
+       mutex_unlock(&zr->resource_lock);
+
+       return 0;
+}
+
+static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res;
+
+       mutex_lock(&zr->resource_lock);
+       res = zoran_set_input(zr, input);
+       if (res)
+               goto sinput_unlock_and_return;
+
+       /* Make sure the changes come into effect */
+       res = wait_grab_pending(zr);
+sinput_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_enum_output(struct file *file, void *__fh,
+                                 struct v4l2_output *outp)
+{
+       if (outp->index != 0)
+               return -EINVAL;
+
+       outp->index = 0;
+       outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
+       strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
+
+       return 0;
+}
+
+static int zoran_g_output(struct file *file, void *__fh, unsigned int *output)
+{
+       *output = 0;
+
+       return 0;
+}
+
+static int zoran_s_output(struct file *file, void *__fh, unsigned int output)
+{
+       if (output != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* cropping (sub-frame capture) */
+static int zoran_cropcap(struct file *file, void *__fh,
+                                       struct v4l2_cropcap *cropcap)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int type = cropcap->type, res = 0;
+
+       memset(cropcap, 0, sizeof(*cropcap));
+       cropcap->type = type;
+
+       mutex_lock(&zr->resource_lock);
+
+       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+            fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+               dprintk(1, KERN_ERR
+                       "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
+                       ZR_DEVNAME(zr));
+               res = -EINVAL;
+               goto cropcap_unlock_and_return;
+       }
+
+       cropcap->bounds.top = cropcap->bounds.left = 0;
+       cropcap->bounds.width = BUZ_MAX_WIDTH;
+       cropcap->bounds.height = BUZ_MAX_HEIGHT;
+       cropcap->defrect.top = cropcap->defrect.left = 0;
+       cropcap->defrect.width = BUZ_MIN_WIDTH;
+       cropcap->defrect.height = BUZ_MIN_HEIGHT;
+cropcap_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int type = crop->type, res = 0;
+
+       memset(crop, 0, sizeof(*crop));
+       crop->type = type;
+
+       mutex_lock(&zr->resource_lock);
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+            fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
+                       ZR_DEVNAME(zr));
+               res = -EINVAL;
+               goto gcrop_unlock_and_return;
+       }
+
+       crop->c.top = fh->jpg_settings.img_y;
+       crop->c.left = fh->jpg_settings.img_x;
+       crop->c.width = fh->jpg_settings.img_width;
+       crop->c.height = fh->jpg_settings.img_height;
+
+gcrop_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0;
+       struct zoran_jpg_settings settings;
+
+       settings = fh->jpg_settings;
+
+       mutex_lock(&zr->resource_lock);
+
+       if (fh->buffers.allocated) {
+               dprintk(1, KERN_ERR
+                       "%s: VIDIOC_S_CROP - cannot change settings while active\n",
+                       ZR_DEVNAME(zr));
+               res = -EBUSY;
+               goto scrop_unlock_and_return;
+       }
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+            fh->map_mode == ZORAN_MAP_MODE_RAW)) {
+               dprintk(1, KERN_ERR
+                       "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
+                       ZR_DEVNAME(zr));
+               res = -EINVAL;
+               goto scrop_unlock_and_return;
+       }
+
+       /* move into a form that we understand */
+       settings.img_x = crop->c.left;
+       settings.img_y = crop->c.top;
+       settings.img_width = crop->c.width;
+       settings.img_height = crop->c.height;
+
+       /* check validity */
+       res = zoran_check_jpg_settings(zr, &settings, 0);
+       if (res)
+               goto scrop_unlock_and_return;
+
+       /* accept */
+       fh->jpg_settings = settings;
+
+scrop_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+       return res;
+}
+
+static int zoran_g_jpegcomp(struct file *file, void *__fh,
+                                       struct v4l2_jpegcompression *params)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       memset(params, 0, sizeof(*params));
+
+       mutex_lock(&zr->resource_lock);
+
+       params->quality = fh->jpg_settings.jpg_comp.quality;
+       params->APPn = fh->jpg_settings.jpg_comp.APPn;
+       memcpy(params->APP_data,
+              fh->jpg_settings.jpg_comp.APP_data,
+              fh->jpg_settings.jpg_comp.APP_len);
+       params->APP_len = fh->jpg_settings.jpg_comp.APP_len;
+       memcpy(params->COM_data,
+              fh->jpg_settings.jpg_comp.COM_data,
+              fh->jpg_settings.jpg_comp.COM_len);
+       params->COM_len = fh->jpg_settings.jpg_comp.COM_len;
+       params->jpeg_markers =
+           fh->jpg_settings.jpg_comp.jpeg_markers;
+
+       mutex_unlock(&zr->resource_lock);
+
+       return 0;
+}
+
+static int zoran_s_jpegcomp(struct file *file, void *__fh,
+                                       struct v4l2_jpegcompression *params)
+{
+       struct zoran_fh *fh = __fh;
+       struct zoran *zr = fh->zr;
+       int res = 0;
+       struct zoran_jpg_settings settings;
+
+       settings = fh->jpg_settings;
+
+       settings.jpg_comp = *params;
+
+       mutex_lock(&zr->resource_lock);
+
+       if (fh->buffers.active != ZORAN_FREE) {
+               dprintk(1, KERN_WARNING
+                       "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
+                       ZR_DEVNAME(zr));
+               res = -EBUSY;
+               goto sjpegc_unlock_and_return;
+       }
+
+       res = zoran_check_jpg_settings(zr, &settings, 0);
+       if (res)
+               goto sjpegc_unlock_and_return;
+       if (!fh->buffers.allocated)
+               fh->buffers.buffer_size =
+                       zoran_v4l2_calc_bufsize(&fh->jpg_settings);
+       fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
+sjpegc_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static unsigned int
+zoran_poll (struct file *file,
+           poll_table  *wait)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int res = 0, frame;
+       unsigned long flags;
+
+       /* we should check whether buffers are ready to be synced on
+        * (w/o waits - O_NONBLOCK) here
+        * if ready for read (sync), return POLLIN|POLLRDNORM,
+        * if ready for write (sync), return POLLOUT|POLLWRNORM,
+        * if error, return POLLERR,
+        * if no buffers queued or so, return POLLNVAL
+        */
+
+       mutex_lock(&zr->resource_lock);
+
+       switch (fh->map_mode) {
+       case ZORAN_MAP_MODE_RAW:
+               poll_wait(file, &zr->v4l_capq, wait);
+               frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->buffers.active], zr->v4l_sync_tail,
+                       "UPMD"[zr->v4l_buffers.buffer[frame].state],
+                       zr->v4l_pend_tail, zr->v4l_pend_head);
+               /* Process is the one capturing? */
+               if (fh->buffers.active != ZORAN_FREE &&
+                   /* Buffer ready to DQBUF? */
+                   zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
+                       res = POLLIN | POLLRDNORM;
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
+               break;
+
+       case ZORAN_MAP_MODE_JPG_REC:
+       case ZORAN_MAP_MODE_JPG_PLAY:
+               poll_wait(file, &zr->jpg_capq, wait);
+               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
+
+               spin_lock_irqsave(&zr->spinlock, flags);
+               dprintk(3,
+                       KERN_DEBUG
+                       "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
+                       ZR_DEVNAME(zr), __func__,
+                       "FAL"[fh->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);
+               if (fh->buffers.active != ZORAN_FREE &&
+                   zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
+                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
+                               res = POLLIN | POLLRDNORM;
+                       else
+                               res = POLLOUT | POLLWRNORM;
+               }
+               spin_unlock_irqrestore(&zr->spinlock, flags);
+
+               break;
+
+       default:
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - internal error, unknown map_mode=%d\n",
+                       ZR_DEVNAME(zr), __func__, fh->map_mode);
+               res = POLLNVAL;
+       }
+
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+
+/*
+ * This maps the buffers to user space.
+ *
+ * Depending on the state of fh->map_mode
+ * the V4L or the MJPEG buffers are mapped
+ * per buffer or all together
+ *
+ * Note that we need to connect to some
+ * unmap signal event to unmap the de-allocate
+ * the buffer accordingly (zoran_vm_close())
+ */
+
+static void
+zoran_vm_open (struct vm_area_struct *vma)
+{
+       struct zoran_mapping *map = vma->vm_private_data;
+
+       map->count++;
+}
+
+static void
+zoran_vm_close (struct vm_area_struct *vma)
+{
+       struct zoran_mapping *map = vma->vm_private_data;
+       struct zoran_fh *fh = map->fh;
+       struct zoran *zr = fh->zr;
+       int i;
+
+       if (--map->count > 0)
+               return;
+
+       dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
+               __func__, mode_name(fh->map_mode));
+
+       for (i = 0; i < fh->buffers.num_buffers; i++) {
+               if (fh->buffers.buffer[i].map == map)
+                       fh->buffers.buffer[i].map = NULL;
+       }
+       kfree(map);
+
+       /* Any buffers still mapped? */
+       for (i = 0; i < fh->buffers.num_buffers; i++)
+               if (fh->buffers.buffer[i].map)
+                       return;
+
+       dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
+               __func__, mode_name(fh->map_mode));
+
+       mutex_lock(&zr->resource_lock);
+
+       if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+               if (fh->buffers.active != ZORAN_FREE) {
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&zr->spinlock, flags);
+                       zr36057_set_memgrab(zr, 0);
+                       zr->v4l_buffers.allocated = 0;
+                       zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
+                       spin_unlock_irqrestore(&zr->spinlock, flags);
+               }
+               v4l_fbuffer_free(fh);
+       } else {
+               if (fh->buffers.active != ZORAN_FREE) {
+                       jpg_qbuf(fh, -1, zr->codec_mode);
+                       zr->jpg_buffers.allocated = 0;
+                       zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
+               }
+               jpg_fbuffer_free(fh);
+       }
+
+       mutex_unlock(&zr->resource_lock);
+}
+
+static const struct vm_operations_struct zoran_vm_ops = {
+       .open = zoran_vm_open,
+       .close = zoran_vm_close,
+};
+
+static int
+zoran_mmap (struct file           *file,
+           struct vm_area_struct *vma)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       unsigned long size = (vma->vm_end - vma->vm_start);
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int i, j;
+       unsigned long page, start = vma->vm_start, todo, pos, fraglen;
+       int first, last;
+       struct zoran_mapping *map;
+       int res = 0;
+
+       dprintk(3,
+               KERN_INFO "%s: %s(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
+               ZR_DEVNAME(zr), __func__,
+               mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size);
+
+       if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) ||
+           !(vma->vm_flags & VM_WRITE)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s - no MAP_SHARED/PROT_{READ,WRITE} given\n",
+                       ZR_DEVNAME(zr), __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&zr->resource_lock);
+
+       if (!fh->buffers.allocated) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s(%s) - buffers not yet allocated\n",
+                       ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode));
+               res = -ENOMEM;
+               goto mmap_unlock_and_return;
+       }
+
+       first = offset / fh->buffers.buffer_size;
+       last = first - 1 + size / fh->buffers.buffer_size;
+       if (offset % fh->buffers.buffer_size != 0 ||
+           size % fh->buffers.buffer_size != 0 || first < 0 ||
+           last < 0 || first >= fh->buffers.num_buffers ||
+           last >= fh->buffers.buffer_size) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: %s(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
+                       ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), offset, size,
+                       fh->buffers.buffer_size,
+                       fh->buffers.num_buffers);
+               res = -EINVAL;
+               goto mmap_unlock_and_return;
+       }
+
+       /* Check if any buffers are already mapped */
+       for (i = first; i <= last; i++) {
+               if (fh->buffers.buffer[i].map) {
+                       dprintk(1,
+                               KERN_ERR
+                               "%s: %s(%s) - buffer %d already mapped\n",
+                               ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i);
+                       res = -EBUSY;
+                       goto mmap_unlock_and_return;
+               }
+       }
+
+       /* map these buffers */
+       map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
+       if (!map) {
+               res = -ENOMEM;
+               goto mmap_unlock_and_return;
+       }
+       map->fh = fh;
+       map->count = 1;
+
+       vma->vm_ops = &zoran_vm_ops;
+       vma->vm_flags |= VM_DONTEXPAND;
+       vma->vm_private_data = map;
+
+       if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
+               for (i = first; i <= last; i++) {
+                       todo = size;
+                       if (todo > fh->buffers.buffer_size)
+                               todo = fh->buffers.buffer_size;
+                       page = fh->buffers.buffer[i].v4l.fbuffer_phys;
+                       if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
+                                                       todo, PAGE_SHARED)) {
+                               dprintk(1,
+                                       KERN_ERR
+                                       "%s: %s(V4L) - remap_pfn_range failed\n",
+                                       ZR_DEVNAME(zr), __func__);
+                               res = -EAGAIN;
+                               goto mmap_unlock_and_return;
+                       }
+                       size -= todo;
+                       start += todo;
+                       fh->buffers.buffer[i].map = map;
+                       if (size == 0)
+                               break;
+               }
+       } else {
+               for (i = first; i <= last; i++) {
+                       for (j = 0;
+                            j < fh->buffers.buffer_size / PAGE_SIZE;
+                            j++) {
+                               fraglen =
+                                   (le32_to_cpu(fh->buffers.buffer[i].jpg.
+                                    frag_tab[2 * j + 1]) & ~1) << 1;
+                               todo = size;
+                               if (todo > fraglen)
+                                       todo = fraglen;
+                               pos =
+                                   le32_to_cpu(fh->buffers.
+                                   buffer[i].jpg.frag_tab[2 * j]);
+                               /* should just be pos on i386 */
+                               page = virt_to_phys(bus_to_virt(pos))
+                                                               >> PAGE_SHIFT;
+                               if (remap_pfn_range(vma, start, page,
+                                                       todo, PAGE_SHARED)) {
+                                       dprintk(1,
+                                               KERN_ERR
+                                               "%s: %s(V4L) - remap_pfn_range failed\n",
+                                               ZR_DEVNAME(zr), __func__);
+                                       res = -EAGAIN;
+                                       goto mmap_unlock_and_return;
+                               }
+                               size -= todo;
+                               start += todo;
+                               if (size == 0)
+                                       break;
+                               if (le32_to_cpu(fh->buffers.buffer[i].jpg.
+                                   frag_tab[2 * j + 1]) & 1)
+                                       break;  /* was last fragment */
+                       }
+                       fh->buffers.buffer[i].map = map;
+                       if (size == 0)
+                               break;
+
+               }
+       }
+
+mmap_unlock_and_return:
+       mutex_unlock(&zr->resource_lock);
+
+       return res;
+}
+
+static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
+       .vidioc_querycap                    = zoran_querycap,
+       .vidioc_cropcap                     = zoran_cropcap,
+       .vidioc_s_crop                      = zoran_s_crop,
+       .vidioc_g_crop                      = zoran_g_crop,
+       .vidioc_enum_input                  = zoran_enum_input,
+       .vidioc_g_input                     = zoran_g_input,
+       .vidioc_s_input                     = zoran_s_input,
+       .vidioc_enum_output                 = zoran_enum_output,
+       .vidioc_g_output                    = zoran_g_output,
+       .vidioc_s_output                    = zoran_s_output,
+       .vidioc_g_fbuf                      = zoran_g_fbuf,
+       .vidioc_s_fbuf                      = zoran_s_fbuf,
+       .vidioc_g_std                       = zoran_g_std,
+       .vidioc_s_std                       = zoran_s_std,
+       .vidioc_g_jpegcomp                  = zoran_g_jpegcomp,
+       .vidioc_s_jpegcomp                  = zoran_s_jpegcomp,
+       .vidioc_overlay                     = zoran_overlay,
+       .vidioc_reqbufs                     = zoran_reqbufs,
+       .vidioc_querybuf                    = zoran_querybuf,
+       .vidioc_qbuf                        = zoran_qbuf,
+       .vidioc_dqbuf                       = zoran_dqbuf,
+       .vidioc_streamon                    = zoran_streamon,
+       .vidioc_streamoff                   = zoran_streamoff,
+       .vidioc_enum_fmt_vid_cap            = zoran_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_out            = zoran_enum_fmt_vid_out,
+       .vidioc_enum_fmt_vid_overlay        = zoran_enum_fmt_vid_overlay,
+       .vidioc_g_fmt_vid_cap               = zoran_g_fmt_vid_cap,
+       .vidioc_g_fmt_vid_out               = zoran_g_fmt_vid_out,
+       .vidioc_g_fmt_vid_overlay           = zoran_g_fmt_vid_overlay,
+       .vidioc_s_fmt_vid_cap               = zoran_s_fmt_vid_cap,
+       .vidioc_s_fmt_vid_out               = zoran_s_fmt_vid_out,
+       .vidioc_s_fmt_vid_overlay           = zoran_s_fmt_vid_overlay,
+       .vidioc_try_fmt_vid_cap             = zoran_try_fmt_vid_cap,
+       .vidioc_try_fmt_vid_out             = zoran_try_fmt_vid_out,
+       .vidioc_try_fmt_vid_overlay         = zoran_try_fmt_vid_overlay,
+       .vidioc_queryctrl                   = zoran_queryctrl,
+       .vidioc_s_ctrl                      = zoran_s_ctrl,
+       .vidioc_g_ctrl                      = zoran_g_ctrl,
+};
+
+/* please use zr->resource_lock consistently and kill this wrapper */
+static long zoran_ioctl(struct file *file, unsigned int cmd,
+                       unsigned long arg)
+{
+       struct zoran_fh *fh = file->private_data;
+       struct zoran *zr = fh->zr;
+       int ret;
+
+       mutex_lock(&zr->other_lock);
+       ret = video_ioctl2(file, cmd, arg);
+       mutex_unlock(&zr->other_lock);
+
+       return ret;
+}
+
+static const struct v4l2_file_operations zoran_fops = {
+       .owner = THIS_MODULE,
+       .open = zoran_open,
+       .release = zoran_close,
+       .unlocked_ioctl = zoran_ioctl,
+       .read = zoran_read,
+       .write = zoran_write,
+       .mmap = zoran_mmap,
+       .poll = zoran_poll,
+};
+
+struct video_device zoran_template __devinitdata = {
+       .name = ZORAN_NAME,
+       .fops = &zoran_fops,
+       .ioctl_ops = &zoran_ioctl_ops,
+       .release = &zoran_vdev_release,
+       .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+};
+
diff --git a/drivers/media/pci/zoran/zoran_procfs.c b/drivers/media/pci/zoran/zoran_procfs.c
new file mode 100644 (file)
index 0000000..f1423b7
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles the procFS entries (/proc/ZORAN[%d])
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.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/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/seq_file.h>
+
+#include <linux/ctype.h>
+#include <linux/poll.h>
+#include <asm/io.h>
+
+#include "videocodec.h"
+#include "zoran.h"
+#include "zoran_procfs.h"
+#include "zoran_card.h"
+
+#ifdef CONFIG_PROC_FS
+struct procfs_params_zr36067 {
+       char *name;
+       short reg;
+       u32 mask;
+       short bit;
+};
+
+static const struct procfs_params_zr36067 zr67[] = {
+       {"HSPol", 0x000, 1, 30},
+       {"HStart", 0x000, 0x3ff, 10},
+       {"HEnd", 0x000, 0x3ff, 0},
+
+       {"VSPol", 0x004, 1, 30},
+       {"VStart", 0x004, 0x3ff, 10},
+       {"VEnd", 0x004, 0x3ff, 0},
+
+       {"ExtFl", 0x008, 1, 26},
+       {"TopField", 0x008, 1, 25},
+       {"VCLKPol", 0x008, 1, 24},
+       {"DupFld", 0x008, 1, 20},
+       {"LittleEndian", 0x008, 1, 0},
+
+       {"HsyncStart", 0x10c, 0xffff, 16},
+       {"LineTot", 0x10c, 0xffff, 0},
+
+       {"NAX", 0x110, 0xffff, 16},
+       {"PAX", 0x110, 0xffff, 0},
+
+       {"NAY", 0x114, 0xffff, 16},
+       {"PAY", 0x114, 0xffff, 0},
+
+       /* {"",,,}, */
+
+       {NULL, 0, 0, 0},
+};
+
+static void
+setparam (struct zoran *zr,
+         char         *name,
+         char         *sval)
+{
+       int i = 0, reg0, reg, val;
+
+       while (zr67[i].name != NULL) {
+               if (!strncmp(name, zr67[i].name, strlen(zr67[i].name))) {
+                       reg = reg0 = btread(zr67[i].reg);
+                       reg &= ~(zr67[i].mask << zr67[i].bit);
+                       if (!isdigit(sval[0]))
+                               break;
+                       val = simple_strtoul(sval, NULL, 0);
+                       if ((val & ~zr67[i].mask))
+                               break;
+                       reg |= (val & zr67[i].mask) << zr67[i].bit;
+                       dprintk(4,
+                               KERN_INFO
+                               "%s: setparam: setting ZR36067 register 0x%03x: 0x%08x=>0x%08x %s=%d\n",
+                               ZR_DEVNAME(zr), zr67[i].reg, reg0, reg,
+                               zr67[i].name, val);
+                       btwrite(reg, zr67[i].reg);
+                       break;
+               }
+               i++;
+       }
+}
+
+static int zoran_show(struct seq_file *p, void *v)
+{
+       struct zoran *zr = p->private;
+       int i;
+
+       seq_printf(p, "ZR36067 registers:\n");
+       for (i = 0; i < 0x130; i += 16)
+               seq_printf(p, "%03X %08X  %08X  %08X  %08X \n", i,
+                          btread(i), btread(i+4), btread(i+8), btread(i+12));
+       return 0;
+}
+
+static int zoran_open(struct inode *inode, struct file *file)
+{
+       struct zoran *data = PDE(inode)->data;
+       return single_open(file, zoran_show, data);
+}
+
+static ssize_t zoran_write(struct file *file, const char __user *buffer,
+                       size_t count, loff_t *ppos)
+{
+       struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
+       char *string, *sp;
+       char *line, *ldelim, *varname, *svar, *tdelim;
+
+       if (count > 32768)      /* Stupidity filter */
+               return -EINVAL;
+
+       string = sp = vmalloc(count + 1);
+       if (!string) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: write_proc: can not allocate memory\n",
+                       ZR_DEVNAME(zr));
+               return -ENOMEM;
+       }
+       if (copy_from_user(string, buffer, count)) {
+               vfree (string);
+               return -EFAULT;
+       }
+       string[count] = 0;
+       dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
+               ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
+       ldelim = " \t\n";
+       tdelim = "=";
+       line = strpbrk(sp, ldelim);
+       while (line) {
+               *line = 0;
+               svar = strpbrk(sp, tdelim);
+               if (svar) {
+                       *svar = 0;
+                       varname = sp;
+                       svar++;
+                       setparam(zr, varname, svar);
+               }
+               sp = line + 1;
+               line = strpbrk(sp, ldelim);
+       }
+       vfree(string);
+
+       return count;
+}
+
+static const struct file_operations zoran_operations = {
+       .owner          = THIS_MODULE,
+       .open           = zoran_open,
+       .read           = seq_read,
+       .write          = zoran_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif
+
+int
+zoran_proc_init (struct zoran *zr)
+{
+#ifdef CONFIG_PROC_FS
+       char name[8];
+
+       snprintf(name, 7, "zoran%d", zr->id);
+       zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
+       if (zr->zoran_proc != NULL) {
+               dprintk(2,
+                       KERN_INFO
+                       "%s: procfs entry /proc/%s allocated. data=%p\n",
+                       ZR_DEVNAME(zr), name, zr->zoran_proc->data);
+       } else {
+               dprintk(1, KERN_ERR "%s: Unable to initialise /proc/%s\n",
+                       ZR_DEVNAME(zr), name);
+               return 1;
+       }
+#endif
+       return 0;
+}
+
+void
+zoran_proc_cleanup (struct zoran *zr)
+{
+#ifdef CONFIG_PROC_FS
+       char name[8];
+
+       snprintf(name, 7, "zoran%d", zr->id);
+       if (zr->zoran_proc)
+               remove_proc_entry(name, NULL);
+       zr->zoran_proc = NULL;
+#endif
+}
diff --git a/drivers/media/pci/zoran/zoran_procfs.h b/drivers/media/pci/zoran/zoran_procfs.h
new file mode 100644 (file)
index 0000000..f2d5b1b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Zoran zr36057/zr36067 PCI controller driver, for the
+ * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
+ * Media Labs LML33/LML33R10.
+ *
+ * This part handles card-specific data and detection
+ *
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Currently maintained by:
+ *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
+ *   Laurent Pinchart <laurent.pinchart@skynet.be>
+ *   Mailinglist      <mjpeg-users@lists.sf.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.
+ */
+
+#ifndef __ZORAN_PROCFS_H__
+#define __ZORAN_PROCFS_H__
+
+extern int zoran_proc_init(struct zoran *zr);
+extern void zoran_proc_cleanup(struct zoran *zr);
+
+#endif                         /* __ZORAN_PROCFS_H__ */
diff --git a/drivers/media/pci/zoran/zr36016.c b/drivers/media/pci/zoran/zr36016.c
new file mode 100644 (file)
index 0000000..b87ddba
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+ * Zoran ZR36016 basic configuration functions
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 ZR016_VERSION "v0.7"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* I/O commands, error codes */
+#include <asm/io.h>
+
+/* v4l  API */
+
+/* headerfile of this module */
+#include "zr36016.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so,
+  just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36016_codecs;
+
+/* debugging is available via module parameter */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* =========================================================================
+   Local hardware I/O functions:
+
+   read/write via codec layer (registers are located in the master device)
+   ========================================================================= */
+
+/* read and write functions */
+static u8
+zr36016_read (struct zr36016 *ptr,
+             u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->readreg)
+               value =
+                   (ptr->codec->master_data->
+                    readreg(ptr->codec, reg)) & 0xFF;
+       else
+               dprintk(1,
+                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
+                       ptr->name);
+
+       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
+               value);
+
+       return value;
+}
+
+static void
+zr36016_write (struct zr36016 *ptr,
+              u16             reg,
+              u8              value)
+{
+       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
+               reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg) {
+               ptr->codec->master_data->writereg(ptr->codec, reg, value);
+       } else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written!\n",
+                       ptr->name);
+}
+
+/* indirect read and write functions */
+/* the 016 supports auto-addr-increment, but
+ * writing it all time cost not much and is safer... */
+static u8
+zr36016_readi (struct zr36016 *ptr,
+              u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if ((ptr->codec->master_data->writereg) &&
+           (ptr->codec->master_data->readreg)) {
+               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
+               value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;     // DATA
+       } else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing read (i)!\n",
+                       ptr->name);
+
+       dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
+               reg, value);
+       return value;
+}
+
+static void
+zr36016_writei (struct zr36016 *ptr,
+               u16             reg,
+               u8              value)
+{
+       dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
+               value, reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg) {
+               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
+               ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);      // DATA
+       } else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written (i)!\n",
+                       ptr->name);
+}
+
+/* =========================================================================
+   Local helper function:
+
+   version read
+   ========================================================================= */
+
+/* version kept in datastructure */
+static u8
+zr36016_read_version (struct zr36016 *ptr)
+{
+       ptr->version = zr36016_read(ptr, 0) >> 4;
+       return ptr->version;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   basic test of "connectivity", writes/reads to/from PAX-Lo register
+   ========================================================================= */
+
+static int
+zr36016_basic_test (struct zr36016 *ptr)
+{
+       if (debug) {
+               int i;
+               zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
+               dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
+               for (i = 0; i <= 0x0b; i++)
+                       dprintk(1, "%02x ", zr36016_readi(ptr, i));
+               dprintk(1, "\n");
+       }
+       // for testing just write 0, then the default value to a register and read
+       // it back in both cases
+       zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
+       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to vfe processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+       zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
+       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to vfe processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+       // we allow version numbers from 0-3, should be enough, though
+       zr36016_read_version(ptr);
+       if (ptr->version & 0x0c) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, suspicious version %d found...\n",
+                       ptr->name, ptr->version);
+               return -ENXIO;
+       }
+
+       return 0;               /* looks good! */
+}
+
+/* =========================================================================
+   Local helper function:
+
+   simple loop for pushing the init datasets - NO USE --
+   ========================================================================= */
+
+#if 0
+static int zr36016_pushit (struct zr36016 *ptr,
+                          u16             startreg,
+                          u16             len,
+                          const char     *data)
+{
+       int i=0;
+
+       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
+               ptr->name, startreg,len);
+       while (i<len) {
+               zr36016_writei(ptr, startreg++,  data[i++]);
+       }
+
+       return i;
+}
+#endif
+
+/* =========================================================================
+   Basic datasets & init:
+
+   //TODO//
+   ========================================================================= */
+
+// needed offset values          PAL NTSC SECAM
+static const int zr016_xoff[] = { 20, 20, 20 };
+static const int zr016_yoff[] = { 8, 9, 7 };
+
+static void
+zr36016_init (struct zr36016 *ptr)
+{
+       // stop any processing
+       zr36016_write(ptr, ZR016_GOSTOP, 0);
+
+       // mode setup (yuv422 in and out, compression/expansuon due to mode)
+       zr36016_write(ptr, ZR016_MODE,
+                     ZR016_YUV422 | ZR016_YUV422_YUV422 |
+                     (ptr->mode == CODEC_DO_COMPRESSION ?
+                      ZR016_COMPRESSION : ZR016_EXPANSION));
+
+       // misc setup
+       zr36016_writei(ptr, ZR016I_SETUP1,
+                      (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
+                      (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
+       zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
+
+       // Window setup
+       // (no extra offset for now, norm defines offset, default width height)
+       zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
+       zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
+       zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
+       zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
+       zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
+       zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
+       zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
+       zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
+
+       /* shall we continue now, please? */
+       zr36016_write(ptr, ZR016_GOSTOP, 1);
+}
+
+/* =========================================================================
+   CODEC API FUNCTIONS
+
+   this functions are accessed by the master via the API structure
+   ========================================================================= */
+
+/* set compression/expansion mode and launches codec -
+   this should be the last call from the master before starting processing */
+static int
+zr36016_set_mode (struct videocodec *codec,
+                 int                mode)
+{
+       struct zr36016 *ptr = (struct zr36016 *) codec->data;
+
+       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
+
+       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+               return -EINVAL;
+
+       ptr->mode = mode;
+       zr36016_init(ptr);
+
+       return 0;
+}
+
+/* set picture size */
+static int
+zr36016_set_video (struct videocodec   *codec,
+                  struct tvnorm       *norm,
+                  struct vfe_settings *cap,
+                  struct vfe_polarity *pol)
+{
+       struct zr36016 *ptr = (struct zr36016 *) codec->data;
+
+       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
+               ptr->name, norm->HStart, norm->VStart,
+               cap->x, cap->y, cap->width, cap->height,
+               cap->decimation);
+
+       /* if () return -EINVAL;
+        * trust the master driver that it knows what it does - so
+        * we allow invalid startx/y for now ... */
+       ptr->width = cap->width;
+       ptr->height = cap->height;
+       /* (Ronald) This is ugly. zoran_device.c, line 387
+        * already mentions what happens if HStart is even
+        * (blue faces, etc., cr/cb inversed). There's probably
+        * some good reason why HStart is 0 instead of 1, so I'm
+        * leaving it to this for now, but really... This can be
+        * done a lot simpler */
+       ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
+       /* Something to note here (I don't understand it), setting
+        * VStart too high will cause the codec to 'not work'. I
+        * really don't get it. values of 16 (VStart) already break
+        * it here. Just '0' seems to work. More testing needed! */
+       ptr->yoff = norm->VStart + cap->y;
+       /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
+       ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
+       ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
+
+       return 0;
+}
+
+/* additional control functions */
+static int
+zr36016_control (struct videocodec *codec,
+                int                type,
+                int                size,
+                void              *data)
+{
+       struct zr36016 *ptr = (struct zr36016 *) codec->data;
+       int *ival = (int *) data;
+
+       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
+               size);
+
+       switch (type) {
+       case CODEC_G_STATUS:    /* get last status - we don't know it ... */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = 0;
+               break;
+
+       case CODEC_G_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = 0;
+               break;
+
+       case CODEC_S_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               if (*ival != 0)
+                       return -EINVAL;
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_G_VFE:
+       case CODEC_S_VFE:
+               return 0;
+
+       case CODEC_S_MMAP:
+               /* not available, give an error */
+               return -ENXIO;
+
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+/* =========================================================================
+   Exit and unregister function:
+
+   Deinitializes Zoran's JPEG processor
+   ========================================================================= */
+
+static int
+zr36016_unset (struct videocodec *codec)
+{
+       struct zr36016 *ptr = codec->data;
+
+       if (ptr) {
+               /* do wee need some codec deinit here, too ???? */
+
+               dprintk(1, "%s: finished codec #%d\n", ptr->name,
+                       ptr->num);
+               kfree(ptr);
+               codec->data = NULL;
+
+               zr36016_codecs--;
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+/* =========================================================================
+   Setup and registry function:
+
+   Initializes Zoran's JPEG processor
+
+   Also sets pixel size, average code size, mode (compr./decompr.)
+   (the given size is determined by the processor with the video interface)
+   ========================================================================= */
+
+static int
+zr36016_setup (struct videocodec *codec)
+{
+       struct zr36016 *ptr;
+       int res;
+
+       dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
+               zr36016_codecs);
+
+       if (zr36016_codecs == MAX_CODECS) {
+               dprintk(1,
+                       KERN_ERR "zr36016: Can't attach more codecs!\n");
+               return -ENOSPC;
+       }
+       //mem structure init
+       codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
+       if (NULL == ptr) {
+               dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
+               return -ENOMEM;
+       }
+
+       snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
+                zr36016_codecs);
+       ptr->num = zr36016_codecs++;
+       ptr->codec = codec;
+
+       //testing
+       res = zr36016_basic_test(ptr);
+       if (res < 0) {
+               zr36016_unset(codec);
+               return res;
+       }
+       //final setup
+       ptr->mode = CODEC_DO_COMPRESSION;
+       ptr->width = 768;
+       ptr->height = 288;
+       ptr->xdec = 1;
+       ptr->ydec = 0;
+       zr36016_init(ptr);
+
+       dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
+               ptr->name, ptr->version);
+
+       return 0;
+}
+
+static const struct videocodec zr36016_codec = {
+       .owner = THIS_MODULE,
+       .name = "zr36016",
+       .magic = 0L,            // magic not used
+       .flags =
+           CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
+           CODEC_FLAG_DECODER,
+       .type = CODEC_TYPE_ZR36016,
+       .setup = zr36016_setup, // functionality
+       .unset = zr36016_unset,
+       .set_mode = zr36016_set_mode,
+       .set_video = zr36016_set_video,
+       .control = zr36016_control,
+       // others are not used
+};
+
+/* =========================================================================
+   HOOK IN DRIVER AS KERNEL MODULE
+   ========================================================================= */
+
+static int __init
+zr36016_init_module (void)
+{
+       //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
+       zr36016_codecs = 0;
+       return videocodec_register(&zr36016_codec);
+}
+
+static void __exit
+zr36016_cleanup_module (void)
+{
+       if (zr36016_codecs) {
+               dprintk(1,
+                       "zr36016: something's wrong - %d codecs left somehow.\n",
+                       zr36016_codecs);
+       }
+       videocodec_unregister(&zr36016_codec);
+}
+
+module_init(zr36016_init_module);
+module_exit(zr36016_cleanup_module);
+
+MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
+MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
+                  ZR016_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/zoran/zr36016.h b/drivers/media/pci/zoran/zr36016.h
new file mode 100644 (file)
index 0000000..8c79229
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Zoran ZR36016 basic configuration functions - header file
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36016.h,v 1.1.2.3 2003/01/14 21:18:07 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 ZR36016_H
+#define ZR36016_H
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36016 {
+       char name[32];
+       int num;
+       /* io datastructure */
+       struct videocodec *codec;
+       // coder status
+       __u8 version;
+       // actual coder setup
+       int mode;
+
+       __u16 xoff;
+       __u16 yoff;
+       __u16 width;
+       __u16 height;
+       __u16 xdec;
+       __u16 ydec;
+};
+
+/* direct  register addresses */
+#define ZR016_GOSTOP      0x00
+#define ZR016_MODE        0x01
+#define ZR016_IADDR       0x02
+#define ZR016_IDATA       0x03
+
+/* indirect  register addresses */
+#define ZR016I_SETUP1     0x00
+#define ZR016I_SETUP2     0x01
+#define ZR016I_NAX_LO     0x02
+#define ZR016I_NAX_HI     0x03
+#define ZR016I_PAX_LO     0x04
+#define ZR016I_PAX_HI     0x05
+#define ZR016I_NAY_LO     0x06
+#define ZR016I_NAY_HI     0x07
+#define ZR016I_PAY_LO     0x08
+#define ZR016I_PAY_HI     0x09
+#define ZR016I_NOL_LO     0x0a
+#define ZR016I_NOL_HI     0x0b
+
+/* possible values for mode register */
+#define ZR016_RGB444_YUV444  0x00
+#define ZR016_RGB444_YUV422  0x01
+#define ZR016_RGB444_YUV411  0x02
+#define ZR016_RGB444_Y400    0x03
+#define ZR016_RGB444_RGB444  0x04
+#define ZR016_YUV444_YUV444  0x08
+#define ZR016_YUV444_YUV422  0x09
+#define ZR016_YUV444_YUV411  0x0a
+#define ZR016_YUV444_Y400    0x0b
+#define ZR016_YUV444_RGB444  0x0c
+#define ZR016_YUV422_YUV422  0x11
+#define ZR016_YUV422_YUV411  0x12
+#define ZR016_YUV422_Y400    0x13
+#define ZR016_YUV411_YUV411  0x16
+#define ZR016_YUV411_Y400    0x17
+#define ZR016_4444_4444      0x19
+#define ZR016_100_100        0x1b
+
+#define ZR016_RGB444         0x00
+#define ZR016_YUV444         0x20
+#define ZR016_YUV422         0x40
+
+#define ZR016_COMPRESSION    0x80
+#define ZR016_EXPANSION      0x80
+
+/* possible values for setup 1 register */
+#define ZR016_CKRT           0x80
+#define ZR016_VERT           0x40
+#define ZR016_HORZ           0x20
+#define ZR016_HRFL           0x10
+#define ZR016_DSFL           0x08
+#define ZR016_SBFL           0x04
+#define ZR016_RSTR           0x02
+#define ZR016_CNTI           0x01
+
+/* possible values for setup 2 register */
+#define ZR016_SYEN           0x40
+#define ZR016_CCIR           0x04
+#define ZR016_SIGN           0x02
+#define ZR016_YMCS           0x01
+
+#endif                         /*fndef ZR36016_H */
diff --git a/drivers/media/pci/zoran/zr36050.c b/drivers/media/pci/zoran/zr36050.c
new file mode 100644 (file)
index 0000000..e198560
--- /dev/null
@@ -0,0 +1,900 @@
+/*
+ * Zoran ZR36050 basic configuration functions
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 ZR050_VERSION "v0.7.1"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* I/O commands, error codes */
+#include <asm/io.h>
+
+/* headerfile of this module */
+#include "zr36050.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so,
+  just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36050_codecs;
+
+/* debugging is available via module parameter */
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* =========================================================================
+   Local hardware I/O functions:
+
+   read/write via codec layer (registers are located in the master device)
+   ========================================================================= */
+
+/* read and write functions */
+static u8
+zr36050_read (struct zr36050 *ptr,
+             u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->readreg)
+               value = (ptr->codec->master_data->readreg(ptr->codec,
+                                                         reg)) & 0xFF;
+       else
+               dprintk(1,
+                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
+                       ptr->name);
+
+       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
+               value);
+
+       return value;
+}
+
+static void
+zr36050_write (struct zr36050 *ptr,
+              u16             reg,
+              u8              value)
+{
+       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
+               reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg)
+               ptr->codec->master_data->writereg(ptr->codec, reg, value);
+       else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written!\n",
+                       ptr->name);
+}
+
+/* =========================================================================
+   Local helper function:
+
+   status read
+   ========================================================================= */
+
+/* status is kept in datastructure */
+static u8
+zr36050_read_status1 (struct zr36050 *ptr)
+{
+       ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1);
+
+       zr36050_read(ptr, 0);
+       return ptr->status1;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   scale factor read
+   ========================================================================= */
+
+/* scale factor is kept in datastructure */
+static u16
+zr36050_read_scalefactor (struct zr36050 *ptr)
+{
+       ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) |
+                        (zr36050_read(ptr, ZR050_SF_LO) & 0xFF);
+
+       /* leave 0 selected for an eventually GO from master */
+       zr36050_read(ptr, 0);
+       return ptr->scalefact;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   wait if codec is ready to proceed (end of processing) or time is over
+   ========================================================================= */
+
+static void
+zr36050_wait_end (struct zr36050 *ptr)
+{
+       int i = 0;
+
+       while (!(zr36050_read_status1(ptr) & 0x4)) {
+               udelay(1);
+               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
+                       dprintk(1,
+                               "%s: timeout at wait_end (last status: 0x%02x)\n",
+                               ptr->name, ptr->status1);
+                       break;
+               }
+       }
+}
+
+/* =========================================================================
+   Local helper function:
+
+   basic test of "connectivity", writes/reads to/from memory the SOF marker
+   ========================================================================= */
+
+static int
+zr36050_basic_test (struct zr36050 *ptr)
+{
+       zr36050_write(ptr, ZR050_SOF_IDX, 0x00);
+       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00);
+       if ((zr36050_read(ptr, ZR050_SOF_IDX) |
+            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to jpeg processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+       zr36050_write(ptr, ZR050_SOF_IDX, 0xff);
+       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0);
+       if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) |
+            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to jpeg processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+
+       zr36050_wait_end(ptr);
+       if ((ptr->status1 & 0x4) == 0) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, jpeg processor failed (end flag)!\n",
+                       ptr->name);
+               return -EBUSY;
+       }
+
+       return 0;               /* looks good! */
+}
+
+/* =========================================================================
+   Local helper function:
+
+   simple loop for pushing the init datasets
+   ========================================================================= */
+
+static int
+zr36050_pushit (struct zr36050 *ptr,
+               u16             startreg,
+               u16             len,
+               const char     *data)
+{
+       int i = 0;
+
+       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
+               startreg, len);
+       while (i < len) {
+               zr36050_write(ptr, startreg++, data[i++]);
+       }
+
+       return i;
+}
+
+/* =========================================================================
+   Basic datasets:
+
+   jpeg baseline setup data (you find it on lots places in internet, or just
+   extract it from any regular .jpg image...)
+
+   Could be variable, but until it's not needed it they are just fixed to save
+   memory. Otherwise expand zr36050 structure with arrays, push the values to
+   it and initialize from there, as e.g. the linux zr36057/60 driver does it.
+   ========================================================================= */
+
+static const char zr36050_dqt[0x86] = {
+       0xff, 0xdb,             //Marker: DQT
+       0x00, 0x84,             //Length: 2*65+2
+       0x00,                   //Pq,Tq first table
+       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+       0x01,                   //Pq,Tq second table
+       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const char zr36050_dht[0x1a4] = {
+       0xff, 0xc4,             //Marker: DHT
+       0x01, 0xa2,             //Length: 2*AC, 2*DC
+       0x00,                   //DC first table
+       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x01,                   //DC second table
+       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x10,                   //AC first table
+       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
+       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
+       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
+       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+       0xF8, 0xF9, 0xFA,
+       0x11,                   //AC second table
+       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
+       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
+       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
+       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+       0xF9, 0xFA
+};
+
+/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
+#define NO_OF_COMPONENTS          0x3  //Y,U,V
+#define BASELINE_PRECISION        0x8  //MCU size (?)
+static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
+static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
+static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
+
+/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
+static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
+static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
+
+/* =========================================================================
+   Local helper functions:
+
+   calculation and setup of parameter-dependent JPEG baseline segments
+   (needed for compression only)
+   ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+
+/* SOF (start of frame) segment depends on width, height and sampling ratio
+                        of each color component */
+
+static int
+zr36050_set_sof (struct zr36050 *ptr)
+{
+       char sof_data[34];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
+               ptr->width, ptr->height, NO_OF_COMPONENTS);
+       sof_data[0] = 0xff;
+       sof_data[1] = 0xc0;
+       sof_data[2] = 0x00;
+       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
+       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36050
+       sof_data[5] = (ptr->height) >> 8;
+       sof_data[6] = (ptr->height) & 0xff;
+       sof_data[7] = (ptr->width) >> 8;
+       sof_data[8] = (ptr->width) & 0xff;
+       sof_data[9] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sof_data[10 + (i * 3)] = i;     // index identifier
+               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]);  // sampling ratios
+               sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection
+       }
+       return zr36050_pushit(ptr, ZR050_SOF_IDX,
+                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* SOS (start of scan) segment depends on the used scan components
+                       of each color component */
+
+static int
+zr36050_set_sos (struct zr36050 *ptr)
+{
+       char sos_data[16];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOS\n", ptr->name);
+       sos_data[0] = 0xff;
+       sos_data[1] = 0xda;
+       sos_data[2] = 0x00;
+       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
+       sos_data[4] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sos_data[5 + (i * 2)] = i;      // index
+               sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i];   // AC/DC tbl.sel.
+       }
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F;
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
+       return zr36050_pushit(ptr, ZR050_SOS1_IDX,
+                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
+                             sos_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* DRI (define restart interval) */
+
+static int
+zr36050_set_dri (struct zr36050 *ptr)
+{
+       char dri_data[6];       // max. size of register set
+
+       dprintk(3, "%s: write DRI\n", ptr->name);
+       dri_data[0] = 0xff;
+       dri_data[1] = 0xdd;
+       dri_data[2] = 0x00;
+       dri_data[3] = 0x04;
+       dri_data[4] = ptr->dri >> 8;
+       dri_data[5] = ptr->dri & 0xff;
+       return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
+}
+
+/* =========================================================================
+   Setup function:
+
+   Setup compression/decompression of Zoran's JPEG processor
+   ( see also zoran 36050 manual )
+
+   ... sorry for the spaghetti code ...
+   ========================================================================= */
+static void
+zr36050_init (struct zr36050 *ptr)
+{
+       int sum = 0;
+       long bitcnt, tmp;
+
+       if (ptr->mode == CODEC_DO_COMPRESSION) {
+               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
+
+               /* 050 communicates with 057 in master mode */
+               zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR);
+
+               /* encoding table preload for compression */
+               zr36050_write(ptr, ZR050_MODE,
+                             ZR050_MO_COMP | ZR050_MO_TLM);
+               zr36050_write(ptr, ZR050_OPTIONS, 0);
+
+               /* disable all IRQs */
+               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
+               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
+
+               /* volume control settings */
+               /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
+               zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
+               zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
+
+               zr36050_write(ptr, ZR050_AF_HI, 0xff);
+               zr36050_write(ptr, ZR050_AF_M, 0xff);
+               zr36050_write(ptr, ZR050_AF_LO, 0xff);
+
+               /* setup the variable jpeg tables */
+               sum += zr36050_set_sof(ptr);
+               sum += zr36050_set_sos(ptr);
+               sum += zr36050_set_dri(ptr);
+
+               /* setup the fixed jpeg tables - maybe variable, though -
+                * (see table init section above) */
+               dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name);
+               sum += zr36050_pushit(ptr, ZR050_DQT_IDX,
+                                     sizeof(zr36050_dqt), zr36050_dqt);
+               sum += zr36050_pushit(ptr, ZR050_DHT_IDX,
+                                     sizeof(zr36050_dht), zr36050_dht);
+               zr36050_write(ptr, ZR050_APP_IDX, 0xff);
+               zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn);
+               zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00);
+               zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2);
+               sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60,
+                                     ptr->app.data) + 4;
+               zr36050_write(ptr, ZR050_COM_IDX, 0xff);
+               zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe);
+               zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00);
+               zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2);
+               sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60,
+                                     ptr->com.data) + 4;
+
+               /* do the internal huffman table preload */
+               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
+
+               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
+               zr36050_wait_end(ptr);
+               dprintk(2, "%s: Status after table preload: 0x%02x\n",
+                       ptr->name, ptr->status1);
+
+               if ((ptr->status1 & 0x4) == 0) {
+                       dprintk(1, KERN_ERR "%s: init aborted!\n",
+                               ptr->name);
+                       return; // something is wrong, its timed out!!!!
+               }
+
+               /* setup misc. data for compression (target code sizes) */
+
+               /* size of compressed code to reach without header data */
+               sum = ptr->real_code_vol - sum;
+               bitcnt = sum << 3;      /* need the size in bits */
+
+               tmp = bitcnt >> 16;
+               dprintk(3,
+                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
+                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
+               zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff);
+
+               bitcnt -= bitcnt >> 7;  // bits without stuffing
+               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
+
+               tmp = bitcnt >> 16;
+               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
+                       ptr->name, bitcnt, tmp);
+               zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8);
+               zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff);
+
+               /* compression setup with or without bitrate control */
+               zr36050_write(ptr, ZR050_MODE,
+                             ZR050_MO_COMP | ZR050_MO_PASS2 |
+                             (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0));
+
+               /* this headers seem to deliver "valid AVI" jpeg frames */
+               zr36050_write(ptr, ZR050_MARKERS_EN,
+                             ZR050_ME_DQT | ZR050_ME_DHT |
+                             ((ptr->app.len > 0) ? ZR050_ME_APP : 0) |
+                             ((ptr->com.len > 0) ? ZR050_ME_COM : 0));
+       } else {
+               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
+
+               /* 050 communicates with 055 in master mode */
+               zr36050_write(ptr, ZR050_HARDWARE,
+                             ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK);
+
+               /* encoding table preload */
+               zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM);
+
+               /* disable all IRQs */
+               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
+               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
+
+               dprintk(3, "%s: write DHT\n", ptr->name);
+               zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht),
+                              zr36050_dht);
+
+               /* do the internal huffman table preload */
+               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
+
+               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
+               zr36050_wait_end(ptr);
+               dprintk(2, "%s: Status after table preload: 0x%02x\n",
+                       ptr->name, ptr->status1);
+
+               if ((ptr->status1 & 0x4) == 0) {
+                       dprintk(1, KERN_ERR "%s: init aborted!\n",
+                               ptr->name);
+                       return; // something is wrong, its timed out!!!!
+               }
+
+               /* setup misc. data for expansion */
+               zr36050_write(ptr, ZR050_MODE, 0);
+               zr36050_write(ptr, ZR050_MARKERS_EN, 0);
+       }
+
+       /* adr on selected, to allow GO from master */
+       zr36050_read(ptr, 0);
+}
+
+/* =========================================================================
+   CODEC API FUNCTIONS
+
+   this functions are accessed by the master via the API structure
+   ========================================================================= */
+
+/* set compression/expansion mode and launches codec -
+   this should be the last call from the master before starting processing */
+static int
+zr36050_set_mode (struct videocodec *codec,
+                 int                mode)
+{
+       struct zr36050 *ptr = (struct zr36050 *) codec->data;
+
+       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
+
+       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+               return -EINVAL;
+
+       ptr->mode = mode;
+       zr36050_init(ptr);
+
+       return 0;
+}
+
+/* set picture size (norm is ignored as the codec doesn't know about it) */
+static int
+zr36050_set_video (struct videocodec   *codec,
+                  struct tvnorm       *norm,
+                  struct vfe_settings *cap,
+                  struct vfe_polarity *pol)
+{
+       struct zr36050 *ptr = (struct zr36050 *) codec->data;
+       int size;
+
+       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
+               ptr->name, norm->HStart, norm->VStart,
+               cap->x, cap->y, cap->width, cap->height,
+               cap->decimation, cap->quality);
+       /* if () return -EINVAL;
+        * trust the master driver that it knows what it does - so
+        * we allow invalid startx/y and norm for now ... */
+       ptr->width = cap->width / (cap->decimation & 0xff);
+       ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
+
+       /* (KM) JPEG quality */
+       size = ptr->width * ptr->height;
+       size *= 16; /* size in bits */
+       /* apply quality setting */
+       size = size * cap->quality / 200;
+
+       /* Minimum: 1kb */
+       if (size < 8192)
+               size = 8192;
+       /* Maximum: 7/8 of code buffer */
+       if (size > ptr->total_code_vol * 7)
+               size = ptr->total_code_vol * 7;
+
+       ptr->real_code_vol = size >> 3; /* in bytes */
+
+       /* Set max_block_vol here (previously in zr36050_init, moved
+        * here for consistency with zr36060 code */
+       zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
+
+       return 0;
+}
+
+/* additional control functions */
+static int
+zr36050_control (struct videocodec *codec,
+                int                type,
+                int                size,
+                void              *data)
+{
+       struct zr36050 *ptr = (struct zr36050 *) codec->data;
+       int *ival = (int *) data;
+
+       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
+               size);
+
+       switch (type) {
+       case CODEC_G_STATUS:    /* get last status */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               zr36050_read_status1(ptr);
+               *ival = ptr->status1;
+               break;
+
+       case CODEC_G_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = CODEC_MODE_BJPG;
+               break;
+
+       case CODEC_S_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               if (*ival != CODEC_MODE_BJPG)
+                       return -EINVAL;
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_G_VFE:
+       case CODEC_S_VFE:
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_S_MMAP:
+               /* not available, give an error */
+               return -ENXIO;
+
+       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = ptr->total_code_vol;
+               break;
+
+       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->total_code_vol = *ival;
+               /* (Kieran Morrissey)
+                * code copied from zr36060.c to ensure proper bitrate */
+               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+               break;
+
+       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = zr36050_read_scalefactor(ptr);
+               break;
+
+       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->scalefact = *ival;
+               break;
+
+       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               *app = ptr->app;
+               break;
+       }
+
+       case CODEC_S_JPEG_APP_DATA: {    /* set appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               ptr->app = *app;
+               break;
+       }
+
+       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               *com = ptr->com;
+               break;
+       }
+
+       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               ptr->com = *com;
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+/* =========================================================================
+   Exit and unregister function:
+
+   Deinitializes Zoran's JPEG processor
+   ========================================================================= */
+
+static int
+zr36050_unset (struct videocodec *codec)
+{
+       struct zr36050 *ptr = codec->data;
+
+       if (ptr) {
+               /* do wee need some codec deinit here, too ???? */
+
+               dprintk(1, "%s: finished codec #%d\n", ptr->name,
+                       ptr->num);
+               kfree(ptr);
+               codec->data = NULL;
+
+               zr36050_codecs--;
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+/* =========================================================================
+   Setup and registry function:
+
+   Initializes Zoran's JPEG processor
+
+   Also sets pixel size, average code size, mode (compr./decompr.)
+   (the given size is determined by the processor with the video interface)
+   ========================================================================= */
+
+static int
+zr36050_setup (struct videocodec *codec)
+{
+       struct zr36050 *ptr;
+       int res;
+
+       dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n",
+               zr36050_codecs);
+
+       if (zr36050_codecs == MAX_CODECS) {
+               dprintk(1,
+                       KERN_ERR "zr36050: Can't attach more codecs!\n");
+               return -ENOSPC;
+       }
+       //mem structure init
+       codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
+       if (NULL == ptr) {
+               dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
+               return -ENOMEM;
+       }
+
+       snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
+                zr36050_codecs);
+       ptr->num = zr36050_codecs++;
+       ptr->codec = codec;
+
+       //testing
+       res = zr36050_basic_test(ptr);
+       if (res < 0) {
+               zr36050_unset(codec);
+               return res;
+       }
+       //final setup
+       memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8);
+       memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8);
+
+       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
+                                * (what is the difference?) */
+       ptr->mode = CODEC_DO_COMPRESSION;
+       ptr->width = 384;
+       ptr->height = 288;
+       ptr->total_code_vol = 16000;
+       ptr->max_block_vol = 240;
+       ptr->scalefact = 0x100;
+       ptr->dri = 1;
+
+       /* no app/com marker by default */
+       ptr->app.appn = 0;
+       ptr->app.len = 0;
+       ptr->com.len = 0;
+
+       zr36050_init(ptr);
+
+       dprintk(1, KERN_INFO "%s: codec attached and running\n",
+               ptr->name);
+
+       return 0;
+}
+
+static const struct videocodec zr36050_codec = {
+       .owner = THIS_MODULE,
+       .name = "zr36050",
+       .magic = 0L,            // magic not used
+       .flags =
+           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
+           CODEC_FLAG_DECODER,
+       .type = CODEC_TYPE_ZR36050,
+       .setup = zr36050_setup, // functionality
+       .unset = zr36050_unset,
+       .set_mode = zr36050_set_mode,
+       .set_video = zr36050_set_video,
+       .control = zr36050_control,
+       // others are not used
+};
+
+/* =========================================================================
+   HOOK IN DRIVER AS KERNEL MODULE
+   ========================================================================= */
+
+static int __init
+zr36050_init_module (void)
+{
+       //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION);
+       zr36050_codecs = 0;
+       return videocodec_register(&zr36050_codec);
+}
+
+static void __exit
+zr36050_cleanup_module (void)
+{
+       if (zr36050_codecs) {
+               dprintk(1,
+                       "zr36050: something's wrong - %d codecs left somehow.\n",
+                       zr36050_codecs);
+       }
+       videocodec_unregister(&zr36050_codec);
+}
+
+module_init(zr36050_init_module);
+module_exit(zr36050_cleanup_module);
+
+MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
+MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors "
+                  ZR050_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/zoran/zr36050.h b/drivers/media/pci/zoran/zr36050.h
new file mode 100644 (file)
index 0000000..9f52f0c
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Zoran ZR36050 basic configuration functions - header file
+ *
+ * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
+ *
+ * $Id: zr36050.h,v 1.1.2.2 2003/01/14 21:18:22 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 ZR36050_H
+#define ZR36050_H
+
+#include "videocodec.h"
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36050 {
+       char name[32];
+       int num;
+       /* io datastructure */
+       struct videocodec *codec;
+       // last coder status
+       __u8 status1;
+       // actual coder setup
+       int mode;
+
+       __u16 width;
+       __u16 height;
+
+       __u16 bitrate_ctrl;
+
+       __u32 total_code_vol;
+       __u32 real_code_vol;
+       __u16 max_block_vol;
+
+       __u8 h_samp_ratio[8];
+       __u8 v_samp_ratio[8];
+       __u16 scalefact;
+       __u16 dri;
+
+       /* com/app marker */
+       struct jpeg_com_marker com;
+       struct jpeg_app_marker app;
+};
+
+/* zr36050 register addresses */
+#define ZR050_GO                  0x000
+#define ZR050_HARDWARE            0x002
+#define ZR050_MODE                0x003
+#define ZR050_OPTIONS             0x004
+#define ZR050_MBCV                0x005
+#define ZR050_MARKERS_EN          0x006
+#define ZR050_INT_REQ_0           0x007
+#define ZR050_INT_REQ_1           0x008
+#define ZR050_TCV_NET_HI          0x009
+#define ZR050_TCV_NET_MH          0x00a
+#define ZR050_TCV_NET_ML          0x00b
+#define ZR050_TCV_NET_LO          0x00c
+#define ZR050_TCV_DATA_HI         0x00d
+#define ZR050_TCV_DATA_MH         0x00e
+#define ZR050_TCV_DATA_ML         0x00f
+#define ZR050_TCV_DATA_LO         0x010
+#define ZR050_SF_HI               0x011
+#define ZR050_SF_LO               0x012
+#define ZR050_AF_HI               0x013
+#define ZR050_AF_M                0x014
+#define ZR050_AF_LO               0x015
+#define ZR050_ACV_HI              0x016
+#define ZR050_ACV_MH              0x017
+#define ZR050_ACV_ML              0x018
+#define ZR050_ACV_LO              0x019
+#define ZR050_ACT_HI              0x01a
+#define ZR050_ACT_MH              0x01b
+#define ZR050_ACT_ML              0x01c
+#define ZR050_ACT_LO              0x01d
+#define ZR050_ACV_TRUN_HI         0x01e
+#define ZR050_ACV_TRUN_MH         0x01f
+#define ZR050_ACV_TRUN_ML         0x020
+#define ZR050_ACV_TRUN_LO         0x021
+#define ZR050_STATUS_0            0x02e
+#define ZR050_STATUS_1            0x02f
+
+#define ZR050_SOF_IDX             0x040
+#define ZR050_SOS1_IDX            0x07a
+#define ZR050_SOS2_IDX            0x08a
+#define ZR050_SOS3_IDX            0x09a
+#define ZR050_SOS4_IDX            0x0aa
+#define ZR050_DRI_IDX             0x0c0
+#define ZR050_DNL_IDX             0x0c6
+#define ZR050_DQT_IDX             0x0cc
+#define ZR050_DHT_IDX             0x1d4
+#define ZR050_APP_IDX             0x380
+#define ZR050_COM_IDX             0x3c0
+
+/* zr36050 hardware register bits */
+
+#define ZR050_HW_BSWD                0x80
+#define ZR050_HW_MSTR                0x40
+#define ZR050_HW_DMA                 0x20
+#define ZR050_HW_CFIS_1_CLK          0x00
+#define ZR050_HW_CFIS_2_CLK          0x04
+#define ZR050_HW_CFIS_3_CLK          0x08
+#define ZR050_HW_CFIS_4_CLK          0x0C
+#define ZR050_HW_CFIS_5_CLK          0x10
+#define ZR050_HW_CFIS_6_CLK          0x14
+#define ZR050_HW_CFIS_7_CLK          0x18
+#define ZR050_HW_CFIS_8_CLK          0x1C
+#define ZR050_HW_BELE                0x01
+
+/* zr36050 mode register bits */
+
+#define ZR050_MO_COMP                0x80
+#define ZR050_MO_COMP                0x80
+#define ZR050_MO_ATP                 0x40
+#define ZR050_MO_PASS2               0x20
+#define ZR050_MO_TLM                 0x10
+#define ZR050_MO_DCONLY              0x08
+#define ZR050_MO_BRC                 0x04
+
+#define ZR050_MO_ATP                 0x40
+#define ZR050_MO_PASS2               0x20
+#define ZR050_MO_TLM                 0x10
+#define ZR050_MO_DCONLY              0x08
+
+/* zr36050 option register bits */
+
+#define ZR050_OP_NSCN_1              0x00
+#define ZR050_OP_NSCN_2              0x20
+#define ZR050_OP_NSCN_3              0x40
+#define ZR050_OP_NSCN_4              0x60
+#define ZR050_OP_NSCN_5              0x80
+#define ZR050_OP_NSCN_6              0xA0
+#define ZR050_OP_NSCN_7              0xC0
+#define ZR050_OP_NSCN_8              0xE0
+#define ZR050_OP_OVF                 0x10
+
+
+/* zr36050 markers-enable register bits */
+
+#define ZR050_ME_APP                 0x80
+#define ZR050_ME_COM                 0x40
+#define ZR050_ME_DRI                 0x20
+#define ZR050_ME_DQT                 0x10
+#define ZR050_ME_DHT                 0x08
+#define ZR050_ME_DNL                 0x04
+#define ZR050_ME_DQTI                0x02
+#define ZR050_ME_DHTI                0x01
+
+/* zr36050 status0/1 register bit masks */
+
+#define ZR050_ST_RST_MASK            0x20
+#define ZR050_ST_SOF_MASK            0x02
+#define ZR050_ST_SOS_MASK            0x02
+#define ZR050_ST_DATRDY_MASK         0x80
+#define ZR050_ST_MRKDET_MASK         0x40
+#define ZR050_ST_RFM_MASK            0x10
+#define ZR050_ST_RFD_MASK            0x08
+#define ZR050_ST_END_MASK            0x04
+#define ZR050_ST_TCVOVF_MASK         0x02
+#define ZR050_ST_DATOVF_MASK         0x01
+
+/* pixel component idx */
+
+#define ZR050_Y_COMPONENT         0
+#define ZR050_U_COMPONENT         1
+#define ZR050_V_COMPONENT         2
+
+#endif                         /*fndef ZR36050_H */
diff --git a/drivers/media/pci/zoran/zr36057.h b/drivers/media/pci/zoran/zr36057.h
new file mode 100644 (file)
index 0000000..54c9362
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * zr36057.h - zr36057 register offsets
+ *
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.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.
+ */
+
+#ifndef _ZR36057_H_
+#define _ZR36057_H_
+
+
+/* Zoran ZR36057 registers */
+
+#define ZR36057_VFEHCR          0x000  /* Video Front End, Horizontal Configuration Register */
+#define ZR36057_VFEHCR_HSPol            (1<<30)
+#define ZR36057_VFEHCR_HStart           10
+#define ZR36057_VFEHCR_HEnd            0
+#define ZR36057_VFEHCR_Hmask           0x3ff
+
+#define ZR36057_VFEVCR          0x004  /* Video Front End, Vertical Configuration Register */
+#define ZR36057_VFEVCR_VSPol            (1<<30)
+#define ZR36057_VFEVCR_VStart           10
+#define ZR36057_VFEVCR_VEnd            0
+#define ZR36057_VFEVCR_Vmask           0x3ff
+
+#define ZR36057_VFESPFR         0x008  /* Video Front End, Scaler and Pixel Format Register */
+#define ZR36057_VFESPFR_ExtFl           (1<<26)
+#define ZR36057_VFESPFR_TopField        (1<<25)
+#define ZR36057_VFESPFR_VCLKPol         (1<<24)
+#define ZR36057_VFESPFR_HFilter         21
+#define ZR36057_VFESPFR_HorDcm          14
+#define ZR36057_VFESPFR_VerDcm          8
+#define ZR36057_VFESPFR_DispMode        6
+#define ZR36057_VFESPFR_YUV422          (0<<3)
+#define ZR36057_VFESPFR_RGB888          (1<<3)
+#define ZR36057_VFESPFR_RGB565          (2<<3)
+#define ZR36057_VFESPFR_RGB555          (3<<3)
+#define ZR36057_VFESPFR_ErrDif          (1<<2)
+#define ZR36057_VFESPFR_Pack24          (1<<1)
+#define ZR36057_VFESPFR_LittleEndian    (1<<0)
+
+#define ZR36057_VDTR            0x00c  /* Video Display "Top" Register */
+
+#define ZR36057_VDBR            0x010  /* Video Display "Bottom" Register */
+
+#define ZR36057_VSSFGR          0x014  /* Video Stride, Status, and Frame Grab Register */
+#define ZR36057_VSSFGR_DispStride       16
+#define ZR36057_VSSFGR_VidOvf           (1<<8)
+#define ZR36057_VSSFGR_SnapShot         (1<<1)
+#define ZR36057_VSSFGR_FrameGrab        (1<<0)
+
+#define ZR36057_VDCR            0x018  /* Video Display Configuration Register */
+#define ZR36057_VDCR_VidEn              (1<<31)
+#define ZR36057_VDCR_MinPix             24
+#define ZR36057_VDCR_Triton             (1<<24)
+#define ZR36057_VDCR_VidWinHt           12
+#define ZR36057_VDCR_VidWinWid          0
+
+#define ZR36057_MMTR            0x01c  /* Masking Map "Top" Register */
+
+#define ZR36057_MMBR            0x020  /* Masking Map "Bottom" Register */
+
+#define ZR36057_OCR             0x024  /* Overlay Control Register */
+#define ZR36057_OCR_OvlEnable           (1 << 15)
+#define ZR36057_OCR_MaskStride          0
+
+#define ZR36057_SPGPPCR         0x028  /* System, PCI, and General Purpose Pins Control Register */
+#define ZR36057_SPGPPCR_SoftReset      (1<<24)
+
+#define ZR36057_GPPGCR1         0x02c  /* General Purpose Pins and GuestBus Control Register (1) */
+
+#define ZR36057_MCSAR           0x030  /* MPEG Code Source Address Register */
+
+#define ZR36057_MCTCR           0x034  /* MPEG Code Transfer Control Register */
+#define ZR36057_MCTCR_CodTime           (1 << 30)
+#define ZR36057_MCTCR_CEmpty            (1 << 29)
+#define ZR36057_MCTCR_CFlush            (1 << 28)
+#define ZR36057_MCTCR_CodGuestID       20
+#define ZR36057_MCTCR_CodGuestReg      16
+
+#define ZR36057_MCMPR           0x038  /* MPEG Code Memory Pointer Register */
+
+#define ZR36057_ISR             0x03c  /* Interrupt Status Register */
+#define ZR36057_ISR_GIRQ1               (1<<30)
+#define ZR36057_ISR_GIRQ0               (1<<29)
+#define ZR36057_ISR_CodRepIRQ           (1<<28)
+#define ZR36057_ISR_JPEGRepIRQ          (1<<27)
+
+#define ZR36057_ICR             0x040  /* Interrupt Control Register */
+#define ZR36057_ICR_GIRQ1               (1<<30)
+#define ZR36057_ICR_GIRQ0               (1<<29)
+#define ZR36057_ICR_CodRepIRQ           (1<<28)
+#define ZR36057_ICR_JPEGRepIRQ          (1<<27)
+#define ZR36057_ICR_IntPinEn            (1<<24)
+
+#define ZR36057_I2CBR           0x044  /* I2C Bus Register */
+#define ZR36057_I2CBR_SDA              (1<<1)
+#define ZR36057_I2CBR_SCL              (1<<0)
+
+#define ZR36057_JMC             0x100  /* JPEG Mode and Control */
+#define ZR36057_JMC_JPG                 (1 << 31)
+#define ZR36057_JMC_JPGExpMode          (0 << 29)
+#define ZR36057_JMC_JPGCmpMode          (1 << 29)
+#define ZR36057_JMC_MJPGExpMode         (2 << 29)
+#define ZR36057_JMC_MJPGCmpMode         (3 << 29)
+#define ZR36057_JMC_RTBUSY_FB           (1 << 6)
+#define ZR36057_JMC_Go_en               (1 << 5)
+#define ZR36057_JMC_SyncMstr            (1 << 4)
+#define ZR36057_JMC_Fld_per_buff        (1 << 3)
+#define ZR36057_JMC_VFIFO_FB            (1 << 2)
+#define ZR36057_JMC_CFIFO_FB            (1 << 1)
+#define ZR36057_JMC_Stll_LitEndian      (1 << 0)
+
+#define ZR36057_JPC             0x104  /* JPEG Process Control */
+#define ZR36057_JPC_P_Reset             (1 << 7)
+#define ZR36057_JPC_CodTrnsEn           (1 << 5)
+#define ZR36057_JPC_Active              (1 << 0)
+
+#define ZR36057_VSP             0x108  /* Vertical Sync Parameters */
+#define ZR36057_VSP_VsyncSize           16
+#define ZR36057_VSP_FrmTot              0
+
+#define ZR36057_HSP             0x10c  /* Horizontal Sync Parameters */
+#define ZR36057_HSP_HsyncStart          16
+#define ZR36057_HSP_LineTot             0
+
+#define ZR36057_FHAP            0x110  /* Field Horizontal Active Portion */
+#define ZR36057_FHAP_NAX                16
+#define ZR36057_FHAP_PAX                0
+
+#define ZR36057_FVAP            0x114  /* Field Vertical Active Portion */
+#define ZR36057_FVAP_NAY                16
+#define ZR36057_FVAP_PAY                0
+
+#define ZR36057_FPP             0x118  /* Field Process Parameters */
+#define ZR36057_FPP_Odd_Even            (1 << 0)
+
+#define ZR36057_JCBA            0x11c  /* JPEG Code Base Address */
+
+#define ZR36057_JCFT            0x120  /* JPEG Code FIFO Threshold */
+
+#define ZR36057_JCGI            0x124  /* JPEG Codec Guest ID */
+#define ZR36057_JCGI_JPEGuestID         4
+#define ZR36057_JCGI_JPEGuestReg        0
+
+#define ZR36057_GCR2            0x12c  /* GuestBus Control Register (2) */
+
+#define ZR36057_POR             0x200  /* Post Office Register */
+#define ZR36057_POR_POPen               (1<<25)
+#define ZR36057_POR_POTime              (1<<24)
+#define ZR36057_POR_PODir               (1<<23)
+
+#define ZR36057_STR             0x300  /* "Still" Transfer Register */
+
+#endif
diff --git a/drivers/media/pci/zoran/zr36060.c b/drivers/media/pci/zoran/zr36060.c
new file mode 100644 (file)
index 0000000..f08546f
--- /dev/null
@@ -0,0 +1,1010 @@
+/*
+ * Zoran ZR36060 basic configuration functions
+ *
+ * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * $Id: zr36060.c,v 1.1.2.22 2003/05/06 09:35:36 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 ZR060_VERSION "v0.7"
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <linux/types.h>
+#include <linux/wait.h>
+
+/* I/O commands, error codes */
+#include <asm/io.h>
+
+/* headerfile of this module */
+#include "zr36060.h"
+
+/* codec io API */
+#include "videocodec.h"
+
+/* it doesn't make sense to have more than 20 or so,
+  just to prevent some unwanted loops */
+#define MAX_CODECS 20
+
+/* amount of chips attached via this driver */
+static int zr36060_codecs;
+
+static bool 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;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-4)");
+
+#define dprintk(num, format, args...) \
+       do { \
+               if (debug >= num) \
+                       printk(format, ##args); \
+       } while (0)
+
+/* =========================================================================
+   Local hardware I/O functions:
+
+   read/write via codec layer (registers are located in the master device)
+   ========================================================================= */
+
+/* read and write functions */
+static u8
+zr36060_read (struct zr36060 *ptr,
+             u16             reg)
+{
+       u8 value = 0;
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->readreg)
+               value = (ptr->codec->master_data->readreg(ptr->codec,
+                                                         reg)) & 0xff;
+       else
+               dprintk(1,
+                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
+                       ptr->name);
+
+       //dprintk(4, "%s: reading from 0x%04x: %02x\n",ptr->name,reg,value);
+
+       return value;
+}
+
+static void
+zr36060_write(struct zr36060 *ptr,
+             u16             reg,
+             u8              value)
+{
+       //dprintk(4, "%s: writing 0x%02x to 0x%04x\n",ptr->name,value,reg);
+       dprintk(4, "0x%02x @0x%04x\n", value, reg);
+
+       // just in case something is wrong...
+       if (ptr->codec->master_data->writereg)
+               ptr->codec->master_data->writereg(ptr->codec, reg, value);
+       else
+               dprintk(1,
+                       KERN_ERR
+                       "%s: invalid I/O setup, nothing written!\n",
+                       ptr->name);
+}
+
+/* =========================================================================
+   Local helper function:
+
+   status read
+   ========================================================================= */
+
+/* status is kept in datastructure */
+static u8
+zr36060_read_status (struct zr36060 *ptr)
+{
+       ptr->status = zr36060_read(ptr, ZR060_CFSR);
+
+       zr36060_read(ptr, 0);
+       return ptr->status;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   scale factor read
+   ========================================================================= */
+
+/* scale factor is kept in datastructure */
+static u16
+zr36060_read_scalefactor (struct zr36060 *ptr)
+{
+       ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
+                        (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
+
+       /* leave 0 selected for an eventually GO from master */
+       zr36060_read(ptr, 0);
+       return ptr->scalefact;
+}
+
+/* =========================================================================
+   Local helper function:
+
+   wait if codec is ready to proceed (end of processing) or time is over
+   ========================================================================= */
+
+static void
+zr36060_wait_end (struct zr36060 *ptr)
+{
+       int i = 0;
+
+       while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
+               udelay(1);
+               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
+                       dprintk(1,
+                               "%s: timeout at wait_end (last status: 0x%02x)\n",
+                               ptr->name, ptr->status);
+                       break;
+               }
+       }
+}
+
+/* =========================================================================
+   Local helper function:
+
+   basic test of "connectivity", writes/reads to/from memory the SOF marker
+   ========================================================================= */
+
+static int
+zr36060_basic_test (struct zr36060 *ptr)
+{
+       if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
+           (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, can't connect to jpeg processor!\n",
+                       ptr->name);
+               return -ENXIO;
+       }
+
+       zr36060_wait_end(ptr);
+       if (ptr->status & ZR060_CFSR_Busy) {
+               dprintk(1,
+                       KERN_ERR
+                       "%s: attach failed, jpeg processor failed (end flag)!\n",
+                       ptr->name);
+               return -EBUSY;
+       }
+
+       return 0;               /* looks good! */
+}
+
+/* =========================================================================
+   Local helper function:
+
+   simple loop for pushing the init datasets
+   ========================================================================= */
+
+static int
+zr36060_pushit (struct zr36060 *ptr,
+               u16             startreg,
+               u16             len,
+               const char     *data)
+{
+       int i = 0;
+
+       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
+               startreg, len);
+       while (i < len) {
+               zr36060_write(ptr, startreg++, data[i++]);
+       }
+
+       return i;
+}
+
+/* =========================================================================
+   Basic datasets:
+
+   jpeg baseline setup data (you find it on lots places in internet, or just
+   extract it from any regular .jpg image...)
+
+   Could be variable, but until it's not needed it they are just fixed to save
+   memory. Otherwise expand zr36060 structure with arrays, push the values to
+   it and initialize from there, as e.g. the linux zr36057/60 driver does it.
+   ========================================================================= */
+
+static const char zr36060_dqt[0x86] = {
+       0xff, 0xdb,             //Marker: DQT
+       0x00, 0x84,             //Length: 2*65+2
+       0x00,                   //Pq,Tq first table
+       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+       0x01,                   //Pq,Tq second table
+       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
+};
+
+static const char zr36060_dht[0x1a4] = {
+       0xff, 0xc4,             //Marker: DHT
+       0x01, 0xa2,             //Length: 2*AC, 2*DC
+       0x00,                   //DC first table
+       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x01,                   //DC second table
+       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+       0x10,                   //AC first table
+       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
+       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
+       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
+       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
+       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
+       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
+       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
+       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+       0xF8, 0xF9, 0xFA,
+       0x11,                   //AC second table
+       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
+       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
+       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
+       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
+       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
+       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
+       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
+       0xF9, 0xFA
+};
+
+/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
+#define NO_OF_COMPONENTS          0x3  //Y,U,V
+#define BASELINE_PRECISION        0x8  //MCU size (?)
+static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
+static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
+static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
+
+/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
+static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
+static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
+
+/* =========================================================================
+   Local helper functions:
+
+   calculation and setup of parameter-dependent JPEG baseline segments
+   (needed for compression only)
+   ========================================================================= */
+
+/* ------------------------------------------------------------------------- */
+
+/* SOF (start of frame) segment depends on width, height and sampling ratio
+                        of each color component */
+
+static int
+zr36060_set_sof (struct zr36060 *ptr)
+{
+       char sof_data[34];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
+               ptr->width, ptr->height, NO_OF_COMPONENTS);
+       sof_data[0] = 0xff;
+       sof_data[1] = 0xc0;
+       sof_data[2] = 0x00;
+       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
+       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36060
+       sof_data[5] = (ptr->height) >> 8;
+       sof_data[6] = (ptr->height) & 0xff;
+       sof_data[7] = (ptr->width) >> 8;
+       sof_data[8] = (ptr->width) & 0xff;
+       sof_data[9] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sof_data[10 + (i * 3)] = i;     // index identifier
+               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
+                                        (ptr->v_samp_ratio[i]); // sampling ratios
+               sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
+       }
+       return zr36060_pushit(ptr, ZR060_SOF_IDX,
+                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* SOS (start of scan) segment depends on the used scan components
+                       of each color component */
+
+static int
+zr36060_set_sos (struct zr36060 *ptr)
+{
+       char sos_data[16];      // max. size of register set
+       int i;
+
+       dprintk(3, "%s: write SOS\n", ptr->name);
+       sos_data[0] = 0xff;
+       sos_data[1] = 0xda;
+       sos_data[2] = 0x00;
+       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
+       sos_data[4] = NO_OF_COMPONENTS;
+       for (i = 0; i < NO_OF_COMPONENTS; i++) {
+               sos_data[5 + (i * 2)] = i;      // index
+               sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
+                                       zr36060_ta[i]; // AC/DC tbl.sel.
+       }
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
+       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
+       return zr36060_pushit(ptr, ZR060_SOS_IDX,
+                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
+                             sos_data);
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* DRI (define restart interval) */
+
+static int
+zr36060_set_dri (struct zr36060 *ptr)
+{
+       char dri_data[6];       // max. size of register set
+
+       dprintk(3, "%s: write DRI\n", ptr->name);
+       dri_data[0] = 0xff;
+       dri_data[1] = 0xdd;
+       dri_data[2] = 0x00;
+       dri_data[3] = 0x04;
+       dri_data[4] = (ptr->dri) >> 8;
+       dri_data[5] = (ptr->dri) & 0xff;
+       return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
+}
+
+/* =========================================================================
+   Setup function:
+
+   Setup compression/decompression of Zoran's JPEG processor
+   ( see also zoran 36060 manual )
+
+   ... sorry for the spaghetti code ...
+   ========================================================================= */
+static void
+zr36060_init (struct zr36060 *ptr)
+{
+       int sum = 0;
+       long bitcnt, tmp;
+
+       if (ptr->mode == CODEC_DO_COMPRESSION) {
+               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
+
+               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
+
+               /* 060 communicates with 067 in master mode */
+               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
+
+               /* Compression with or without variable scale factor */
+               /*FIXME: What about ptr->bitrate_ctrl? */
+               zr36060_write(ptr, ZR060_CMR,
+                             ZR060_CMR_Comp | ZR060_CMR_Pass2 |
+                             ZR060_CMR_BRB);
+
+               /* Must be zero */
+               zr36060_write(ptr, ZR060_MBZ, 0x00);
+               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
+               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
+
+               /* Disable all IRQs - no DataErr means autoreset */
+               zr36060_write(ptr, ZR060_IMR, 0);
+
+               /* volume control settings */
+               zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
+               zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
+
+               zr36060_write(ptr, ZR060_AF_HI, 0xff);
+               zr36060_write(ptr, ZR060_AF_M, 0xff);
+               zr36060_write(ptr, ZR060_AF_LO, 0xff);
+
+               /* setup the variable jpeg tables */
+               sum += zr36060_set_sof(ptr);
+               sum += zr36060_set_sos(ptr);
+               sum += zr36060_set_dri(ptr);
+
+               /* setup the fixed jpeg tables - maybe variable, though -
+                * (see table init section above) */
+               sum +=
+                   zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
+                                  zr36060_dqt);
+               sum +=
+                   zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
+                                  zr36060_dht);
+               zr36060_write(ptr, ZR060_APP_IDX, 0xff);
+               zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
+               zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
+               zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
+               sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60,
+                                     ptr->app.data) + 4;
+               zr36060_write(ptr, ZR060_COM_IDX, 0xff);
+               zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
+               zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
+               zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
+               sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60,
+                                     ptr->com.data) + 4;
+
+               /* setup misc. data for compression (target code sizes) */
+
+               /* size of compressed code to reach without header data */
+               sum = ptr->real_code_vol - sum;
+               bitcnt = sum << 3;      /* need the size in bits */
+
+               tmp = bitcnt >> 16;
+               dprintk(3,
+                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
+                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
+               zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
+
+               bitcnt -= bitcnt >> 7;  // bits without stuffing
+               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
+
+               tmp = bitcnt >> 16;
+               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
+                       ptr->name, bitcnt, tmp);
+               zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
+               tmp = bitcnt & 0xffff;
+               zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
+               zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
+
+               /* JPEG markers to be included in the compressed stream */
+               zr36060_write(ptr, ZR060_MER,
+                             ZR060_MER_DQT | ZR060_MER_DHT |
+                             ((ptr->com.len > 0) ? ZR060_MER_Com : 0) |
+                             ((ptr->app.len > 0) ? ZR060_MER_App : 0));
+
+               /* Setup the Video Frontend */
+               /* Limit pixel range to 16..235 as per CCIR-601 */
+               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
+
+       } else {
+               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
+
+               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
+
+               /* 060 communicates with 067 in master mode */
+               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
+
+               /* Decompression */
+               zr36060_write(ptr, ZR060_CMR, 0);
+
+               /* Must be zero */
+               zr36060_write(ptr, ZR060_MBZ, 0x00);
+               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
+               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
+
+               /* Disable all IRQs - no DataErr means autoreset */
+               zr36060_write(ptr, ZR060_IMR, 0);
+
+               /* setup misc. data for expansion */
+               zr36060_write(ptr, ZR060_MER, 0);
+
+               /* setup the fixed jpeg tables - maybe variable, though -
+                * (see table init section above) */
+               zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
+                              zr36060_dht);
+
+               /* Setup the Video Frontend */
+               //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt);
+               //this doesn't seem right and doesn't work...
+               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
+       }
+
+       /* Load the tables */
+       zr36060_write(ptr, ZR060_LOAD,
+                     ZR060_LOAD_SyncRst | ZR060_LOAD_Load);
+       zr36060_wait_end(ptr);
+       dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name,
+               ptr->status);
+
+       if (ptr->status & ZR060_CFSR_Busy) {
+               dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
+               return;         // something is wrong, its timed out!!!!
+       }
+}
+
+/* =========================================================================
+   CODEC API FUNCTIONS
+
+   this functions are accessed by the master via the API structure
+   ========================================================================= */
+
+/* set compression/expansion mode and launches codec -
+   this should be the last call from the master before starting processing */
+static int
+zr36060_set_mode (struct videocodec *codec,
+                 int                mode)
+{
+       struct zr36060 *ptr = (struct zr36060 *) codec->data;
+
+       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
+
+       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
+               return -EINVAL;
+
+       ptr->mode = mode;
+       zr36060_init(ptr);
+
+       return 0;
+}
+
+/* set picture size (norm is ignored as the codec doesn't know about it) */
+static int
+zr36060_set_video (struct videocodec   *codec,
+                  struct tvnorm       *norm,
+                  struct vfe_settings *cap,
+                  struct vfe_polarity *pol)
+{
+       struct zr36060 *ptr = (struct zr36060 *) codec->data;
+       u32 reg;
+       int size;
+
+       dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
+               cap->x, cap->y, cap->width, cap->height, cap->decimation);
+
+       /* if () return -EINVAL;
+        * trust the master driver that it knows what it does - so
+        * we allow invalid startx/y and norm for now ... */
+       ptr->width = cap->width / (cap->decimation & 0xff);
+       ptr->height = cap->height / (cap->decimation >> 8);
+
+       zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
+
+       /* Note that VSPol/HSPol bits in zr36060 have the opposite
+        * meaning of their zr360x7 counterparts with the same names
+        * N.b. for VSPol this is only true if FIVEdge = 0 (default,
+        * left unchanged here - in accordance with datasheet).
+       */
+       reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0)
+           | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0)
+           | (pol->field_pol ? ZR060_VPR_FIPol : 0)
+           | (pol->blank_pol ? ZR060_VPR_BLPol : 0)
+           | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0)
+           | (pol->poe_pol ? ZR060_VPR_PoePol : 0)
+           | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0)
+           | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0);
+       zr36060_write(ptr, ZR060_VPR, reg);
+
+       reg = 0;
+       switch (cap->decimation & 0xff) {
+       default:
+       case 1:
+               break;
+
+       case 2:
+               reg |= ZR060_SR_HScale2;
+               break;
+
+       case 4:
+               reg |= ZR060_SR_HScale4;
+               break;
+       }
+
+       switch (cap->decimation >> 8) {
+       default:
+       case 1:
+               break;
+
+       case 2:
+               reg |= ZR060_SR_VScale;
+               break;
+       }
+       zr36060_write(ptr, ZR060_SR, reg);
+
+       zr36060_write(ptr, ZR060_BCR_Y, 0x00);
+       zr36060_write(ptr, ZR060_BCR_U, 0x80);
+       zr36060_write(ptr, ZR060_BCR_V, 0x80);
+
+       /* sync generator */
+
+       reg = norm->Ht - 1;     /* Vtotal */
+       zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
+
+       reg = norm->Wt - 1;     /* Htotal */
+       zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
+
+       reg = 6 - 1;            /* VsyncSize */
+       zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
+
+       //reg   = 30 - 1;               /* HsyncSize */
+///*CP*/        reg = (zr->params.norm == 1 ? 57 : 68);
+       reg = 68;
+       zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
+
+       reg = norm->VStart - 1; /* BVstart */
+       zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
+
+       reg += norm->Ha / 2;    /* BVend */
+       zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
+
+       reg = norm->HStart - 1; /* BHstart */
+       zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
+
+       reg += norm->Wa;        /* BHend */
+       zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
+
+       /* active area */
+       reg = cap->y + norm->VStart;    /* Vstart */
+       zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
+
+       reg += cap->height;     /* Vend */
+       zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
+
+       reg = cap->x + norm->HStart;    /* Hstart */
+       zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
+
+       reg += cap->width;      /* Hend */
+       zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
+
+       /* subimage area */
+       reg = norm->VStart - 4; /* SVstart */
+       zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
+
+       reg += norm->Ha / 2 + 8;        /* SVend */
+       zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
+
+       reg = norm->HStart /*+ 64 */  - 4;      /* SHstart */
+       zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
+
+       reg += norm->Wa + 8;    /* SHend */
+       zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
+       zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
+
+       size = ptr->width * ptr->height;
+       /* Target compressed field size in bits: */
+       size = size * 16;       /* uncompressed size in bits */
+       /* (Ronald) by default, quality = 100 is a compression
+        * ratio 1:2. Setting low_bitrate (insmod option) sets
+        * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
+        * buz can't handle more at decimation=1... Use low_bitrate if
+        * you have a Buz, unless you know what you're doing */
+       size = size * cap->quality / (low_bitrate ? 400 : 200);
+       /* Lower limit (arbitrary, 1 KB) */
+       if (size < 8192)
+               size = 8192;
+       /* Upper limit: 7/8 of the code buffers */
+       if (size > ptr->total_code_vol * 7)
+               size = ptr->total_code_vol * 7;
+
+       ptr->real_code_vol = size >> 3; /* in bytes */
+
+       /* the MBCVR is the *maximum* block volume, according to the
+        * JPEG ISO specs, this shouldn't be used, since that allows
+        * for the best encoding quality. So set it to it's max value */
+       reg = ptr->max_block_vol;
+       zr36060_write(ptr, ZR060_MBCVR, reg);
+
+       return 0;
+}
+
+/* additional control functions */
+static int
+zr36060_control (struct videocodec *codec,
+                int                type,
+                int                size,
+                void              *data)
+{
+       struct zr36060 *ptr = (struct zr36060 *) codec->data;
+       int *ival = (int *) data;
+
+       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
+               size);
+
+       switch (type) {
+       case CODEC_G_STATUS:    /* get last status */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               zr36060_read_status(ptr);
+               *ival = ptr->status;
+               break;
+
+       case CODEC_G_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = CODEC_MODE_BJPG;
+               break;
+
+       case CODEC_S_CODEC_MODE:
+               if (size != sizeof(int))
+                       return -EFAULT;
+               if (*ival != CODEC_MODE_BJPG)
+                       return -EINVAL;
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_G_VFE:
+       case CODEC_S_VFE:
+               /* not needed, do nothing */
+               return 0;
+
+       case CODEC_S_MMAP:
+               /* not available, give an error */
+               return -ENXIO;
+
+       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = ptr->total_code_vol;
+               break;
+
+       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->total_code_vol = *ival;
+               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+               break;
+
+       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               *ival = zr36060_read_scalefactor(ptr);
+               break;
+
+       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
+               if (size != sizeof(int))
+                       return -EFAULT;
+               ptr->scalefact = *ival;
+               break;
+
+       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               *app = ptr->app;
+               break;
+       }
+
+       case CODEC_S_JPEG_APP_DATA: {   /* set appn marker data */
+               struct jpeg_app_marker *app = data;
+
+               if (size != sizeof(struct jpeg_app_marker))
+                       return -EFAULT;
+
+               ptr->app = *app;
+               break;
+       }
+
+       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               *com = ptr->com;
+               break;
+       }
+
+       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
+               struct jpeg_com_marker *com = data;
+
+               if (size != sizeof(struct jpeg_com_marker))
+                       return -EFAULT;
+
+               ptr->com = *com;
+               break;
+       }
+
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
+
+/* =========================================================================
+   Exit and unregister function:
+
+   Deinitializes Zoran's JPEG processor
+   ========================================================================= */
+
+static int
+zr36060_unset (struct videocodec *codec)
+{
+       struct zr36060 *ptr = codec->data;
+
+       if (ptr) {
+               /* do wee need some codec deinit here, too ???? */
+
+               dprintk(1, "%s: finished codec #%d\n", ptr->name,
+                       ptr->num);
+               kfree(ptr);
+               codec->data = NULL;
+
+               zr36060_codecs--;
+               return 0;
+       }
+
+       return -EFAULT;
+}
+
+/* =========================================================================
+   Setup and registry function:
+
+   Initializes Zoran's JPEG processor
+
+   Also sets pixel size, average code size, mode (compr./decompr.)
+   (the given size is determined by the processor with the video interface)
+   ========================================================================= */
+
+static int
+zr36060_setup (struct videocodec *codec)
+{
+       struct zr36060 *ptr;
+       int res;
+
+       dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
+               zr36060_codecs);
+
+       if (zr36060_codecs == MAX_CODECS) {
+               dprintk(1,
+                       KERN_ERR "zr36060: Can't attach more codecs!\n");
+               return -ENOSPC;
+       }
+       //mem structure init
+       codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
+       if (NULL == ptr) {
+               dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
+               return -ENOMEM;
+       }
+
+       snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
+                zr36060_codecs);
+       ptr->num = zr36060_codecs++;
+       ptr->codec = codec;
+
+       //testing
+       res = zr36060_basic_test(ptr);
+       if (res < 0) {
+               zr36060_unset(codec);
+               return res;
+       }
+       //final setup
+       memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
+       memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
+
+       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
+                                * (what is the difference?) */
+       ptr->mode = CODEC_DO_COMPRESSION;
+       ptr->width = 384;
+       ptr->height = 288;
+       ptr->total_code_vol = 16000;    /* CHECKME */
+       ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
+       ptr->max_block_vol = 240;       /* CHECKME, was 120 is 240 */
+       ptr->scalefact = 0x100;
+       ptr->dri = 1;           /* CHECKME, was 8 is 1 */
+
+       /* by default, no COM or APP markers - app should set those */
+       ptr->com.len = 0;
+       ptr->app.appn = 0;
+       ptr->app.len = 0;
+
+       zr36060_init(ptr);
+
+       dprintk(1, KERN_INFO "%s: codec attached and running\n",
+               ptr->name);
+
+       return 0;
+}
+
+static const struct videocodec zr36060_codec = {
+       .owner = THIS_MODULE,
+       .name = "zr36060",
+       .magic = 0L,            // magic not used
+       .flags =
+           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
+           CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
+       .type = CODEC_TYPE_ZR36060,
+       .setup = zr36060_setup, // functionality
+       .unset = zr36060_unset,
+       .set_mode = zr36060_set_mode,
+       .set_video = zr36060_set_video,
+       .control = zr36060_control,
+       // others are not used
+};
+
+/* =========================================================================
+   HOOK IN DRIVER AS KERNEL MODULE
+   ========================================================================= */
+
+static int __init
+zr36060_init_module (void)
+{
+       //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION);
+       zr36060_codecs = 0;
+       return videocodec_register(&zr36060_codec);
+}
+
+static void __exit
+zr36060_cleanup_module (void)
+{
+       if (zr36060_codecs) {
+               dprintk(1,
+                       "zr36060: something's wrong - %d codecs left somehow.\n",
+                       zr36060_codecs);
+       }
+
+       /* however, we can't just stay alive */
+       videocodec_unregister(&zr36060_codec);
+}
+
+module_init(zr36060_init_module);
+module_exit(zr36060_cleanup_module);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
+MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
+                  ZR060_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/zoran/zr36060.h b/drivers/media/pci/zoran/zr36060.h
new file mode 100644 (file)
index 0000000..914ffa4
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Zoran ZR36060 basic configuration functions - header file
+ *
+ * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * $Id: zr36060.h,v 1.1.1.1.2.3 2003/01/14 21:18:47 rbultje Exp $
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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 ZR36060_H
+#define ZR36060_H
+
+#include "videocodec.h"
+
+/* data stored for each zoran jpeg codec chip */
+struct zr36060 {
+       char name[32];
+       int num;
+       /* io datastructure */
+       struct videocodec *codec;
+       // last coder status
+       __u8 status;
+       // actual coder setup
+       int mode;
+
+       __u16 width;
+       __u16 height;
+
+       __u16 bitrate_ctrl;
+
+       __u32 total_code_vol;
+       __u32 real_code_vol;
+       __u16 max_block_vol;
+
+       __u8 h_samp_ratio[8];
+       __u8 v_samp_ratio[8];
+       __u16 scalefact;
+       __u16 dri;
+
+       /* app/com marker data */
+       struct jpeg_app_marker app;
+       struct jpeg_com_marker com;
+};
+
+/* ZR36060 register addresses */
+#define ZR060_LOAD                     0x000
+#define ZR060_CFSR                     0x001
+#define ZR060_CIR                      0x002
+#define ZR060_CMR                      0x003
+#define ZR060_MBZ                      0x004
+#define ZR060_MBCVR                    0x005
+#define ZR060_MER                      0x006
+#define ZR060_IMR                      0x007
+#define ZR060_ISR                      0x008
+#define ZR060_TCV_NET_HI               0x009
+#define ZR060_TCV_NET_MH               0x00a
+#define ZR060_TCV_NET_ML               0x00b
+#define ZR060_TCV_NET_LO               0x00c
+#define ZR060_TCV_DATA_HI              0x00d
+#define ZR060_TCV_DATA_MH              0x00e
+#define ZR060_TCV_DATA_ML              0x00f
+#define ZR060_TCV_DATA_LO              0x010
+#define ZR060_SF_HI                    0x011
+#define ZR060_SF_LO                    0x012
+#define ZR060_AF_HI                    0x013
+#define ZR060_AF_M                     0x014
+#define ZR060_AF_LO                    0x015
+#define ZR060_ACV_HI                   0x016
+#define ZR060_ACV_MH                   0x017
+#define ZR060_ACV_ML                   0x018
+#define ZR060_ACV_LO                   0x019
+#define ZR060_ACT_HI                   0x01a
+#define ZR060_ACT_MH                   0x01b
+#define ZR060_ACT_ML                   0x01c
+#define ZR060_ACT_LO                   0x01d
+#define ZR060_ACV_TRUN_HI              0x01e
+#define ZR060_ACV_TRUN_MH              0x01f
+#define ZR060_ACV_TRUN_ML              0x020
+#define ZR060_ACV_TRUN_LO              0x021
+#define ZR060_IDR_DEV                  0x022
+#define ZR060_IDR_REV                  0x023
+#define ZR060_TCR_HI                   0x024
+#define ZR060_TCR_LO                   0x025
+#define ZR060_VCR                      0x030
+#define ZR060_VPR                      0x031
+#define ZR060_SR                       0x032
+#define ZR060_BCR_Y                    0x033
+#define ZR060_BCR_U                    0x034
+#define ZR060_BCR_V                    0x035
+#define ZR060_SGR_VTOTAL_HI            0x036
+#define ZR060_SGR_VTOTAL_LO            0x037
+#define ZR060_SGR_HTOTAL_HI            0x038
+#define ZR060_SGR_HTOTAL_LO            0x039
+#define ZR060_SGR_VSYNC                        0x03a
+#define ZR060_SGR_HSYNC                        0x03b
+#define ZR060_SGR_BVSTART              0x03c
+#define ZR060_SGR_BHSTART              0x03d
+#define ZR060_SGR_BVEND_HI             0x03e
+#define ZR060_SGR_BVEND_LO             0x03f
+#define ZR060_SGR_BHEND_HI             0x040
+#define ZR060_SGR_BHEND_LO             0x041
+#define ZR060_AAR_VSTART_HI            0x042
+#define ZR060_AAR_VSTART_LO            0x043
+#define ZR060_AAR_VEND_HI              0x044
+#define ZR060_AAR_VEND_LO              0x045
+#define ZR060_AAR_HSTART_HI            0x046
+#define ZR060_AAR_HSTART_LO            0x047
+#define ZR060_AAR_HEND_HI              0x048
+#define ZR060_AAR_HEND_LO              0x049
+#define ZR060_SWR_VSTART_HI            0x04a
+#define ZR060_SWR_VSTART_LO            0x04b
+#define ZR060_SWR_VEND_HI              0x04c
+#define ZR060_SWR_VEND_LO              0x04d
+#define ZR060_SWR_HSTART_HI            0x04e
+#define ZR060_SWR_HSTART_LO            0x04f
+#define ZR060_SWR_HEND_HI              0x050
+#define ZR060_SWR_HEND_LO              0x051
+
+#define ZR060_SOF_IDX                  0x060
+#define ZR060_SOS_IDX                  0x07a
+#define ZR060_DRI_IDX                  0x0c0
+#define ZR060_DQT_IDX                  0x0cc
+#define ZR060_DHT_IDX                  0x1d4
+#define ZR060_APP_IDX                  0x380
+#define ZR060_COM_IDX                  0x3c0
+
+/* ZR36060 LOAD register bits */
+
+#define ZR060_LOAD_Load                        (1 << 7)
+#define ZR060_LOAD_SyncRst             (1 << 0)
+
+/* ZR36060 Code FIFO Status register bits */
+
+#define ZR060_CFSR_Busy                        (1 << 7)
+#define ZR060_CFSR_CBusy               (1 << 2)
+#define ZR060_CFSR_CFIFO               (3 << 0)
+
+/* ZR36060 Code Interface register */
+
+#define ZR060_CIR_Code16               (1 << 7)
+#define ZR060_CIR_Endian               (1 << 6)
+#define ZR060_CIR_CFIS                 (1 << 2)
+#define ZR060_CIR_CodeMstr             (1 << 0)
+
+/* ZR36060 Codec Mode register */
+
+#define ZR060_CMR_Comp                 (1 << 7)
+#define ZR060_CMR_ATP                  (1 << 6)
+#define ZR060_CMR_Pass2                        (1 << 5)
+#define ZR060_CMR_TLM                  (1 << 4)
+#define ZR060_CMR_BRB                  (1 << 2)
+#define ZR060_CMR_FSF                  (1 << 1)
+
+/* ZR36060 Markers Enable register */
+
+#define ZR060_MER_App                  (1 << 7)
+#define ZR060_MER_Com                  (1 << 6)
+#define ZR060_MER_DRI                  (1 << 5)
+#define ZR060_MER_DQT                  (1 << 4)
+#define ZR060_MER_DHT                  (1 << 3)
+
+/* ZR36060 Interrupt Mask register */
+
+#define ZR060_IMR_EOAV                 (1 << 3)
+#define ZR060_IMR_EOI                  (1 << 2)
+#define ZR060_IMR_End                  (1 << 1)
+#define ZR060_IMR_DataErr              (1 << 0)
+
+/* ZR36060 Interrupt Status register */
+
+#define ZR060_ISR_ProCnt               (3 << 6)
+#define ZR060_ISR_EOAV                 (1 << 3)
+#define ZR060_ISR_EOI                  (1 << 2)
+#define ZR060_ISR_End                  (1 << 1)
+#define ZR060_ISR_DataErr              (1 << 0)
+
+/* ZR36060 Video Control register */
+
+#define ZR060_VCR_Video8               (1 << 7)
+#define ZR060_VCR_Range                        (1 << 6)
+#define ZR060_VCR_FIDet                        (1 << 3)
+#define ZR060_VCR_FIVedge              (1 << 2)
+#define ZR060_VCR_FIExt                        (1 << 1)
+#define ZR060_VCR_SyncMstr             (1 << 0)
+
+/* ZR36060 Video Polarity register */
+
+#define ZR060_VPR_VCLKPol              (1 << 7)
+#define ZR060_VPR_PValPol              (1 << 6)
+#define ZR060_VPR_PoePol               (1 << 5)
+#define ZR060_VPR_SImgPol              (1 << 4)
+#define ZR060_VPR_BLPol                        (1 << 3)
+#define ZR060_VPR_FIPol                        (1 << 2)
+#define ZR060_VPR_HSPol                        (1 << 1)
+#define ZR060_VPR_VSPol                        (1 << 0)
+
+/* ZR36060 Scaling register */
+
+#define ZR060_SR_VScale                        (1 << 2)
+#define ZR060_SR_HScale2               (1 << 0)
+#define ZR060_SR_HScale4               (2 << 0)
+
+#endif                         /*fndef ZR36060_H */
index f3d4228..a837194 100644 (file)
@@ -619,14 +619,6 @@ menuconfig V4L_PCI_DRIVERS
 
 if V4L_PCI_DRIVERS
 
-source "drivers/media/video/cx18/Kconfig"
-
-source "drivers/media/video/cx23885/Kconfig"
-
-source "drivers/media/video/cx25821/Kconfig"
-
-source "drivers/media/video/cx88/Kconfig"
-
 config VIDEO_HEXIUM_GEMINI
        tristate "Hexium Gemini frame grabber"
        depends on PCI && VIDEO_V4L2 && I2C
@@ -650,8 +642,6 @@ config VIDEO_HEXIUM_ORION
          To compile this driver as a module, choose M here: the
          module will be called hexium_orion.
 
-source "drivers/media/video/ivtv/Kconfig"
-
 config VIDEO_MEYE
        tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
        depends on PCI && SONY_LAPTOP && VIDEO_V4L2
@@ -682,11 +672,6 @@ config VIDEO_MXB
          To compile this driver as a module, choose M here: the
          module will be called mxb.
 
-source "drivers/media/video/saa7134/Kconfig"
-
-source "drivers/media/video/saa7164/Kconfig"
-
-source "drivers/media/video/zoran/Kconfig"
 
 config STA2X11_VIP
        tristate "STA2X11 VIP Video For Linux"
index df60ffa..322a159 100644 (file)
@@ -87,16 +87,12 @@ obj-$(CONFIG_SOC_CAMERA_TW9910)             += tw9910.o
 
 # And now the v4l2 drivers:
 
-obj-$(CONFIG_VIDEO_ZORAN) += zoran/
 obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
 obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
 obj-$(CONFIG_VIDEO_W9966) += w9966.o
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_VINO) += vino.o
 obj-$(CONFIG_VIDEO_MEYE) += meye.o
-obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
-obj-$(CONFIG_VIDEO_CX88) += cx88/
-obj-$(CONFIG_VIDEO_CX25821) += cx25821/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
@@ -116,13 +112,9 @@ obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
 obj-$(CONFIG_VIDEO_OMAP3)      += omap3isp/
 
-obj-$(CONFIG_VIDEO_IVTV) += ivtv/
-obj-$(CONFIG_VIDEO_CX18) += cx18/
-
 obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
-obj-$(CONFIG_VIDEO_CX23885) += cx23885/
 
 obj-$(CONFIG_VIDEO_AK881X)             += ak881x.o
 
@@ -157,8 +149,6 @@ obj-$(CONFIG_ARCH_DAVINCI)          += davinci/
 
 obj-$(CONFIG_VIDEO_SH_VOU)             += sh_vou.o
 
-obj-$(CONFIG_VIDEO_SAA7164)     += saa7164/
-
 obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
 
 obj-y  += davinci/
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig
deleted file mode 100644 (file)
index 53b3c77..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-config VIDEO_CX18
-       tristate "Conexant cx23418 MPEG encoder support"
-       depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
-       select I2C_ALGOBIT
-       select VIDEOBUF_VMALLOC
-       depends on RC_CORE
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEO_CX2341X
-       select VIDEO_CS5345
-       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         This is a video4linux driver for Conexant cx23418 based
-         PCI combo video recorder devices.
-
-         This is used in devices such as the Hauppauge HVR-1600
-         cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx18.
-
-config VIDEO_CX18_ALSA
-       tristate "Conexant 23418 DMA audio support"
-       depends on VIDEO_CX18 && SND && EXPERIMENTAL
-       select SND_PCM
-       ---help---
-         This is a video4linux driver for direct (DMA) audio on
-         Conexant 23418 based TV cards using ALSA.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx18-alsa.
diff --git a/drivers/media/video/cx18/Makefile b/drivers/media/video/cx18/Makefile
deleted file mode 100644 (file)
index d3ff154..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-cx18-objs    := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.o \
-       cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
-       cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
-       cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
-       cx18-dvb.o cx18-io.o
-cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
-
-obj-$(CONFIG_VIDEO_CX18) += cx18.o
-obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
-
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c
deleted file mode 100644 (file)
index 6d2a982..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- *  ALSA interface to cx18 PCM capture streams
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
- *
- *  Portions of this work were sponsored by ONELAN Limited.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-
-#include <media/v4l2-device.h>
-
-#include <sound/core.h>
-#include <sound/initval.h>
-
-#include "cx18-driver.h"
-#include "cx18-version.h"
-#include "cx18-alsa.h"
-#include "cx18-alsa-mixer.h"
-#include "cx18-alsa-pcm.h"
-
-int cx18_alsa_debug;
-
-#define CX18_DEBUG_ALSA_INFO(fmt, arg...) \
-       do { \
-               if (cx18_alsa_debug & 2) \
-                       printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \
-       } while (0);
-
-module_param_named(debug, cx18_alsa_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-                "Debug level (bitmask). Default: 0\n"
-                "\t\t\t  1/0x0001: warning\n"
-                "\t\t\t  2/0x0002: info\n");
-
-MODULE_AUTHOR("Andy Walls");
-MODULE_DESCRIPTION("CX23418 ALSA Interface");
-MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
-MODULE_LICENSE("GPL");
-
-MODULE_VERSION(CX18_VERSION);
-
-static inline
-struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev)
-{
-       return to_cx18(v4l2_dev)->alsa;
-}
-
-static inline
-struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev)
-{
-       return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev);
-}
-
-static void snd_cx18_card_free(struct snd_cx18_card *cxsc)
-{
-       if (cxsc == NULL)
-               return;
-
-       if (cxsc->v4l2_dev != NULL)
-               to_cx18(cxsc->v4l2_dev)->alsa = NULL;
-
-       /* FIXME - take any other stopping actions needed */
-
-       kfree(cxsc);
-}
-
-static void snd_cx18_card_private_free(struct snd_card *sc)
-{
-       if (sc == NULL)
-               return;
-       snd_cx18_card_free(sc->private_data);
-       sc->private_data = NULL;
-       sc->private_free = NULL;
-}
-
-static int snd_cx18_card_create(struct v4l2_device *v4l2_dev,
-                                      struct snd_card *sc,
-                                      struct snd_cx18_card **cxsc)
-{
-       *cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL);
-       if (*cxsc == NULL)
-               return -ENOMEM;
-
-       (*cxsc)->v4l2_dev = v4l2_dev;
-       (*cxsc)->sc = sc;
-
-       sc->private_data = *cxsc;
-       sc->private_free = snd_cx18_card_private_free;
-
-       return 0;
-}
-
-static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc)
-{
-       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
-       struct snd_card *sc = cxsc->sc;
-
-       /* sc->driver is used by alsa-lib's configurator: simple, unique */
-       strlcpy(sc->driver, "CX23418", sizeof(sc->driver));
-
-       /* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */
-       snprintf(sc->shortname,  sizeof(sc->shortname), "CX18-%d",
-                cx->instance);
-
-       /* sc->longname is read from /proc/asound/cards */
-       snprintf(sc->longname, sizeof(sc->longname),
-                "CX23418 #%d %s TV/FM Radio/Line-In Capture",
-                cx->instance, cx->card_name);
-
-       return 0;
-}
-
-static int snd_cx18_init(struct v4l2_device *v4l2_dev)
-{
-       struct cx18 *cx = to_cx18(v4l2_dev);
-       struct snd_card *sc = NULL;
-       struct snd_cx18_card *cxsc;
-       int ret;
-
-       /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
-
-       /* (1) Check and increment the device index */
-       /* This is a no-op for us.  We'll use the cx->instance */
-
-       /* (2) Create a card instance */
-       ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
-                             SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
-                             THIS_MODULE, 0, &sc);
-       if (ret) {
-               CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
-                             __func__, ret);
-               goto err_exit;
-       }
-
-       /* (3) Create a main component */
-       ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc);
-       if (ret) {
-               CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n",
-                             __func__, ret);
-               goto err_exit_free;
-       }
-
-       /* (4) Set the driver ID and name strings */
-       snd_cx18_card_set_names(cxsc);
-
-
-       ret = snd_cx18_pcm_create(cxsc);
-       if (ret) {
-               CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
-                             __func__, ret);
-               goto err_exit_free;
-       }
-       /* FIXME - proc files */
-
-       /* (7) Set the driver data and return 0 */
-       /* We do this out of normal order for PCI drivers to avoid races */
-       cx->alsa = cxsc;
-
-       /* (6) Register the card instance */
-       ret = snd_card_register(sc);
-       if (ret) {
-               cx->alsa = NULL;
-               CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
-                             __func__, ret);
-               goto err_exit_free;
-       }
-
-       return 0;
-
-err_exit_free:
-       if (sc != NULL)
-               snd_card_free(sc);
-       kfree(cxsc);
-err_exit:
-       return ret;
-}
-
-int cx18_alsa_load(struct cx18 *cx)
-{
-       struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
-       struct cx18_stream *s;
-
-       if (v4l2_dev == NULL) {
-               printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
-                      __func__);
-               return 0;
-       }
-
-       cx = to_cx18(v4l2_dev);
-       if (cx == NULL) {
-               printk(KERN_ERR "cx18-alsa cx is NULL\n");
-               return 0;
-       }
-
-       s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
-       if (s->video_dev == NULL) {
-               CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
-                                    "skipping\n", __func__);
-               return 0;
-       }
-
-       if (cx->alsa != NULL) {
-               CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n",
-                             __func__);
-               return 0;
-       }
-
-       if (snd_cx18_init(v4l2_dev)) {
-               CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n",
-                             __func__);
-       } else {
-               CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance "
-                                    "\n", __func__);
-       }
-       return 0;
-}
-
-static int __init cx18_alsa_init(void)
-{
-       printk(KERN_INFO "cx18-alsa: module loading...\n");
-       cx18_ext_init = &cx18_alsa_load;
-       return 0;
-}
-
-static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc)
-{
-       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
-
-       /* FIXME - pointer checks & shutdown cxsc */
-
-       snd_card_free(cxsc->sc);
-       cx->alsa = NULL;
-}
-
-static int __exit cx18_alsa_exit_callback(struct device *dev, void *data)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-       struct snd_cx18_card *cxsc;
-
-       if (v4l2_dev == NULL) {
-               printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
-                      __func__);
-               return 0;
-       }
-
-       cxsc = to_snd_cx18_card(v4l2_dev);
-       if (cxsc == NULL) {
-               CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n",
-                              __func__);
-               return 0;
-       }
-
-       snd_cx18_exit(cxsc);
-       return 0;
-}
-
-static void __exit cx18_alsa_exit(void)
-{
-       struct device_driver *drv;
-       int ret;
-
-       printk(KERN_INFO "cx18-alsa: module unloading...\n");
-
-       drv = driver_find("cx18", &pci_bus_type);
-       ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
-       (void)ret;      /* suppress compiler warning */
-
-       cx18_ext_init = NULL;
-       printk(KERN_INFO "cx18-alsa: module unload complete\n");
-}
-
-module_init(cx18_alsa_init);
-module_exit(cx18_alsa_exit);
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.c b/drivers/media/video/cx18/cx18-alsa-mixer.c
deleted file mode 100644 (file)
index 341bddc..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  ALSA mixer controls for the
- *  ALSA interface to cx18 PCM capture streams
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/spinlock.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-device.h>
-
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/tlv.h>
-
-#include "cx18-alsa.h"
-#include "cx18-driver.h"
-
-/*
- * Note the cx18-av-core volume scale is funny, due to the alignment of the
- * scale with another chip's range:
- *
- * v4l2_control value  /512    indicated dB    actual dB       reg 0x8d4
- * 0x0000 - 0x01ff       0     -119            -96             228
- * 0x0200 - 0x02ff       1     -118            -96             228
- * ...
- * 0x2c00 - 0x2dff      22      -97            -96             228
- * 0x2e00 - 0x2fff      23      -96            -96             228
- * 0x3000 - 0x31ff      24      -95            -95             226
- * ...
- * 0xee00 - 0xefff     119        0              0              36
- * ...
- * 0xfe00 - 0xffff     127       +8             +8              20
- */
-static inline int dB_to_cx18_av_vol(int dB)
-{
-       if (dB < -96)
-               dB = -96;
-       else if (dB > 8)
-               dB = 8;
-       return (dB + 119) << 9;
-}
-
-static inline int cx18_av_vol_to_dB(int v)
-{
-       if (v < (23 << 9))
-               v = (23 << 9);
-       else if (v > (127 << 9))
-               v = (127 << 9);
-       return (v >> 9) - 119;
-}
-
-static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol,
-                                     struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 1;
-       /* We're already translating values, just keep this control in dB */
-       uinfo->value.integer.min  = -96;
-       uinfo->value.integer.max  =   8;
-       uinfo->value.integer.step =   1;
-       return 0;
-}
-
-static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl,
-                                    struct snd_ctl_elem_value *uctl)
-{
-       struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
-       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
-       struct v4l2_control vctrl;
-       int ret;
-
-       vctrl.id = V4L2_CID_AUDIO_VOLUME;
-       vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
-
-       snd_cx18_lock(cxsc);
-       ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
-       snd_cx18_unlock(cxsc);
-
-       if (!ret)
-               uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value);
-       return ret;
-}
-
-static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl,
-                                    struct snd_ctl_elem_value *uctl)
-{
-       struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
-       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
-       struct v4l2_control vctrl;
-       int ret;
-
-       vctrl.id = V4L2_CID_AUDIO_VOLUME;
-       vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
-
-       snd_cx18_lock(cxsc);
-
-       /* Fetch current state */
-       ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
-
-       if (ret ||
-           (cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
-
-               /* Set, if needed */
-               vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
-               ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl);
-               if (!ret)
-                       ret = 1; /* Indicate control was changed w/o error */
-       }
-       snd_cx18_unlock(cxsc);
-
-       return ret;
-}
-
-
-/* This is a bit of overkill, the slider is already in dB internally */
-static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0);
-
-static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Analog TV Capture Volume",
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-       .info = snd_cx18_mixer_tv_volume_info,
-       .get = snd_cx18_mixer_tv_volume_get,
-       .put = snd_cx18_mixer_tv_volume_put,
-       .tlv.p = snd_cx18_mixer_tv_vol_db_scale
-};
-
-/* FIXME - add mute switch and balance, bass, treble sliders:
-       V4L2_CID_AUDIO_MUTE
-
-       V4L2_CID_AUDIO_BALANCE
-
-       V4L2_CID_AUDIO_BASS
-       V4L2_CID_AUDIO_TREBLE
-*/
-
-/* FIXME - add stereo, lang1, lang2, mono menu */
-/* FIXME - add CS5345 I2S volume for HVR-1600 */
-
-int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc)
-{
-       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
-       struct snd_card *sc = cxsc->sc;
-       int ret;
-
-       strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername));
-
-       ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc));
-       if (ret) {
-               CX18_ALSA_WARN("%s: failed to add %s control, err %d\n",
-                               __func__, snd_cx18_mixer_tv_vol.name, ret);
-       }
-       return ret;
-}
diff --git a/drivers/media/video/cx18/cx18-alsa-mixer.h b/drivers/media/video/cx18/cx18-alsa-mixer.h
deleted file mode 100644 (file)
index ec92387..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  ALSA mixer controls for the
- *  ALSA interface to cx18 PCM capture streams
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc);
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.c b/drivers/media/video/cx18/cx18-alsa-pcm.c
deleted file mode 100644 (file)
index 7a5b84a..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- *  ALSA PCM device for the
- *  ALSA interface to cx18 PCM capture streams
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
- *
- *  Portions of this work were sponsored by ONELAN Limited.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/vmalloc.h>
-
-#include <media/v4l2-device.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-
-#include "cx18-driver.h"
-#include "cx18-queue.h"
-#include "cx18-streams.h"
-#include "cx18-fileops.h"
-#include "cx18-alsa.h"
-
-static unsigned int pcm_debug;
-module_param(pcm_debug, int, 0644);
-MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
-
-#define dprintk(fmt, arg...) do {                                      \
-           if (pcm_debug)                                              \
-               printk(KERN_INFO "cx18-alsa-pcm %s: " fmt,              \
-                                 __func__, ##arg);                     \
-       } while (0)
-
-static struct snd_pcm_hardware snd_cx18_hw_capture = {
-       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP           |
-               SNDRV_PCM_INFO_INTERLEAVED    |
-               SNDRV_PCM_INFO_MMAP_VALID,
-
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates = SNDRV_PCM_RATE_48000,
-
-       .rate_min = 48000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
-       .period_bytes_min = 64,         /* 12544/2, */
-       .period_bytes_max = 12544,
-       .periods_min = 2,
-       .periods_max = 98,              /* 12544, */
-};
-
-void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data,
-                                size_t num_bytes)
-{
-       struct snd_pcm_substream *substream;
-       struct snd_pcm_runtime *runtime;
-       unsigned int oldptr;
-       unsigned int stride;
-       int period_elapsed = 0;
-       int length;
-
-       dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc,
-               pcm_data, num_bytes);
-
-       substream = cxsc->capture_pcm_substream;
-       if (substream == NULL) {
-               dprintk("substream was NULL\n");
-               return;
-       }
-
-       runtime = substream->runtime;
-       if (runtime == NULL) {
-               dprintk("runtime was NULL\n");
-               return;
-       }
-
-       stride = runtime->frame_bits >> 3;
-       if (stride == 0) {
-               dprintk("stride is zero\n");
-               return;
-       }
-
-       length = num_bytes / stride;
-       if (length == 0) {
-               dprintk("%s: length was zero\n", __func__);
-               return;
-       }
-
-       if (runtime->dma_area == NULL) {
-               dprintk("dma area was NULL - ignoring\n");
-               return;
-       }
-
-       oldptr = cxsc->hwptr_done_capture;
-       if (oldptr + length >= runtime->buffer_size) {
-               unsigned int cnt =
-                       runtime->buffer_size - oldptr;
-               memcpy(runtime->dma_area + oldptr * stride, pcm_data,
-                      cnt * stride);
-               memcpy(runtime->dma_area, pcm_data + cnt * stride,
-                      length * stride - cnt * stride);
-       } else {
-               memcpy(runtime->dma_area + oldptr * stride, pcm_data,
-                      length * stride);
-       }
-       snd_pcm_stream_lock(substream);
-
-       cxsc->hwptr_done_capture += length;
-       if (cxsc->hwptr_done_capture >=
-           runtime->buffer_size)
-               cxsc->hwptr_done_capture -=
-                       runtime->buffer_size;
-
-       cxsc->capture_transfer_done += length;
-       if (cxsc->capture_transfer_done >=
-           runtime->period_size) {
-               cxsc->capture_transfer_done -=
-                       runtime->period_size;
-               period_elapsed = 1;
-       }
-
-       snd_pcm_stream_unlock(substream);
-
-       if (period_elapsed)
-               snd_pcm_period_elapsed(substream);
-}
-
-static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream)
-{
-       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
-       struct cx18 *cx = to_cx18(v4l2_dev);
-       struct cx18_stream *s;
-       struct cx18_open_id item;
-       int ret;
-
-       /* Instruct the cx18 to start sending packets */
-       snd_cx18_lock(cxsc);
-       s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
-
-       item.cx = cx;
-       item.type = s->type;
-       item.open_id = cx->open_id++;
-
-       /* See if the stream is available */
-       if (cx18_claim_stream(&item, item.type)) {
-               /* No, it's already in use */
-               snd_cx18_unlock(cxsc);
-               return -EBUSY;
-       }
-
-       if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
-           test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-               /* We're already streaming.  No additional action required */
-               snd_cx18_unlock(cxsc);
-               return 0;
-       }
-
-
-       runtime->hw = snd_cx18_hw_capture;
-       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-       cxsc->capture_pcm_substream = substream;
-       runtime->private_data = cx;
-
-       cx->pcm_announce_callback = cx18_alsa_announce_pcm_data;
-
-       /* Not currently streaming, so start it up */
-       set_bit(CX18_F_S_STREAMING, &s->s_flags);
-       ret = cx18_start_v4l2_encode_stream(s);
-       snd_cx18_unlock(cxsc);
-
-       return ret;
-}
-
-static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
-{
-       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
-       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
-       struct cx18 *cx = to_cx18(v4l2_dev);
-       struct cx18_stream *s;
-
-       /* Instruct the cx18 to stop sending packets */
-       snd_cx18_lock(cxsc);
-       s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
-       cx18_stop_v4l2_encode_stream(s, 0);
-       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-
-       cx18_release_stream(s);
-
-       cx->pcm_announce_callback = NULL;
-       snd_cx18_unlock(cxsc);
-
-       return 0;
-}
-
-static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
-                    unsigned int cmd, void *arg)
-{
-       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
-       int ret;
-
-       snd_cx18_lock(cxsc);
-       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
-       snd_cx18_unlock(cxsc);
-       return ret;
-}
-
-
-static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
-                                       size_t size)
-{
-       struct snd_pcm_runtime *runtime = subs->runtime;
-
-       dprintk("Allocating vbuffer\n");
-       if (runtime->dma_area) {
-               if (runtime->dma_bytes > size)
-                       return 0;
-
-               vfree(runtime->dma_area);
-       }
-       runtime->dma_area = vmalloc(size);
-       if (!runtime->dma_area)
-               return -ENOMEM;
-
-       runtime->dma_bytes = size;
-
-       return 0;
-}
-
-static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream,
-                        struct snd_pcm_hw_params *params)
-{
-       dprintk("%s called\n", __func__);
-
-       return snd_pcm_alloc_vmalloc_buffer(substream,
-                                          params_buffer_bytes(params));
-}
-
-static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
-       unsigned long flags;
-
-       spin_lock_irqsave(&cxsc->slock, flags);
-       if (substream->runtime->dma_area) {
-               dprintk("freeing pcm capture region\n");
-               vfree(substream->runtime->dma_area);
-               substream->runtime->dma_area = NULL;
-       }
-       spin_unlock_irqrestore(&cxsc->slock, flags);
-
-       return 0;
-}
-
-static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream)
-{
-       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
-
-       cxsc->hwptr_done_capture = 0;
-       cxsc->capture_transfer_done = 0;
-
-       return 0;
-}
-
-static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       return 0;
-}
-
-static
-snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream)
-{
-       unsigned long flags;
-       snd_pcm_uframes_t hwptr_done;
-       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
-
-       spin_lock_irqsave(&cxsc->slock, flags);
-       hwptr_done = cxsc->hwptr_done_capture;
-       spin_unlock_irqrestore(&cxsc->slock, flags);
-
-       return hwptr_done;
-}
-
-static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
-                                            unsigned long offset)
-{
-       void *pageptr = subs->runtime->dma_area + offset;
-
-       return vmalloc_to_page(pageptr);
-}
-
-static struct snd_pcm_ops snd_cx18_pcm_capture_ops = {
-       .open           = snd_cx18_pcm_capture_open,
-       .close          = snd_cx18_pcm_capture_close,
-       .ioctl          = snd_cx18_pcm_ioctl,
-       .hw_params      = snd_cx18_pcm_hw_params,
-       .hw_free        = snd_cx18_pcm_hw_free,
-       .prepare        = snd_cx18_pcm_prepare,
-       .trigger        = snd_cx18_pcm_trigger,
-       .pointer        = snd_cx18_pcm_pointer,
-       .page           = snd_pcm_get_vmalloc_page,
-};
-
-int snd_cx18_pcm_create(struct snd_cx18_card *cxsc)
-{
-       struct snd_pcm *sp;
-       struct snd_card *sc = cxsc->sc;
-       struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
-       struct cx18 *cx = to_cx18(v4l2_dev);
-       int ret;
-
-       ret = snd_pcm_new(sc, "CX23418 PCM",
-                         0, /* PCM device 0, the only one for this card */
-                         0, /* 0 playback substreams */
-                         1, /* 1 capture substream */
-                         &sp);
-       if (ret) {
-               CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
-                             __func__, ret);
-               goto err_exit;
-       }
-
-       spin_lock_init(&cxsc->slock);
-
-       snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
-                       &snd_cx18_pcm_capture_ops);
-       sp->info_flags = 0;
-       sp->private_data = cxsc;
-       strlcpy(sp->name, cx->card_name, sizeof(sp->name));
-
-       return 0;
-
-err_exit:
-       return ret;
-}
diff --git a/drivers/media/video/cx18/cx18-alsa-pcm.h b/drivers/media/video/cx18/cx18-alsa-pcm.h
deleted file mode 100644 (file)
index d26e51f..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  ALSA PCM device for the
- *  ALSA interface to cx18 PCM capture streams
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc);
-
-/* Used by cx18-mailbox to announce the PCM data to the module */
-void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data,
-                                size_t num_bytes);
diff --git a/drivers/media/video/cx18/cx18-alsa.h b/drivers/media/video/cx18/cx18-alsa.h
deleted file mode 100644 (file)
index 447da37..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  ALSA interface to cx18 PCM capture streams
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-struct snd_card;
-
-struct snd_cx18_card {
-       struct v4l2_device *v4l2_dev;
-       struct snd_card *sc;
-       unsigned int capture_transfer_done;
-       unsigned int hwptr_done_capture;
-       struct snd_pcm_substream *capture_pcm_substream;
-       spinlock_t slock;
-};
-
-extern int cx18_alsa_debug;
-
-/*
- * File operations that manipulate the encoder or video or audio subdevices
- * need to be serialized.  Use the same lock we use for v4l2 file ops.
- */
-static inline void snd_cx18_lock(struct snd_cx18_card *cxsc)
-{
-       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
-       mutex_lock(&cx->serialize_lock);
-}
-
-static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
-{
-       struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
-       mutex_unlock(&cx->serialize_lock);
-}
-
-#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
-#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
-#define CX18_ALSA_DBGFLG_INFO  (1 << 1)
-
-#define CX18_ALSA_DEBUG(x, type, fmt, args...) \
-       do { \
-               if ((x) & cx18_alsa_debug) \
-                       printk(KERN_INFO "%s-alsa: " type ": " fmt, \
-                               v4l2_dev->name , ## args); \
-       } while (0)
-
-#define CX18_ALSA_DEBUG_WARN(fmt, args...) \
-       CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_WARN, "warning", fmt , ## args)
-
-#define CX18_ALSA_DEBUG_INFO(fmt, args...) \
-       CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_INFO, "info", fmt , ## args)
-
-#define CX18_ALSA_ERR(fmt, args...) \
-       printk(KERN_ERR "%s-alsa: " fmt, v4l2_dev->name , ## args)
-
-#define CX18_ALSA_WARN(fmt, args...) \
-       printk(KERN_WARNING "%s-alsa: " fmt, v4l2_dev->name , ## args)
-
-#define CX18_ALSA_INFO(fmt, args...) \
-       printk(KERN_INFO "%s-alsa: " fmt, v4l2_dev->name , ## args)
diff --git a/drivers/media/video/cx18/cx18-audio.c b/drivers/media/video/cx18/cx18-audio.c
deleted file mode 100644 (file)
index 3526892..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  cx18 audio-related functions
- *
- *  Derived from ivtv-audio.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-cards.h"
-#include "cx18-audio.h"
-
-#define CX18_AUDIO_ENABLE    0xc72014
-#define CX18_AI1_MUX_MASK    0x30
-#define CX18_AI1_MUX_I2S1    0x00
-#define CX18_AI1_MUX_I2S2    0x10
-#define CX18_AI1_MUX_843_I2S 0x20
-
-/* Selects the audio input and output according to the current
-   settings. */
-int cx18_audio_set_io(struct cx18 *cx)
-{
-       const struct cx18_card_audio_input *in;
-       u32 u, v;
-       int err;
-
-       /* Determine which input to use */
-       if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
-               in = &cx->card->radio_input;
-       else
-               in = &cx->card->audio_inputs[cx->audio_input];
-
-       /* handle muxer chips */
-       v4l2_subdev_call(cx->sd_extmux, audio, s_routing,
-                        (u32) in->muxer_input, 0, 0);
-
-       err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl,
-                              audio, s_routing, in->audio_input, 0, 0);
-       if (err)
-               return err;
-
-       /* FIXME - this internal mux should be abstracted to a subdev */
-       u = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
-       v = u & ~CX18_AI1_MUX_MASK;
-       switch (in->audio_input) {
-       case CX18_AV_AUDIO_SERIAL1:
-               v |= CX18_AI1_MUX_I2S1;
-               break;
-       case CX18_AV_AUDIO_SERIAL2:
-               v |= CX18_AI1_MUX_I2S2;
-               break;
-       default:
-               v |= CX18_AI1_MUX_843_I2S;
-               break;
-       }
-       if (v == u) {
-               /* force a toggle of some AI1 MUX control bits */
-               u &= ~CX18_AI1_MUX_MASK;
-               switch (in->audio_input) {
-               case CX18_AV_AUDIO_SERIAL1:
-                       u |= CX18_AI1_MUX_843_I2S;
-                       break;
-               case CX18_AV_AUDIO_SERIAL2:
-                       u |= CX18_AI1_MUX_843_I2S;
-                       break;
-               default:
-                       u |= CX18_AI1_MUX_I2S1;
-                       break;
-               }
-               cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE,
-                                     u, CX18_AI1_MUX_MASK);
-       }
-       cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
-                             v, CX18_AI1_MUX_MASK);
-       return 0;
-}
diff --git a/drivers/media/video/cx18/cx18-audio.h b/drivers/media/video/cx18/cx18-audio.h
deleted file mode 100644 (file)
index 2731d29..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  cx18 audio-related functions
- *
- *  Derived from ivtv-audio.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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
- */
-
-int cx18_audio_set_io(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
deleted file mode 100644 (file)
index 4a24ffb..0000000
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- *  cx18 ADEC audio functions
- *
- *  Derived from cx25840-audio.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include "cx18-driver.h"
-
-static int set_audclk_freq(struct cx18 *cx, u32 freq)
-{
-       struct cx18_av_state *state = &cx->av_state;
-
-       if (freq != 32000 && freq != 44100 && freq != 48000)
-               return -EINVAL;
-
-       /*
-        * The PLL parameters are based on the external crystal frequency that
-        * would ideally be:
-        *
-        * NTSC Color subcarrier freq * 8 =
-        *      4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
-        *
-        * The accidents of history and rationale that explain from where this
-        * combination of magic numbers originate can be found in:
-        *
-        * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
-        * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
-        *
-        * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
-        * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
-        *
-        * As Mike Bradley has rightly pointed out, it's not the exact crystal
-        * frequency that matters, only that all parts of the driver and
-        * firmware are using the same value (close to the ideal value).
-        *
-        * Since I have a strong suspicion that, if the firmware ever assumes a
-        * crystal value at all, it will assume 28.636360 MHz, the crystal
-        * freq used in calculations in this driver will be:
-        *
-        *      xtal_freq = 28.636360 MHz
-        *
-        * an error of less than 0.13 ppm which is way, way better than any off
-        * the shelf crystal will have for accuracy anyway.
-        *
-        * Below I aim to run the PLLs' VCOs near 400 MHz to minimze error.
-        *
-        * Many thanks to Jeff Campbell and Mike Bradley for their extensive
-        * investigation, experimentation, testing, and suggested solutions of
-        * of audio/video sync problems with SVideo and CVBS captures.
-        */
-
-       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-               switch (freq) {
-               case 32000:
-                       /*
-                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
-                        * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
-                        */
-                       cx18_av_write4(cx, 0x108, 0x200d040f);
-
-                       /* VID_PLL Fraction = 0x2be2fe */
-                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
-                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
-
-                       /* AUX_PLL Fraction = 0x176740c */
-                       /* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/
-                       cx18_av_write4(cx, 0x110, 0x0176740c);
-
-                       /* src3/4/6_ctl */
-                       /* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */
-                       cx18_av_write4(cx, 0x900, 0x0801f77f);
-                       cx18_av_write4(cx, 0x904, 0x0801f77f);
-                       cx18_av_write4(cx, 0x90c, 0x0801f77f);
-
-                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
-                       cx18_av_write(cx, 0x127, 0x60);
-
-                       /* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
-                       cx18_av_write4(cx, 0x12c, 0x11202fff);
-
-                       /*
-                        * EN_AV_LOCK = 0
-                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
-                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
-                        */
-                       cx18_av_write4(cx, 0x128, 0xa00d2ef8);
-                       break;
-
-               case 44100:
-                       /*
-                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
-                        * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x18
-                        */
-                       cx18_av_write4(cx, 0x108, 0x180e040f);
-
-                       /* VID_PLL Fraction = 0x2be2fe */
-                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
-                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
-
-                       /* AUX_PLL Fraction = 0x062a1f2 */
-                       /* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/
-                       cx18_av_write4(cx, 0x110, 0x0062a1f2);
-
-                       /* src3/4/6_ctl */
-                       /* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */
-                       cx18_av_write4(cx, 0x900, 0x08016d59);
-                       cx18_av_write4(cx, 0x904, 0x08016d59);
-                       cx18_av_write4(cx, 0x90c, 0x08016d59);
-
-                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */
-                       cx18_av_write(cx, 0x127, 0x58);
-
-                       /* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
-                       cx18_av_write4(cx, 0x12c, 0x112092ff);
-
-                       /*
-                        * EN_AV_LOCK = 0
-                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
-                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
-                        */
-                       cx18_av_write4(cx, 0x128, 0xa01d4bf8);
-                       break;
-
-               case 48000:
-                       /*
-                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
-                        * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16
-                        */
-                       cx18_av_write4(cx, 0x108, 0x160e040f);
-
-                       /* VID_PLL Fraction = 0x2be2fe */
-                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
-                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
-
-                       /* AUX_PLL Fraction = 0x05227ad */
-                       /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/
-                       cx18_av_write4(cx, 0x110, 0x005227ad);
-
-                       /* src3/4/6_ctl */
-                       /* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */
-                       cx18_av_write4(cx, 0x900, 0x08014faa);
-                       cx18_av_write4(cx, 0x904, 0x08014faa);
-                       cx18_av_write4(cx, 0x90c, 0x08014faa);
-
-                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
-                       cx18_av_write(cx, 0x127, 0x56);
-
-                       /* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
-                       cx18_av_write4(cx, 0x12c, 0x11205fff);
-
-                       /*
-                        * EN_AV_LOCK = 0
-                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
-                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
-                        */
-                       cx18_av_write4(cx, 0x128, 0xa01193f8);
-                       break;
-               }
-       } else {
-               switch (freq) {
-               case 32000:
-                       /*
-                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
-                        * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30
-                        */
-                       cx18_av_write4(cx, 0x108, 0x300d040f);
-
-                       /* VID_PLL Fraction = 0x2be2fe */
-                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
-                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
-
-                       /* AUX_PLL Fraction = 0x176740c */
-                       /* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/
-                       cx18_av_write4(cx, 0x110, 0x0176740c);
-
-                       /* src1_ctl */
-                       /* 0x1.0000 = 32000/32000 */
-                       cx18_av_write4(cx, 0x8f8, 0x08010000);
-
-                       /* src3/4/6_ctl */
-                       /* 0x2.0000 = 2 * (32000/32000) */
-                       cx18_av_write4(cx, 0x900, 0x08020000);
-                       cx18_av_write4(cx, 0x904, 0x08020000);
-                       cx18_av_write4(cx, 0x90c, 0x08020000);
-
-                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */
-                       cx18_av_write(cx, 0x127, 0x70);
-
-                       /* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
-                       cx18_av_write4(cx, 0x12c, 0x11201fff);
-
-                       /*
-                        * EN_AV_LOCK = 0
-                        * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
-                        *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
-                        */
-                       cx18_av_write4(cx, 0x128, 0xa00d2ef8);
-                       break;
-
-               case 44100:
-                       /*
-                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
-                        * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24
-                        */
-                       cx18_av_write4(cx, 0x108, 0x240e040f);
-
-                       /* VID_PLL Fraction = 0x2be2fe */
-                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
-                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
-
-                       /* AUX_PLL Fraction = 0x062a1f2 */
-                       /* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/
-                       cx18_av_write4(cx, 0x110, 0x0062a1f2);
-
-                       /* src1_ctl */
-                       /* 0x1.60cd = 44100/32000 */
-                       cx18_av_write4(cx, 0x8f8, 0x080160cd);
-
-                       /* src3/4/6_ctl */
-                       /* 0x1.7385 = 2 * (32000/44100) */
-                       cx18_av_write4(cx, 0x900, 0x08017385);
-                       cx18_av_write4(cx, 0x904, 0x08017385);
-                       cx18_av_write4(cx, 0x90c, 0x08017385);
-
-                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */
-                       cx18_av_write(cx, 0x127, 0x64);
-
-                       /* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
-                       cx18_av_write4(cx, 0x12c, 0x112061ff);
-
-                       /*
-                        * EN_AV_LOCK = 0
-                        * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
-                        *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
-                        */
-                       cx18_av_write4(cx, 0x128, 0xa01d4bf8);
-                       break;
-
-               case 48000:
-                       /*
-                        * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
-                        * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
-                        */
-                       cx18_av_write4(cx, 0x108, 0x200d040f);
-
-                       /* VID_PLL Fraction = 0x2be2fe */
-                       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
-                       cx18_av_write4(cx, 0x10c, 0x002be2fe);
-
-                       /* AUX_PLL Fraction = 0x176740c */
-                       /* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/
-                       cx18_av_write4(cx, 0x110, 0x0176740c);
-
-                       /* src1_ctl */
-                       /* 0x1.8000 = 48000/32000 */
-                       cx18_av_write4(cx, 0x8f8, 0x08018000);
-
-                       /* src3/4/6_ctl */
-                       /* 0x1.5555 = 2 * (32000/48000) */
-                       cx18_av_write4(cx, 0x900, 0x08015555);
-                       cx18_av_write4(cx, 0x904, 0x08015555);
-                       cx18_av_write4(cx, 0x90c, 0x08015555);
-
-                       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
-                       cx18_av_write(cx, 0x127, 0x60);
-
-                       /* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
-                       cx18_av_write4(cx, 0x12c, 0x11203fff);
-
-                       /*
-                        * EN_AV_LOCK = 0
-                        * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
-                        *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
-                        */
-                       cx18_av_write4(cx, 0x128, 0xa01193f8);
-                       break;
-               }
-       }
-
-       state->audclk_freq = freq;
-
-       return 0;
-}
-
-void cx18_av_audio_set_path(struct cx18 *cx)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       u8 v;
-
-       /* stop microcontroller */
-       v = cx18_av_read(cx, 0x803) & ~0x10;
-       cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-
-       /* assert soft reset */
-       v = cx18_av_read(cx, 0x810) | 0x01;
-       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
-
-       /* Mute everything to prevent the PFFT! */
-       cx18_av_write(cx, 0x8d3, 0x1f);
-
-       if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
-               /* Set Path1 to Serial Audio Input */
-               cx18_av_write4(cx, 0x8d0, 0x01011012);
-
-               /* The microcontroller should not be started for the
-                * non-tuner inputs: autodetection is specific for
-                * TV audio. */
-       } else {
-               /* Set Path1 to Analog Demod Main Channel */
-               cx18_av_write4(cx, 0x8d0, 0x1f063870);
-       }
-
-       set_audclk_freq(cx, state->audclk_freq);
-
-       /* deassert soft reset */
-       v = cx18_av_read(cx, 0x810) & ~0x01;
-       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
-
-       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-               /* When the microcontroller detects the
-                * audio format, it will unmute the lines */
-               v = cx18_av_read(cx, 0x803) | 0x10;
-               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-       }
-}
-
-static void set_volume(struct cx18 *cx, int volume)
-{
-       /* First convert the volume to msp3400 values (0-127) */
-       int vol = volume >> 9;
-       /* now scale it up to cx18_av values
-        * -114dB to -96dB maps to 0
-        * this should be 19, but in my testing that was 4dB too loud */
-       if (vol <= 23)
-               vol = 0;
-       else
-               vol -= 23;
-
-       /* PATH1_VOLUME */
-       cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
-}
-
-static void set_bass(struct cx18 *cx, int bass)
-{
-       /* PATH1_EQ_BASS_VOL */
-       cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
-}
-
-static void set_treble(struct cx18 *cx, int treble)
-{
-       /* PATH1_EQ_TREBLE_VOL */
-       cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
-}
-
-static void set_balance(struct cx18 *cx, int balance)
-{
-       int bal = balance >> 8;
-       if (bal > 0x80) {
-               /* PATH1_BAL_LEFT */
-               cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
-               /* PATH1_BAL_LEVEL */
-               cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
-       } else {
-               /* PATH1_BAL_LEFT */
-               cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
-               /* PATH1_BAL_LEVEL */
-               cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
-       }
-}
-
-static void set_mute(struct cx18 *cx, int mute)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       u8 v;
-
-       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-               /* Must turn off microcontroller in order to mute sound.
-                * Not sure if this is the best method, but it does work.
-                * If the microcontroller is running, then it will undo any
-                * changes to the mute register. */
-               v = cx18_av_read(cx, 0x803);
-               if (mute) {
-                       /* disable microcontroller */
-                       v &= ~0x10;
-                       cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-                       cx18_av_write(cx, 0x8d3, 0x1f);
-               } else {
-                       /* enable microcontroller */
-                       v |= 0x10;
-                       cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-               }
-       } else {
-               /* SRC1_MUTE_EN */
-               cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
-       }
-}
-
-int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       struct cx18_av_state *state = &cx->av_state;
-       int retval;
-       u8 v;
-
-       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-               v = cx18_av_read(cx, 0x803) & ~0x10;
-               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-               cx18_av_write(cx, 0x8d3, 0x1f);
-       }
-       v = cx18_av_read(cx, 0x810) | 0x1;
-       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
-
-       retval = set_audclk_freq(cx, freq);
-
-       v = cx18_av_read(cx, 0x810) & ~0x1;
-       cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
-       if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
-               v = cx18_av_read(cx, 0x803) | 0x10;
-               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-       }
-       return retval;
-}
-
-static int cx18_av_audio_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_VOLUME:
-               set_volume(cx, ctrl->val);
-               break;
-       case V4L2_CID_AUDIO_BASS:
-               set_bass(cx, ctrl->val);
-               break;
-       case V4L2_CID_AUDIO_TREBLE:
-               set_treble(cx, ctrl->val);
-               break;
-       case V4L2_CID_AUDIO_BALANCE:
-               set_balance(cx, ctrl->val);
-               break;
-       case V4L2_CID_AUDIO_MUTE:
-               set_mute(cx, ctrl->val);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops = {
-       .s_ctrl = cx18_av_audio_s_ctrl,
-};
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
deleted file mode 100644 (file)
index f164b7f..0000000
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*
- *  cx18 ADEC audio functions
- *
- *  Derived from cx25840-core.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include <media/v4l2-chip-ident.h>
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-cards.h"
-
-int cx18_av_write(struct cx18 *cx, u16 addr, u8 value)
-{
-       u32 reg = 0xc40000 + (addr & ~3);
-       u32 mask = 0xff;
-       int shift = (addr & 3) * 8;
-       u32 x = cx18_read_reg(cx, reg);
-
-       x = (x & ~(mask << shift)) | ((u32)value << shift);
-       cx18_write_reg(cx, x, reg);
-       return 0;
-}
-
-int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
-{
-       u32 reg = 0xc40000 + (addr & ~3);
-       int shift = (addr & 3) * 8;
-       u32 x = cx18_read_reg(cx, reg);
-
-       x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
-       cx18_write_reg_expect(cx, x, reg,
-                               ((u32)eval << shift), ((u32)mask << shift));
-       return 0;
-}
-
-int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
-{
-       cx18_write_reg(cx, value, 0xc40000 + addr);
-       return 0;
-}
-
-int
-cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
-{
-       cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
-       return 0;
-}
-
-int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
-{
-       cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
-       return 0;
-}
-
-u8 cx18_av_read(struct cx18 *cx, u16 addr)
-{
-       u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
-       int shift = (addr & 3) * 8;
-
-       return (x >> shift) & 0xff;
-}
-
-u32 cx18_av_read4(struct cx18 *cx, u16 addr)
-{
-       return cx18_read_reg(cx, 0xc40000 + addr);
-}
-
-int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
-                  u8 or_value)
-{
-       return cx18_av_write(cx, addr,
-                            (cx18_av_read(cx, addr) & and_mask) |
-                            or_value);
-}
-
-int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
-                  u32 or_value)
-{
-       return cx18_av_write4(cx, addr,
-                            (cx18_av_read4(cx, addr) & and_mask) |
-                            or_value);
-}
-
-static void cx18_av_init(struct cx18 *cx)
-{
-       /*
-        * The crystal freq used in calculations in this driver will be
-        * 28.636360 MHz.
-        * Aim to run the PLLs' VCOs near 400 MHz to minimze errors.
-        */
-
-       /*
-        * VDCLK  Integer = 0x0f, Post Divider = 0x04
-        * AIMCLK Integer = 0x0e, Post Divider = 0x16
-        */
-       cx18_av_write4(cx, CXADEC_PLL_CTRL1, 0x160e040f);
-
-       /* VDCLK Fraction = 0x2be2fe */
-       /* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz before post divide */
-       cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, 0x002be2fe);
-
-       /* AIMCLK Fraction = 0x05227ad */
-       /* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz pre post-div*/
-       cx18_av_write4(cx, CXADEC_AUX_PLL_FRAC, 0x005227ad);
-
-       /* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
-       cx18_av_write(cx, CXADEC_I2S_MCLK, 0x56);
-}
-
-static void cx18_av_initialize(struct v4l2_subdev *sd)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       int default_volume;
-       u32 v;
-
-       cx18_av_loadfw(cx);
-       /* Stop 8051 code execution */
-       cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
-                                                0x03000000, 0x13000000);
-
-       /* initallize the PLL by toggling sleep bit */
-       v = cx18_av_read4(cx, CXADEC_HOST_REG1);
-       /* enable sleep mode - register appears to be read only... */
-       cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
-       /* disable sleep mode */
-       cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
-                                                   v & 0xfffe, 0xffff);
-
-       /* initialize DLLs */
-       v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
-       /* disable FLD */
-       cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
-       /* enable FLD */
-       cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
-
-       v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
-       /* disable FLD */
-       cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
-       /* enable FLD */
-       cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
-
-       /* set analog bias currents. Set Vreg to 1.20V. */
-       cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
-
-       v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
-       /* enable TUNE_FIL_RST */
-       cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
-       /* disable TUNE_FIL_RST */
-       cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
-                             v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);
-
-       /* enable 656 output */
-       cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
-
-       /* video output drive strength */
-       cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
-
-       /* reset video */
-       cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
-       cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
-
-       /*
-        * Disable Video Auto-config of the Analog Front End and Video PLL.
-        *
-        * Since we only use BT.656 pixel mode, which works for both 525 and 625
-        * line systems, it's just easier for us to set registers
-        * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL),
-        * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC)
-        * ourselves, than to run around cleaning up after the auto-config.
-        *
-        * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit
-        * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL
-        * autoconfig either.)
-        *
-        * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3.
-        */
-       cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
-
-       /* Setup the Video and and Aux/Audio PLLs */
-       cx18_av_init(cx);
-
-       /* set video to auto-detect */
-       /* Clear bits 11-12 to enable slow locking mode.  Set autodetect mode */
-       /* set the comb notch = 1 */
-       cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
-
-       /* Enable wtw_en in CRUSH_CTRL (Set bit 22) */
-       /* Enable maj_sel in CRUSH_CTRL (Set bit 20) */
-       cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
-
-       /* Set VGA_TRACK_RANGE to 0x20 */
-       cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
-
-       /*
-        * Initial VBI setup
-        * VIP-1.1, 10 bit mode, enable Raw, disable sliced,
-        * don't clamp raw samples when codes are in use, 1 byte user D-words,
-        * IDID0 has line #, RP code V bit transition on VBLANK, data during
-        * blanking intervals
-        */
-       cx18_av_write4(cx, CXADEC_OUT_CTRL1, 0x4013252e);
-
-       /* Set the video input.
-          The setting in MODE_CTRL gets lost when we do the above setup */
-       /* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
-       /* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
-
-       /*
-        * Analog Front End (AFE)
-        * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2
-        *  bypass_ch[1-3]     use filter
-        *  droop_comp_ch[1-3] disable
-        *  clamp_en_ch[1-3]   disable
-        *  aud_in_sel         ADC2
-        *  luma_in_sel        ADC1
-        *  chroma_in_sel      ADC2
-        *  clamp_sel_ch[2-3]  midcode
-        *  clamp_sel_ch1      video decoder
-        *  vga_sel_ch3        audio decoder
-        *  vga_sel_ch[1-2]    video decoder
-        *  half_bw_ch[1-3]    disable
-        *  +12db_ch[1-3]      disable
-        */
-       cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
-
-/*     if(dwEnable && dw3DCombAvailable) { */
-/*             CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
-/*    } else { */
-/*             CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
-/*    } */
-       cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
-       default_volume = cx18_av_read(cx, 0x8d4);
-       /*
-        * Enforce the legacy volume scale mapping limits to avoid
-        * -ERANGE errors when initializing the volume control
-        */
-       if (default_volume > 228) {
-               /* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
-               default_volume = 228;
-               cx18_av_write(cx, 0x8d4, 228);
-       } else if (default_volume < 20) {
-               /* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
-               default_volume = 20;
-               cx18_av_write(cx, 0x8d4, 20);
-       }
-       default_volume = (((228 - default_volume) >> 1) + 23) << 9;
-       state->volume->cur.val = state->volume->default_value = default_volume;
-       v4l2_ctrl_handler_setup(&state->hdl);
-}
-
-static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
-{
-       cx18_av_initialize(sd);
-       return 0;
-}
-
-static int cx18_av_load_fw(struct v4l2_subdev *sd)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-
-       if (!state->is_initialized) {
-               /* initialize on first use */
-               state->is_initialized = 1;
-               cx18_av_initialize(sd);
-       }
-       return 0;
-}
-
-void cx18_av_std_setup(struct cx18 *cx)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       struct v4l2_subdev *sd = &state->sd;
-       v4l2_std_id std = state->std;
-
-       /*
-        * Video ADC crystal clock to pixel clock SRC decimation ratio
-        * 28.636360 MHz/13.5 Mpps * 256 = 0x21f.07b
-        */
-       const int src_decimation = 0x21f;
-
-       int hblank, hactive, burst, vblank, vactive, sc;
-       int vblank656;
-       int luma_lpf, uv_lpf, comb;
-       u32 pll_int, pll_frac, pll_post;
-
-       /* datasheet startup, step 8d */
-       if (std & ~V4L2_STD_NTSC)
-               cx18_av_write(cx, 0x49f, 0x11);
-       else
-               cx18_av_write(cx, 0x49f, 0x14);
-
-       /*
-        * Note: At the end of a field, there are 3 sets of half line duration
-        * (double horizontal rate) pulses:
-        *
-        * 5 (625) or 6 (525) half-lines to blank for the vertical retrace
-        * 5 (625) or 6 (525) vertical sync pulses of half line duration
-        * 5 (625) or 6 (525) half-lines of equalization pulses
-        */
-       if (std & V4L2_STD_625_50) {
-               /*
-                * The following relationships of half line counts should hold:
-                * 625 = vblank656 + vactive
-                * 10 = vblank656 - vblank = vsync pulses + equalization pulses
-                *
-                * vblank656: half lines after line 625/mid-313 of blanked video
-                * vblank:    half lines, after line 5/317, of blanked video
-                * vactive:   half lines of active video +
-                *              5 half lines after the end of active video
-                *
-                * As far as I can tell:
-                * vblank656 starts counting from the falling edge of the first
-                *      vsync pulse (start of line 1 or mid-313)
-                * vblank starts counting from the after the 5 vsync pulses and
-                *      5 or 4 equalization pulses (start of line 6 or 318)
-                *
-                * For 625 line systems the driver will extract VBI information
-                * from lines 6-23 and lines 318-335 (but the slicer can only
-                * handle 17 lines, not the 18 in the vblank region).
-                * In addition, we need vblank656 and vblank to be one whole
-                * line longer, to cover line 24 and 336, so the SAV/EAV RP
-                * codes get generated such that the encoder can actually
-                * extract line 23 & 335 (WSS).  We'll lose 1 line in each field
-                * at the top of the screen.
-                *
-                * It appears the 5 half lines that happen after active
-                * video must be included in vactive (579 instead of 574),
-                * otherwise the colors get badly displayed in various regions
-                * of the screen.  I guess the chroma comb filter gets confused
-                * without them (at least when a PVR-350 is the PAL source).
-                */
-               vblank656 = 48; /* lines  1 -  24  &  313 - 336 */
-               vblank = 38;    /* lines  6 -  24  &  318 - 336 */
-               vactive = 579;  /* lines 24 - 313  &  337 - 626 */
-
-               /*
-                * For a 13.5 Mpps clock and 15,625 Hz line rate, a line is
-                * is 864 pixels = 720 active + 144 blanking.  ITU-R BT.601
-                * specifies 12 luma clock periods or ~ 0.9 * 13.5 Mpps after
-                * the end of active video to start a horizontal line, so that
-                * leaves 132 pixels of hblank to ignore.
-                */
-               hblank = 132;
-               hactive = 720;
-
-               /*
-                * Burst gate delay (for 625 line systems)
-                * Hsync leading edge to color burst rise = 5.6 us
-                * Color burst width = 2.25 us
-                * Gate width = 4 pixel clocks
-                * (5.6 us + 2.25/2 us) * 13.5 Mpps + 4/2 clocks = 92.79 clocks
-                */
-               burst = 93;
-               luma_lpf = 2;
-               if (std & V4L2_STD_PAL) {
-                       uv_lpf = 1;
-                       comb = 0x20;
-                       /* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
-                       sc = 688700;
-               } else if (std == V4L2_STD_PAL_Nc) {
-                       uv_lpf = 1;
-                       comb = 0x20;
-                       /* sc = 3582056.25 * src_decimation/28636360 * 2^13 */
-                       sc = 556422;
-               } else { /* SECAM */
-                       uv_lpf = 0;
-                       comb = 0;
-                       /* (fr + fb)/2 = (4406260 + 4250000)/2 = 4328130 */
-                       /* sc = 4328130 * src_decimation/28636360 * 2^13 */
-                       sc = 672314;
-               }
-       } else {
-               /*
-                * The following relationships of half line counts should hold:
-                * 525 = prevsync + vblank656 + vactive
-                * 12 = vblank656 - vblank = vsync pulses + equalization pulses
-                *
-                * prevsync:  6 half-lines before the vsync pulses
-                * vblank656: half lines, after line 3/mid-266, of blanked video
-                * vblank:    half lines, after line 9/272, of blanked video
-                * vactive:   half lines of active video
-                *
-                * As far as I can tell:
-                * vblank656 starts counting from the falling edge of the first
-                *      vsync pulse (start of line 4 or mid-266)
-                * vblank starts counting from the after the 6 vsync pulses and
-                *      6 or 5 equalization pulses (start of line 10 or 272)
-                *
-                * For 525 line systems the driver will extract VBI information
-                * from lines 10-21 and lines 273-284.
-                */
-               vblank656 = 38; /* lines  4 -  22  &  266 - 284 */
-               vblank = 26;    /* lines 10 -  22  &  272 - 284 */
-               vactive = 481;  /* lines 23 - 263  &  285 - 525 */
-
-               /*
-                * For a 13.5 Mpps clock and 15,734.26 Hz line rate, a line is
-                * is 858 pixels = 720 active + 138 blanking.  The Hsync leading
-                * edge should happen 1.2 us * 13.5 Mpps ~= 16 pixels after the
-                * end of active video, leaving 122 pixels of hblank to ignore
-                * before active video starts.
-                */
-               hactive = 720;
-               hblank = 122;
-               luma_lpf = 1;
-               uv_lpf = 1;
-
-               /*
-                * Burst gate delay (for 525 line systems)
-                * Hsync leading edge to color burst rise = 5.3 us
-                * Color burst width = 2.5 us
-                * Gate width = 4 pixel clocks
-                * (5.3 us + 2.5/2 us) * 13.5 Mpps + 4/2 clocks = 90.425 clocks
-                */
-               if (std == V4L2_STD_PAL_60) {
-                       burst = 90;
-                       luma_lpf = 2;
-                       comb = 0x20;
-                       /* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
-                       sc = 688700;
-               } else if (std == V4L2_STD_PAL_M) {
-                       /* The 97 needs to be verified against PAL-M timings */
-                       burst = 97;
-                       comb = 0x20;
-                       /* sc = 3575611.49 * src_decimation/28636360 * 2^13 */
-                       sc = 555421;
-               } else {
-                       burst = 90;
-                       comb = 0x66;
-                       /* sc = 3579545.45.. * src_decimation/28636360 * 2^13 */
-                       sc = 556032;
-               }
-       }
-
-       /* DEBUG: Displays configured PLL frequency */
-       pll_int = cx18_av_read(cx, 0x108);
-       pll_frac = cx18_av_read4(cx, 0x10c) & 0x1ffffff;
-       pll_post = cx18_av_read(cx, 0x109);
-       CX18_DEBUG_INFO_DEV(sd, "PLL regs = int: %u, frac: %u, post: %u\n",
-                           pll_int, pll_frac, pll_post);
-
-       if (pll_post) {
-               int fsc, pll;
-               u64 tmp;
-
-               pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
-               pll /= pll_post;
-               CX18_DEBUG_INFO_DEV(sd, "Video PLL = %d.%06d MHz\n",
-                                   pll / 1000000, pll % 1000000);
-               CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n",
-                                   pll / 8000000, (pll / 8) % 1000000);
-
-               CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio "
-                                   "= %d.%03d\n", src_decimation / 256,
-                                   ((src_decimation % 256) * 1000) / 256);
-
-               tmp = 28636360 * (u64) sc;
-               do_div(tmp, src_decimation);
-               fsc = tmp >> 13;
-               CX18_DEBUG_INFO_DEV(sd,
-                                   "Chroma sub-carrier initial freq = %d.%06d "
-                                   "MHz\n", fsc / 1000000, fsc % 1000000);
-
-               CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, "
-                                   "vactive %i, vblank656 %i, src_dec %i, "
-                                   "burst 0x%02x, luma_lpf %i, uv_lpf %i, "
-                                   "comb 0x%02x, sc 0x%06x\n",
-                                   hblank, hactive, vblank, vactive, vblank656,
-                                   src_decimation, burst, luma_lpf, uv_lpf,
-                                   comb, sc);
-       }
-
-       /* Sets horizontal blanking delay and active lines */
-       cx18_av_write(cx, 0x470, hblank);
-       cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
-                                               (hactive << 4)));
-       cx18_av_write(cx, 0x472, hactive >> 4);
-
-       /* Sets burst gate delay */
-       cx18_av_write(cx, 0x473, burst);
-
-       /* Sets vertical blanking delay and active duration */
-       cx18_av_write(cx, 0x474, vblank);
-       cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
-                                               (vactive << 4)));
-       cx18_av_write(cx, 0x476, vactive >> 4);
-       cx18_av_write(cx, 0x477, vblank656);
-
-       /* Sets src decimation rate */
-       cx18_av_write(cx, 0x478, 0xff & src_decimation);
-       cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
-
-       /* Sets Luma and UV Low pass filters */
-       cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
-
-       /* Enables comb filters */
-       cx18_av_write(cx, 0x47b, comb);
-
-       /* Sets SC Step*/
-       cx18_av_write(cx, 0x47c, sc);
-       cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
-       cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
-
-       if (std & V4L2_STD_625_50) {
-               state->slicer_line_delay = 1;
-               state->slicer_line_offset = (6 + state->slicer_line_delay - 2);
-       } else {
-               state->slicer_line_delay = 0;
-               state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
-       }
-       cx18_av_write(cx, 0x47f, state->slicer_line_delay);
-}
-
-static void input_change(struct cx18 *cx)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       v4l2_std_id std = state->std;
-       u8 v;
-
-       /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
-       cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
-       cx18_av_and_or(cx, 0x401, ~0x60, 0);
-       cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
-
-       if (std & V4L2_STD_525_60) {
-               if (std == V4L2_STD_NTSC_M_JP) {
-                       /* Japan uses EIAJ audio standard */
-                       cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
-                       cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
-               } else if (std == V4L2_STD_NTSC_M_KR) {
-                       /* South Korea uses A2 audio standard */
-                       cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
-                       cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
-               } else {
-                       /* Others use the BTSC audio standard */
-                       cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
-                       cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
-               }
-       } else if (std & V4L2_STD_PAL) {
-               /* Follow tuner change procedure for PAL */
-               cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
-               cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
-       } else if (std & V4L2_STD_SECAM) {
-               /* Select autodetect for SECAM */
-               cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
-               cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
-       }
-
-       v = cx18_av_read(cx, 0x803);
-       if (v & 0x10) {
-               /* restart audio decoder microcontroller */
-               v &= ~0x10;
-               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-               v |= 0x10;
-               cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
-       }
-}
-
-static int cx18_av_s_frequency(struct v4l2_subdev *sd,
-                              struct v4l2_frequency *freq)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       input_change(cx);
-       return 0;
-}
-
-static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input,
-                                       enum cx18_av_audio_input aud_input)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       struct v4l2_subdev *sd = &state->sd;
-
-       enum analog_signal_type {
-               NONE, CVBS, Y, C, SIF, Pb, Pr
-       } ch[3] = {NONE, NONE, NONE};
-
-       u8 afe_mux_cfg;
-       u8 adc2_cfg;
-       u8 input_mode;
-       u32 afe_cfg;
-       int i;
-
-       CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
-                           vid_input, aud_input);
-
-       if (vid_input >= CX18_AV_COMPOSITE1 &&
-           vid_input <= CX18_AV_COMPOSITE8) {
-               afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
-               ch[0] = CVBS;
-               input_mode = 0x0;
-       } else if (vid_input >= CX18_AV_COMPONENT_LUMA1) {
-               int luma = vid_input & 0xf000;
-               int r_chroma = vid_input & 0xf0000;
-               int b_chroma = vid_input & 0xf00000;
-
-               if ((vid_input & ~0xfff000) ||
-                   luma < CX18_AV_COMPONENT_LUMA1 ||
-                   luma > CX18_AV_COMPONENT_LUMA8 ||
-                   r_chroma < CX18_AV_COMPONENT_R_CHROMA4 ||
-                   r_chroma > CX18_AV_COMPONENT_R_CHROMA6 ||
-                   b_chroma < CX18_AV_COMPONENT_B_CHROMA7 ||
-                   b_chroma > CX18_AV_COMPONENT_B_CHROMA8) {
-                       CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
-                                    vid_input);
-                       return -EINVAL;
-               }
-               afe_mux_cfg = (luma - CX18_AV_COMPONENT_LUMA1) >> 12;
-               ch[0] = Y;
-               afe_mux_cfg |= (r_chroma - CX18_AV_COMPONENT_R_CHROMA4) >> 12;
-               ch[1] = Pr;
-               afe_mux_cfg |= (b_chroma - CX18_AV_COMPONENT_B_CHROMA7) >> 14;
-               ch[2] = Pb;
-               input_mode = 0x6;
-       } else {
-               int luma = vid_input & 0xf0;
-               int chroma = vid_input & 0xf00;
-
-               if ((vid_input & ~0xff0) ||
-                   luma < CX18_AV_SVIDEO_LUMA1 ||
-                   luma > CX18_AV_SVIDEO_LUMA8 ||
-                   chroma < CX18_AV_SVIDEO_CHROMA4 ||
-                   chroma > CX18_AV_SVIDEO_CHROMA8) {
-                       CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
-                                    vid_input);
-                       return -EINVAL;
-               }
-               afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
-               ch[0] = Y;
-               if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
-                       afe_mux_cfg &= 0x3f;
-                       afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
-                       ch[2] = C;
-               } else {
-                       afe_mux_cfg &= 0xcf;
-                       afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
-                       ch[1] = C;
-               }
-               input_mode = 0x2;
-       }
-
-       switch (aud_input) {
-       case CX18_AV_AUDIO_SERIAL1:
-       case CX18_AV_AUDIO_SERIAL2:
-               /* do nothing, use serial audio input */
-               break;
-       case CX18_AV_AUDIO4:
-               afe_mux_cfg &= ~0x30;
-               ch[1] = SIF;
-               break;
-       case CX18_AV_AUDIO5:
-               afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
-               ch[1] = SIF;
-               break;
-       case CX18_AV_AUDIO6:
-               afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
-               ch[1] = SIF;
-               break;
-       case CX18_AV_AUDIO7:
-               afe_mux_cfg &= ~0xc0;
-               ch[2] = SIF;
-               break;
-       case CX18_AV_AUDIO8:
-               afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
-               ch[2] = SIF;
-               break;
-
-       default:
-               CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
-                            aud_input);
-               return -EINVAL;
-       }
-
-       /* Set up analog front end multiplexers */
-       cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
-       /* Set INPUT_MODE to Composite, S-Video, or Component */
-       cx18_av_and_or(cx, 0x401, ~0x6, input_mode);
-
-       /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
-       adc2_cfg = cx18_av_read(cx, 0x102);
-       if (ch[2] == NONE)
-               adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */
-       else
-               adc2_cfg |= 0x2;  /* Signal on CH3, set ADC2 to CH3 for input */
-
-       /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
-       if (ch[1] != NONE && ch[2] != NONE)
-               adc2_cfg |= 0x4; /* Set dual mode */
-       else
-               adc2_cfg &= ~0x4; /* Clear dual mode */
-       cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
-
-       /* Configure the analog front end */
-       afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
-       afe_cfg &= 0xff000000;
-       afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */
-       if (ch[1] != NONE && ch[2] != NONE)
-               afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */
-
-       for (i = 0; i < 3; i++) {
-               switch (ch[i]) {
-               default:
-               case NONE:
-                       /* CLAMP_SEL = Fixed to midcode clamp level */
-                       afe_cfg |= (0x00000200 << i);
-                       break;
-               case CVBS:
-               case Y:
-                       if (i > 0)
-                               afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */
-                       break;
-               case C:
-               case Pb:
-               case Pr:
-                       /* CLAMP_SEL = Fixed to midcode clamp level */
-                       afe_cfg |= (0x00000200 << i);
-                       if (i == 0 && ch[i] == C)
-                               afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */
-                       break;
-               case SIF:
-                       /*
-                        * VGA_GAIN_SEL = Audio Decoder
-                        * CLAMP_SEL = Fixed to midcode clamp level
-                        */
-                       afe_cfg |= (0x00000240 << i);
-                       if (i == 0)
-                               afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */
-                       break;
-               }
-       }
-
-       cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
-
-       state->vid_input = vid_input;
-       state->aud_input = aud_input;
-       cx18_av_audio_set_path(cx);
-       input_change(cx);
-       return 0;
-}
-
-static int cx18_av_s_video_routing(struct v4l2_subdev *sd,
-                                  u32 input, u32 output, u32 config)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       return set_input(cx, input, state->aud_input);
-}
-
-static int cx18_av_s_audio_routing(struct v4l2_subdev *sd,
-                                  u32 input, u32 output, u32 config)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       return set_input(cx, state->vid_input, input);
-}
-
-static int cx18_av_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       u8 vpres;
-       u8 mode;
-       int val = 0;
-
-       if (state->radio)
-               return 0;
-
-       vpres = cx18_av_read(cx, 0x40e) & 0x20;
-       vt->signal = vpres ? 0xffff : 0x0;
-
-       vt->capability |=
-                   V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
-                   V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
-
-       mode = cx18_av_read(cx, 0x804);
-
-       /* get rxsubchans and audmode */
-       if ((mode & 0xf) == 1)
-               val |= V4L2_TUNER_SUB_STEREO;
-       else
-               val |= V4L2_TUNER_SUB_MONO;
-
-       if (mode == 2 || mode == 4)
-               val = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-
-       if (mode & 0x10)
-               val |= V4L2_TUNER_SUB_SAP;
-
-       vt->rxsubchans = val;
-       vt->audmode = state->audmode;
-       return 0;
-}
-
-static int cx18_av_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       u8 v;
-
-       if (state->radio)
-               return 0;
-
-       v = cx18_av_read(cx, 0x809);
-       v &= ~0xf;
-
-       switch (vt->audmode) {
-       case V4L2_TUNER_MODE_MONO:
-               /* mono      -> mono
-                  stereo    -> mono
-                  bilingual -> lang1 */
-               break;
-       case V4L2_TUNER_MODE_STEREO:
-       case V4L2_TUNER_MODE_LANG1:
-               /* mono      -> mono
-                  stereo    -> stereo
-                  bilingual -> lang1 */
-               v |= 0x4;
-               break;
-       case V4L2_TUNER_MODE_LANG1_LANG2:
-               /* mono      -> mono
-                  stereo    -> stereo
-                  bilingual -> lang1/lang2 */
-               v |= 0x7;
-               break;
-       case V4L2_TUNER_MODE_LANG2:
-               /* mono      -> mono
-                  stereo    -> stereo
-                  bilingual -> lang2 */
-               v |= 0x1;
-               break;
-       default:
-               return -EINVAL;
-       }
-       cx18_av_write_expect(cx, 0x809, v, v, 0xff);
-       state->audmode = vt->audmode;
-       return 0;
-}
-
-static int cx18_av_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       u8 fmt = 0;     /* zero is autodetect */
-       u8 pal_m = 0;
-
-       if (state->radio == 0 && state->std == norm)
-               return 0;
-
-       state->radio = 0;
-       state->std = norm;
-
-       /* First tests should be against specific std */
-       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 (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;
-       }
-
-       CX18_DEBUG_INFO_DEV(sd, "changing video std to fmt %i\n", fmt);
-
-       /* Follow step 9 of section 3.16 in the cx18_av datasheet.
-          Without this PAL may display a vertical ghosting effect.
-          This happens for example with the Yuan MPC622. */
-       if (fmt >= 4 && fmt < 8) {
-               /* Set format to NTSC-M */
-               cx18_av_and_or(cx, 0x400, ~0xf, 1);
-               /* Turn off LCOMB */
-               cx18_av_and_or(cx, 0x47b, ~6, 0);
-       }
-       cx18_av_and_or(cx, 0x400, ~0x2f, fmt | 0x20);
-       cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
-       cx18_av_std_setup(cx);
-       input_change(cx);
-       return 0;
-}
-
-static int cx18_av_s_radio(struct v4l2_subdev *sd)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       state->radio = 1;
-       return 0;
-}
-
-static int cx18_av_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               cx18_av_write(cx, 0x414, ctrl->val - 128);
-               break;
-
-       case V4L2_CID_CONTRAST:
-               cx18_av_write(cx, 0x415, ctrl->val << 1);
-               break;
-
-       case V4L2_CID_SATURATION:
-               cx18_av_write(cx, 0x420, ctrl->val << 1);
-               cx18_av_write(cx, 0x421, ctrl->val << 1);
-               break;
-
-       case V4L2_CID_HUE:
-               cx18_av_write(cx, 0x422, ctrl->val);
-               break;
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
-       int is_50Hz = !(state->std & V4L2_STD_525_60);
-
-       if (fmt->code != V4L2_MBUS_FMT_FIXED)
-               return -EINVAL;
-
-       fmt->field = V4L2_FIELD_INTERLACED;
-       fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
-       Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
-
-       Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
-       Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
-
-       /*
-        * This adjustment reflects the excess of vactive, set in
-        * cx18_av_std_setup(), above standard values:
-        *
-        * 480 + 1 for 60 Hz systems
-        * 576 + 3 for 50 Hz systems
-        */
-       Vlines = fmt->height + (is_50Hz ? 3 : 1);
-
-       /*
-        * Invalid height and width scaling requests are:
-        * 1. width less than 1/16 of the source width
-        * 2. width greater than the source width
-        * 3. height less than 1/8 of the source height
-        * 4. height greater than the source height
-        */
-       if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
-           (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
-               CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
-                            fmt->width, fmt->height);
-               return -ERANGE;
-       }
-
-       HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
-       VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
-       VSC &= 0x1fff;
-
-       if (fmt->width >= 385)
-               filter = 0;
-       else if (fmt->width > 192)
-               filter = 1;
-       else if (fmt->width > 96)
-               filter = 2;
-       else
-               filter = 3;
-
-       CX18_DEBUG_INFO_DEV(sd,
-                           "decoder set size %dx%d -> scale  %ux%u\n",
-                           fmt->width, fmt->height, HSC, VSC);
-
-       /* HSCALE=HSC */
-       cx18_av_write(cx, 0x418, HSC & 0xff);
-       cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
-       cx18_av_write(cx, 0x41a, HSC >> 16);
-       /* VSCALE=VSC */
-       cx18_av_write(cx, 0x41c, VSC & 0xff);
-       cx18_av_write(cx, 0x41d, VSC >> 8);
-       /* VS_INTRLACE=1 VFILT=filter */
-       cx18_av_write(cx, 0x41e, 0x8 | filter);
-       return 0;
-}
-
-static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       CX18_DEBUG_INFO_DEV(sd, "%s output\n", enable ? "enable" : "disable");
-       if (enable) {
-               cx18_av_write(cx, 0x115, 0x8c);
-               cx18_av_write(cx, 0x116, 0x07);
-       } else {
-               cx18_av_write(cx, 0x115, 0x00);
-               cx18_av_write(cx, 0x116, 0x00);
-       }
-       return 0;
-}
-
-static void log_video_status(struct cx18 *cx)
-{
-       static const char *const fmt_strs[] = {
-               "0x0",
-               "NTSC-M", "NTSC-J", "NTSC-4.43",
-               "PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
-               "0x9", "0xA", "0xB",
-               "SECAM",
-               "0xD", "0xE", "0xF"
-       };
-
-       struct cx18_av_state *state = &cx->av_state;
-       struct v4l2_subdev *sd = &state->sd;
-       u8 vidfmt_sel = cx18_av_read(cx, 0x400) & 0xf;
-       u8 gen_stat1 = cx18_av_read(cx, 0x40d);
-       u8 gen_stat2 = cx18_av_read(cx, 0x40e);
-       int vid_input = state->vid_input;
-
-       CX18_INFO_DEV(sd, "Video signal:              %spresent\n",
-                     (gen_stat2 & 0x20) ? "" : "not ");
-       CX18_INFO_DEV(sd, "Detected format:           %s\n",
-                     fmt_strs[gen_stat1 & 0xf]);
-
-       CX18_INFO_DEV(sd, "Specified standard:        %s\n",
-                     vidfmt_sel ? fmt_strs[vidfmt_sel]
-                                : "automatic detection");
-
-       if (vid_input >= CX18_AV_COMPOSITE1 &&
-           vid_input <= CX18_AV_COMPOSITE8) {
-               CX18_INFO_DEV(sd, "Specified video input:     Composite %d\n",
-                             vid_input - CX18_AV_COMPOSITE1 + 1);
-       } else {
-               CX18_INFO_DEV(sd, "Specified video input:     "
-                             "S-Video (Luma In%d, Chroma In%d)\n",
-                             (vid_input & 0xf0) >> 4,
-                             (vid_input & 0xf00) >> 8);
-       }
-
-       CX18_INFO_DEV(sd, "Specified audioclock freq: %d Hz\n",
-                     state->audclk_freq);
-}
-
-static void log_audio_status(struct cx18 *cx)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       struct v4l2_subdev *sd = &state->sd;
-       u8 download_ctl = cx18_av_read(cx, 0x803);
-       u8 mod_det_stat0 = cx18_av_read(cx, 0x804);
-       u8 mod_det_stat1 = cx18_av_read(cx, 0x805);
-       u8 audio_config = cx18_av_read(cx, 0x808);
-       u8 pref_mode = cx18_av_read(cx, 0x809);
-       u8 afc0 = cx18_av_read(cx, 0x80b);
-       u8 mute_ctl = cx18_av_read(cx, 0x8d3);
-       int aud_input = state->aud_input;
-       char *p;
-
-       switch (mod_det_stat0) {
-       case 0x00: p = "mono"; break;
-       case 0x01: p = "stereo"; break;
-       case 0x02: p = "dual"; break;
-       case 0x04: p = "tri"; break;
-       case 0x10: p = "mono with SAP"; break;
-       case 0x11: p = "stereo with SAP"; break;
-       case 0x12: p = "dual with SAP"; break;
-       case 0x14: p = "tri with SAP"; break;
-       case 0xfe: p = "forced mode"; break;
-       default: p = "not defined"; break;
-       }
-       CX18_INFO_DEV(sd, "Detected audio mode:       %s\n", p);
-
-       switch (mod_det_stat1) {
-       case 0x00: p = "not defined"; break;
-       case 0x01: p = "EIAJ"; break;
-       case 0x02: p = "A2-M"; break;
-       case 0x03: p = "A2-BG"; break;
-       case 0x04: p = "A2-DK1"; break;
-       case 0x05: p = "A2-DK2"; break;
-       case 0x06: p = "A2-DK3"; break;
-       case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
-       case 0x08: p = "AM-L"; break;
-       case 0x09: p = "NICAM-BG"; break;
-       case 0x0a: p = "NICAM-DK"; break;
-       case 0x0b: p = "NICAM-I"; break;
-       case 0x0c: p = "NICAM-L"; break;
-       case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
-       case 0x0e: p = "IF FM Radio"; break;
-       case 0x0f: p = "BTSC"; break;
-       case 0x10: p = "detected chrominance"; break;
-       case 0xfd: p = "unknown audio standard"; break;
-       case 0xfe: p = "forced audio standard"; break;
-       case 0xff: p = "no detected audio standard"; break;
-       default: p = "not defined"; break;
-       }
-       CX18_INFO_DEV(sd, "Detected audio standard:   %s\n", p);
-       CX18_INFO_DEV(sd, "Audio muted:               %s\n",
-                     (mute_ctl & 0x2) ? "yes" : "no");
-       CX18_INFO_DEV(sd, "Audio microcontroller:     %s\n",
-                     (download_ctl & 0x10) ? "running" : "stopped");
-
-       switch (audio_config >> 4) {
-       case 0x00: p = "undefined"; break;
-       case 0x01: p = "BTSC"; break;
-       case 0x02: p = "EIAJ"; break;
-       case 0x03: p = "A2-M"; break;
-       case 0x04: p = "A2-BG"; break;
-       case 0x05: p = "A2-DK1"; break;
-       case 0x06: p = "A2-DK2"; break;
-       case 0x07: p = "A2-DK3"; break;
-       case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
-       case 0x09: p = "AM-L"; break;
-       case 0x0a: p = "NICAM-BG"; break;
-       case 0x0b: p = "NICAM-DK"; break;
-       case 0x0c: p = "NICAM-I"; break;
-       case 0x0d: p = "NICAM-L"; break;
-       case 0x0e: p = "FM radio"; break;
-       case 0x0f: p = "automatic detection"; break;
-       default: p = "undefined"; break;
-       }
-       CX18_INFO_DEV(sd, "Configured audio standard: %s\n", p);
-
-       if ((audio_config >> 4) < 0xF) {
-               switch (audio_config & 0xF) {
-               case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
-               case 0x01: p = "MONO2 (LANGUAGE B)"; break;
-               case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
-               case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
-               case 0x04: p = "STEREO"; break;
-               case 0x05: p = "DUAL1 (AC)"; break;
-               case 0x06: p = "DUAL2 (BC)"; break;
-               case 0x07: p = "DUAL3 (AB)"; break;
-               default: p = "undefined";
-               }
-               CX18_INFO_DEV(sd, "Configured audio mode:     %s\n", p);
-       } else {
-               switch (audio_config & 0xF) {
-               case 0x00: p = "BG"; break;
-               case 0x01: p = "DK1"; break;
-               case 0x02: p = "DK2"; break;
-               case 0x03: p = "DK3"; break;
-               case 0x04: p = "I"; break;
-               case 0x05: p = "L"; break;
-               case 0x06: p = "BTSC"; break;
-               case 0x07: p = "EIAJ"; break;
-               case 0x08: p = "A2-M"; break;
-               case 0x09: p = "FM Radio (4.5 MHz)"; break;
-               case 0x0a: p = "FM Radio (5.5 MHz)"; break;
-               case 0x0b: p = "S-Video"; break;
-               case 0x0f: p = "automatic standard and mode detection"; break;
-               default: p = "undefined"; break;
-               }
-               CX18_INFO_DEV(sd, "Configured audio system:   %s\n", p);
-       }
-
-       if (aud_input)
-               CX18_INFO_DEV(sd, "Specified audio input:     Tuner (In%d)\n",
-                             aud_input);
-       else
-               CX18_INFO_DEV(sd, "Specified audio input:     External\n");
-
-       switch (pref_mode & 0xf) {
-       case 0: p = "mono/language A"; break;
-       case 1: p = "language B"; break;
-       case 2: p = "language C"; break;
-       case 3: p = "analog fallback"; break;
-       case 4: p = "stereo"; break;
-       case 5: p = "language AC"; break;
-       case 6: p = "language BC"; break;
-       case 7: p = "language AB"; break;
-       default: p = "undefined"; break;
-       }
-       CX18_INFO_DEV(sd, "Preferred audio mode:      %s\n", p);
-
-       if ((audio_config & 0xf) == 0xf) {
-               switch ((afc0 >> 3) & 0x1) {
-               case 0: p = "system DK"; break;
-               case 1: p = "system L"; break;
-               }
-               CX18_INFO_DEV(sd, "Selected 65 MHz format:    %s\n", p);
-
-               switch (afc0 & 0x7) {
-               case 0: p = "Chroma"; break;
-               case 1: p = "BTSC"; break;
-               case 2: p = "EIAJ"; break;
-               case 3: p = "A2-M"; break;
-               case 4: p = "autodetect"; break;
-               default: p = "undefined"; break;
-               }
-               CX18_INFO_DEV(sd, "Selected 45 MHz format:    %s\n", p);
-       }
-}
-
-static int cx18_av_log_status(struct v4l2_subdev *sd)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       log_video_status(cx);
-       log_audio_status(cx);
-       return 0;
-}
-
-static inline int cx18_av_dbg_match(const struct v4l2_dbg_match *match)
-{
-       return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 1;
-}
-
-static int cx18_av_g_chip_ident(struct v4l2_subdev *sd,
-                               struct v4l2_dbg_chip_ident *chip)
-{
-       struct cx18_av_state *state = to_cx18_av_state(sd);
-
-       if (cx18_av_dbg_match(&chip->match)) {
-               chip->ident = state->id;
-               chip->revision = state->rev;
-       }
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx18_av_g_register(struct v4l2_subdev *sd,
-                             struct v4l2_dbg_register *reg)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       if (!cx18_av_dbg_match(&reg->match))
-               return -EINVAL;
-       if ((reg->reg & 0x3) != 0)
-               return -EINVAL;
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       reg->size = 4;
-       reg->val = cx18_av_read4(cx, reg->reg & 0x00000ffc);
-       return 0;
-}
-
-static int cx18_av_s_register(struct v4l2_subdev *sd,
-                             struct v4l2_dbg_register *reg)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       if (!cx18_av_dbg_match(&reg->match))
-               return -EINVAL;
-       if ((reg->reg & 0x3) != 0)
-               return -EINVAL;
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       cx18_av_write4(cx, reg->reg & 0x00000ffc, reg->val);
-       return 0;
-}
-#endif
-
-static const struct v4l2_ctrl_ops cx18_av_ctrl_ops = {
-       .s_ctrl = cx18_av_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops cx18_av_general_ops = {
-       .g_chip_ident = cx18_av_g_chip_ident,
-       .log_status = cx18_av_log_status,
-       .load_fw = cx18_av_load_fw,
-       .reset = cx18_av_reset,
-       .g_ctrl = v4l2_subdev_g_ctrl,
-       .s_ctrl = v4l2_subdev_s_ctrl,
-       .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
-       .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
-       .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
-       .queryctrl = v4l2_subdev_queryctrl,
-       .querymenu = v4l2_subdev_querymenu,
-       .s_std = cx18_av_s_std,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register = cx18_av_g_register,
-       .s_register = cx18_av_s_register,
-#endif
-};
-
-static const struct v4l2_subdev_tuner_ops cx18_av_tuner_ops = {
-       .s_radio = cx18_av_s_radio,
-       .s_frequency = cx18_av_s_frequency,
-       .g_tuner = cx18_av_g_tuner,
-       .s_tuner = cx18_av_s_tuner,
-};
-
-static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
-       .s_clock_freq = cx18_av_s_clock_freq,
-       .s_routing = cx18_av_s_audio_routing,
-};
-
-static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
-       .s_routing = cx18_av_s_video_routing,
-       .s_stream = cx18_av_s_stream,
-       .s_mbus_fmt = cx18_av_s_mbus_fmt,
-};
-
-static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
-       .decode_vbi_line = cx18_av_decode_vbi_line,
-       .g_sliced_fmt = cx18_av_g_sliced_fmt,
-       .s_sliced_fmt = cx18_av_s_sliced_fmt,
-       .s_raw_fmt = cx18_av_s_raw_fmt,
-};
-
-static const struct v4l2_subdev_ops cx18_av_ops = {
-       .core = &cx18_av_general_ops,
-       .tuner = &cx18_av_tuner_ops,
-       .audio = &cx18_av_audio_ops,
-       .video = &cx18_av_video_ops,
-       .vbi = &cx18_av_vbi_ops,
-};
-
-int cx18_av_probe(struct cx18 *cx)
-{
-       struct cx18_av_state *state = &cx->av_state;
-       struct v4l2_subdev *sd;
-       int err;
-
-       state->rev = cx18_av_read4(cx, CXADEC_CHIP_CTRL) & 0xffff;
-       state->id = ((state->rev >> 4) == CXADEC_CHIP_TYPE_MAKO)
-                   ? V4L2_IDENT_CX23418_843 : V4L2_IDENT_UNKNOWN;
-
-       state->vid_input = CX18_AV_COMPOSITE7;
-       state->aud_input = CX18_AV_AUDIO8;
-       state->audclk_freq = 48000;
-       state->audmode = V4L2_TUNER_MODE_LANG1;
-       state->slicer_line_delay = 0;
-       state->slicer_line_offset = (10 + state->slicer_line_delay - 2);
-
-       sd = &state->sd;
-       v4l2_subdev_init(sd, &cx18_av_ops);
-       v4l2_set_subdevdata(sd, cx);
-       snprintf(sd->name, sizeof(sd->name),
-                "%s %03x", cx->v4l2_dev.name, (state->rev >> 4));
-       sd->grp_id = CX18_HW_418_AV;
-       v4l2_ctrl_handler_init(&state->hdl, 9);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 127, 1, 64);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 127, 1, 64);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
-                       V4L2_CID_HUE, -128, 127, 1, 0);
-
-       state->volume = v4l2_ctrl_new_std(&state->hdl,
-                       &cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
-                       0, 65535, 65535 / 100, 0);
-       v4l2_ctrl_new_std(&state->hdl,
-                       &cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
-                       0, 1, 1, 0);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
-                       V4L2_CID_AUDIO_BALANCE,
-                       0, 65535, 65535 / 100, 32768);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
-                       V4L2_CID_AUDIO_BASS,
-                       0, 65535, 65535 / 100, 32768);
-       v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
-                       V4L2_CID_AUDIO_TREBLE,
-                       0, 65535, 65535 / 100, 32768);
-       sd->ctrl_handler = &state->hdl;
-       if (state->hdl.error) {
-               int err = state->hdl.error;
-
-               v4l2_ctrl_handler_free(&state->hdl);
-               return err;
-       }
-       err = v4l2_device_register_subdev(&cx->v4l2_dev, sd);
-       if (err)
-               v4l2_ctrl_handler_free(&state->hdl);
-       else
-               cx18_av_init(cx);
-       return err;
-}
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
deleted file mode 100644 (file)
index e9c69d9..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- *  cx18 ADEC header
- *
- *  Derived from cx25840-core.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#ifndef _CX18_AV_CORE_H_
-#define _CX18_AV_CORE_H_
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-struct cx18;
-
-enum cx18_av_video_input {
-       /* Composite video inputs In1-In8 */
-       CX18_AV_COMPOSITE1 = 1,
-       CX18_AV_COMPOSITE2,
-       CX18_AV_COMPOSITE3,
-       CX18_AV_COMPOSITE4,
-       CX18_AV_COMPOSITE5,
-       CX18_AV_COMPOSITE6,
-       CX18_AV_COMPOSITE7,
-       CX18_AV_COMPOSITE8,
-
-       /* S-Video inputs consist of one luma input (In1-In8) ORed with one
-          chroma input (In5-In8) */
-       CX18_AV_SVIDEO_LUMA1 = 0x10,
-       CX18_AV_SVIDEO_LUMA2 = 0x20,
-       CX18_AV_SVIDEO_LUMA3 = 0x30,
-       CX18_AV_SVIDEO_LUMA4 = 0x40,
-       CX18_AV_SVIDEO_LUMA5 = 0x50,
-       CX18_AV_SVIDEO_LUMA6 = 0x60,
-       CX18_AV_SVIDEO_LUMA7 = 0x70,
-       CX18_AV_SVIDEO_LUMA8 = 0x80,
-       CX18_AV_SVIDEO_CHROMA4 = 0x400,
-       CX18_AV_SVIDEO_CHROMA5 = 0x500,
-       CX18_AV_SVIDEO_CHROMA6 = 0x600,
-       CX18_AV_SVIDEO_CHROMA7 = 0x700,
-       CX18_AV_SVIDEO_CHROMA8 = 0x800,
-
-       /* S-Video aliases for common luma/chroma combinations */
-       CX18_AV_SVIDEO1 = 0x510,
-       CX18_AV_SVIDEO2 = 0x620,
-       CX18_AV_SVIDEO3 = 0x730,
-       CX18_AV_SVIDEO4 = 0x840,
-
-       /* Component Video inputs consist of one luma input (In1-In8) ORed
-          with a red chroma (In4-In6) and blue chroma input (In7-In8) */
-       CX18_AV_COMPONENT_LUMA1 = 0x1000,
-       CX18_AV_COMPONENT_LUMA2 = 0x2000,
-       CX18_AV_COMPONENT_LUMA3 = 0x3000,
-       CX18_AV_COMPONENT_LUMA4 = 0x4000,
-       CX18_AV_COMPONENT_LUMA5 = 0x5000,
-       CX18_AV_COMPONENT_LUMA6 = 0x6000,
-       CX18_AV_COMPONENT_LUMA7 = 0x7000,
-       CX18_AV_COMPONENT_LUMA8 = 0x8000,
-       CX18_AV_COMPONENT_R_CHROMA4 = 0x40000,
-       CX18_AV_COMPONENT_R_CHROMA5 = 0x50000,
-       CX18_AV_COMPONENT_R_CHROMA6 = 0x60000,
-       CX18_AV_COMPONENT_B_CHROMA7 = 0x700000,
-       CX18_AV_COMPONENT_B_CHROMA8 = 0x800000,
-
-       /* Component Video aliases for common combinations */
-       CX18_AV_COMPONENT1 = 0x861000,
-};
-
-enum cx18_av_audio_input {
-       /* Audio inputs: serial or In4-In8 */
-       CX18_AV_AUDIO_SERIAL1,
-       CX18_AV_AUDIO_SERIAL2,
-       CX18_AV_AUDIO4 = 4,
-       CX18_AV_AUDIO5,
-       CX18_AV_AUDIO6,
-       CX18_AV_AUDIO7,
-       CX18_AV_AUDIO8,
-};
-
-struct cx18_av_state {
-       struct v4l2_subdev sd;
-       struct v4l2_ctrl_handler hdl;
-       struct v4l2_ctrl *volume;
-       int radio;
-       v4l2_std_id std;
-       enum cx18_av_video_input vid_input;
-       enum cx18_av_audio_input aud_input;
-       u32 audclk_freq;
-       int audmode;
-       u32 id;
-       u32 rev;
-       int is_initialized;
-
-       /*
-        * The VBI slicer starts operating and counting lines, beginning at
-        * slicer line count of 1, at D lines after the deassertion of VRESET.
-        * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525
-        * line systems respectively.  Sliced ancillary data captured on VBI
-        * slicer line M is inserted after the VBI slicer is done with line M,
-        * when VBI slicer line count is N = M+1.  Thus when the VBI slicer
-        * reports a VBI slicer line number with ancillary data, the IDID0 byte
-        * indicates VBI slicer line N.  The actual field line that the captured
-        * data comes from is
-        *
-        * L = M+(S+D-1) = N-1+(S+D-1) = N + (S+D-2).
-        *
-        * L is the line in the field, not frame, from which the VBI data came.
-        * N is the line reported by the slicer in the ancillary data.
-        * D is the slicer_line_delay value programmed into register 0x47f.
-        * S is 6 for 625 line systems or 10 for 525 line systems
-        * (S+D-2) is the slicer_line_offset used to convert slicer reported
-        * line counts to actual field lines.
-        */
-       int slicer_line_delay;
-       int slicer_line_offset;
-};
-
-
-/* Registers */
-#define CXADEC_CHIP_TYPE_TIGER     0x837
-#define CXADEC_CHIP_TYPE_MAKO      0x843
-
-#define CXADEC_HOST_REG1           0x000
-#define CXADEC_HOST_REG2           0x001
-
-#define CXADEC_CHIP_CTRL           0x100
-#define CXADEC_AFE_CTRL            0x104
-#define CXADEC_PLL_CTRL1           0x108
-#define CXADEC_VID_PLL_FRAC        0x10C
-#define CXADEC_AUX_PLL_FRAC        0x110
-#define CXADEC_PIN_CTRL1           0x114
-#define CXADEC_PIN_CTRL2           0x118
-#define CXADEC_PIN_CFG1            0x11C
-#define CXADEC_PIN_CFG2            0x120
-
-#define CXADEC_PIN_CFG3            0x124
-#define CXADEC_I2S_MCLK            0x127
-
-#define CXADEC_AUD_LOCK1           0x128
-#define CXADEC_AUD_LOCK2           0x12C
-#define CXADEC_POWER_CTRL          0x130
-#define CXADEC_AFE_DIAG_CTRL1      0x134
-#define CXADEC_AFE_DIAG_CTRL2      0x138
-#define CXADEC_AFE_DIAG_CTRL3      0x13C
-#define CXADEC_PLL_DIAG_CTRL       0x140
-#define CXADEC_TEST_CTRL1          0x144
-#define CXADEC_TEST_CTRL2          0x148
-#define CXADEC_BIST_STAT           0x14C
-#define CXADEC_DLL1_DIAG_CTRL      0x158
-#define CXADEC_DLL2_DIAG_CTRL      0x15C
-
-/* IR registers */
-#define CXADEC_IR_CTRL_REG         0x200
-#define CXADEC_IR_TXCLK_REG        0x204
-#define CXADEC_IR_RXCLK_REG        0x208
-#define CXADEC_IR_CDUTY_REG        0x20C
-#define CXADEC_IR_STAT_REG         0x210
-#define CXADEC_IR_IRQEN_REG        0x214
-#define CXADEC_IR_FILTER_REG       0x218
-#define CXADEC_IR_FIFO_REG         0x21C
-
-/* Video Registers */
-#define CXADEC_MODE_CTRL           0x400
-#define CXADEC_OUT_CTRL1           0x404
-#define CXADEC_OUT_CTRL2           0x408
-#define CXADEC_GEN_STAT            0x40C
-#define CXADEC_INT_STAT_MASK       0x410
-#define CXADEC_LUMA_CTRL           0x414
-
-#define CXADEC_BRIGHTNESS_CTRL_BYTE 0x414
-#define CXADEC_CONTRAST_CTRL_BYTE  0x415
-#define CXADEC_LUMA_CTRL_BYTE_3    0x416
-
-#define CXADEC_HSCALE_CTRL         0x418
-#define CXADEC_VSCALE_CTRL         0x41C
-
-#define CXADEC_CHROMA_CTRL         0x420
-
-#define CXADEC_USAT_CTRL_BYTE      0x420
-#define CXADEC_VSAT_CTRL_BYTE      0x421
-#define CXADEC_HUE_CTRL_BYTE       0x422
-
-#define CXADEC_VBI_LINE_CTRL1      0x424
-#define CXADEC_VBI_LINE_CTRL2      0x428
-#define CXADEC_VBI_LINE_CTRL3      0x42C
-#define CXADEC_VBI_LINE_CTRL4      0x430
-#define CXADEC_VBI_LINE_CTRL5      0x434
-#define CXADEC_VBI_FC_CFG          0x438
-#define CXADEC_VBI_MISC_CFG1       0x43C
-#define CXADEC_VBI_MISC_CFG2       0x440
-#define CXADEC_VBI_PAY1            0x444
-#define CXADEC_VBI_PAY2            0x448
-#define CXADEC_VBI_CUST1_CFG1      0x44C
-#define CXADEC_VBI_CUST1_CFG2      0x450
-#define CXADEC_VBI_CUST1_CFG3      0x454
-#define CXADEC_VBI_CUST2_CFG1      0x458
-#define CXADEC_VBI_CUST2_CFG2      0x45C
-#define CXADEC_VBI_CUST2_CFG3      0x460
-#define CXADEC_VBI_CUST3_CFG1      0x464
-#define CXADEC_VBI_CUST3_CFG2      0x468
-#define CXADEC_VBI_CUST3_CFG3      0x46C
-#define CXADEC_HORIZ_TIM_CTRL      0x470
-#define CXADEC_VERT_TIM_CTRL       0x474
-#define CXADEC_SRC_COMB_CFG        0x478
-#define CXADEC_CHROMA_VBIOFF_CFG   0x47C
-#define CXADEC_FIELD_COUNT         0x480
-#define CXADEC_MISC_TIM_CTRL       0x484
-#define CXADEC_DFE_CTRL1           0x488
-#define CXADEC_DFE_CTRL2           0x48C
-#define CXADEC_DFE_CTRL3           0x490
-#define CXADEC_PLL_CTRL2           0x494
-#define CXADEC_HTL_CTRL            0x498
-#define CXADEC_COMB_CTRL           0x49C
-#define CXADEC_CRUSH_CTRL          0x4A0
-#define CXADEC_SOFT_RST_CTRL       0x4A4
-#define CXADEC_MV_DT_CTRL2         0x4A8
-#define CXADEC_MV_DT_CTRL3         0x4AC
-#define CXADEC_MISC_DIAG_CTRL      0x4B8
-
-#define CXADEC_DL_CTL              0x800
-#define CXADEC_DL_CTL_ADDRESS_LOW  0x800   /* Byte 1 in DL_CTL */
-#define CXADEC_DL_CTL_ADDRESS_HIGH 0x801   /* Byte 2 in DL_CTL */
-#define CXADEC_DL_CTL_DATA         0x802   /* Byte 3 in DL_CTL */
-#define CXADEC_DL_CTL_CONTROL      0x803   /* Byte 4 in DL_CTL */
-
-#define CXADEC_STD_DET_STATUS      0x804
-
-#define CXADEC_STD_DET_CTL         0x808
-#define CXADEC_STD_DET_CTL_AUD_CTL   0x808 /* Byte 1 in STD_DET_CTL */
-#define CXADEC_STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */
-
-#define CXADEC_DW8051_INT          0x80C
-#define CXADEC_GENERAL_CTL         0x810
-#define CXADEC_AAGC_CTL            0x814
-#define CXADEC_IF_SRC_CTL          0x818
-#define CXADEC_ANLOG_DEMOD_CTL     0x81C
-#define CXADEC_ROT_FREQ_CTL        0x820
-#define CXADEC_FM1_CTL             0x824
-#define CXADEC_PDF_CTL             0x828
-#define CXADEC_DFT1_CTL1           0x82C
-#define CXADEC_DFT1_CTL2           0x830
-#define CXADEC_DFT_STATUS          0x834
-#define CXADEC_DFT2_CTL1           0x838
-#define CXADEC_DFT2_CTL2           0x83C
-#define CXADEC_DFT2_STATUS         0x840
-#define CXADEC_DFT3_CTL1           0x844
-#define CXADEC_DFT3_CTL2           0x848
-#define CXADEC_DFT3_STATUS         0x84C
-#define CXADEC_DFT4_CTL1           0x850
-#define CXADEC_DFT4_CTL2           0x854
-#define CXADEC_DFT4_STATUS         0x858
-#define CXADEC_AM_MTS_DET          0x85C
-#define CXADEC_ANALOG_MUX_CTL      0x860
-#define CXADEC_DIG_PLL_CTL1        0x864
-#define CXADEC_DIG_PLL_CTL2        0x868
-#define CXADEC_DIG_PLL_CTL3        0x86C
-#define CXADEC_DIG_PLL_CTL4        0x870
-#define CXADEC_DIG_PLL_CTL5        0x874
-#define CXADEC_DEEMPH_GAIN_CTL     0x878
-#define CXADEC_DEEMPH_COEF1        0x87C
-#define CXADEC_DEEMPH_COEF2        0x880
-#define CXADEC_DBX1_CTL1           0x884
-#define CXADEC_DBX1_CTL2           0x888
-#define CXADEC_DBX1_STATUS         0x88C
-#define CXADEC_DBX2_CTL1           0x890
-#define CXADEC_DBX2_CTL2           0x894
-#define CXADEC_DBX2_STATUS         0x898
-#define CXADEC_AM_FM_DIFF          0x89C
-
-/* NICAM registers go here */
-#define CXADEC_NICAM_STATUS        0x8C8
-#define CXADEC_DEMATRIX_CTL        0x8CC
-
-#define CXADEC_PATH1_CTL1          0x8D0
-#define CXADEC_PATH1_VOL_CTL       0x8D4
-#define CXADEC_PATH1_EQ_CTL        0x8D8
-#define CXADEC_PATH1_SC_CTL        0x8DC
-
-#define CXADEC_PATH2_CTL1          0x8E0
-#define CXADEC_PATH2_VOL_CTL       0x8E4
-#define CXADEC_PATH2_EQ_CTL        0x8E8
-#define CXADEC_PATH2_SC_CTL        0x8EC
-
-#define CXADEC_SRC_CTL             0x8F0
-#define CXADEC_SRC_LF_COEF         0x8F4
-#define CXADEC_SRC1_CTL            0x8F8
-#define CXADEC_SRC2_CTL            0x8FC
-#define CXADEC_SRC3_CTL            0x900
-#define CXADEC_SRC4_CTL            0x904
-#define CXADEC_SRC5_CTL            0x908
-#define CXADEC_SRC6_CTL            0x90C
-
-#define CXADEC_BASEBAND_OUT_SEL    0x910
-#define CXADEC_I2S_IN_CTL          0x914
-#define CXADEC_I2S_OUT_CTL         0x918
-#define CXADEC_AC97_CTL            0x91C
-#define CXADEC_QAM_PDF             0x920
-#define CXADEC_QAM_CONST_DEC       0x924
-#define CXADEC_QAM_ROTATOR_FREQ    0x948
-
-/* Bit definitions / settings used in Mako Audio */
-#define CXADEC_PREF_MODE_MONO_LANGA        0
-#define CXADEC_PREF_MODE_MONO_LANGB        1
-#define CXADEC_PREF_MODE_MONO_LANGC        2
-#define CXADEC_PREF_MODE_FALLBACK          3
-#define CXADEC_PREF_MODE_STEREO            4
-#define CXADEC_PREF_MODE_DUAL_LANG_AC      5
-#define CXADEC_PREF_MODE_DUAL_LANG_BC      6
-#define CXADEC_PREF_MODE_DUAL_LANG_AB      7
-
-
-#define CXADEC_DETECT_STEREO               1
-#define CXADEC_DETECT_DUAL                 2
-#define CXADEC_DETECT_TRI                  4
-#define CXADEC_DETECT_SAP                  0x10
-#define CXADEC_DETECT_NO_SIGNAL            0xFF
-
-#define CXADEC_SELECT_AUDIO_STANDARD_BG    0xF0  /* NICAM BG and A2 BG */
-#define CXADEC_SELECT_AUDIO_STANDARD_DK1   0xF1  /* NICAM DK and A2 DK */
-#define CXADEC_SELECT_AUDIO_STANDARD_DK2   0xF2
-#define CXADEC_SELECT_AUDIO_STANDARD_DK3   0xF3
-#define CXADEC_SELECT_AUDIO_STANDARD_I     0xF4  /* NICAM I and A1 */
-#define CXADEC_SELECT_AUDIO_STANDARD_L     0xF5  /* NICAM L and System L AM */
-#define CXADEC_SELECT_AUDIO_STANDARD_BTSC  0xF6
-#define CXADEC_SELECT_AUDIO_STANDARD_EIAJ  0xF7
-#define CXADEC_SELECT_AUDIO_STANDARD_A2_M  0xF8  /* A2 M */
-#define CXADEC_SELECT_AUDIO_STANDARD_FM    0xF9  /* FM radio */
-#define CXADEC_SELECT_AUDIO_STANDARD_AUTO  0xFF  /* Auto detect */
-
-static inline struct cx18_av_state *to_cx18_av_state(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct cx18_av_state, sd);
-}
-
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-       return &container_of(ctrl->handler, struct cx18_av_state, hdl)->sd;
-}
-
-/* ----------------------------------------------------------------------- */
-/* cx18_av-core.c                                                         */
-int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
-int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
-int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
-int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask);
-int cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval,
-                         u32 mask);
-u8 cx18_av_read(struct cx18 *cx, u16 addr);
-u32 cx18_av_read4(struct cx18 *cx, u16 addr);
-int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
-int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
-void cx18_av_std_setup(struct cx18 *cx);
-
-int cx18_av_probe(struct cx18 *cx);
-
-/* ----------------------------------------------------------------------- */
-/* cx18_av-firmware.c                                                      */
-int cx18_av_loadfw(struct cx18 *cx);
-
-/* ----------------------------------------------------------------------- */
-/* cx18_av-audio.c                                                         */
-int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
-void cx18_av_audio_set_path(struct cx18 *cx);
-extern const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops;
-
-/* ----------------------------------------------------------------------- */
-/* cx18_av-vbi.c                                                           */
-int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
-                          struct v4l2_decode_vbi_line *vbi);
-int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
-int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
-int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
-
-#endif
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
deleted file mode 100644 (file)
index a34fd08..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- *  cx18 ADEC firmware functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include <linux/firmware.h>
-
-#define CX18_AUDIO_ENABLE    0xc72014
-#define CX18_AI1_MUX_MASK    0x30
-#define CX18_AI1_MUX_I2S1    0x00
-#define CX18_AI1_MUX_I2S2    0x10
-#define CX18_AI1_MUX_843_I2S 0x20
-#define CX18_AI1_MUX_INVALID 0x30
-
-#define FWFILE "v4l-cx23418-dig.fw"
-
-static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
-{
-       struct v4l2_subdev *sd = &cx->av_state.sd;
-       int ret = 0;
-       const u8 *data;
-       u32 size;
-       int addr;
-       u32 expected, dl_control;
-
-       /* Ensure we put the 8051 in reset and enable firmware upload mode */
-       dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
-       do {
-               dl_control &= 0x00ffffff;
-               dl_control |= 0x0f000000;
-               cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
-               dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
-       } while ((dl_control & 0xff000000) != 0x0f000000);
-
-       /* Read and auto increment until at address 0x0000 */
-       while (dl_control & 0x3fff)
-               dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
-
-       data = fw->data;
-       size = fw->size;
-       for (addr = 0; addr < size; addr++) {
-               dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
-               expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
-               if (expected != dl_control) {
-                       CX18_ERR_DEV(sd, "verification of %s firmware load "
-                                    "failed: expected %#010x got %#010x\n",
-                                    FWFILE, expected, dl_control);
-                       ret = -EIO;
-                       break;
-               }
-               dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
-       }
-       if (ret == 0)
-               CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
-                             FWFILE, size);
-       return ret;
-}
-
-int cx18_av_loadfw(struct cx18 *cx)
-{
-       struct v4l2_subdev *sd = &cx->av_state.sd;
-       const struct firmware *fw = NULL;
-       u32 size;
-       u32 u, v;
-       const u8 *ptr;
-       int i;
-       int retries1 = 0;
-
-       if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) {
-               CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE);
-               return -EINVAL;
-       }
-
-       /* The firmware load often has byte errors, so allow for several
-          retries, both at byte level and at the firmware load level. */
-       while (retries1 < 5) {
-               cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000,
-                                         0x00008430, 0xffffffff); /* cx25843 */
-               cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff);
-
-               /* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */
-               cx18_av_write4_expect(cx, 0x8100, 0x00010000,
-                                         0x00008430, 0xffffffff); /* cx25843 */
-
-               /* Put the 8051 in reset and enable firmware upload */
-               cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
-
-               ptr = fw->data;
-               size = fw->size;
-
-               for (i = 0; i < size; i++) {
-                       u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
-                       u32 value = 0;
-                       int retries2;
-                       int unrec_err = 0;
-
-                       for (retries2 = 0; retries2 < CX18_MAX_MMIO_WR_RETRIES;
-                            retries2++) {
-                               cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
-                                                      dl_control);
-                               udelay(10);
-                               value = cx18_av_read4(cx, CXADEC_DL_CTL);
-                               if (value == dl_control)
-                                       break;
-                               /* Check if we can correct the byte by changing
-                                  the address.  We can only write the lower
-                                  address byte of the address. */
-                               if ((value & 0x3F00) != (dl_control & 0x3F00)) {
-                                       unrec_err = 1;
-                                       break;
-                               }
-                       }
-                       if (unrec_err || retries2 >= CX18_MAX_MMIO_WR_RETRIES)
-                               break;
-               }
-               if (i == size)
-                       break;
-               retries1++;
-       }
-       if (retries1 >= 5) {
-               CX18_ERR_DEV(sd, "unable to load firmware %s\n", FWFILE);
-               release_firmware(fw);
-               return -EIO;
-       }
-
-       cx18_av_write4_expect(cx, CXADEC_DL_CTL,
-                               0x03000000 | fw->size, 0x03000000, 0x13000000);
-
-       CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
-
-       if (cx18_av_verifyfw(cx, fw) == 0)
-               cx18_av_write4_expect(cx, CXADEC_DL_CTL,
-                               0x13000000 | fw->size, 0x13000000, 0x13000000);
-
-       /* Output to the 416 */
-       cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
-
-       /* Audio input control 1 set to Sony mode */
-       /* Audio output input 2 is 0 for slave operation input */
-       /* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
-       /* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
-          after WS transition for first bit of audio word. */
-       cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0);
-
-       /* Audio output control 1 is set to Sony mode */
-       /* Audio output control 2 is set to 1 for master mode */
-       /* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
-       /* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
-          after WS transition for first bit of audio word. */
-       /* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT
-          are generated) */
-       cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
-
-       /* set alt I2s master clock to /0x16 and enable alt divider i2s
-          passthrough */
-       cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5600B687);
-
-       cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
-                                                                 0x3F00FFFF);
-       /* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
-
-       /* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
-       /* Register 0x09CC is defined by the Merlin firmware, and doesn't
-          have a name in the spec. */
-       cx18_av_write4(cx, 0x09CC, 1);
-
-       v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
-       /* If bit 11 is 1, clear bit 10 */
-       if (v & 0x800)
-               cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE,
-                                     0, 0x400);
-
-       /* Toggle the AI1 MUX */
-       v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
-       u = v & CX18_AI1_MUX_MASK;
-       v &= ~CX18_AI1_MUX_MASK;
-       if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) {
-               /* Switch to I2S1 */
-               v |= CX18_AI1_MUX_I2S1;
-               cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
-                                     v, CX18_AI1_MUX_MASK);
-               /* Switch back to the A/V decoder core I2S output */
-               v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S;
-       } else {
-               /* Switch to the A/V decoder core I2S output */
-               v |= CX18_AI1_MUX_843_I2S;
-               cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
-                                     v, CX18_AI1_MUX_MASK);
-               /* Switch back to I2S1 or I2S2 */
-               v = (v & ~CX18_AI1_MUX_MASK) | u;
-       }
-       cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
-                             v, CX18_AI1_MUX_MASK);
-
-       /* Enable WW auto audio standard detection */
-       v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
-       v |= 0xFF;   /* Auto by default */
-       v |= 0x400;  /* Stereo by default */
-       v |= 0x14000000;
-       cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
-
-       release_firmware(fw);
-       return 0;
-}
-
-MODULE_FIRMWARE(FWFILE);
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c
deleted file mode 100644 (file)
index baa36fb..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- *  cx18 ADEC VBI functions
- *
- *  Derived from cx25840-vbi.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-
-#include "cx18-driver.h"
-
-/*
- * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
- * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
- * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
- * (should!) look like:
- *     4 byte EAV code:          0xff 0x00 0x00 0xRP
- *     unknown number of possible idle bytes
- *     3 byte Anc data preamble: 0x00 0xff 0xff
- *     1 byte data identifier:   ne010iii (parity bits, 010, DID bits)
- *     1 byte secondary data id: nessssss (parity bits, SDID bits)
- *     1 byte data word count:   necccccc (parity bits, NN Dword count)
- *     2 byte Internal DID:      VBI-line-# 0x80
- *     NN data bytes
- *     1 byte checksum
- *     Fill bytes needed to fil out to 4*NN bytes of payload
- *
- * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
- * in the vertical blanking interval are:
- *     0xb0 (Task         0 VerticalBlank HorizontalBlank 0 0 0 0)
- *     0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
- *
- * Since the V bit is only allowed to toggle in the EAV RP code, just
- * before the first active region line and for active lines, they are:
- *     0x90 (Task         0 0 HorizontalBlank 0 0 0 0)
- *     0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
- *
- * The user application DID bytes we care about are:
- *     0x91 (1 0 010        0 !ActiveLine AncDataPresent)
- *     0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
- *
- */
-static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
-
-struct vbi_anc_data {
-       /* u8 eav[4]; */
-       /* u8 idle[]; Variable number of idle bytes */
-       u8 preamble[3];
-       u8 did;
-       u8 sdid;
-       u8 data_count;
-       u8 idid[2];
-       u8 payload[1]; /* data_count of payload */
-       /* u8 checksum; */
-       /* u8 fill[]; Variable number of fill bytes */
-};
-
-static int odd_parity(u8 c)
-{
-       c ^= (c >> 4);
-       c ^= (c >> 2);
-       c ^= (c >> 1);
-
-       return c & 1;
-}
-
-static int decode_vps(u8 *dst, u8 *p)
-{
-       static const u8 biphase_tbl[] = {
-               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
-               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
-               0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
-               0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
-               0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
-               0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
-               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
-               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
-               0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
-               0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
-               0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
-               0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
-               0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
-               0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
-               0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
-               0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
-               0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
-               0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
-               0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
-               0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
-               0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
-               0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
-               0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
-               0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
-               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
-               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
-               0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
-               0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
-               0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
-               0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
-               0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
-               0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
-       };
-
-       u8 c, err = 0;
-       int i;
-
-       for (i = 0; i < 2 * 13; i += 2) {
-               err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
-               c = (biphase_tbl[p[i + 1]] & 0xf) |
-                   ((biphase_tbl[p[i]] & 0xf) << 4);
-               dst[i / 2] = c;
-       }
-
-       return err & 0xf0;
-}
-
-int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       struct cx18_av_state *state = &cx->av_state;
-       static const u16 lcr2vbi[] = {
-               0, V4L2_SLICED_TELETEXT_B, 0,   /* 1 */
-               0, V4L2_SLICED_WSS_625, 0,      /* 4 */
-               V4L2_SLICED_CAPTION_525,        /* 6 */
-               0, 0, V4L2_SLICED_VPS, 0, 0,    /* 9 */
-               0, 0, 0, 0
-       };
-       int is_pal = !(state->std & V4L2_STD_525_60);
-       int i;
-
-       memset(svbi, 0, sizeof(*svbi));
-       /* we're done if raw VBI is active */
-       if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
-               return 0;
-
-       if (is_pal) {
-               for (i = 7; i <= 23; i++) {
-                       u8 v = cx18_av_read(cx, 0x424 + i - 7);
-
-                       svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-                       svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-                       svbi->service_set |= svbi->service_lines[0][i] |
-                               svbi->service_lines[1][i];
-               }
-       } else {
-               for (i = 10; i <= 21; i++) {
-                       u8 v = cx18_av_read(cx, 0x424 + i - 10);
-
-                       svbi->service_lines[0][i] = lcr2vbi[v >> 4];
-                       svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
-                       svbi->service_set |= svbi->service_lines[0][i] |
-                               svbi->service_lines[1][i];
-               }
-       }
-       return 0;
-}
-
-int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       struct cx18_av_state *state = &cx->av_state;
-
-       /* Setup standard */
-       cx18_av_std_setup(cx);
-
-       /* VBI Offset */
-       cx18_av_write(cx, 0x47f, state->slicer_line_delay);
-       cx18_av_write(cx, 0x404, 0x2e);
-       return 0;
-}
-
-int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       struct cx18_av_state *state = &cx->av_state;
-       int is_pal = !(state->std & V4L2_STD_525_60);
-       int i, x;
-       u8 lcr[24];
-
-       for (x = 0; x <= 23; x++)
-               lcr[x] = 0x00;
-
-       /* Setup standard */
-       cx18_av_std_setup(cx);
-
-       /* Sliced VBI */
-       cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
-       cx18_av_write(cx, 0x406, 0x13);
-       cx18_av_write(cx, 0x47f, state->slicer_line_delay);
-
-       /* Force impossible lines to 0 */
-       if (is_pal) {
-               for (i = 0; i <= 6; i++)
-                       svbi->service_lines[0][i] =
-                               svbi->service_lines[1][i] = 0;
-       } else {
-               for (i = 0; i <= 9; i++)
-                       svbi->service_lines[0][i] =
-                               svbi->service_lines[1][i] = 0;
-
-               for (i = 22; i <= 23; i++)
-                       svbi->service_lines[0][i] =
-                               svbi->service_lines[1][i] = 0;
-       }
-
-       /* Build register values for requested service lines */
-       for (i = 7; i <= 23; i++) {
-               for (x = 0; x <= 1; x++) {
-                       switch (svbi->service_lines[1-x][i]) {
-                       case V4L2_SLICED_TELETEXT_B:
-                               lcr[i] |= 1 << (4 * x);
-                               break;
-                       case V4L2_SLICED_WSS_625:
-                               lcr[i] |= 4 << (4 * x);
-                               break;
-                       case V4L2_SLICED_CAPTION_525:
-                               lcr[i] |= 6 << (4 * x);
-                               break;
-                       case V4L2_SLICED_VPS:
-                               lcr[i] |= 9 << (4 * x);
-                               break;
-                       }
-               }
-       }
-
-       if (is_pal) {
-               for (x = 1, i = 0x424; i <= 0x434; i++, x++)
-                       cx18_av_write(cx, i, lcr[6 + x]);
-       } else {
-               for (x = 1, i = 0x424; i <= 0x430; i++, x++)
-                       cx18_av_write(cx, i, lcr[9 + x]);
-               for (i = 0x431; i <= 0x434; i++)
-                       cx18_av_write(cx, i, 0);
-       }
-
-       cx18_av_write(cx, 0x43c, 0x16);
-       /* Should match vblank set in cx18_av_std_setup() */
-       cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
-       return 0;
-}
-
-int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
-                                  struct v4l2_decode_vbi_line *vbi)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       struct cx18_av_state *state = &cx->av_state;
-       struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
-       u8 *p;
-       int did, sdid, l, err = 0;
-
-       /*
-        * Check for the ancillary data header for sliced VBI
-        */
-       if (anc->preamble[0] ||
-                       anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
-                       (anc->did != sliced_vbi_did[0] &&
-                        anc->did != sliced_vbi_did[1])) {
-               vbi->line = vbi->type = 0;
-               return 0;
-       }
-
-       did = anc->did;
-       sdid = anc->sdid & 0xf;
-       l = anc->idid[0] & 0x3f;
-       l += state->slicer_line_offset;
-       p = anc->payload;
-
-       /* Decode the SDID set by the slicer */
-       switch (sdid) {
-       case 1:
-               sdid = V4L2_SLICED_TELETEXT_B;
-               break;
-       case 4:
-               sdid = V4L2_SLICED_WSS_625;
-               break;
-       case 6:
-               sdid = V4L2_SLICED_CAPTION_525;
-               err = !odd_parity(p[0]) || !odd_parity(p[1]);
-               break;
-       case 9:
-               sdid = V4L2_SLICED_VPS;
-               if (decode_vps(p, p) != 0)
-                       err = 1;
-               break;
-       default:
-               sdid = 0;
-               err = 1;
-               break;
-       }
-
-       vbi->type = err ? 0 : sdid;
-       vbi->line = err ? 0 : l;
-       vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
-       vbi->p = p;
-       return 0;
-}
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c
deleted file mode 100644 (file)
index c07c849..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- *  cx18 functions to query card hardware
- *
- *  Derived from ivtv-cards.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-cards.h"
-#include "cx18-av-core.h"
-#include "cx18-i2c.h"
-#include <media/cs5345.h>
-
-#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
-
-/********************** card configuration *******************************/
-
-/* usual i2c tuner addresses to probe */
-static struct cx18_card_tuner_i2c cx18_i2c_std = {
-       .radio = { I2C_CLIENT_END },
-       .demod = { 0x43, I2C_CLIENT_END },
-       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
-};
-
-/*
- * usual i2c tuner addresses to probe with additional demod address for
- * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too).
- */
-static struct cx18_card_tuner_i2c cx18_i2c_nxp = {
-       .radio = { I2C_CLIENT_END },
-       .demod = { 0x42, 0x43, I2C_CLIENT_END },
-       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
-};
-
-/* Please add new PCI IDs to: http://pci-ids.ucw.cz/
-   This keeps the PCI ID database up to date. Note that the entries
-   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
-   New vendor IDs should still be added to the vendor ID list. */
-
-/* Hauppauge HVR-1600 cards */
-
-/* Note: for Hauppauge cards the tveeprom information is used instead
-   of PCI IDs */
-static const struct cx18_card cx18_card_hvr1600_esmt = {
-       .type = CX18_CARD_HVR_1600_ESMT,
-       .name = "Hauppauge HVR-1600",
-       .comment = "Simultaneous Digital and Analog TV capture supported\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_CS5345,
-       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
-                 CX18_HW_Z8F0811_IR_HAUP,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
-               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
-               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER,
-                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
-               { CX18_CARD_INPUT_LINE_IN1,
-                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
-               { CX18_CARD_INPUT_LINE_IN2,
-                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
-       .ddr = {
-               /* ESMT M13S128324A-5B memory */
-               .chip_config = 0x003,
-               .refresh = 0x30c,
-               .timing1 = 0x44220e82,
-               .timing2 = 0x08,
-               .tune_lane = 0,
-               .initial_emrs = 0,
-       },
-       .gpio_init.initial_value = 0x3001,
-       .gpio_init.direction = 0x3001,
-       .gpio_i2c_slave_reset = {
-               .active_lo_mask = 0x3001,
-               .msecs_asserted = 10,
-               .msecs_recovery = 40,
-               .ir_reset_mask  = 0x0001,
-       },
-       .i2c = &cx18_i2c_std,
-};
-
-static const struct cx18_card cx18_card_hvr1600_s5h1411 = {
-       .type = CX18_CARD_HVR_1600_S5H1411,
-       .name = "Hauppauge HVR-1600",
-       .comment = "Simultaneous Digital and Analog TV capture supported\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_CS5345,
-       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
-                 CX18_HW_Z8F0811_IR_HAUP,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
-               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
-               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER,
-                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
-               { CX18_CARD_INPUT_LINE_IN1,
-                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
-               { CX18_CARD_INPUT_LINE_IN2,
-                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
-       .ddr = {
-               /* ESMT M13S128324A-5B memory */
-               .chip_config = 0x003,
-               .refresh = 0x30c,
-               .timing1 = 0x44220e82,
-               .timing2 = 0x08,
-               .tune_lane = 0,
-               .initial_emrs = 0,
-       },
-       .gpio_init.initial_value = 0x3801,
-       .gpio_init.direction = 0x3801,
-       .gpio_i2c_slave_reset = {
-               .active_lo_mask = 0x3801,
-               .msecs_asserted = 10,
-               .msecs_recovery = 40,
-               .ir_reset_mask  = 0x0001,
-       },
-       .i2c = &cx18_i2c_nxp,
-};
-
-static const struct cx18_card cx18_card_hvr1600_samsung = {
-       .type = CX18_CARD_HVR_1600_SAMSUNG,
-       .name = "Hauppauge HVR-1600 (Preproduction)",
-       .comment = "Simultaneous Digital and Analog TV capture supported\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_CS5345,
-       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
-                 CX18_HW_Z8F0811_IR_HAUP,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
-               { CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
-               { CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER,
-                 CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
-               { CX18_CARD_INPUT_LINE_IN1,
-                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
-               { CX18_CARD_INPUT_LINE_IN2,
-                 CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
-       .ddr = {
-               /* Samsung K4D263238G-VC33 memory */
-               .chip_config = 0x003,
-               .refresh = 0x30c,
-               .timing1 = 0x23230b73,
-               .timing2 = 0x08,
-               .tune_lane = 0,
-               .initial_emrs = 2,
-       },
-       .gpio_init.initial_value = 0x3001,
-       .gpio_init.direction = 0x3001,
-       .gpio_i2c_slave_reset = {
-               .active_lo_mask = 0x3001,
-               .msecs_asserted = 10,
-               .msecs_recovery = 40,
-               .ir_reset_mask  = 0x0001,
-       },
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Compro VideoMate H900: note that this card is analog only! */
-
-static const struct cx18_card_pci_info cx18_pci_h900[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_h900 = {
-       .type = CX18_CARD_COMPRO_H900,
-       .name = "Compro VideoMate H900",
-       .comment = "Analog TV capture supported\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER,
-                 CX18_AV_AUDIO5, 0 },
-               { CX18_CARD_INPUT_LINE_IN1,
-                 CX18_AV_AUDIO_SERIAL1, 0 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER,
-                        CX18_AV_AUDIO_SERIAL1, 0 },
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .ddr = {
-               /* EtronTech EM6A9160TS-5G memory */
-               .chip_config = 0x50003,
-               .refresh = 0x753,
-               .timing1 = 0x24330e84,
-               .timing2 = 0x1f,
-               .tune_lane = 0,
-               .initial_emrs = 0,
-       },
-       .xceive_pin = 15,
-       .pci_list = cx18_pci_h900,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan MPC718: not working at the moment! */
-
-static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_YUAN, 0x0718 },
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_mpc718 = {
-       .type = CX18_CARD_YUAN_MPC718,
-       .name = "Yuan MPC718 MiniPCI DVB-T/Analog",
-       .comment = "Experimenters needed for device to work well.\n"
-                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_MUX,
-       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                               CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
-               { CX18_CARD_INPUT_SVIDEO2,    2,
-                               CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
-               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
-       },
-       .tuners = {
-               /* XC3028 tuner */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       /* FIXME - the FM radio is just a guess and driver doesn't use SIF */
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
-       .ddr = {
-               /* Hynix HY5DU283222B DDR RAM */
-               .chip_config = 0x303,
-               .refresh = 0x3bd,
-               .timing1 = 0x36320966,
-               .timing2 = 0x1f,
-               .tune_lane = 0,
-               .initial_emrs = 2,
-       },
-       .gpio_init.initial_value = 0x1,
-       .gpio_init.direction = 0x3,
-       /* FIXME - these GPIO's are just guesses */
-       .gpio_audio_input = { .mask   = 0x3,
-                             .tuner  = 0x1,
-                             .linein = 0x3,
-                             .radio  = 0x1 },
-       .xceive_pin = 0,
-       .pci_list = cx18_pci_mpc718,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* GoTView PCI */
-
-static const struct cx18_card_pci_info cx18_pci_gotview_dvd3[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_GOTVIEW, 0x3343 },
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_gotview_dvd3 = {
-       .type = CX18_CARD_GOTVIEW_PCI_DVD3,
-       .name = "GoTView PCI DVD3 Hybrid",
-       .comment = "Experimenters needed for device to work well.\n"
-                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_MUX,
-       .hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
-                 CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                               CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
-               { CX18_CARD_INPUT_SVIDEO2,    2,
-                               CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
-               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
-       },
-       .tuners = {
-               /* XC3028 tuner */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       /* FIXME - the FM radio is just a guess and driver doesn't use SIF */
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
-       .ddr = {
-               /* Hynix HY5DU283222B DDR RAM */
-               .chip_config = 0x303,
-               .refresh = 0x3bd,
-               .timing1 = 0x36320966,
-               .timing2 = 0x1f,
-               .tune_lane = 0,
-               .initial_emrs = 2,
-       },
-       .gpio_init.initial_value = 0x1,
-       .gpio_init.direction = 0x3,
-
-       .gpio_audio_input = { .mask   = 0x3,
-                             .tuner  = 0x1,
-                             .linein = 0x2,
-                             .radio  = 0x1 },
-       .xceive_pin = 0,
-       .pci_list = cx18_pci_gotview_dvd3,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Conexant Raptor PAL/SECAM: note that this card is analog only! */
-
-static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_CONEXANT, 0x0009 },
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_cnxt_raptor_pal = {
-       .type = CX18_CARD_CNXT_RAPTOR_PAL,
-       .name = "Conexant Raptor PAL/SECAM",
-       .comment = "Analog TV capture supported\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_MUX,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
-               { CX18_CARD_INPUT_SVIDEO2,    2,
-                       CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
-               { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
-               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
-       },
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 2 },
-       .ddr = {
-               /* MT 46V16M16 memory */
-               .chip_config = 0x50306,
-               .refresh = 0x753,
-               .timing1 = 0x33220953,
-               .timing2 = 0x09,
-               .tune_lane = 0,
-               .initial_emrs = 0,
-       },
-       .gpio_init.initial_value = 0x1002,
-       .gpio_init.direction = 0xf002,
-       .gpio_audio_input = { .mask   = 0xf002,
-                             .tuner  = 0x1002,   /* LED D1  Tuner AF  */
-                             .linein = 0x2000,   /* LED D2  Line In 1 */
-                             .radio  = 0x4002 }, /* LED D3  Tuner AF  */
-       .pci_list = cx18_pci_cnxt_raptor_pal,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */
-
-static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 },
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
-       .type = CX18_CARD_TOSHIBA_QOSMIO_DVBT,
-       .name = "Toshiba Qosmio DVB-T/Analog",
-       .comment = "Experimenters and photos needed for device to work well.\n"
-                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE6 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
-       },
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .ddr = {
-               .chip_config = 0x202,
-               .refresh = 0x3bb,
-               .timing1 = 0x33320a63,
-               .timing2 = 0x0a,
-               .tune_lane = 0,
-               .initial_emrs = 0x42,
-       },
-       .xceive_pin = 15,
-       .pci_list = cx18_pci_toshiba_qosmio_dvbt,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Leadtek WinFast PVR2100 */
-
-static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100   */
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_leadtek_pvr2100 = {
-       .type = CX18_CARD_LEADTEK_PVR2100,
-       .name = "Leadtek WinFast PVR2100",
-       .comment = "Experimenters and photos needed for device to work well.\n"
-                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_MUX,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
-                 CX18_HW_GPIO_RESET_CTRL,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
-               { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
-       },
-       .tuners = {
-               /* XC2028 tuner */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
-       .ddr = {
-               /* Pointer to proper DDR config values provided by Terry Wu */
-               .chip_config = 0x303,
-               .refresh = 0x3bb,
-               .timing1 = 0x24220e83,
-               .timing2 = 0x1f,
-               .tune_lane = 0,
-               .initial_emrs = 0x2,
-       },
-       .gpio_init.initial_value = 0x6,
-       .gpio_init.direction = 0x7,
-       .gpio_audio_input = { .mask   = 0x7,
-                             .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
-       .xceive_pin = 1,
-       .pci_list = cx18_pci_leadtek_pvr2100,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Leadtek WinFast DVR3100 H */
-
-static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = {
-       { PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
-       { 0, 0, 0 }
-};
-
-static const struct cx18_card cx18_card_leadtek_dvr3100h = {
-       .type = CX18_CARD_LEADTEK_DVR3100H,
-       .name = "Leadtek WinFast DVR3100 H",
-       .comment = "Simultaneous DVB-T and Analog capture supported,\n"
-                 "\texcept when capturing Analog from the antenna input.\n",
-       .v4l2_capabilities = CX18_CAP_ENCODER,
-       .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_muxer = CX18_HW_GPIO_MUX,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_MUX |
-                 CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
-       .video_inputs = {
-               { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
-               { CX18_CARD_INPUT_SVIDEO1,    1,
-                       CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
-               { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
-               { CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 },
-       },
-       .audio_inputs = {
-               { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
-       },
-       .tuners = {
-               /* XC3028 tuner */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
-       .ddr = {
-               /* Pointer to proper DDR config values provided by Terry Wu */
-               .chip_config = 0x303,
-               .refresh = 0x3bb,
-               .timing1 = 0x24220e83,
-               .timing2 = 0x1f,
-               .tune_lane = 0,
-               .initial_emrs = 0x2,
-       },
-       .gpio_init.initial_value = 0x6,
-       .gpio_init.direction = 0x7,
-       .gpio_audio_input = { .mask   = 0x7,
-                             .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
-       .xceive_pin = 1,
-       .pci_list = cx18_pci_leadtek_dvr3100h,
-       .i2c = &cx18_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-static const struct cx18_card *cx18_card_list[] = {
-       &cx18_card_hvr1600_esmt,
-       &cx18_card_hvr1600_samsung,
-       &cx18_card_h900,
-       &cx18_card_mpc718,
-       &cx18_card_cnxt_raptor_pal,
-       &cx18_card_toshiba_qosmio_dvbt,
-       &cx18_card_leadtek_pvr2100,
-       &cx18_card_leadtek_dvr3100h,
-       &cx18_card_gotview_dvd3,
-       &cx18_card_hvr1600_s5h1411
-};
-
-const struct cx18_card *cx18_get_card(u16 index)
-{
-       if (index >= ARRAY_SIZE(cx18_card_list))
-               return NULL;
-       return cx18_card_list[index];
-}
-
-int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
-{
-       const struct cx18_card_video_input *card_input =
-               cx->card->video_inputs + index;
-       static const char * const input_strs[] = {
-               "Tuner 1",
-               "S-Video 1",
-               "S-Video 2",
-               "Composite 1",
-               "Composite 2",
-               "Component 1"
-       };
-
-       if (index >= cx->nof_inputs)
-               return -EINVAL;
-       input->index = index;
-       strlcpy(input->name, input_strs[card_input->video_type - 1],
-                       sizeof(input->name));
-       input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
-                       V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
-       input->audioset = (1 << cx->nof_audio_inputs) - 1;
-       input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
-                               cx->tuner_std : V4L2_STD_ALL;
-       return 0;
-}
-
-int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
-{
-       const struct cx18_card_audio_input *aud_input =
-               cx->card->audio_inputs + index;
-       static const char * const input_strs[] = {
-               "Tuner 1",
-               "Line In 1",
-               "Line In 2"
-       };
-
-       memset(audio, 0, sizeof(*audio));
-       if (index >= cx->nof_audio_inputs)
-               return -EINVAL;
-       strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
-                       sizeof(audio->name));
-       audio->index = index;
-       audio->capability = V4L2_AUDCAP_STEREO;
-       return 0;
-}
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h
deleted file mode 100644 (file)
index add7391..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- *  cx18 functions to query card hardware
- *
- *  Derived from ivtv-cards.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* hardware flags */
-#define CX18_HW_TUNER                  (1 << 0)
-#define CX18_HW_TVEEPROM               (1 << 1)
-#define CX18_HW_CS5345                 (1 << 2)
-#define CX18_HW_DVB                    (1 << 3)
-#define CX18_HW_418_AV                 (1 << 4)
-#define CX18_HW_GPIO_MUX               (1 << 5)
-#define CX18_HW_GPIO_RESET_CTRL                (1 << 6)
-#define CX18_HW_Z8F0811_IR_TX_HAUP     (1 << 7)
-#define CX18_HW_Z8F0811_IR_RX_HAUP     (1 << 8)
-#define CX18_HW_Z8F0811_IR_HAUP        (CX18_HW_Z8F0811_IR_RX_HAUP | \
-                                CX18_HW_Z8F0811_IR_TX_HAUP)
-
-#define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \
-                       CX18_HW_Z8F0811_IR_TX_HAUP)
-
-/* video inputs */
-#define        CX18_CARD_INPUT_VID_TUNER       1
-#define        CX18_CARD_INPUT_SVIDEO1         2
-#define        CX18_CARD_INPUT_SVIDEO2         3
-#define        CX18_CARD_INPUT_COMPOSITE1      4
-#define        CX18_CARD_INPUT_COMPOSITE2      5
-#define        CX18_CARD_INPUT_COMPONENT1      6
-
-/* audio inputs */
-#define        CX18_CARD_INPUT_AUD_TUNER       1
-#define        CX18_CARD_INPUT_LINE_IN1        2
-#define        CX18_CARD_INPUT_LINE_IN2        3
-
-#define CX18_CARD_MAX_VIDEO_INPUTS 6
-#define CX18_CARD_MAX_AUDIO_INPUTS 3
-#define CX18_CARD_MAX_TUNERS      2
-
-/* V4L2 capability aliases */
-#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
-                         V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \
-                         V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)
-
-struct cx18_card_video_input {
-       u8  video_type;         /* video input type */
-       u8  audio_index;        /* index in cx18_card_audio_input array */
-       u32 video_input;        /* hardware video input */
-};
-
-struct cx18_card_audio_input {
-       u8  audio_type;         /* audio input type */
-       u32 audio_input;        /* hardware audio input */
-       u16 muxer_input;        /* hardware muxer input for boards with a
-                                  multiplexer chip */
-};
-
-struct cx18_card_pci_info {
-       u16 device;
-       u16 subsystem_vendor;
-       u16 subsystem_device;
-};
-
-/* GPIO definitions */
-
-/* The mask is the set of bits used by the operation */
-
-struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
-       u32 direction;  /* DIR setting. Leave to 0 if no init is needed */
-       u32 initial_value;
-};
-
-struct cx18_gpio_i2c_slave_reset {
-       u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */
-       u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
-       int msecs_asserted; /* time period reset must remain asserted */
-       int msecs_recovery; /* time after deassert for chips to be ready */
-       u32 ir_reset_mask;  /* GPIO to reset the Zilog Z8F0811 IR contoller */
-};
-
-struct cx18_gpio_audio_input {         /* select tuner/line in input */
-       u32 mask;               /* leave to 0 if not supported */
-       u32 tuner;
-       u32 linein;
-       u32 radio;
-};
-
-struct cx18_card_tuner {
-       v4l2_std_id std;        /* standard for which the tuner is suitable */
-       int         tuner;      /* tuner ID (from tuner.h) */
-};
-
-struct cx18_card_tuner_i2c {
-       unsigned short radio[2];/* radio tuner i2c address to probe */
-       unsigned short demod[3];/* demodulator i2c address to probe */
-       unsigned short tv[4];   /* tv tuner i2c addresses to probe */
-};
-
-struct cx18_ddr {              /* DDR config data */
-       u32 chip_config;
-       u32 refresh;
-       u32 timing1;
-       u32 timing2;
-       u32 tune_lane;
-       u32 initial_emrs;
-};
-
-/* for card information/parameters */
-struct cx18_card {
-       int type;
-       char *name;
-       char *comment;
-       u32 v4l2_capabilities;
-       u32 hw_audio_ctrl;      /* hardware used for the V4L2 controls (only
-                                  1 dev allowed currently) */
-       u32 hw_muxer;           /* hardware used to multiplex audio input */
-       u32 hw_all;             /* all hardware used by the board */
-       struct cx18_card_video_input video_inputs[CX18_CARD_MAX_VIDEO_INPUTS];
-       struct cx18_card_audio_input audio_inputs[CX18_CARD_MAX_AUDIO_INPUTS];
-       struct cx18_card_audio_input radio_input;
-
-       /* GPIO card-specific settings */
-       u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
-       struct cx18_gpio_init            gpio_init;
-       struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
-       struct cx18_gpio_audio_input    gpio_audio_input;
-
-       struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
-       struct cx18_card_tuner_i2c *i2c;
-
-       struct cx18_ddr ddr;
-
-       /* list of device and subsystem vendor/devices that
-          correspond to this card type. */
-       const struct cx18_card_pci_info *pci_list;
-};
-
-int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input);
-int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *input);
-const struct cx18_card *cx18_get_card(u16 index);
diff --git a/drivers/media/video/cx18/cx18-controls.c b/drivers/media/video/cx18/cx18-controls.c
deleted file mode 100644 (file)
index 282a3d2..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  cx18 ioctl control functions
- *
- *  Derived from ivtv-controls.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include "cx18-driver.h"
-#include "cx18-cards.h"
-#include "cx18-ioctl.h"
-#include "cx18-audio.h"
-#include "cx18-mailbox.h"
-#include "cx18-controls.h"
-
-static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
-{
-       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
-       int type = cxhdl->stream_type->val;
-
-       if (atomic_read(&cx->ana_capturing) > 0)
-               return -EBUSY;
-
-       if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV ||
-           !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS ||
-             type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD ||
-             type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) {
-               /* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */
-               cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE;
-               CX18_DEBUG_INFO("disabled insertion of sliced VBI data into "
-                               "the MPEG stream\n");
-               return 0;
-       }
-
-       /* Allocate sliced VBI buffers if needed. */
-       if (cx->vbi.sliced_mpeg_data[0] == NULL) {
-               int i;
-
-               for (i = 0; i < CX18_VBI_FRAMES; i++) {
-                       cx->vbi.sliced_mpeg_data[i] =
-                              kmalloc(CX18_SLICED_MPEG_DATA_BUFSZ, GFP_KERNEL);
-                       if (cx->vbi.sliced_mpeg_data[i] == NULL) {
-                               while (--i >= 0) {
-                                       kfree(cx->vbi.sliced_mpeg_data[i]);
-                                       cx->vbi.sliced_mpeg_data[i] = NULL;
-                               }
-                               cx->vbi.insert_mpeg =
-                                                 V4L2_MPEG_STREAM_VBI_FMT_NONE;
-                               CX18_WARN("Unable to allocate buffers for "
-                                         "sliced VBI data insertion\n");
-                               return -ENOMEM;
-                       }
-               }
-       }
-
-       cx->vbi.insert_mpeg = fmt;
-       CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS,"
-                       "when sliced VBI is enabled\n");
-
-       /*
-        * If our current settings have no lines set for capture, store a valid,
-        * default set of service lines to capture, in our current settings.
-        */
-       if (cx18_get_service_set(cx->vbi.sliced_in) == 0) {
-               if (cx->is_60hz)
-                       cx->vbi.sliced_in->service_set =
-                                                       V4L2_SLICED_CAPTION_525;
-               else
-                       cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
-               cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
-       }
-       return 0;
-}
-
-static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
-{
-       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
-       int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-       struct v4l2_mbus_framefmt fmt;
-
-       /* fix videodecoder resolution */
-       fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
-       fmt.height = cxhdl->height;
-       fmt.code = V4L2_MBUS_FMT_FIXED;
-       v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
-       return 0;
-}
-
-static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
-{
-       static const u32 freqs[3] = { 44100, 48000, 32000 };
-       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
-
-       /* The audio clock of the digitizer must match the codec sample
-          rate otherwise you get some very strange effects. */
-       if (idx < ARRAY_SIZE(freqs))
-               cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
-       return 0;
-}
-
-static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
-{
-       struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
-
-       cx->dualwatch_stereo_mode = val;
-       return 0;
-}
-
-struct cx2341x_handler_ops cx18_cxhdl_ops = {
-       .s_audio_mode = cx18_s_audio_mode,
-       .s_audio_sampling_freq = cx18_s_audio_sampling_freq,
-       .s_video_encoding = cx18_s_video_encoding,
-       .s_stream_vbi_fmt = cx18_s_stream_vbi_fmt,
-};
diff --git a/drivers/media/video/cx18/cx18-controls.h b/drivers/media/video/cx18/cx18-controls.h
deleted file mode 100644 (file)
index cb5dfc7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  cx18 ioctl control functions
- *
- *  Derived from ivtv-controls.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
-
- *  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
- */
-
-extern struct cx2341x_handler_ops cx18_cxhdl_ops;
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
deleted file mode 100644 (file)
index c67733d..0000000
+++ /dev/null
@@ -1,1360 +0,0 @@
-/*
- *  cx18 driver initialization and card probing
- *
- *  Derived from ivtv-driver.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-version.h"
-#include "cx18-cards.h"
-#include "cx18-i2c.h"
-#include "cx18-irq.h"
-#include "cx18-gpio.h"
-#include "cx18-firmware.h"
-#include "cx18-queue.h"
-#include "cx18-streams.h"
-#include "cx18-av-core.h"
-#include "cx18-scb.h"
-#include "cx18-mailbox.h"
-#include "cx18-ioctl.h"
-#include "cx18-controls.h"
-#include "tuner-xc2028.h"
-#include <linux/dma-mapping.h>
-#include <media/tveeprom.h>
-
-/* If you have already X v4l cards, then set this to X. This way
-   the device numbers stay matched. Example: you have a WinTV card
-   without radio and a Compro H900 with. Normally this would give a
-   video1 device together with a radio0 device for the Compro. By
-   setting this to 1 you ensure that radio0 is now also radio1. */
-int cx18_first_minor;
-
-/* Callback for registering extensions */
-int (*cx18_ext_init)(struct cx18 *);
-EXPORT_SYMBOL(cx18_ext_init);
-
-/* add your revision and whatnot here */
-static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
-       {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
-
-static atomic_t cx18_instance = ATOMIC_INIT(0);
-
-/* Parameter declarations */
-static int cardtype[CX18_MAX_CARDS];
-static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1 };
-static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1 };
-static unsigned cardtype_c = 1;
-static unsigned tuner_c = 1;
-static unsigned radio_c = 1;
-static char pal[] = "--";
-static char secam[] = "--";
-static char ntsc[] = "-";
-
-/* Buffers */
-static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
-static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
-static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS;
-static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
-static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
-static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
-
-static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE;
-static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE;
-static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE;
-static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE;
-static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE;
-
-static int enc_ts_bufs = -1;
-static int enc_mpg_bufs = -1;
-static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM;
-static int enc_yuv_bufs = -1;
-static int enc_vbi_bufs = -1;
-static int enc_pcm_bufs = -1;
-
-
-static int cx18_pci_latency = 1;
-
-static int mmio_ndelay;
-static int retry_mmio = 1;
-
-int cx18_debug;
-
-module_param_array(tuner, int, &tuner_c, 0644);
-module_param_array(radio, int, &radio_c, 0644);
-module_param_array(cardtype, int, &cardtype_c, 0644);
-module_param_string(pal, pal, sizeof(pal), 0644);
-module_param_string(secam, secam, sizeof(secam), 0644);
-module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
-module_param_named(debug, cx18_debug, int, 0644);
-module_param(mmio_ndelay, int, 0644);
-module_param(retry_mmio, int, 0644);
-module_param(cx18_pci_latency, int, 0644);
-module_param(cx18_first_minor, int, 0644);
-
-module_param(enc_ts_buffers, int, 0644);
-module_param(enc_mpg_buffers, int, 0644);
-module_param(enc_idx_buffers, int, 0644);
-module_param(enc_yuv_buffers, int, 0644);
-module_param(enc_vbi_buffers, int, 0644);
-module_param(enc_pcm_buffers, int, 0644);
-
-module_param(enc_ts_bufsize, int, 0644);
-module_param(enc_mpg_bufsize, int, 0644);
-module_param(enc_idx_bufsize, int, 0644);
-module_param(enc_yuv_bufsize, int, 0644);
-module_param(enc_pcm_bufsize, int, 0644);
-
-module_param(enc_ts_bufs, int, 0644);
-module_param(enc_mpg_bufs, int, 0644);
-module_param(enc_idx_bufs, int, 0644);
-module_param(enc_yuv_bufs, int, 0644);
-module_param(enc_vbi_bufs, int, 0644);
-module_param(enc_pcm_bufs, int, 0644);
-
-MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
-                       "\t\t\tsee tuner.h for values");
-MODULE_PARM_DESC(radio,
-                "Enable or disable the radio. Use only if autodetection\n"
-                "\t\t\tfails. 0 = disable, 1 = enable");
-MODULE_PARM_DESC(cardtype,
-                "Only use this option if your card is not detected properly.\n"
-                "\t\tSpecify card type:\n"
-                "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
-                "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
-                "\t\t\t 3 = Compro VideoMate H900\n"
-                "\t\t\t 4 = Yuan MPC718\n"
-                "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
-                "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
-                "\t\t\t 7 = Leadtek WinFast PVR2100\n"
-                "\t\t\t 8 = Leadtek WinFast DVR3100 H\n"
-                "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n"
-                "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\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(debug,
-                "Debug level (bitmask). Default: 0\n"
-                "\t\t\t  1/0x0001: warning\n"
-                "\t\t\t  2/0x0002: info\n"
-                "\t\t\t  4/0x0004: mailbox\n"
-                "\t\t\t  8/0x0008: dma\n"
-                "\t\t\t 16/0x0010: ioctl\n"
-                "\t\t\t 32/0x0020: file\n"
-                "\t\t\t 64/0x0040: i2c\n"
-                "\t\t\t128/0x0080: irq\n"
-                "\t\t\t256/0x0100: high volume\n");
-MODULE_PARM_DESC(cx18_pci_latency,
-                "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
-                "\t\t\tDefault: Yes");
-MODULE_PARM_DESC(retry_mmio,
-                "(Deprecated) MMIO writes are now always checked and retried\n"
-                "\t\t\tEffectively: 1 [Yes]");
-MODULE_PARM_DESC(mmio_ndelay,
-                "(Deprecated) MMIO accesses are now never purposely delayed\n"
-                "\t\t\tEffectively: 0 ns");
-MODULE_PARM_DESC(enc_ts_buffers,
-                "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
-MODULE_PARM_DESC(enc_ts_bufsize,
-                "Size of an encoder TS buffer (kB)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE));
-MODULE_PARM_DESC(enc_ts_bufs,
-                "Number of encoder TS buffers\n"
-                "\t\t\tDefault is computed from other enc_ts_* parameters");
-MODULE_PARM_DESC(enc_mpg_buffers,
-                "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
-MODULE_PARM_DESC(enc_mpg_bufsize,
-                "Size of an encoder MPG buffer (kB)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE));
-MODULE_PARM_DESC(enc_mpg_bufs,
-                "Number of encoder MPG buffers\n"
-                "\t\t\tDefault is computed from other enc_mpg_* parameters");
-MODULE_PARM_DESC(enc_idx_buffers,
-                "(Deprecated) Encoder IDX buffer memory (MB)\n"
-                "\t\t\tIgnored, except 0 disables IDX buffer allocations\n"
-                "\t\t\tDefault: 1 [Enabled]");
-MODULE_PARM_DESC(enc_idx_bufsize,
-                "Size of an encoder IDX buffer (kB)\n"
-                "\t\t\tAllowed values are multiples of 1.5 kB rounded up\n"
-                "\t\t\t(multiples of size required for 64 index entries)\n"
-                "\t\t\tDefault: 2");
-MODULE_PARM_DESC(enc_idx_bufs,
-                "Number of encoder IDX buffers\n"
-                "\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM));
-MODULE_PARM_DESC(enc_yuv_buffers,
-                "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
-MODULE_PARM_DESC(enc_yuv_bufsize,
-                "Size of an encoder YUV buffer (kB)\n"
-                "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n"
-                "\t\t\t(multiples of size required for 32 screen lines)\n"
-                "\t\t\tDefault: 102");
-MODULE_PARM_DESC(enc_yuv_bufs,
-                "Number of encoder YUV buffers\n"
-                "\t\t\tDefault is computed from other enc_yuv_* parameters");
-MODULE_PARM_DESC(enc_vbi_buffers,
-                "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
-MODULE_PARM_DESC(enc_vbi_bufs,
-                "Number of encoder VBI buffers\n"
-                "\t\t\tDefault is computed from enc_vbi_buffers");
-MODULE_PARM_DESC(enc_pcm_buffers,
-                "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
-MODULE_PARM_DESC(enc_pcm_bufsize,
-                "Size of an encoder PCM buffer (kB)\n"
-                "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE));
-MODULE_PARM_DESC(enc_pcm_bufs,
-                "Number of encoder PCM buffers\n"
-                "\t\t\tDefault is computed from other enc_pcm_* parameters");
-
-MODULE_PARM_DESC(cx18_first_minor,
-                "Set device node number assigned to first card");
-
-MODULE_AUTHOR("Hans Verkuil");
-MODULE_DESCRIPTION("CX23418 driver");
-MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
-MODULE_LICENSE("GPL");
-
-MODULE_VERSION(CX18_VERSION);
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-static void request_module_async(struct work_struct *work)
-{
-       struct cx18 *dev = container_of(work, struct cx18, request_module_wk);
-
-       /* Make sure cx18-alsa module is loaded */
-       request_module("cx18-alsa");
-
-       /* Initialize cx18-alsa for this instance of the cx18 device */
-       if (cx18_ext_init != NULL)
-               cx18_ext_init(dev);
-}
-
-static void request_modules(struct cx18 *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_modules(struct cx18 *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
-
-/* Generic utility functions */
-int cx18_msleep_timeout(unsigned int msecs, int intr)
-{
-       long int timeout = msecs_to_jiffies(msecs);
-       int sig;
-
-       do {
-               set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-               sig = intr ? signal_pending(current) : 0;
-       } while (!sig && timeout);
-       return sig;
-}
-
-/* Release ioremapped memory */
-static void cx18_iounmap(struct cx18 *cx)
-{
-       if (cx == NULL)
-               return;
-
-       /* Release io memory */
-       if (cx->enc_mem != NULL) {
-               CX18_DEBUG_INFO("releasing enc_mem\n");
-               iounmap(cx->enc_mem);
-               cx->enc_mem = NULL;
-       }
-}
-
-static void cx18_eeprom_dump(struct cx18 *cx, unsigned char *eedata, int len)
-{
-       int i;
-
-       CX18_INFO("eeprom dump:\n");
-       for (i = 0; i < len; i++) {
-               if (0 == (i % 16))
-                       CX18_INFO("eeprom %02x:", i);
-               printk(KERN_CONT " %02x", eedata[i]);
-               if (15 == (i % 16))
-                       printk(KERN_CONT "\n");
-       }
-}
-
-/* Hauppauge card? get values from tveeprom */
-void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
-{
-       struct i2c_client c;
-       u8 eedata[256];
-
-       memset(&c, 0, sizeof(c));
-       strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name));
-       c.adapter = &cx->i2c_adap[0];
-       c.addr = 0xA0 >> 1;
-
-       memset(tv, 0, sizeof(*tv));
-       if (tveeprom_read(&c, eedata, sizeof(eedata)))
-               return;
-
-       switch (cx->card->type) {
-       case CX18_CARD_HVR_1600_ESMT:
-       case CX18_CARD_HVR_1600_SAMSUNG:
-       case CX18_CARD_HVR_1600_S5H1411:
-               tveeprom_hauppauge_analog(&c, tv, eedata);
-               break;
-       case CX18_CARD_YUAN_MPC718:
-       case CX18_CARD_GOTVIEW_PCI_DVD3:
-               tv->model = 0x718;
-               cx18_eeprom_dump(cx, eedata, sizeof(eedata));
-               CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n",
-                         eedata[2], eedata[1], eedata[4], eedata[3]);
-               break;
-       default:
-               tv->model = 0xffffffff;
-               cx18_eeprom_dump(cx, eedata, sizeof(eedata));
-               break;
-       }
-}
-
-static void cx18_process_eeprom(struct cx18 *cx)
-{
-       struct tveeprom tv;
-
-       cx18_read_eeprom(cx, &tv);
-
-       /* Many thanks to Steven Toth from Hauppauge for providing the
-          model numbers */
-       /* Note: the Samsung memory models cannot be reliably determined
-          from the model number. Use the cardtype module option if you
-          have one of these preproduction models. */
-       switch (tv.model) {
-       case 74301: /* Retail models */
-       case 74321:
-       case 74351: /* OEM models */
-       case 74361:
-               /* Digital side is s5h1411/tda18271 */
-               cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411);
-               break;
-       case 74021: /* Retail models */
-       case 74031:
-       case 74041:
-       case 74141:
-       case 74541: /* OEM models */
-       case 74551:
-       case 74591:
-       case 74651:
-       case 74691:
-       case 74751:
-       case 74891:
-               /* Digital side is s5h1409/mxl5005s */
-               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
-               break;
-       case 0x718:
-               return;
-       case 0xffffffff:
-               CX18_INFO("Unknown EEPROM encoding\n");
-               return;
-       case 0:
-               CX18_ERR("Invalid EEPROM\n");
-               return;
-       default:
-               CX18_ERR("Unknown model %d, defaulting to original HVR-1600 "
-                        "(cardtype=1)\n", tv.model);
-               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
-               break;
-       }
-
-       cx->v4l2_cap = cx->card->v4l2_capabilities;
-       cx->card_name = cx->card->name;
-       cx->card_i2c = cx->card->i2c;
-
-       CX18_INFO("Autodetected %s\n", cx->card_name);
-
-       if (tv.tuner_type == TUNER_ABSENT)
-               CX18_ERR("tveeprom cannot autodetect tuner!\n");
-
-       if (cx->options.tuner == -1)
-               cx->options.tuner = tv.tuner_type;
-       if (cx->options.radio == -1)
-               cx->options.radio = (tv.has_radio != 0);
-
-       if (cx->std != 0)
-               /* user specified tuner standard */
-               return;
-
-       /* autodetect tuner standard */
-#define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B  | V4L2_STD_GH | \
-                                  V4L2_STD_MN | \
-                                  V4L2_STD_PAL_I | \
-                                  V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \
-                                  V4L2_STD_DK)
-       if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL)
-                                       == TVEEPROM_TUNER_FORMAT_ALL) {
-               CX18_DEBUG_INFO("Worldwide tuner detected\n");
-               cx->std = V4L2_STD_ALL;
-       } else if (tv.tuner_formats & V4L2_STD_PAL) {
-               CX18_DEBUG_INFO("PAL tuner detected\n");
-               cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
-       } else if (tv.tuner_formats & V4L2_STD_NTSC) {
-               CX18_DEBUG_INFO("NTSC tuner detected\n");
-               cx->std |= V4L2_STD_NTSC_M;
-       } else if (tv.tuner_formats & V4L2_STD_SECAM) {
-               CX18_DEBUG_INFO("SECAM tuner detected\n");
-               cx->std |= V4L2_STD_SECAM_L;
-       } else {
-               CX18_INFO("No tuner detected, default to NTSC-M\n");
-               cx->std |= V4L2_STD_NTSC_M;
-       }
-}
-
-static v4l2_std_id cx18_parse_std(struct cx18 *cx)
-{
-       switch (pal[0]) {
-       case '6':
-               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;
-       case 'n':
-       case 'N':
-               if (pal[1] == 'c' || pal[1] == 'C')
-                       return V4L2_STD_PAL_Nc;
-               return V4L2_STD_PAL_N;
-       case 'i':
-       case 'I':
-               return V4L2_STD_PAL_I;
-       case 'd':
-       case 'D':
-       case 'k':
-       case 'K':
-               return V4L2_STD_PAL_DK;
-       case 'M':
-       case 'm':
-               return V4L2_STD_PAL_M;
-       case '-':
-               break;
-       default:
-               CX18_WARN("pal= argument not recognised\n");
-               return 0;
-       }
-
-       switch (secam[0]) {
-       case 'b':
-       case 'B':
-       case 'g':
-       case 'G':
-       case 'h':
-       case 'H':
-               return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
-       case 'd':
-       case 'D':
-       case 'k':
-       case 'K':
-               return V4L2_STD_SECAM_DK;
-       case 'l':
-       case 'L':
-               if (secam[1] == 'C' || secam[1] == 'c')
-                       return V4L2_STD_SECAM_LC;
-               return V4L2_STD_SECAM_L;
-       case '-':
-               break;
-       default:
-               CX18_WARN("secam= argument not recognised\n");
-               return 0;
-       }
-
-       switch (ntsc[0]) {
-       case 'm':
-       case 'M':
-               return V4L2_STD_NTSC_M;
-       case 'j':
-       case 'J':
-               return V4L2_STD_NTSC_M_JP;
-       case 'k':
-       case 'K':
-               return V4L2_STD_NTSC_M_KR;
-       case '-':
-               break;
-       default:
-               CX18_WARN("ntsc= argument not recognised\n");
-               return 0;
-       }
-
-       /* no match found */
-       return 0;
-}
-
-static void cx18_process_options(struct cx18 *cx)
-{
-       int i, j;
-
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers;
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
-       cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */
-
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs;
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs;
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs;
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs;
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs;
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs;
-       cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */
-
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize;
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufsize;
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufsize;
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufsize;
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_active_samples * 36;
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufsize;
-       cx->stream_buf_size[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control no data */
-
-       /* Ensure stream_buffers & stream_buf_size are valid */
-       for (i = 0; i < CX18_MAX_STREAMS; i++) {
-               if (cx->stream_buffers[i] == 0 ||     /* User said 0 buffers */
-                   cx->options.megabytes[i] <= 0 ||  /* User said 0 MB total */
-                   cx->stream_buf_size[i] <= 0) {    /* User said buf size 0 */
-                       cx->options.megabytes[i] = 0;
-                       cx->stream_buffers[i] = 0;
-                       cx->stream_buf_size[i] = 0;
-                       continue;
-               }
-               /*
-                * YUV is a special case where the stream_buf_size needs to be
-                * an integral multiple of 33.75 kB (storage for 32 screens
-                * lines to maintain alignment in case of lost buffers).
-                *
-                * IDX is a special case where the stream_buf_size should be
-                * an integral multiple of 1.5 kB (storage for 64 index entries
-                * to maintain alignment in case of lost buffers).
-                *
-                */
-               if (i == CX18_ENC_STREAM_TYPE_YUV) {
-                       cx->stream_buf_size[i] *= 1024;
-                       cx->stream_buf_size[i] -=
-                          (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE);
-
-                       if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE)
-                               cx->stream_buf_size[i] =
-                                               CX18_UNIT_ENC_YUV_BUFSIZE;
-               } else if (i == CX18_ENC_STREAM_TYPE_IDX) {
-                       cx->stream_buf_size[i] *= 1024;
-                       cx->stream_buf_size[i] -=
-                          (cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE);
-
-                       if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE)
-                               cx->stream_buf_size[i] =
-                                               CX18_UNIT_ENC_IDX_BUFSIZE;
-               }
-               /*
-                * YUV and IDX are special cases where the stream_buf_size is
-                * now in bytes.
-                * VBI is a special case where the stream_buf_size is fixed
-                * and already in bytes
-                */
-               if (i == CX18_ENC_STREAM_TYPE_VBI ||
-                   i == CX18_ENC_STREAM_TYPE_YUV ||
-                   i == CX18_ENC_STREAM_TYPE_IDX) {
-                       if (cx->stream_buffers[i] < 0) {
-                               cx->stream_buffers[i] =
-                                       cx->options.megabytes[i] * 1024 * 1024
-                                       / cx->stream_buf_size[i];
-                       } else {
-                               /* N.B. This might round down to 0 */
-                               cx->options.megabytes[i] =
-                                       cx->stream_buffers[i]
-                                       * cx->stream_buf_size[i]/(1024 * 1024);
-                       }
-               } else {
-                       /* All other streams have stream_buf_size in kB here */
-                       if (cx->stream_buffers[i] < 0) {
-                               cx->stream_buffers[i] =
-                                               cx->options.megabytes[i] * 1024
-                                               / cx->stream_buf_size[i];
-                       } else {
-                               /* N.B. This might round down to 0 */
-                               cx->options.megabytes[i] =
-                                               cx->stream_buffers[i]
-                                               * cx->stream_buf_size[i] / 1024;
-                       }
-                       /* convert from kB to bytes */
-                       cx->stream_buf_size[i] *= 1024;
-               }
-               CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, "
-                               "%d bytes\n", i, cx->options.megabytes[i],
-                               cx->stream_buffers[i], cx->stream_buf_size[i]);
-       }
-
-       cx->options.cardtype = cardtype[cx->instance];
-       cx->options.tuner = tuner[cx->instance];
-       cx->options.radio = radio[cx->instance];
-
-       cx->std = cx18_parse_std(cx);
-       if (cx->options.cardtype == -1) {
-               CX18_INFO("Ignore card\n");
-               return;
-       }
-       cx->card = cx18_get_card(cx->options.cardtype - 1);
-       if (cx->card)
-               CX18_INFO("User specified %s card\n", cx->card->name);
-       else if (cx->options.cardtype != 0)
-               CX18_ERR("Unknown user specified type, trying to autodetect card\n");
-       if (cx->card == NULL) {
-               if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
-                       cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
-                       CX18_INFO("Autodetected Hauppauge card\n");
-               }
-       }
-       if (cx->card == NULL) {
-               for (i = 0; (cx->card = cx18_get_card(i)); i++) {
-                       if (cx->card->pci_list == NULL)
-                               continue;
-                       for (j = 0; cx->card->pci_list[j].device; j++) {
-                               if (cx->pci_dev->device !=
-                                   cx->card->pci_list[j].device)
-                                       continue;
-                               if (cx->pci_dev->subsystem_vendor !=
-                                   cx->card->pci_list[j].subsystem_vendor)
-                                       continue;
-                               if (cx->pci_dev->subsystem_device !=
-                                   cx->card->pci_list[j].subsystem_device)
-                                       continue;
-                               CX18_INFO("Autodetected %s card\n", cx->card->name);
-                               goto done;
-                       }
-               }
-       }
-done:
-
-       if (cx->card == NULL) {
-               cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
-               CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
-                        cx->pci_dev->vendor, cx->pci_dev->device);
-               CX18_ERR("              subsystem vendor/device: [%04x:%04x]\n",
-                        cx->pci_dev->subsystem_vendor,
-                        cx->pci_dev->subsystem_device);
-               CX18_ERR("Defaulting to %s card\n", cx->card->name);
-               CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
-               CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
-               CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
-       }
-       cx->v4l2_cap = cx->card->v4l2_capabilities;
-       cx->card_name = cx->card->name;
-       cx->card_i2c = cx->card->i2c;
-}
-
-static int __devinit cx18_create_in_workq(struct cx18 *cx)
-{
-       snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
-                cx->v4l2_dev.name);
-       cx->in_work_queue = alloc_ordered_workqueue(cx->in_workq_name, 0);
-       if (cx->in_work_queue == NULL) {
-               CX18_ERR("Unable to create incoming mailbox handler thread\n");
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
-               cx->in_work_order[i].cx = cx;
-               cx->in_work_order[i].str = cx->epu_debug_str;
-               INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler);
-       }
-}
-
-/* Precondition: the cx18 structure has been memset to 0. Only
-   the dev and instance fields have been filled in.
-   No assumptions on the card type may be made here (see cx18_init_struct2
-   for that).
- */
-static int __devinit cx18_init_struct1(struct cx18 *cx)
-{
-       int ret;
-
-       cx->base_addr = pci_resource_start(cx->pci_dev, 0);
-
-       mutex_init(&cx->serialize_lock);
-       mutex_init(&cx->gpio_lock);
-       mutex_init(&cx->epu2apu_mb_lock);
-       mutex_init(&cx->epu2cpu_mb_lock);
-
-       ret = cx18_create_in_workq(cx);
-       if (ret)
-               return ret;
-
-       cx18_init_in_work_orders(cx);
-
-       /* start counting open_id at 1 */
-       cx->open_id = 1;
-
-       /* Initial settings */
-       cx->cxhdl.port = CX2341X_PORT_MEMORY;
-       cx->cxhdl.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI;
-       cx->cxhdl.ops = &cx18_cxhdl_ops;
-       cx->cxhdl.func = cx18_api_func;
-       cx->cxhdl.priv = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
-       ret = cx2341x_handler_init(&cx->cxhdl, 50);
-       if (ret)
-               return ret;
-       cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl;
-
-       cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val;
-       cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val;
-       cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val |
-               (cx->cxhdl.video_temporal_filter_mode->cur.val << 1) |
-               (cx->cxhdl.video_median_filter_type->cur.val << 2);
-
-       init_waitqueue_head(&cx->cap_w);
-       init_waitqueue_head(&cx->mb_apu_waitq);
-       init_waitqueue_head(&cx->mb_cpu_waitq);
-       init_waitqueue_head(&cx->dma_waitq);
-
-       /* VBI */
-       cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
-
-       /* IVTV style VBI insertion into MPEG streams */
-       INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list);
-       INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list);
-       INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list);
-       list_add(&cx->vbi.sliced_mpeg_buf.list,
-                &cx->vbi.sliced_mpeg_mdl.buf_list);
-       return 0;
-}
-
-/* Second initialization part. Here the card type has been
-   autodetected. */
-static void __devinit cx18_init_struct2(struct cx18 *cx)
-{
-       int i;
-
-       for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
-               if (cx->card->video_inputs[i].video_type == 0)
-                       break;
-       cx->nof_inputs = i;
-       for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
-               if (cx->card->audio_inputs[i].audio_type == 0)
-                       break;
-       cx->nof_audio_inputs = i;
-
-       /* Find tuner input */
-       for (i = 0; i < cx->nof_inputs; i++) {
-               if (cx->card->video_inputs[i].video_type ==
-                               CX18_CARD_INPUT_VID_TUNER)
-                       break;
-       }
-       if (i == cx->nof_inputs)
-               i = 0;
-       cx->active_input = i;
-       cx->audio_input = cx->card->video_inputs[i].audio_index;
-}
-
-static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
-                         const struct pci_device_id *pci_id)
-{
-       u16 cmd;
-       unsigned char pci_latency;
-
-       CX18_DEBUG_INFO("Enabling pci device\n");
-
-       if (pci_enable_device(pci_dev)) {
-               CX18_ERR("Can't enable device %d!\n", cx->instance);
-               return -EIO;
-       }
-       if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
-               CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
-               return -EIO;
-       }
-       if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
-               CX18_ERR("Cannot request encoder memory region, card %d\n",
-                        cx->instance);
-               return -EIO;
-       }
-
-       /* Enable bus mastering and memory mapped IO for the CX23418 */
-       pci_read_config_word(pci_dev, PCI_COMMAND, &cmd);
-       cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-       pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
-
-       cx->card_rev = pci_dev->revision;
-       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
-
-       if (pci_latency < 64 && cx18_pci_latency) {
-               CX18_INFO("Unreasonably low latency timer, "
-                              "setting to 64 (was %d)\n", pci_latency);
-               pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 64);
-               pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
-       }
-
-       CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
-                  "irq: %d, latency: %d, memory: 0x%llx\n",
-                  cx->pci_dev->device, cx->card_rev, pci_dev->bus->number,
-                  PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn),
-                  cx->pci_dev->irq, pci_latency, (u64)cx->base_addr);
-
-       return 0;
-}
-
-static void cx18_init_subdevs(struct cx18 *cx)
-{
-       u32 hw = cx->card->hw_all;
-       u32 device;
-       int i;
-
-       for (i = 0, device = 1; i < 32; i++, device <<= 1) {
-
-               if (!(device & hw))
-                       continue;
-
-               switch (device) {
-               case CX18_HW_DVB:
-               case CX18_HW_TVEEPROM:
-                       /* These subordinate devices do not use probing */
-                       cx->hw_flags |= device;
-                       break;
-               case CX18_HW_418_AV:
-                       /* The A/V decoder gets probed earlier to set PLLs */
-                       /* Just note that the card uses it (i.e. has analog) */
-                       cx->hw_flags |= device;
-                       break;
-               case CX18_HW_GPIO_RESET_CTRL:
-                       /*
-                        * The Reset Controller gets probed and added to
-                        * hw_flags earlier for i2c adapter/bus initialization
-                        */
-                       break;
-               case CX18_HW_GPIO_MUX:
-                       if (cx18_gpio_register(cx, device) == 0)
-                               cx->hw_flags |= device;
-                       break;
-               default:
-                       if (cx18_i2c_register(cx, i) == 0)
-                               cx->hw_flags |= device;
-                       break;
-               }
-       }
-
-       if (cx->hw_flags & CX18_HW_418_AV)
-               cx->sd_av = cx18_find_hw(cx, CX18_HW_418_AV);
-
-       if (cx->card->hw_muxer != 0)
-               cx->sd_extmux = cx18_find_hw(cx, cx->card->hw_muxer);
-}
-
-static int __devinit cx18_probe(struct pci_dev *pci_dev,
-                               const struct pci_device_id *pci_id)
-{
-       int retval = 0;
-       int i;
-       u32 devtype;
-       struct cx18 *cx;
-
-       /* FIXME - module parameter arrays constrain max instances */
-       i = atomic_inc_return(&cx18_instance) - 1;
-       if (i >= CX18_MAX_CARDS) {
-               printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
-                      "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
-               return -ENOMEM;
-       }
-
-       cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
-       if (cx == NULL) {
-               printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
-                      i);
-               return -ENOMEM;
-       }
-       cx->pci_dev = pci_dev;
-       cx->instance = i;
-
-       retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
-       if (retval) {
-               printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
-                      "\n", cx->instance);
-               kfree(cx);
-               return retval;
-       }
-       snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d",
-                cx->instance);
-       CX18_INFO("Initializing card %d\n", cx->instance);
-
-       cx18_process_options(cx);
-       if (cx->options.cardtype == -1) {
-               retval = -ENODEV;
-               goto err;
-       }
-
-       retval = cx18_init_struct1(cx);
-       if (retval)
-               goto err;
-
-       CX18_DEBUG_INFO("base addr: 0x%llx\n", (u64)cx->base_addr);
-
-       /* PCI Device Setup */
-       retval = cx18_setup_pci(cx, pci_dev, pci_id);
-       if (retval != 0)
-               goto free_workqueues;
-
-       /* map io memory */
-       CX18_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
-                  (u64)cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
-       cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
-                                      CX18_MEM_SIZE);
-       if (!cx->enc_mem) {
-               CX18_ERR("ioremap failed. Can't get a window into CX23418 "
-                        "memory and register space\n");
-               CX18_ERR("Each capture card with a CX23418 needs 64 MB of "
-                        "vmalloc address space for the window\n");
-               CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
-               CX18_ERR("Use the vmalloc= kernel command line option to set "
-                        "VmallocTotal to a larger value\n");
-               retval = -ENOMEM;
-               goto free_mem;
-       }
-       cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
-       devtype = cx18_read_reg(cx, 0xC72028);
-       switch (devtype & 0xff000000) {
-       case 0xff000000:
-               CX18_INFO("cx23418 revision %08x (A)\n", devtype);
-               break;
-       case 0x01000000:
-               CX18_INFO("cx23418 revision %08x (B)\n", devtype);
-               break;
-       default:
-               CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
-               break;
-       }
-
-       cx18_init_power(cx, 1);
-       cx18_init_memory(cx);
-
-       cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
-       cx18_init_scb(cx);
-
-       cx18_gpio_init(cx);
-
-       /* Initialize integrated A/V decoder early to set PLLs, just in case */
-       retval = cx18_av_probe(cx);
-       if (retval) {
-               CX18_ERR("Could not register A/V decoder subdevice\n");
-               goto free_map;
-       }
-
-       /* Initialize GPIO Reset Controller to do chip resets during i2c init */
-       if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
-               if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0)
-                       CX18_WARN("Could not register GPIO reset controller"
-                                 "subdevice; proceeding anyway.\n");
-               else
-                       cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL;
-       }
-
-       /* active i2c  */
-       CX18_DEBUG_INFO("activating i2c...\n");
-       retval = init_cx18_i2c(cx);
-       if (retval) {
-               CX18_ERR("Could not initialize i2c\n");
-               goto free_map;
-       }
-
-       if (cx->card->hw_all & CX18_HW_TVEEPROM) {
-               /* Based on the model number the cardtype may be changed.
-                  The PCI IDs are not always reliable. */
-               const struct cx18_card *orig_card = cx->card;
-               cx18_process_eeprom(cx);
-
-               if (cx->card != orig_card) {
-                       /* Changed the cardtype; re-reset the I2C chips */
-                       cx18_gpio_init(cx);
-                       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
-                                       core, reset, (u32) CX18_GPIO_RESET_I2C);
-               }
-       }
-       if (cx->card->comment)
-               CX18_INFO("%s", cx->card->comment);
-       if (cx->card->v4l2_capabilities == 0) {
-               retval = -ENODEV;
-               goto free_i2c;
-       }
-       cx18_init_memory(cx);
-       cx18_init_scb(cx);
-
-       /* Register IRQ */
-       retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
-                            IRQF_SHARED | IRQF_DISABLED,
-                            cx->v4l2_dev.name, (void *)cx);
-       if (retval) {
-               CX18_ERR("Failed to register irq %d\n", retval);
-               goto free_i2c;
-       }
-
-       if (cx->std == 0)
-               cx->std = V4L2_STD_NTSC_M;
-
-       if (cx->options.tuner == -1) {
-               for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
-                       if ((cx->std & cx->card->tuners[i].std) == 0)
-                               continue;
-                       cx->options.tuner = cx->card->tuners[i].tuner;
-                       break;
-               }
-       }
-       /* if no tuner was found, then pick the first tuner in the card list */
-       if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
-               cx->std = cx->card->tuners[0].std;
-               if (cx->std & V4L2_STD_PAL)
-                       cx->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
-               else if (cx->std & V4L2_STD_NTSC)
-                       cx->std = V4L2_STD_NTSC_M;
-               else if (cx->std & V4L2_STD_SECAM)
-                       cx->std = V4L2_STD_SECAM_L;
-               cx->options.tuner = cx->card->tuners[0].tuner;
-       }
-       if (cx->options.radio == -1)
-               cx->options.radio = (cx->card->radio_input.audio_type != 0);
-
-       /* The card is now fully identified, continue with card-specific
-          initialization. */
-       cx18_init_struct2(cx);
-
-       cx18_init_subdevs(cx);
-
-       if (cx->std & V4L2_STD_525_60)
-               cx->is_60hz = 1;
-       else
-               cx->is_50hz = 1;
-
-       cx2341x_handler_set_50hz(&cx->cxhdl, !cx->is_60hz);
-
-       if (cx->options.radio > 0)
-               cx->v4l2_cap |= V4L2_CAP_RADIO;
-
-       if (cx->options.tuner > -1) {
-               struct tuner_setup setup;
-
-               setup.addr = ADDR_UNSET;
-               setup.type = cx->options.tuner;
-               setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
-               if (cx->options.radio > 0)
-                       setup.mode_mask |= T_RADIO;
-               setup.tuner_callback = (setup.type == TUNER_XC2028) ?
-                       cx18_reset_tuner_gpio : NULL;
-               cx18_call_all(cx, tuner, s_type_addr, &setup);
-               if (setup.type == TUNER_XC2028) {
-                       static struct xc2028_ctrl ctrl = {
-                               .fname = XC2028_DEFAULT_FIRMWARE,
-                               .max_len = 64,
-                       };
-                       struct v4l2_priv_tun_config cfg = {
-                               .tuner = cx->options.tuner,
-                               .priv = &ctrl,
-                       };
-                       cx18_call_all(cx, tuner, s_config, &cfg);
-               }
-       }
-
-       /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
-          are not. */
-       cx->tuner_std = cx->std;
-       if (cx->std == V4L2_STD_ALL)
-               cx->std = V4L2_STD_NTSC_M;
-
-       retval = cx18_streams_setup(cx);
-       if (retval) {
-               CX18_ERR("Error %d setting up streams\n", retval);
-               goto free_irq;
-       }
-       retval = cx18_streams_register(cx);
-       if (retval) {
-               CX18_ERR("Error %d registering devices\n", retval);
-               goto free_streams;
-       }
-
-       CX18_INFO("Initialized card: %s\n", cx->card_name);
-
-       /* Load cx18 submodules (cx18-alsa) */
-       request_modules(cx);
-       return 0;
-
-free_streams:
-       cx18_streams_cleanup(cx, 1);
-free_irq:
-       free_irq(cx->pci_dev->irq, (void *)cx);
-free_i2c:
-       exit_cx18_i2c(cx);
-free_map:
-       cx18_iounmap(cx);
-free_mem:
-       release_mem_region(cx->base_addr, CX18_MEM_SIZE);
-free_workqueues:
-       destroy_workqueue(cx->in_work_queue);
-err:
-       if (retval == 0)
-               retval = -ENODEV;
-       CX18_ERR("Error %d on initialization\n", retval);
-
-       v4l2_device_unregister(&cx->v4l2_dev);
-       kfree(cx);
-       return retval;
-}
-
-int cx18_init_on_first_open(struct cx18 *cx)
-{
-       int video_input;
-       int fw_retry_count = 3;
-       struct v4l2_frequency vf;
-       struct cx18_open_id fh;
-       v4l2_std_id std;
-
-       fh.cx = cx;
-
-       if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
-               return -ENXIO;
-
-       if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
-               return 0;
-
-       while (--fw_retry_count > 0) {
-               /* load firmware */
-               if (cx18_firmware_init(cx) == 0)
-                       break;
-               if (fw_retry_count > 1)
-                       CX18_WARN("Retry loading firmware\n");
-       }
-
-       if (fw_retry_count == 0) {
-               set_bit(CX18_F_I_FAILED, &cx->i_flags);
-               return -ENXIO;
-       }
-       set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
-
-       /*
-        * Init the firmware twice to work around a silicon bug
-        * with the digital TS.
-        *
-        * The second firmware load requires us to normalize the APU state,
-        * or the audio for the first analog capture will be badly incorrect.
-        *
-        * I can't seem to call APU_RESETAI and have it succeed without the
-        * APU capturing audio, so we start and stop it here to do the reset
-        */
-
-       /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */
-       cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0);
-       cx18_vapi(cx, CX18_APU_RESETAI, 0);
-       cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);
-
-       fw_retry_count = 3;
-       while (--fw_retry_count > 0) {
-               /* load firmware */
-               if (cx18_firmware_init(cx) == 0)
-                       break;
-               if (fw_retry_count > 1)
-                       CX18_WARN("Retry loading firmware\n");
-       }
-
-       if (fw_retry_count == 0) {
-               set_bit(CX18_F_I_FAILED, &cx->i_flags);
-               return -ENXIO;
-       }
-
-       /*
-        * The second firmware load requires us to normalize the APU state,
-        * or the audio for the first analog capture will be badly incorrect.
-        *
-        * I can't seem to call APU_RESETAI and have it succeed without the
-        * APU capturing audio, so we start and stop it here to do the reset
-        */
-
-       /* MPEG Encoding, 224 kbps, MPEG Layer II, 48 ksps */
-       cx18_vapi(cx, CX18_APU_START, 2, CX18_APU_ENCODING_METHOD_MPEG|0xb9, 0);
-       cx18_vapi(cx, CX18_APU_RESETAI, 0);
-       cx18_vapi(cx, CX18_APU_STOP, 1, CX18_APU_ENCODING_METHOD_MPEG);
-
-       /* Init the A/V decoder, if it hasn't been already */
-       v4l2_subdev_call(cx->sd_av, core, load_fw);
-
-       vf.tuner = 0;
-       vf.type = V4L2_TUNER_ANALOG_TV;
-       vf.frequency = 6400; /* the tuner 'baseline' frequency */
-
-       /* Set initial frequency. For PAL/SECAM broadcasts no
-          'default' channel exists AFAIK. */
-       if (cx->std == V4L2_STD_NTSC_M_JP)
-               vf.frequency = 1460;    /* ch. 1 91250*16/1000 */
-       else if (cx->std & V4L2_STD_NTSC_M)
-               vf.frequency = 1076;    /* ch. 4 67250*16/1000 */
-
-       video_input = cx->active_input;
-       cx->active_input++;     /* Force update of input */
-       cx18_s_input(NULL, &fh, video_input);
-
-       /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
-          in one place. */
-       cx->std++;              /* Force full standard initialization */
-       std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std;
-       cx18_s_std(NULL, &fh, &std);
-       cx18_s_frequency(NULL, &fh, &vf);
-       return 0;
-}
-
-static void cx18_cancel_in_work_orders(struct cx18 *cx)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++)
-               cancel_work_sync(&cx->in_work_order[i].work);
-}
-
-static void cx18_cancel_out_work_orders(struct cx18 *cx)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_STREAMS; i++)
-               if (&cx->streams[i].video_dev != NULL)
-                       cancel_work_sync(&cx->streams[i].out_work_order);
-}
-
-static void cx18_remove(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct cx18 *cx = to_cx18(v4l2_dev);
-       int i;
-
-       CX18_DEBUG_INFO("Removing Card\n");
-
-       flush_request_modules(cx);
-
-       /* Stop all captures */
-       CX18_DEBUG_INFO("Stopping all streams\n");
-       if (atomic_read(&cx->tot_capturing) > 0)
-               cx18_stop_all_captures(cx);
-
-       /* Stop interrupts that cause incoming work to be queued */
-       cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
-
-       /* Incoming work can cause outgoing work, so clean up incoming first */
-       cx18_cancel_in_work_orders(cx);
-       cx18_cancel_out_work_orders(cx);
-
-       /* Stop ack interrupts that may have been needed for work to finish */
-       cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
-
-       cx18_halt_firmware(cx);
-
-       destroy_workqueue(cx->in_work_queue);
-
-       cx18_streams_cleanup(cx, 1);
-
-       exit_cx18_i2c(cx);
-
-       free_irq(cx->pci_dev->irq, (void *)cx);
-
-       cx18_iounmap(cx);
-
-       release_mem_region(cx->base_addr, CX18_MEM_SIZE);
-
-       pci_disable_device(cx->pci_dev);
-
-       if (cx->vbi.sliced_mpeg_data[0] != NULL)
-               for (i = 0; i < CX18_VBI_FRAMES; i++)
-                       kfree(cx->vbi.sliced_mpeg_data[i]);
-
-       v4l2_ctrl_handler_free(&cx->av_state.hdl);
-
-       CX18_INFO("Removed %s\n", cx->card_name);
-
-       v4l2_device_unregister(v4l2_dev);
-       kfree(cx);
-}
-
-
-/* define a pci_driver for card detection */
-static struct pci_driver cx18_pci_driver = {
-      .name =     "cx18",
-      .id_table = cx18_pci_tbl,
-      .probe =    cx18_probe,
-      .remove =   cx18_remove,
-};
-
-static int __init module_start(void)
-{
-       printk(KERN_INFO "cx18:  Start initialization, version %s\n",
-              CX18_VERSION);
-
-       /* Validate parameters */
-       if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
-               printk(KERN_ERR "cx18:  Exiting, cx18_first_minor must be between 0 and %d\n",
-                    CX18_MAX_CARDS - 1);
-               return -1;
-       }
-
-       if (cx18_debug < 0 || cx18_debug > 511) {
-               cx18_debug = 0;
-               printk(KERN_INFO "cx18:   Debug value must be >= 0 and <= 511!\n");
-       }
-
-       if (pci_register_driver(&cx18_pci_driver)) {
-               printk(KERN_ERR "cx18:   Error detecting PCI card\n");
-               return -ENODEV;
-       }
-       printk(KERN_INFO "cx18:  End initialization\n");
-       return 0;
-}
-
-static void __exit module_cleanup(void)
-{
-       pci_unregister_driver(&cx18_pci_driver);
-}
-
-module_init(module_start);
-module_exit(module_cleanup);
-MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
deleted file mode 100644 (file)
index 2767c64..0000000
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- *  cx18 driver internal defines and structures
- *
- *  Derived from ivtv-driver.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#ifndef CX18_DRIVER_H
-#define CX18_DRIVER_H
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/list.h>
-#include <linux/unistd.h>
-#include <linux/pagemap.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/tuner.h>
-#include <media/ir-kbd-i2c.h>
-#include "cx18-mailbox.h"
-#include "cx18-av-core.h"
-#include "cx23418.h"
-
-/* DVB */
-#include "demux.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvbdev.h"
-
-/* Videobuf / YUV support */
-#include <media/videobuf-core.h>
-#include <media/videobuf-vmalloc.h>
-
-#ifndef CONFIG_PCI
-#  error "This driver requires kernel PCI support."
-#endif
-
-#define CX18_MEM_OFFSET        0x00000000
-#define CX18_MEM_SIZE  0x04000000
-#define CX18_REG_OFFSET        0x02000000
-
-/* Maximum cx18 driver instances. */
-#define CX18_MAX_CARDS 32
-
-/* Supported cards */
-#define CX18_CARD_HVR_1600_ESMT              0 /* Hauppauge HVR 1600 (ESMT memory) */
-#define CX18_CARD_HVR_1600_SAMSUNG    1        /* Hauppauge HVR 1600 (Samsung memory) */
-#define CX18_CARD_COMPRO_H900        2 /* Compro VideoMate H900 */
-#define CX18_CARD_YUAN_MPC718        3 /* Yuan MPC718 */
-#define CX18_CARD_CNXT_RAPTOR_PAL     4        /* Conexant Raptor PAL */
-#define CX18_CARD_TOSHIBA_QOSMIO_DVBT 5 /* Toshiba Qosmio Interal DVB-T/Analog*/
-#define CX18_CARD_LEADTEK_PVR2100     6 /* Leadtek WinFast PVR2100 */
-#define CX18_CARD_LEADTEK_DVR3100H    7 /* Leadtek WinFast DVR3100 H */
-#define CX18_CARD_GOTVIEW_PCI_DVD3    8 /* GoTView PCI DVD3 Hybrid */
-#define CX18_CARD_HVR_1600_S5H1411    9 /* Hauppauge HVR 1600 s5h1411/tda18271*/
-#define CX18_CARD_LAST               9
-
-#define CX18_ENC_STREAM_TYPE_MPG  0
-#define CX18_ENC_STREAM_TYPE_TS   1
-#define CX18_ENC_STREAM_TYPE_YUV  2
-#define CX18_ENC_STREAM_TYPE_VBI  3
-#define CX18_ENC_STREAM_TYPE_PCM  4
-#define CX18_ENC_STREAM_TYPE_IDX  5
-#define CX18_ENC_STREAM_TYPE_RAD  6
-#define CX18_MAX_STREAMS         7
-
-/* system vendor and device IDs */
-#define PCI_VENDOR_ID_CX      0x14f1
-#define PCI_DEVICE_ID_CX23418 0x5b7a
-
-/* subsystem vendor ID */
-#define CX18_PCI_ID_HAUPPAUGE          0x0070
-#define CX18_PCI_ID_COMPRO             0x185b
-#define CX18_PCI_ID_YUAN               0x12ab
-#define CX18_PCI_ID_CONEXANT           0x14f1
-#define CX18_PCI_ID_TOSHIBA            0x1179
-#define CX18_PCI_ID_LEADTEK            0x107D
-#define CX18_PCI_ID_GOTVIEW            0x5854
-
-/* ======================================================================== */
-/* ========================== START USER SETTABLE DMA VARIABLES =========== */
-/* ======================================================================== */
-
-/* DMA Buffers, Default size in MB allocated */
-#define CX18_DEFAULT_ENC_TS_BUFFERS  1
-#define CX18_DEFAULT_ENC_MPG_BUFFERS 2
-#define CX18_DEFAULT_ENC_IDX_BUFFERS 1
-#define CX18_DEFAULT_ENC_YUV_BUFFERS 2
-#define CX18_DEFAULT_ENC_VBI_BUFFERS 1
-#define CX18_DEFAULT_ENC_PCM_BUFFERS 1
-
-/* Maximum firmware DMA buffers per stream */
-#define CX18_MAX_FW_MDLS_PER_STREAM 63
-
-/* YUV buffer sizes in bytes to ensure integer # of frames per buffer */
-#define CX18_UNIT_ENC_YUV_BUFSIZE      (720 *  32 * 3 / 2) /* bytes */
-#define CX18_625_LINE_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 576/32)
-#define CX18_525_LINE_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 480/32)
-
-/* IDX buffer size should be a multiple of the index entry size from the chip */
-struct cx18_enc_idx_entry {
-       __le32 length;
-       __le32 offset_low;
-       __le32 offset_high;
-       __le32 flags;
-       __le32 pts_low;
-       __le32 pts_high;
-} __attribute__ ((packed));
-#define CX18_UNIT_ENC_IDX_BUFSIZE \
-       (sizeof(struct cx18_enc_idx_entry) * V4L2_ENC_IDX_ENTRIES)
-
-/* DMA buffer, default size in kB allocated */
-#define CX18_DEFAULT_ENC_TS_BUFSIZE   32
-#define CX18_DEFAULT_ENC_MPG_BUFSIZE  32
-#define CX18_DEFAULT_ENC_IDX_BUFSIZE  (CX18_UNIT_ENC_IDX_BUFSIZE * 1 / 1024 + 1)
-#define CX18_DEFAULT_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1)
-#define CX18_DEFAULT_ENC_PCM_BUFSIZE   4
-
-/* i2c stuff */
-#define I2C_CLIENTS_MAX 16
-
-/* debugging */
-
-/* Flag to turn on high volume debugging */
-#define CX18_DBGFLG_WARN  (1 << 0)
-#define CX18_DBGFLG_INFO  (1 << 1)
-#define CX18_DBGFLG_API   (1 << 2)
-#define CX18_DBGFLG_DMA   (1 << 3)
-#define CX18_DBGFLG_IOCTL (1 << 4)
-#define CX18_DBGFLG_FILE  (1 << 5)
-#define CX18_DBGFLG_I2C   (1 << 6)
-#define CX18_DBGFLG_IRQ   (1 << 7)
-/* Flag to turn on high volume debugging */
-#define CX18_DBGFLG_HIGHVOL (1 << 8)
-
-/* NOTE: extra space before comma in 'fmt , ## args' is required for
-   gcc-2.95, otherwise it won't compile. */
-#define CX18_DEBUG(x, type, fmt, args...) \
-       do { \
-               if ((x) & cx18_debug) \
-                       v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
-       } while (0)
-#define CX18_DEBUG_WARN(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
-#define CX18_DEBUG_INFO(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
-#define CX18_DEBUG_API(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_API, "api", fmt , ## args)
-#define CX18_DEBUG_DMA(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_DMA, "dma", fmt , ## args)
-#define CX18_DEBUG_IOCTL(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
-#define CX18_DEBUG_FILE(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_FILE, "file", fmt , ## args)
-#define CX18_DEBUG_I2C(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
-#define CX18_DEBUG_IRQ(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
-
-#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
-       do { \
-               if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
-                       v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
-       } while (0)
-#define CX18_DEBUG_HI_WARN(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
-#define CX18_DEBUG_HI_INFO(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
-#define CX18_DEBUG_HI_API(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_API, "api", fmt , ## args)
-#define CX18_DEBUG_HI_DMA(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_DMA, "dma", fmt , ## args)
-#define CX18_DEBUG_HI_IOCTL(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
-#define CX18_DEBUG_HI_FILE(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_FILE, "file", fmt , ## args)
-#define CX18_DEBUG_HI_I2C(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
-#define CX18_DEBUG_HI_IRQ(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
-
-/* Standard kernel messages */
-#define CX18_ERR(fmt, args...)      v4l2_err(&cx->v4l2_dev, fmt , ## args)
-#define CX18_WARN(fmt, args...)     v4l2_warn(&cx->v4l2_dev, fmt , ## args)
-#define CX18_INFO(fmt, args...)     v4l2_info(&cx->v4l2_dev, fmt , ## args)
-
-/* Messages for internal subdevs to use */
-#define CX18_DEBUG_DEV(x, dev, type, fmt, args...) \
-       do { \
-               if ((x) & cx18_debug) \
-                       v4l2_info(dev, " " type ": " fmt , ## args); \
-       } while (0)
-#define CX18_DEBUG_WARN_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args)
-#define CX18_DEBUG_INFO_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args)
-#define CX18_DEBUG_API_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args)
-#define CX18_DEBUG_DMA_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args)
-#define CX18_DEBUG_IOCTL_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args)
-#define CX18_DEBUG_FILE_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args)
-#define CX18_DEBUG_I2C_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args)
-#define CX18_DEBUG_IRQ_DEV(dev, fmt, args...) \
-               CX18_DEBUG_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args)
-
-#define CX18_DEBUG_HIGH_VOL_DEV(x, dev, type, fmt, args...) \
-       do { \
-               if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
-                       v4l2_info(dev, " " type ": " fmt , ## args); \
-       } while (0)
-#define CX18_DEBUG_HI_WARN_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_WARN, dev, "warning", fmt , ## args)
-#define CX18_DEBUG_HI_INFO_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_INFO, dev, "info", fmt , ## args)
-#define CX18_DEBUG_HI_API_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_API, dev, "api", fmt , ## args)
-#define CX18_DEBUG_HI_DMA_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_DMA, dev, "dma", fmt , ## args)
-#define CX18_DEBUG_HI_IOCTL_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IOCTL, dev, "ioctl", fmt , ## args)
-#define CX18_DEBUG_HI_FILE_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_FILE, dev, "file", fmt , ## args)
-#define CX18_DEBUG_HI_I2C_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_I2C, dev, "i2c", fmt , ## args)
-#define CX18_DEBUG_HI_IRQ_DEV(dev, fmt, args...) \
-       CX18_DEBUG_HIGH_VOL_DEV(CX18_DBGFLG_IRQ, dev, "irq", fmt , ## args)
-
-#define CX18_ERR_DEV(dev, fmt, args...)      v4l2_err(dev, fmt , ## args)
-#define CX18_WARN_DEV(dev, fmt, args...)     v4l2_warn(dev, fmt , ## args)
-#define CX18_INFO_DEV(dev, fmt, args...)     v4l2_info(dev, fmt , ## args)
-
-extern int cx18_debug;
-
-struct cx18_options {
-       int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
-       int cardtype;           /* force card type on load */
-       int tuner;              /* set tuner on load */
-       int radio;              /* enable/disable radio */
-};
-
-/* per-mdl bit flags */
-#define CX18_F_M_NEED_SWAP  0  /* mdl buffer data must be endianess swapped */
-
-/* per-stream, s_flags */
-#define CX18_F_S_CLAIMED       3       /* this stream is claimed */
-#define CX18_F_S_STREAMING      4      /* the fw is decoding/encoding this stream */
-#define CX18_F_S_INTERNAL_USE  5       /* this stream is used internally (sliced VBI processing) */
-#define CX18_F_S_STREAMOFF     7       /* signal end of stream EOS */
-#define CX18_F_S_APPL_IO        8      /* this stream is used read/written by an application */
-#define CX18_F_S_STOPPING      9       /* telling the fw to stop capturing */
-
-/* per-cx18, i_flags */
-#define CX18_F_I_LOADED_FW             0       /* Loaded firmware 1st time */
-#define CX18_F_I_EOS                   4       /* End of encoder stream */
-#define CX18_F_I_RADIO_USER            5       /* radio tuner is selected */
-#define CX18_F_I_ENC_PAUSED            13      /* the encoder is paused */
-#define CX18_F_I_INITED                        21      /* set after first open */
-#define CX18_F_I_FAILED                        22      /* set if first open failed */
-
-/* These are the VBI types as they appear in the embedded VBI private packets. */
-#define CX18_SLICED_TYPE_TELETEXT_B     (1)
-#define CX18_SLICED_TYPE_CAPTION_525    (4)
-#define CX18_SLICED_TYPE_WSS_625        (5)
-#define CX18_SLICED_TYPE_VPS            (7)
-
-/**
- * list_entry_is_past_end - check if a previous loop cursor is off list end
- * @pos:       the type * previously used as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- *
- * Check if the entry's list_head is the head of the list, thus it's not a
- * real entry but was the loop cursor that walked past the end
- */
-#define list_entry_is_past_end(pos, head, member) \
-       (&pos->member == (head))
-
-struct cx18_buffer {
-       struct list_head list;
-       dma_addr_t dma_handle;
-       char *buf;
-
-       u32 bytesused;
-       u32 readpos;
-};
-
-struct cx18_mdl {
-       struct list_head list;
-       u32 id;         /* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */
-
-       unsigned int skipped;
-       unsigned long m_flags;
-
-       struct list_head buf_list;
-       struct cx18_buffer *curr_buf; /* current buffer in list for reading */
-
-       u32 bytesused;
-       u32 readpos;
-};
-
-struct cx18_queue {
-       struct list_head list;
-       atomic_t depth;
-       u32 bytesused;
-       spinlock_t lock;
-};
-
-struct cx18_stream; /* forward reference */
-
-struct cx18_dvb {
-       struct cx18_stream *stream;
-       struct dmx_frontend hw_frontend;
-       struct dmx_frontend mem_frontend;
-       struct dmxdev dmxdev;
-       struct dvb_adapter dvb_adapter;
-       struct dvb_demux demux;
-       struct dvb_frontend *fe;
-       struct dvb_net dvbnet;
-       int enabled;
-       int feeding;
-       struct mutex feedlock;
-};
-
-struct cx18;    /* forward reference */
-struct cx18_scb; /* forward reference */
-
-
-#define CX18_MAX_MDL_ACKS 2
-#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
-/* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */
-
-#define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1
-#define CX18_F_EWO_MB_STALE_WHILE_PROC   0x2
-#define CX18_F_EWO_MB_STALE \
-            (CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC)
-
-struct cx18_in_work_order {
-       struct work_struct work;
-       atomic_t pending;
-       struct cx18 *cx;
-       unsigned long flags;
-       int rpu;
-       struct cx18_mailbox mb;
-       struct cx18_mdl_ack mdl_ack[CX18_MAX_MDL_ACKS];
-       char *str;
-};
-
-#define CX18_INVALID_TASK_HANDLE 0xffffffff
-
-struct cx18_stream {
-       /* These first five fields are always set, even if the stream
-          is not actually created. */
-       struct video_device *video_dev; /* NULL when stream not created */
-       struct cx18_dvb *dvb;           /* DVB / Digital Transport */
-       struct cx18 *cx;                /* for ease of use */
-       const char *name;               /* name of the stream */
-       int type;                       /* stream type */
-       u32 handle;                     /* task handle */
-       unsigned int mdl_base_idx;
-
-       u32 id;
-       unsigned long s_flags;  /* status flags, see above */
-       int dma;                /* can be PCI_DMA_TODEVICE,
-                                  PCI_DMA_FROMDEVICE or
-                                  PCI_DMA_NONE */
-       wait_queue_head_t waitq;
-
-       /* Buffers */
-       struct list_head buf_pool;      /* buffers not attached to an MDL */
-       u32 buffers;                    /* total buffers owned by this stream */
-       u32 buf_size;                   /* size in bytes of a single buffer */
-
-       /* MDL sizes - all stream MDLs are the same size */
-       u32 bufs_per_mdl;
-       u32 mdl_size;           /* total bytes in all buffers in a mdl */
-
-       /* MDL Queues */
-       struct cx18_queue q_free;       /* free - in rotation, not committed */
-       struct cx18_queue q_busy;       /* busy - in use by firmware */
-       struct cx18_queue q_full;       /* full - data for user apps */
-       struct cx18_queue q_idle;       /* idle - not in rotation */
-
-       struct work_struct out_work_order;
-
-       /* Videobuf for YUV video */
-       u32 pixelformat;
-       u32 vb_bytes_per_frame;
-       struct list_head vb_capture;    /* video capture queue */
-       spinlock_t vb_lock;
-       struct timer_list vb_timeout;
-
-       struct videobuf_queue vbuf_q;
-       spinlock_t vbuf_q_lock; /* Protect vbuf_q */
-       enum v4l2_buf_type vb_type;
-};
-
-struct cx18_videobuf_buffer {
-       /* Common video buffer sub-system struct */
-       struct videobuf_buffer vb;
-       v4l2_std_id tvnorm; /* selected tv norm */
-       u32 bytes_used;
-};
-
-struct cx18_open_id {
-       struct v4l2_fh fh;
-       u32 open_id;
-       int type;
-       struct cx18 *cx;
-};
-
-static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
-{
-       return container_of(fh, struct cx18_open_id, fh);
-}
-
-static inline struct cx18_open_id *file2id(struct file *file)
-{
-       return fh2id(file->private_data);
-}
-
-/* forward declaration of struct defined in cx18-cards.h */
-struct cx18_card;
-
-/*
- * A note about "sliced" VBI data as implemented in this driver:
- *
- * Currently we collect the sliced VBI in the form of Ancillary Data
- * packets, inserted by the AV core decoder/digitizer/slicer in the
- * horizontal blanking region of the VBI lines, in "raw" mode as far as
- * the Encoder is concerned.  We don't ever tell the Encoder itself
- * to provide sliced VBI. (AV Core: sliced mode - Encoder: raw mode)
- *
- * We then process the ancillary data ourselves to send the sliced data
- * to the user application directly or build up MPEG-2 private stream 1
- * packets to splice into (only!) MPEG-2 PS streams for the user app.
- *
- * (That's how ivtv essentially does it.)
- *
- * The Encoder should be able to extract certain sliced VBI data for
- * us and provide it in a separate stream or splice it into any type of
- * MPEG PS or TS stream, but this isn't implemented yet.
- */
-
-/*
- * Number of "raw" VBI samples per horizontal line we tell the Encoder to
- * grab from the decoder/digitizer/slicer output for raw or sliced VBI.
- * It depends on the pixel clock and the horiz rate:
- *
- * (1/Fh)*(2*Fp) = Samples/line
- *     = 4 bytes EAV + Anc data in hblank + 4 bytes SAV + active samples
- *
- *  Sliced VBI data is sent as ancillary data during horizontal blanking
- *  Raw VBI is sent as active video samples during vertcal blanking
- *
- *  We use a  BT.656 pxiel clock of 13.5 MHz and a BT.656 active line
- *  length of 720 pixels @ 4:2:2 sampling.  Thus...
- *
- *  For systems that use a 15.734 kHz horizontal rate, such as
- *  NTSC-M, PAL-M, PAL-60, and other 60 Hz/525 line systems, we have:
- *
- *  (1/15.734 kHz) * 2 * 13.5 MHz = 1716 samples/line =
- *  4 bytes SAV + 268 bytes anc data + 4 bytes SAV + 1440 active samples
- *
- *  For systems that use a 15.625 kHz horizontal rate, such as
- *  PAL-B/G/H, PAL-I, SECAM-L and other 50 Hz/625 line systems, we have:
- *
- *  (1/15.625 kHz) * 2 * 13.5 MHz = 1728 samples/line =
- *  4 bytes SAV + 280 bytes anc data + 4 bytes SAV + 1440 active samples
- */
-static const u32 vbi_active_samples = 1444; /* 4 byte SAV + 720 Y + 720 U/V */
-static const u32 vbi_hblank_samples_60Hz = 272; /* 4 byte EAV + 268 anc/fill */
-static const u32 vbi_hblank_samples_50Hz = 284; /* 4 byte EAV + 280 anc/fill */
-
-#define CX18_VBI_FRAMES 32
-
-struct vbi_info {
-       /* Current state of v4l2 VBI settings for this device */
-       struct v4l2_format in;
-       struct v4l2_sliced_vbi_format *sliced_in; /* pointer to in.fmt.sliced */
-       u32 count;    /* Count of VBI data lines: 60 Hz: 12 or 50 Hz: 18 */
-       u32 start[2]; /* First VBI data line per field: 10 & 273 or 6 & 318 */
-
-       u32 frame; /* Count of VBI buffers/frames received from Encoder */
-
-       /*
-        * Vars for creation and insertion of MPEG Private Stream 1 packets
-        * of sliced VBI data into an MPEG PS
-        */
-
-       /* Boolean: create and insert Private Stream 1 packets into the PS */
-       int insert_mpeg;
-
-       /*
-        * Buffer for the maximum of 2 * 18 * packet_size sliced VBI lines.
-        * Used in cx18-vbi.c only for collecting sliced data, and as a source
-        * during conversion of sliced VBI data into MPEG Priv Stream 1 packets.
-        * We don't need to save state here, but the array may have been a bit
-        * too big (2304 bytes) to alloc from the stack.
-        */
-       struct v4l2_sliced_vbi_data sliced_data[36];
-
-       /*
-        * A ring buffer of driver-generated MPEG-2 PS
-        * Program Pack/Private Stream 1 packets for sliced VBI data insertion
-        * into the MPEG PS stream.
-        *
-        * In each sliced_mpeg_data[] buffer is:
-        *      16 byte MPEG-2 PS Program Pack Header
-        *      16 byte MPEG-2 Private Stream 1 PES Header
-        *       4 byte magic number: "itv0" or "ITV0"
-        *       4 byte first  field line mask, if "itv0"
-        *       4 byte second field line mask, if "itv0"
-        *      36 lines, if "ITV0"; or <36 lines, if "itv0"; of sliced VBI data
-        *
-        *      Each line in the payload is
-        *       1 byte line header derived from the SDID (WSS, CC, VPS, etc.)
-        *      42 bytes of line data
-        *
-        * That's a maximum 1552 bytes of payload in the Private Stream 1 packet
-        * which is the payload size a PVR-350 (CX23415) MPEG decoder will
-        * accept for VBI data. So, including the headers, it's a maximum 1584
-        * bytes total.
-        */
-#define CX18_SLICED_MPEG_DATA_MAXSZ    1584
-       /* copy_vbi_buf() needs 8 temp bytes on the end for the worst case */
-#define CX18_SLICED_MPEG_DATA_BUFSZ    (CX18_SLICED_MPEG_DATA_MAXSZ+8)
-       u8 *sliced_mpeg_data[CX18_VBI_FRAMES];
-       u32 sliced_mpeg_size[CX18_VBI_FRAMES];
-
-       /* Count of Program Pack/Program Stream 1 packets inserted into PS */
-       u32 inserted_frame;
-
-       /*
-        * A dummy driver stream transfer mdl & buffer with a copy of the next
-        * sliced_mpeg_data[] buffer for output to userland apps.
-        * Only used in cx18-fileops.c, but its state needs to persist at times.
-        */
-       struct cx18_mdl sliced_mpeg_mdl;
-       struct cx18_buffer sliced_mpeg_buf;
-};
-
-/* Per cx23418, per I2C bus private algo callback data */
-struct cx18_i2c_algo_callback_data {
-       struct cx18 *cx;
-       int bus_index;   /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
-};
-
-#define CX18_MAX_MMIO_WR_RETRIES 10
-
-/* Struct to hold info about cx18 cards */
-struct cx18 {
-       int instance;
-       struct pci_dev *pci_dev;
-       struct v4l2_device v4l2_dev;
-       struct v4l2_subdev *sd_av;     /* A/V decoder/digitizer sub-device */
-       struct v4l2_subdev *sd_extmux; /* External multiplexer sub-dev */
-
-       const struct cx18_card *card;   /* card information */
-       const char *card_name;  /* full name of the card */
-       const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
-       u8 is_50hz;
-       u8 is_60hz;
-       u8 nof_inputs;          /* number of video inputs */
-       u8 nof_audio_inputs;    /* number of audio inputs */
-       u32 v4l2_cap;           /* V4L2 capabilities of card */
-       u32 hw_flags;           /* Hardware description of the board */
-       unsigned int free_mdl_idx;
-       struct cx18_scb __iomem *scb; /* pointer to SCB */
-       struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/
-       struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/
-
-       struct cx18_av_state av_state;
-
-       /* codec settings */
-       struct cx2341x_handler cxhdl;
-       u32 filter_mode;
-       u32 temporal_strength;
-       u32 spatial_strength;
-
-       /* dualwatch */
-       unsigned long dualwatch_jiffies;
-       u32 dualwatch_stereo_mode;
-
-       struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
-       struct cx18_options options;    /* User options */
-       int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */
-       int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
-       struct cx18_stream streams[CX18_MAX_STREAMS];   /* Stream data */
-       struct snd_cx18_card *alsa; /* ALSA interface for PCM capture stream */
-       void (*pcm_announce_callback)(struct snd_cx18_card *card, u8 *pcm_data,
-                                     size_t num_bytes);
-
-       unsigned long i_flags;  /* global cx18 flags */
-       atomic_t ana_capturing; /* count number of active analog capture streams */
-       atomic_t tot_capturing; /* total count number of active capture streams */
-       int search_pack_header;
-
-       int open_id;            /* incremented each time an open occurs, used as
-                                  unique ID. Starts at 1, so 0 can be used as
-                                  uninitialized value in the stream->id. */
-
-       resource_size_t base_addr;
-
-       u8 card_rev;
-       void __iomem *enc_mem, *reg_mem;
-
-       struct vbi_info vbi;
-
-       u64 mpg_data_received;
-       u64 vbi_data_inserted;
-
-       wait_queue_head_t mb_apu_waitq;
-       wait_queue_head_t mb_cpu_waitq;
-       wait_queue_head_t cap_w;
-       /* when the current DMA is finished this queue is woken up */
-       wait_queue_head_t dma_waitq;
-
-       u32 sw1_irq_mask;
-       u32 sw2_irq_mask;
-       u32 hw2_irq_mask;
-
-       struct workqueue_struct *in_work_queue;
-       char in_workq_name[11]; /* "cx18-NN-in" */
-       struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS];
-       char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
-
-       /* i2c */
-       struct i2c_adapter i2c_adap[2];
-       struct i2c_algo_bit_data i2c_algo[2];
-       struct cx18_i2c_algo_callback_data i2c_algo_cb_data[2];
-
-       struct IR_i2c_init_data ir_i2c_init_data;
-
-       /* gpio */
-       u32 gpio_dir;
-       u32 gpio_val;
-       struct mutex gpio_lock;
-       struct v4l2_subdev sd_gpiomux;
-       struct v4l2_subdev sd_resetctrl;
-
-       /* v4l2 and User settings */
-
-       /* codec settings */
-       u32 audio_input;
-       u32 active_input;
-       v4l2_std_id std;
-       v4l2_std_id tuner_std;  /* The norm of the tuner (fixed) */
-
-       /* Used for cx18-alsa module loading */
-       struct work_struct request_module_wk;
-};
-
-static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct cx18, v4l2_dev);
-}
-
-/* cx18 extensions to be loaded */
-extern int (*cx18_ext_init)(struct cx18 *);
-
-/* Globals */
-extern int cx18_first_minor;
-
-/*==============Prototypes==================*/
-
-/* Return non-zero if a signal is pending */
-int cx18_msleep_timeout(unsigned int msecs, int intr);
-
-/* Read Hauppauge eeprom */
-struct tveeprom; /* forward reference */
-void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
-
-/* First-open initialization: load firmware, etc. */
-int cx18_init_on_first_open(struct cx18 *cx);
-
-/* Test if the current VBI mode is raw (1) or sliced (0) */
-static inline int cx18_raw_vbi(const struct cx18 *cx)
-{
-       return cx->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
-}
-
-/* Call the specified callback for all subdevs with a grp_id bit matching the
- * mask in hw (if 0, then match them all). Ignore any errors. */
-#define cx18_call_hw(cx, hw, o, f, args...)                            \
-       do {                                                            \
-               struct v4l2_subdev *__sd;                               \
-               __v4l2_device_call_subdevs_p(&(cx)->v4l2_dev, __sd,     \
-                       !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
-       } while (0)
-
-#define cx18_call_all(cx, o, f, args...) cx18_call_hw(cx, 0, o, f , ##args)
-
-/* Call the specified callback for all subdevs with a grp_id bit matching the
- * mask in hw (if 0, then match them all). If the callback returns an error
- * other than 0 or -ENOIOCTLCMD, then return with that error code. */
-#define cx18_call_hw_err(cx, hw, o, f, args...)                                \
-({                                                                     \
-       struct v4l2_subdev *__sd;                                       \
-       __v4l2_device_call_subdevs_until_err_p(&(cx)->v4l2_dev,         \
-                       __sd, !(hw) || (__sd->grp_id & (hw)), o, f,     \
-                       ##args);                                        \
-})
-
-#define cx18_call_all_err(cx, o, f, args...) \
-       cx18_call_hw_err(cx, 0, o, f , ##args)
-
-#endif /* CX18_DRIVER_H */
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c
deleted file mode 100644 (file)
index 3eac59c..0000000
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- *  cx18 functions for DVB support
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 "cx18-version.h"
-#include "cx18-dvb.h"
-#include "cx18-io.h"
-#include "cx18-queue.h"
-#include "cx18-streams.h"
-#include "cx18-cards.h"
-#include "cx18-gpio.h"
-#include "s5h1409.h"
-#include "mxl5005s.h"
-#include "s5h1411.h"
-#include "tda18271.h"
-#include "zl10353.h"
-
-#include <linux/firmware.h>
-#include "mt352.h"
-#include "mt352_priv.h"
-#include "tuner-xc2028.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define FWFILE "dvb-cx18-mpc718-mt352.fw"
-
-#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
-#define CX18_CLOCK_ENABLE2              0xc71024
-#define CX18_DMUX_CLK_MASK              0x0080
-
-/*
- * CX18_CARD_HVR_1600_ESMT
- * CX18_CARD_HVR_1600_SAMSUNG
- */
-
-static struct mxl5005s_config hauppauge_hvr1600_tuner = {
-       .i2c_address     = 0xC6 >> 1,
-       .if_freq         = IF_FREQ_5380000HZ,
-       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-       .agc_mode        = MXL_SINGLE_AGC,
-       .tracking_filter = MXL_TF_C_H,
-       .rssi_enable     = MXL_RSSI_ENABLE,
-       .cap_select      = MXL_CAP_SEL_ENABLE,
-       .div_out         = MXL_DIV_OUT_4,
-       .clock_out       = MXL_CLOCK_OUT_DISABLE,
-       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
-       .top             = MXL5005S_TOP_25P2,
-       .mod_mode        = MXL_DIGITAL_MODE,
-       .if_mode         = MXL_ZERO_IF,
-       .qam_gain        = 0x02,
-       .AgcMasterByte   = 0x00,
-};
-
-static struct s5h1409_config hauppauge_hvr1600_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_SERIAL_OUTPUT,
-       .gpio          = S5H1409_GPIO_ON,
-       .qam_if        = 44000,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-       .hvr1600_opt   = S5H1409_HVR1600_OPTIMIZE
-};
-
-/*
- * CX18_CARD_HVR_1600_S5H1411
- */
-static struct s5h1411_config hcw_s5h1411_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_OFF,
-       .vsb_if        = S5H1411_IF_44000,
-       .qam_if        = S5H1411_IF_4000,
-       .inversion     = S5H1411_INVERSION_ON,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-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_DIGITAL,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-/*
- * CX18_CARD_LEADTEK_DVR3100H
- */
-/* Information/confirmation of proper config values provided by Terry Wu */
-static struct zl10353_config leadtek_dvr3100h_demod = {
-       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
-       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
-       .parallel_ts           = 1,         /* Not a serial TS */
-       .no_tuner              = 1,         /* XC3028 is not behind the gate */
-       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
-};
-
-/*
- * CX18_CARD_YUAN_MPC718
- */
-/*
- * Due to
- *
- * 1. an absence of information on how to prgram the MT352
- * 2. the Linux mt352 module pushing MT352 initialzation off onto us here
- *
- * We have to use an init sequence that *you* must extract from the Windows
- * driver (yuanrap.sys) and which we load as a firmware.
- *
- * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual
- * with chip programming details, then I can remove this annoyance.
- */
-static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
-                                  const struct firmware **fw)
-{
-       struct cx18 *cx = stream->cx;
-       const char *fn = FWFILE;
-       int ret;
-
-       ret = request_firmware(fw, fn, &cx->pci_dev->dev);
-       if (ret)
-               CX18_ERR("Unable to open firmware file %s\n", fn);
-       else {
-               size_t sz = (*fw)->size;
-               if (sz < 2 || sz > 64 || (sz % 2) != 0) {
-                       CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
-                                fn, (unsigned long) sz);
-                       ret = -EILSEQ;
-                       release_firmware(*fw);
-                       *fw = NULL;
-               }
-       }
-
-       if (ret) {
-               CX18_ERR("The MPC718 board variant with the MT352 DVB-T"
-                         "demodualtor will not work without it\n");
-               CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware "
-                         "mpc718' if you need the firmware\n");
-       }
-       return ret;
-}
-
-static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
-{
-       struct cx18_dvb *dvb = container_of(fe->dvb,
-                                           struct cx18_dvb, dvb_adapter);
-       struct cx18_stream *stream = dvb->stream;
-       const struct firmware *fw = NULL;
-       int ret;
-       int i;
-       u8 buf[3];
-
-       ret = yuan_mpc718_mt352_reqfw(stream, &fw);
-       if (ret)
-               return ret;
-
-       /* Loop through all the register-value pairs in the firmware file */
-       for (i = 0; i < fw->size; i += 2) {
-               buf[0] = fw->data[i];
-               /* Intercept a few registers we want to set ourselves */
-               switch (buf[0]) {
-               case TRL_NOMINAL_RATE_0:
-                       /* Set our custom OFDM bandwidth in the case below */
-                       break;
-               case TRL_NOMINAL_RATE_1:
-                       /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
-                       /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
-                       /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
-                       buf[1] = 0x72;
-                       buf[2] = 0x49;
-                       mt352_write(fe, buf, 3);
-                       break;
-               case INPUT_FREQ_0:
-                       /* Set our custom IF in the case below */
-                       break;
-               case INPUT_FREQ_1:
-                       /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
-                       buf[1] = 0x31;
-                       buf[2] = 0xc0;
-                       mt352_write(fe, buf, 3);
-                       break;
-               default:
-                       /* Pass through the register-value pair from the fw */
-                       buf[1] = fw->data[i+1];
-                       mt352_write(fe, buf, 2);
-                       break;
-               }
-       }
-
-       buf[0] = (u8) TUNER_GO;
-       buf[1] = 0x01; /* Go */
-       mt352_write(fe, buf, 2);
-       release_firmware(fw);
-       return 0;
-}
-
-static struct mt352_config yuan_mpc718_mt352_demod = {
-       .demod_address = 0x1e >> 1,
-       .adc_clock     = 20480,     /* 20.480 MHz */
-       .if2           =  4560,     /*  4.560 MHz */
-       .no_tuner      = 1,         /* XC3028 is not behind the gate */
-       .demod_init    = yuan_mpc718_mt352_init,
-};
-
-static struct zl10353_config yuan_mpc718_zl10353_demod = {
-       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
-       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
-       .parallel_ts           = 1,         /* Not a serial TS */
-       .no_tuner              = 1,         /* XC3028 is not behind the gate */
-       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
-};
-
-static struct zl10353_config gotview_dvd3_zl10353_demod = {
-       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
-       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
-       .parallel_ts           = 1,         /* Not a serial TS */
-       .no_tuner              = 1,         /* XC3028 is not behind the gate */
-       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
-};
-
-static int dvb_register(struct cx18_stream *stream);
-
-/* Kernel DVB framework calls this when the feed needs to start.
- * The CX18 framework should enable the transport DMA handling
- * and queue processing.
- */
-static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
-       struct cx18 *cx;
-       int ret;
-       u32 v;
-
-       if (!stream)
-               return -EINVAL;
-
-       cx = stream->cx;
-       CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
-                       feed->pid, feed->index);
-
-       mutex_lock(&cx->serialize_lock);
-       ret = cx18_init_on_first_open(cx);
-       mutex_unlock(&cx->serialize_lock);
-       if (ret) {
-               CX18_ERR("Failed to initialize firmware starting DVB feed\n");
-               return ret;
-       }
-       ret = -EINVAL;
-
-       switch (cx->card->type) {
-       case CX18_CARD_HVR_1600_ESMT:
-       case CX18_CARD_HVR_1600_SAMSUNG:
-       case CX18_CARD_HVR_1600_S5H1411:
-               v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
-               v |= 0x00400000; /* Serial Mode */
-               v |= 0x00002000; /* Data Length - Byte */
-               v |= 0x00010000; /* Error - Polarity */
-               v |= 0x00020000; /* Error - Passthru */
-               v |= 0x000c0000; /* Error - Ignore */
-               cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
-               break;
-
-       case CX18_CARD_LEADTEK_DVR3100H:
-       case CX18_CARD_YUAN_MPC718:
-       case CX18_CARD_GOTVIEW_PCI_DVD3:
-       default:
-               /* Assumption - Parallel transport - Signalling
-                * undefined or default.
-                */
-               break;
-       }
-
-       if (!demux->dmx.frontend)
-               return -EINVAL;
-
-       mutex_lock(&stream->dvb->feedlock);
-       if (stream->dvb->feeding++ == 0) {
-               CX18_DEBUG_INFO("Starting Transport DMA\n");
-               mutex_lock(&cx->serialize_lock);
-               set_bit(CX18_F_S_STREAMING, &stream->s_flags);
-               ret = cx18_start_v4l2_encode_stream(stream);
-               if (ret < 0) {
-                       CX18_DEBUG_INFO("Failed to start Transport DMA\n");
-                       stream->dvb->feeding--;
-                       if (stream->dvb->feeding == 0)
-                               clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
-               }
-               mutex_unlock(&cx->serialize_lock);
-       } else
-               ret = 0;
-       mutex_unlock(&stream->dvb->feedlock);
-
-       return ret;
-}
-
-/* Kernel DVB framework calls this when the feed needs to stop. */
-static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
-       struct cx18 *cx;
-       int ret = -EINVAL;
-
-       if (stream) {
-               cx = stream->cx;
-               CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
-                               feed->pid, feed->index);
-
-               mutex_lock(&stream->dvb->feedlock);
-               if (--stream->dvb->feeding == 0) {
-                       CX18_DEBUG_INFO("Stopping Transport DMA\n");
-                       mutex_lock(&cx->serialize_lock);
-                       ret = cx18_stop_v4l2_encode_stream(stream, 0);
-                       mutex_unlock(&cx->serialize_lock);
-               } else
-                       ret = 0;
-               mutex_unlock(&stream->dvb->feedlock);
-       }
-
-       return ret;
-}
-
-int cx18_dvb_register(struct cx18_stream *stream)
-{
-       struct cx18 *cx = stream->cx;
-       struct cx18_dvb *dvb = stream->dvb;
-       struct dvb_adapter *dvb_adapter;
-       struct dvb_demux *dvbdemux;
-       struct dmx_demux *dmx;
-       int ret;
-
-       if (!dvb)
-               return -EINVAL;
-
-       dvb->enabled = 0;
-       dvb->stream = stream;
-
-       ret = dvb_register_adapter(&dvb->dvb_adapter,
-                       CX18_DRIVER_NAME,
-                       THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
-       if (ret < 0)
-               goto err_out;
-
-       dvb_adapter = &dvb->dvb_adapter;
-
-       dvbdemux = &dvb->demux;
-
-       dvbdemux->priv = (void *)stream;
-
-       dvbdemux->filternum = 256;
-       dvbdemux->feednum = 256;
-       dvbdemux->start_feed = cx18_dvb_start_feed;
-       dvbdemux->stop_feed = cx18_dvb_stop_feed;
-       dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-               DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
-       ret = dvb_dmx_init(dvbdemux);
-       if (ret < 0)
-               goto err_dvb_unregister_adapter;
-
-       dmx = &dvbdemux->dmx;
-
-       dvb->hw_frontend.source = DMX_FRONTEND_0;
-       dvb->mem_frontend.source = DMX_MEMORY_FE;
-       dvb->dmxdev.filternum = 256;
-       dvb->dmxdev.demux = dmx;
-
-       ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
-       if (ret < 0)
-               goto err_dvb_dmx_release;
-
-       ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
-       if (ret < 0)
-               goto err_dvb_dmxdev_release;
-
-       ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
-       if (ret < 0)
-               goto err_remove_hw_frontend;
-
-       ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
-       if (ret < 0)
-               goto err_remove_mem_frontend;
-
-       ret = dvb_register(stream);
-       if (ret < 0)
-               goto err_disconnect_frontend;
-
-       dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
-
-       CX18_INFO("DVB Frontend registered\n");
-       CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
-                 stream->dvb->dvb_adapter.num, stream->name,
-                 stream->buffers, stream->buf_size/1024,
-                 (stream->buf_size * 100 / 1024) % 100);
-
-       mutex_init(&dvb->feedlock);
-       dvb->enabled = 1;
-       return ret;
-
-err_disconnect_frontend:
-       dmx->disconnect_frontend(dmx);
-err_remove_mem_frontend:
-       dmx->remove_frontend(dmx, &dvb->mem_frontend);
-err_remove_hw_frontend:
-       dmx->remove_frontend(dmx, &dvb->hw_frontend);
-err_dvb_dmxdev_release:
-       dvb_dmxdev_release(&dvb->dmxdev);
-err_dvb_dmx_release:
-       dvb_dmx_release(dvbdemux);
-err_dvb_unregister_adapter:
-       dvb_unregister_adapter(dvb_adapter);
-err_out:
-       return ret;
-}
-
-void cx18_dvb_unregister(struct cx18_stream *stream)
-{
-       struct cx18 *cx = stream->cx;
-       struct cx18_dvb *dvb = stream->dvb;
-       struct dvb_adapter *dvb_adapter;
-       struct dvb_demux *dvbdemux;
-       struct dmx_demux *dmx;
-
-       CX18_INFO("unregister DVB\n");
-
-       if (dvb == NULL || !dvb->enabled)
-               return;
-
-       dvb_adapter = &dvb->dvb_adapter;
-       dvbdemux = &dvb->demux;
-       dmx = &dvbdemux->dmx;
-
-       dmx->close(dmx);
-       dvb_net_release(&dvb->dvbnet);
-       dmx->remove_frontend(dmx, &dvb->mem_frontend);
-       dmx->remove_frontend(dmx, &dvb->hw_frontend);
-       dvb_dmxdev_release(&dvb->dmxdev);
-       dvb_dmx_release(dvbdemux);
-       dvb_unregister_frontend(dvb->fe);
-       dvb_frontend_detach(dvb->fe);
-       dvb_unregister_adapter(dvb_adapter);
-}
-
-/* All the DVB attach calls go here, this function get's modified
- * for each new card. cx18_dvb_start_feed() will also need changes.
- */
-static int dvb_register(struct cx18_stream *stream)
-{
-       struct cx18_dvb *dvb = stream->dvb;
-       struct cx18 *cx = stream->cx;
-       int ret = 0;
-
-       switch (cx->card->type) {
-       case CX18_CARD_HVR_1600_ESMT:
-       case CX18_CARD_HVR_1600_SAMSUNG:
-               dvb->fe = dvb_attach(s5h1409_attach,
-                       &hauppauge_hvr1600_config,
-                       &cx->i2c_adap[0]);
-               if (dvb->fe != NULL) {
-                       dvb_attach(mxl5005s_attach, dvb->fe,
-                               &cx->i2c_adap[0],
-                               &hauppauge_hvr1600_tuner);
-                       ret = 0;
-               }
-               break;
-       case CX18_CARD_HVR_1600_S5H1411:
-               dvb->fe = dvb_attach(s5h1411_attach,
-                                    &hcw_s5h1411_config,
-                                    &cx->i2c_adap[0]);
-               if (dvb->fe != NULL)
-                       dvb_attach(tda18271_attach, dvb->fe,
-                                  0x60, &cx->i2c_adap[0],
-                                  &hauppauge_tda18271_config);
-               break;
-       case CX18_CARD_LEADTEK_DVR3100H:
-               dvb->fe = dvb_attach(zl10353_attach,
-                                    &leadtek_dvr3100h_demod,
-                                    &cx->i2c_adap[1]);
-               if (dvb->fe != NULL) {
-                       struct dvb_frontend *fe;
-                       struct xc2028_config cfg = {
-                               .i2c_adap = &cx->i2c_adap[1],
-                               .i2c_addr = 0xc2 >> 1,
-                               .ctrl = NULL,
-                       };
-                       static struct xc2028_ctrl ctrl = {
-                               .fname   = XC2028_DEFAULT_FIRMWARE,
-                               .max_len = 64,
-                               .demod   = XC3028_FE_ZARLINK456,
-                               .type    = XC2028_AUTO,
-                       };
-
-                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
-                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
-                               fe->ops.tuner_ops.set_config(fe, &ctrl);
-               }
-               break;
-       case CX18_CARD_YUAN_MPC718:
-               /*
-                * TODO
-                * Apparently, these cards also could instead have a
-                * DiBcom demod supported by one of the db7000 drivers
-                */
-               dvb->fe = dvb_attach(mt352_attach,
-                                    &yuan_mpc718_mt352_demod,
-                                    &cx->i2c_adap[1]);
-               if (dvb->fe == NULL)
-                       dvb->fe = dvb_attach(zl10353_attach,
-                                            &yuan_mpc718_zl10353_demod,
-                                            &cx->i2c_adap[1]);
-               if (dvb->fe != NULL) {
-                       struct dvb_frontend *fe;
-                       struct xc2028_config cfg = {
-                               .i2c_adap = &cx->i2c_adap[1],
-                               .i2c_addr = 0xc2 >> 1,
-                               .ctrl = NULL,
-                       };
-                       static struct xc2028_ctrl ctrl = {
-                               .fname   = XC2028_DEFAULT_FIRMWARE,
-                               .max_len = 64,
-                               .demod   = XC3028_FE_ZARLINK456,
-                               .type    = XC2028_AUTO,
-                       };
-
-                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
-                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
-                               fe->ops.tuner_ops.set_config(fe, &ctrl);
-               }
-               break;
-       case CX18_CARD_GOTVIEW_PCI_DVD3:
-                       dvb->fe = dvb_attach(zl10353_attach,
-                                            &gotview_dvd3_zl10353_demod,
-                                            &cx->i2c_adap[1]);
-               if (dvb->fe != NULL) {
-                       struct dvb_frontend *fe;
-                       struct xc2028_config cfg = {
-                               .i2c_adap = &cx->i2c_adap[1],
-                               .i2c_addr = 0xc2 >> 1,
-                               .ctrl = NULL,
-                       };
-                       static struct xc2028_ctrl ctrl = {
-                               .fname   = XC2028_DEFAULT_FIRMWARE,
-                               .max_len = 64,
-                               .demod   = XC3028_FE_ZARLINK456,
-                               .type    = XC2028_AUTO,
-                       };
-
-                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
-                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
-                               fe->ops.tuner_ops.set_config(fe, &ctrl);
-               }
-               break;
-       default:
-               /* No Digital Tv Support */
-               break;
-       }
-
-       if (dvb->fe == NULL) {
-               CX18_ERR("frontend initialization failed\n");
-               return -1;
-       }
-
-       dvb->fe->callback = cx18_reset_tuner_gpio;
-
-       ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
-       if (ret < 0) {
-               if (dvb->fe->ops.release)
-                       dvb->fe->ops.release(dvb->fe);
-               return ret;
-       }
-
-       /*
-        * The firmware seems to enable the TS DMUX clock
-        * under various circumstances.  However, since we know we
-        * might use it, let's just turn it on ourselves here.
-        */
-       cx18_write_reg_expect(cx,
-                             (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK,
-                             CX18_CLOCK_ENABLE2,
-                             CX18_DMUX_CLK_MASK,
-                             (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK);
-
-       return ret;
-}
-
-MODULE_FIRMWARE(FWFILE);
diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h
deleted file mode 100644 (file)
index bf8d8f6..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  cx18 functions for DVB support
- *
- *  Copyright (c) 2008 Steven Toth <stoth@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 "cx18-driver.h"
-
-int cx18_dvb_register(struct cx18_stream *stream);
-void cx18_dvb_unregister(struct cx18_stream *stream);
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
deleted file mode 100644 (file)
index 4bfd865..0000000
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- *  cx18 file operation functions
- *
- *  Derived from ivtv-fileops.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-fileops.h"
-#include "cx18-i2c.h"
-#include "cx18-queue.h"
-#include "cx18-vbi.h"
-#include "cx18-audio.h"
-#include "cx18-mailbox.h"
-#include "cx18-scb.h"
-#include "cx18-streams.h"
-#include "cx18-controls.h"
-#include "cx18-ioctl.h"
-#include "cx18-cards.h"
-
-/* This function tries to claim the stream for a specific file descriptor.
-   If no one else is using this stream then the stream is claimed and
-   associated VBI and IDX streams are also automatically claimed.
-   Possible error returns: -EBUSY if someone else has claimed
-   the stream or 0 on success. */
-int cx18_claim_stream(struct cx18_open_id *id, int type)
-{
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[type];
-       struct cx18_stream *s_assoc;
-
-       /* Nothing should ever try to directly claim the IDX stream */
-       if (type == CX18_ENC_STREAM_TYPE_IDX) {
-               CX18_WARN("MPEG Index stream cannot be claimed "
-                         "directly, but something tried.\n");
-               return -EINVAL;
-       }
-
-       if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
-               /* someone already claimed this stream */
-               if (s->id == id->open_id) {
-                       /* yes, this file descriptor did. So that's OK. */
-                       return 0;
-               }
-               if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
-                       /* VBI is handled already internally, now also assign
-                          the file descriptor to this stream for external
-                          reading of the stream. */
-                       s->id = id->open_id;
-                       CX18_DEBUG_INFO("Start Read VBI\n");
-                       return 0;
-               }
-               /* someone else is using this stream already */
-               CX18_DEBUG_INFO("Stream %d is busy\n", type);
-               return -EBUSY;
-       }
-       s->id = id->open_id;
-
-       /*
-        * CX18_ENC_STREAM_TYPE_MPG needs to claim:
-        * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
-        * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
-        * (We don't yet fix up MPEG Index entries for our inserted packets).
-        *
-        * For all other streams we're done.
-        */
-       if (type != CX18_ENC_STREAM_TYPE_MPG)
-               return 0;
-
-       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-       if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
-               s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       else if (!cx18_stream_enabled(s_assoc))
-               return 0;
-
-       set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
-
-       /* mark that it is used internally */
-       set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
-       return 0;
-}
-EXPORT_SYMBOL(cx18_claim_stream);
-
-/* This function releases a previously claimed stream. It will take into
-   account associated VBI streams. */
-void cx18_release_stream(struct cx18_stream *s)
-{
-       struct cx18 *cx = s->cx;
-       struct cx18_stream *s_assoc;
-
-       s->id = -1;
-       if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
-               /*
-                * The IDX stream is only used internally, and can
-                * only be indirectly unclaimed by unclaiming the MPG stream.
-                */
-               return;
-       }
-
-       if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
-               test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
-               /* this stream is still in use internally */
-               return;
-       }
-       if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
-               CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
-               return;
-       }
-
-       cx18_flush_queues(s);
-
-       /*
-        * CX18_ENC_STREAM_TYPE_MPG needs to release the
-        * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
-        *
-        * For all other streams we're done.
-        */
-       if (s->type != CX18_ENC_STREAM_TYPE_MPG)
-               return;
-
-       /* Unclaim the associated MPEG Index stream */
-       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
-               clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
-               cx18_flush_queues(s_assoc);
-       }
-
-       /* Unclaim the associated VBI stream */
-       s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
-               if (s_assoc->id == -1) {
-                       /*
-                        * The VBI stream is not still claimed by a file
-                        * descriptor, so completely unclaim it.
-                        */
-                       clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
-                       cx18_flush_queues(s_assoc);
-               }
-       }
-}
-EXPORT_SYMBOL(cx18_release_stream);
-
-static void cx18_dualwatch(struct cx18 *cx)
-{
-       struct v4l2_tuner vt;
-       u32 new_stereo_mode;
-       const u32 dual = 0x0200;
-
-       new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
-       memset(&vt, 0, sizeof(vt));
-       cx18_call_all(cx, tuner, g_tuner, &vt);
-       if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
-                       (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
-               new_stereo_mode = dual;
-
-       if (new_stereo_mode == cx->dualwatch_stereo_mode)
-               return;
-
-       CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
-                          cx->dualwatch_stereo_mode, new_stereo_mode);
-       if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
-               CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
-}
-
-
-static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
-                                    int *err)
-{
-       struct cx18 *cx = s->cx;
-       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       struct cx18_mdl *mdl;
-       DEFINE_WAIT(wait);
-
-       *err = 0;
-       while (1) {
-               if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
-                       /* Process pending program updates and VBI data */
-                       if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
-                               cx->dualwatch_jiffies = jiffies;
-                               cx18_dualwatch(cx);
-                       }
-                       if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
-                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
-                               while ((mdl = cx18_dequeue(s_vbi,
-                                                          &s_vbi->q_full))) {
-                                       /* byteswap and process VBI data */
-                                       cx18_process_vbi_data(cx, mdl,
-                                                             s_vbi->type);
-                                       cx18_stream_put_mdl_fw(s_vbi, mdl);
-                               }
-                       }
-                       mdl = &cx->vbi.sliced_mpeg_mdl;
-                       if (mdl->readpos != mdl->bytesused)
-                               return mdl;
-               }
-
-               /* do we have new data? */
-               mdl = cx18_dequeue(s, &s->q_full);
-               if (mdl) {
-                       if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
-                                               &mdl->m_flags))
-                               return mdl;
-                       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
-                               /* byteswap MPG data */
-                               cx18_mdl_swap(mdl);
-                       else {
-                               /* byteswap and process VBI data */
-                               cx18_process_vbi_data(cx, mdl, s->type);
-                       }
-                       return mdl;
-               }
-
-               /* return if end of stream */
-               if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-                       CX18_DEBUG_INFO("EOS %s\n", s->name);
-                       return NULL;
-               }
-
-               /* return if file was opened with O_NONBLOCK */
-               if (non_block) {
-                       *err = -EAGAIN;
-                       return NULL;
-               }
-
-               /* wait for more data to arrive */
-               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
-               /* New buffers might have become available before we were added
-                  to the waitqueue */
-               if (!atomic_read(&s->q_full.depth))
-                       schedule();
-               finish_wait(&s->waitq, &wait);
-               if (signal_pending(current)) {
-                       /* return if a signal was received */
-                       CX18_DEBUG_INFO("User stopped %s\n", s->name);
-                       *err = -EINTR;
-                       return NULL;
-               }
-       }
-}
-
-static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
-{
-       struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
-       struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
-       int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
-
-       buf->buf = cx->vbi.sliced_mpeg_data[idx];
-       buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
-       buf->readpos = 0;
-
-       mdl->curr_buf = NULL;
-       mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
-       mdl->readpos = 0;
-}
-
-static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
-       struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
-{
-       struct cx18 *cx = s->cx;
-       size_t len = buf->bytesused - buf->readpos;
-
-       *stop = false;
-       if (len > ucount)
-               len = ucount;
-       if (cx->vbi.insert_mpeg && s->type == CX18_ENC_STREAM_TYPE_MPG &&
-           !cx18_raw_vbi(cx) && buf != &cx->vbi.sliced_mpeg_buf) {
-               /*
-                * Try to find a good splice point in the PS, just before
-                * an MPEG-2 Program Pack start code, and provide only
-                * up to that point to the user, so it's easy to insert VBI data
-                * the next time around.
-                *
-                * This will not work for an MPEG-2 TS and has only been
-                * verified by analysis to work for an MPEG-2 PS.  Helen Buus
-                * pointed out this works for the CX23416 MPEG-2 DVD compatible
-                * stream, and research indicates both the MPEG 2 SVCD and DVD
-                * stream types use an MPEG-2 PS container.
-                */
-               /*
-                * An MPEG-2 Program Stream (PS) is a series of
-                * MPEG-2 Program Packs terminated by an
-                * MPEG Program End Code after the last Program Pack.
-                * A Program Pack may hold a PS System Header packet and any
-                * number of Program Elementary Stream (PES) Packets
-                */
-               const char *start = buf->buf + buf->readpos;
-               const char *p = start + 1;
-               const u8 *q;
-               u8 ch = cx->search_pack_header ? 0xba : 0xe0;
-               int stuffing, i;
-
-               while (start + len > p) {
-                       /* Scan for a 0 to find a potential MPEG-2 start code */
-                       q = memchr(p, 0, start + len - p);
-                       if (q == NULL)
-                               break;
-                       p = q + 1;
-                       /*
-                        * Keep looking if not a
-                        * MPEG-2 Pack header start code:  0x00 0x00 0x01 0xba
-                        * or MPEG-2 video PES start code: 0x00 0x00 0x01 0xe0
-                        */
-                       if ((char *)q + 15 >= buf->buf + buf->bytesused ||
-                           q[1] != 0 || q[2] != 1 || q[3] != ch)
-                               continue;
-
-                       /* If expecting the primary video PES */
-                       if (!cx->search_pack_header) {
-                               /* Continue if it couldn't be a PES packet */
-                               if ((q[6] & 0xc0) != 0x80)
-                                       continue;
-                               /* Check if a PTS or PTS & DTS follow */
-                               if (((q[7] & 0xc0) == 0x80 &&  /* PTS only */
-                                    (q[9] & 0xf0) == 0x20) || /* PTS only */
-                                   ((q[7] & 0xc0) == 0xc0 &&  /* PTS & DTS */
-                                    (q[9] & 0xf0) == 0x30)) { /* DTS follows */
-                                       /* Assume we found the video PES hdr */
-                                       ch = 0xba; /* next want a Program Pack*/
-                                       cx->search_pack_header = 1;
-                                       p = q + 9; /* Skip this video PES hdr */
-                               }
-                               continue;
-                       }
-
-                       /* We may have found a Program Pack start code */
-
-                       /* Get the count of stuffing bytes & verify them */
-                       stuffing = q[13] & 7;
-                       /* all stuffing bytes must be 0xff */
-                       for (i = 0; i < stuffing; i++)
-                               if (q[14 + i] != 0xff)
-                                       break;
-                       if (i == stuffing && /* right number of stuffing bytes*/
-                           (q[4] & 0xc4) == 0x44 && /* marker check */
-                           (q[12] & 3) == 3 &&  /* marker check */
-                           q[14 + stuffing] == 0 && /* PES Pack or Sys Hdr */
-                           q[15 + stuffing] == 0 &&
-                           q[16 + stuffing] == 1) {
-                               /* We declare we actually found a Program Pack*/
-                               cx->search_pack_header = 0; /* expect vid PES */
-                               len = (char *)q - start;
-                               cx18_setup_sliced_vbi_mdl(cx);
-                               *stop = true;
-                               break;
-                       }
-               }
-       }
-       if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
-               CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
-                               len, s->name);
-               return -EFAULT;
-       }
-       buf->readpos += len;
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
-           buf != &cx->vbi.sliced_mpeg_buf)
-               cx->mpg_data_received += len;
-       return len;
-}
-
-static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
-               struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
-{
-       size_t tot_written = 0;
-       int rc;
-       bool stop = false;
-
-       if (mdl->curr_buf == NULL)
-               mdl->curr_buf = list_first_entry(&mdl->buf_list,
-                                                struct cx18_buffer, list);
-
-       if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
-               /*
-                * For some reason we've exhausted the buffers, but the MDL
-                * object still said some data was unread.
-                * Fix that and bail out.
-                */
-               mdl->readpos = mdl->bytesused;
-               return 0;
-       }
-
-       list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
-
-               if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
-                       continue;
-
-               rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
-                                          ucount - tot_written, &stop);
-               if (rc < 0)
-                       return rc;
-               mdl->readpos += rc;
-               tot_written += rc;
-
-               if (stop ||     /* Forced stopping point for VBI insertion */
-                   tot_written >= ucount ||    /* Reader request statisfied */
-                   mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
-                   mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
-                       break;
-       }
-       return tot_written;
-}
-
-static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
-               size_t tot_count, int non_block)
-{
-       struct cx18 *cx = s->cx;
-       size_t tot_written = 0;
-       int single_frame = 0;
-
-       if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
-               /* shouldn't happen */
-               CX18_DEBUG_WARN("Stream %s not initialized before read\n",
-                               s->name);
-               return -EIO;
-       }
-
-       /* Each VBI buffer is one frame, the v4l2 API says that for VBI the
-          frames should arrive one-by-one, so make sure we never output more
-          than one VBI frame at a time */
-       if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
-               single_frame = 1;
-
-       for (;;) {
-               struct cx18_mdl *mdl;
-               int rc;
-
-               mdl = cx18_get_mdl(s, non_block, &rc);
-               /* if there is no data available... */
-               if (mdl == NULL) {
-                       /* if we got data, then return that regardless */
-                       if (tot_written)
-                               break;
-                       /* EOS condition */
-                       if (rc == 0) {
-                               clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
-                               clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
-                               cx18_release_stream(s);
-                       }
-                       /* set errno */
-                       return rc;
-               }
-
-               rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
-                               tot_count - tot_written);
-
-               if (mdl != &cx->vbi.sliced_mpeg_mdl) {
-                       if (mdl->readpos == mdl->bytesused)
-                               cx18_stream_put_mdl_fw(s, mdl);
-                       else
-                               cx18_push(s, mdl, &s->q_full);
-               } else if (mdl->readpos == mdl->bytesused) {
-                       int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
-
-                       cx->vbi.sliced_mpeg_size[idx] = 0;
-                       cx->vbi.inserted_frame++;
-                       cx->vbi_data_inserted += mdl->bytesused;
-               }
-               if (rc < 0)
-                       return rc;
-               tot_written += rc;
-
-               if (tot_written == tot_count || single_frame)
-                       break;
-       }
-       return tot_written;
-}
-
-static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
-               size_t count, loff_t *pos, int non_block)
-{
-       ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
-       struct cx18 *cx = s->cx;
-
-       CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
-       if (rc > 0)
-               pos += rc;
-       return rc;
-}
-
-int cx18_start_capture(struct cx18_open_id *id)
-{
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       struct cx18_stream *s_vbi;
-       struct cx18_stream *s_idx;
-
-       if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
-               /* you cannot read from these stream types. */
-               return -EPERM;
-       }
-
-       /* Try to claim this stream. */
-       if (cx18_claim_stream(id, s->type))
-               return -EBUSY;
-
-       /* If capture is already in progress, then we also have to
-          do nothing extra. */
-       if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
-           test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-               set_bit(CX18_F_S_APPL_IO, &s->s_flags);
-               return 0;
-       }
-
-       /* Start associated VBI or IDX stream capture if required */
-       s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
-               /*
-                * The VBI and IDX streams should have been claimed
-                * automatically, if for internal use, when the MPG stream was
-                * claimed.  We only need to start these streams capturing.
-                */
-               if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
-                   !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
-                       if (cx18_start_v4l2_encode_stream(s_idx)) {
-                               CX18_DEBUG_WARN("IDX capture start failed\n");
-                               clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
-                               goto start_failed;
-                       }
-                       CX18_DEBUG_INFO("IDX capture started\n");
-               }
-               if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
-                   !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
-                       if (cx18_start_v4l2_encode_stream(s_vbi)) {
-                               CX18_DEBUG_WARN("VBI capture start failed\n");
-                               clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
-                               goto start_failed;
-                       }
-                       CX18_DEBUG_INFO("VBI insertion started\n");
-               }
-       }
-
-       /* Tell the card to start capturing */
-       if (!cx18_start_v4l2_encode_stream(s)) {
-               /* We're done */
-               set_bit(CX18_F_S_APPL_IO, &s->s_flags);
-               /* Resume a possibly paused encoder */
-               if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
-                       cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
-               return 0;
-       }
-
-start_failed:
-       CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
-
-       /*
-        * The associated VBI and IDX streams for internal use are released
-        * automatically when the MPG stream is released.  We only need to stop
-        * the associated stream.
-        */
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
-               /* Stop the IDX stream which is always for internal use */
-               if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
-                       cx18_stop_v4l2_encode_stream(s_idx, 0);
-                       clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
-               }
-               /* Stop the VBI stream, if only running for internal use */
-               if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
-                   !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
-                       cx18_stop_v4l2_encode_stream(s_vbi, 0);
-                       clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
-               }
-       }
-       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-       cx18_release_stream(s); /* Also releases associated streams */
-       return -EIO;
-}
-
-ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
-               loff_t *pos)
-{
-       struct cx18_open_id *id = file2id(filp);
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       int rc;
-
-       CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
-
-       mutex_lock(&cx->serialize_lock);
-       rc = cx18_start_capture(id);
-       mutex_unlock(&cx->serialize_lock);
-       if (rc)
-               return rc;
-
-       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
-               return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
-                       filp->f_flags & O_NONBLOCK);
-       }
-
-       return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
-}
-
-unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
-{
-       struct cx18_open_id *id = file2id(filp);
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
-
-       /* Start a capture if there is none */
-       if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-               int rc;
-
-               mutex_lock(&cx->serialize_lock);
-               rc = cx18_start_capture(id);
-               mutex_unlock(&cx->serialize_lock);
-               if (rc) {
-                       CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
-                                       s->name, rc);
-                       return POLLERR;
-               }
-               CX18_DEBUG_FILE("Encoder poll started capture\n");
-       }
-
-       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
-               int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
-                if (eof && videobuf_poll == POLLERR)
-                        return POLLHUP;
-                else
-                        return videobuf_poll;
-       }
-
-       /* add stream's waitq to the poll list */
-       CX18_DEBUG_HI_FILE("Encoder poll\n");
-       poll_wait(filp, &s->waitq, wait);
-
-       if (atomic_read(&s->q_full.depth))
-               return POLLIN | POLLRDNORM;
-       if (eof)
-               return POLLHUP;
-       return 0;
-}
-
-int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
-
-       if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (id->type == CX18_ENC_STREAM_TYPE_YUV)) {
-
-               /* Start a capture if there is none */
-               if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-                       int rc;
-
-                       mutex_lock(&cx->serialize_lock);
-                       rc = cx18_start_capture(id);
-                       mutex_unlock(&cx->serialize_lock);
-                       if (rc) {
-                               CX18_DEBUG_INFO(
-                                       "Could not start capture for %s (%d)\n",
-                                       s->name, rc);
-                               return -EINVAL;
-                       }
-                       CX18_DEBUG_FILE("Encoder mmap started capture\n");
-               }
-
-               return videobuf_mmap_mapper(&s->vbuf_q, vma);
-       }
-
-       return -EINVAL;
-}
-
-void cx18_vb_timeout(unsigned long data)
-{
-       struct cx18_stream *s = (struct cx18_stream *)data;
-       struct cx18_videobuf_buffer *buf;
-       unsigned long flags;
-
-       /* Return all of the buffers in error state, so the vbi/vid inode
-        * can return from blocking.
-        */
-       spin_lock_irqsave(&s->vb_lock, flags);
-       while (!list_empty(&s->vb_capture)) {
-               buf = list_entry(s->vb_capture.next,
-                       struct cx18_videobuf_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-       }
-       spin_unlock_irqrestore(&s->vb_lock, flags);
-}
-
-void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
-{
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
-       struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-
-       CX18_DEBUG_IOCTL("close() of %s\n", s->name);
-
-       /* 'Unclaim' this stream */
-
-       /* Stop capturing */
-       if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
-               CX18_DEBUG_INFO("close stopping capture\n");
-               if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
-                       /* Stop internal use associated VBI and IDX streams */
-                       if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
-                           !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
-                               CX18_DEBUG_INFO("close stopping embedded VBI "
-                                               "capture\n");
-                               cx18_stop_v4l2_encode_stream(s_vbi, 0);
-                       }
-                       if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
-                               CX18_DEBUG_INFO("close stopping IDX capture\n");
-                               cx18_stop_v4l2_encode_stream(s_idx, 0);
-                       }
-               }
-               if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
-                   test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
-                       /* Also used internally, don't stop capturing */
-                       s->id = -1;
-               else
-                       cx18_stop_v4l2_encode_stream(s, gop_end);
-       }
-       if (!gop_end) {
-               clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
-               clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
-               cx18_release_stream(s);
-       }
-}
-
-int cx18_v4l2_close(struct file *filp)
-{
-       struct v4l2_fh *fh = filp->private_data;
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       CX18_DEBUG_IOCTL("close() of %s\n", s->name);
-
-       mutex_lock(&cx->serialize_lock);
-       /* Stop radio */
-       if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
-                       v4l2_fh_is_singular_file(filp)) {
-               /* Closing radio device, return to TV mode */
-               cx18_mute(cx);
-               /* Mark that the radio is no longer in use */
-               clear_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
-               /* Switch tuner to TV */
-               cx18_call_all(cx, core, s_std, cx->std);
-               /* Select correct audio input (i.e. TV tuner or Line in) */
-               cx18_audio_set_io(cx);
-               if (atomic_read(&cx->ana_capturing) > 0) {
-                       /* Undo video mute */
-                       cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
-                           (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
-                           (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
-               }
-               /* Done! Unmute and continue. */
-               cx18_unmute(cx);
-       }
-
-       v4l2_fh_del(fh);
-       v4l2_fh_exit(fh);
-
-       /* 'Unclaim' this stream */
-       if (s->id == id->open_id)
-               cx18_stop_capture(id, 0);
-       kfree(id);
-       mutex_unlock(&cx->serialize_lock);
-       return 0;
-}
-
-static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
-{
-       struct cx18 *cx = s->cx;
-       struct cx18_open_id *item;
-
-       CX18_DEBUG_FILE("open %s\n", s->name);
-
-       /* Allocate memory */
-       item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
-       if (NULL == item) {
-               CX18_DEBUG_WARN("nomem on v4l2 open\n");
-               return -ENOMEM;
-       }
-       v4l2_fh_init(&item->fh, s->video_dev);
-
-       item->cx = cx;
-       item->type = s->type;
-
-       item->open_id = cx->open_id++;
-       filp->private_data = &item->fh;
-       v4l2_fh_add(&item->fh);
-
-       if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
-                       v4l2_fh_is_singular_file(filp)) {
-               if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
-                       if (atomic_read(&cx->ana_capturing) > 0) {
-                               /* switching to radio while capture is
-                                  in progress is not polite */
-                               v4l2_fh_del(&item->fh);
-                               v4l2_fh_exit(&item->fh);
-                               kfree(item);
-                               return -EBUSY;
-                       }
-               }
-
-               /* Mark that the radio is being used. */
-               set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
-               /* We have the radio */
-               cx18_mute(cx);
-               /* Switch tuner to radio */
-               cx18_call_all(cx, tuner, s_radio);
-               /* Select the correct audio input (i.e. radio tuner) */
-               cx18_audio_set_io(cx);
-               /* Done! Unmute and continue. */
-               cx18_unmute(cx);
-       }
-       return 0;
-}
-
-int cx18_v4l2_open(struct file *filp)
-{
-       int res;
-       struct video_device *video_dev = video_devdata(filp);
-       struct cx18_stream *s = video_get_drvdata(video_dev);
-       struct cx18 *cx = s->cx;
-
-       mutex_lock(&cx->serialize_lock);
-       if (cx18_init_on_first_open(cx)) {
-               CX18_ERR("Failed to initialize on %s\n",
-                        video_device_node_name(video_dev));
-               mutex_unlock(&cx->serialize_lock);
-               return -ENXIO;
-       }
-       res = cx18_serialized_open(s, filp);
-       mutex_unlock(&cx->serialize_lock);
-       return res;
-}
-
-void cx18_mute(struct cx18 *cx)
-{
-       u32 h;
-       if (atomic_read(&cx->ana_capturing)) {
-               h = cx18_find_handle(cx);
-               if (h != CX18_INVALID_TASK_HANDLE)
-                       cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
-               else
-                       CX18_ERR("Can't find valid task handle for mute\n");
-       }
-       CX18_DEBUG_INFO("Mute\n");
-}
-
-void cx18_unmute(struct cx18 *cx)
-{
-       u32 h;
-       if (atomic_read(&cx->ana_capturing)) {
-               h = cx18_find_handle(cx);
-               if (h != CX18_INVALID_TASK_HANDLE) {
-                       cx18_msleep_timeout(100, 0);
-                       cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
-                       cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
-               } else
-                       CX18_ERR("Can't find valid task handle for unmute\n");
-       }
-       CX18_DEBUG_INFO("Unmute\n");
-}
diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h
deleted file mode 100644 (file)
index b9e5110..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  cx18 file operation functions
- *
- *  Derived from ivtv-fileops.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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
- */
-
-/* Testing/Debugging */
-int cx18_v4l2_open(struct file *filp);
-ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
-                     loff_t *pos);
-ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
-                      loff_t *pos);
-int cx18_v4l2_close(struct file *filp);
-unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
-int cx18_start_capture(struct cx18_open_id *id);
-void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
-void cx18_mute(struct cx18 *cx);
-void cx18_unmute(struct cx18 *cx);
-int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
-void cx18_vb_timeout(unsigned long data);
-
-/* Shared with cx18-alsa module */
-int cx18_claim_stream(struct cx18_open_id *id, int type);
-void cx18_release_stream(struct cx18_stream *s);
diff --git a/drivers/media/video/cx18/cx18-firmware.c b/drivers/media/video/cx18/cx18-firmware.c
deleted file mode 100644 (file)
index a1c1cec..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- *  cx18 firmware functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-scb.h"
-#include "cx18-irq.h"
-#include "cx18-firmware.h"
-#include "cx18-cards.h"
-#include <linux/firmware.h>
-
-#define CX18_PROC_SOFT_RESET           0xc70010
-#define CX18_DDR_SOFT_RESET            0xc70014
-#define CX18_CLOCK_SELECT1             0xc71000
-#define CX18_CLOCK_SELECT2             0xc71004
-#define CX18_HALF_CLOCK_SELECT1        0xc71008
-#define CX18_HALF_CLOCK_SELECT2        0xc7100C
-#define CX18_CLOCK_POLARITY1           0xc71010
-#define CX18_CLOCK_POLARITY2           0xc71014
-#define CX18_ADD_DELAY_ENABLE1         0xc71018
-#define CX18_ADD_DELAY_ENABLE2         0xc7101C
-#define CX18_CLOCK_ENABLE1             0xc71020
-#define CX18_CLOCK_ENABLE2             0xc71024
-
-#define CX18_REG_BUS_TIMEOUT_EN        0xc72024
-
-#define CX18_FAST_CLOCK_PLL_INT        0xc78000
-#define CX18_FAST_CLOCK_PLL_FRAC       0xc78004
-#define CX18_FAST_CLOCK_PLL_POST       0xc78008
-#define CX18_FAST_CLOCK_PLL_PRESCALE   0xc7800C
-#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
-
-#define CX18_SLOW_CLOCK_PLL_INT        0xc78014
-#define CX18_SLOW_CLOCK_PLL_FRAC       0xc78018
-#define CX18_SLOW_CLOCK_PLL_POST       0xc7801C
-#define CX18_MPEG_CLOCK_PLL_INT                0xc78040
-#define CX18_MPEG_CLOCK_PLL_FRAC       0xc78044
-#define CX18_MPEG_CLOCK_PLL_POST       0xc78048
-#define CX18_PLL_POWER_DOWN            0xc78088
-#define CX18_SW1_INT_STATUS             0xc73104
-#define CX18_SW1_INT_ENABLE_PCI         0xc7311C
-#define CX18_SW2_INT_SET                0xc73140
-#define CX18_SW2_INT_STATUS             0xc73144
-#define CX18_ADEC_CONTROL              0xc78120
-
-#define CX18_DDR_REQUEST_ENABLE        0xc80000
-#define CX18_DDR_CHIP_CONFIG           0xc80004
-#define CX18_DDR_REFRESH               0xc80008
-#define CX18_DDR_TIMING1               0xc8000C
-#define CX18_DDR_TIMING2               0xc80010
-#define CX18_DDR_POWER_REG             0xc8001C
-
-#define CX18_DDR_TUNE_LANE             0xc80048
-#define CX18_DDR_INITIAL_EMRS          0xc80054
-#define CX18_DDR_MB_PER_ROW_7          0xc8009C
-#define CX18_DDR_BASE_63_ADDR          0xc804FC
-
-#define CX18_WMB_CLIENT02              0xc90108
-#define CX18_WMB_CLIENT05              0xc90114
-#define CX18_WMB_CLIENT06              0xc90118
-#define CX18_WMB_CLIENT07              0xc9011C
-#define CX18_WMB_CLIENT08              0xc90120
-#define CX18_WMB_CLIENT09              0xc90124
-#define CX18_WMB_CLIENT10              0xc90128
-#define CX18_WMB_CLIENT11              0xc9012C
-#define CX18_WMB_CLIENT12              0xc90130
-#define CX18_WMB_CLIENT13              0xc90134
-#define CX18_WMB_CLIENT14              0xc90138
-
-#define CX18_DSP0_INTERRUPT_MASK       0xd0004C
-
-#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
-#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
-
-struct cx18_apu_rom_seghdr {
-       u32 sync1;
-       u32 sync2;
-       u32 addr;
-       u32 size;
-};
-
-static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
-{
-       const struct firmware *fw = NULL;
-       int i, j;
-       unsigned size;
-       u32 __iomem *dst = (u32 __iomem *)mem;
-       const u32 *src;
-
-       if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
-               CX18_ERR("Unable to open firmware %s\n", fn);
-               CX18_ERR("Did you put the firmware in the hotplug firmware directory?\n");
-               return -ENOMEM;
-       }
-
-       src = (const u32 *)fw->data;
-
-       for (i = 0; i < fw->size; i += 4096) {
-               cx18_setup_page(cx, i);
-               for (j = i; j < fw->size && j < i + 4096; j += 4) {
-                       /* no need for endianness conversion on the ppc */
-                       cx18_raw_writel(cx, *src, dst);
-                       if (cx18_raw_readl(cx, dst) != *src) {
-                               CX18_ERR("Mismatch at offset %x\n", i);
-                               release_firmware(fw);
-                               cx18_setup_page(cx, 0);
-                               return -EIO;
-                       }
-                       dst++;
-                       src++;
-               }
-       }
-       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
-               CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
-       size = fw->size;
-       release_firmware(fw);
-       cx18_setup_page(cx, SCB_OFFSET);
-       return size;
-}
-
-static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
-                               u32 *entry_addr)
-{
-       const struct firmware *fw = NULL;
-       int i, j;
-       unsigned size;
-       const u32 *src;
-       struct cx18_apu_rom_seghdr seghdr;
-       const u8 *vers;
-       u32 offset = 0;
-       u32 apu_version = 0;
-       int sz;
-
-       if (request_firmware(&fw, fn, &cx->pci_dev->dev)) {
-               CX18_ERR("unable to open firmware %s\n", fn);
-               CX18_ERR("did you put the firmware in the hotplug firmware directory?\n");
-               cx18_setup_page(cx, 0);
-               return -ENOMEM;
-       }
-
-       *entry_addr = 0;
-       src = (const u32 *)fw->data;
-       vers = fw->data + sizeof(seghdr);
-       sz = fw->size;
-
-       apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
-       while (offset + sizeof(seghdr) < fw->size) {
-               const u32 *shptr = src + offset / 4;
-
-               seghdr.sync1 = le32_to_cpu(shptr[0]);
-               seghdr.sync2 = le32_to_cpu(shptr[1]);
-               seghdr.addr = le32_to_cpu(shptr[2]);
-               seghdr.size = le32_to_cpu(shptr[3]);
-
-               offset += sizeof(seghdr);
-               if (seghdr.sync1 != APU_ROM_SYNC1 ||
-                   seghdr.sync2 != APU_ROM_SYNC2) {
-                       offset += seghdr.size;
-                       continue;
-               }
-               CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
-                               seghdr.addr + seghdr.size - 1);
-               if (*entry_addr == 0)
-                       *entry_addr = seghdr.addr;
-               if (offset + seghdr.size > sz)
-                       break;
-               for (i = 0; i < seghdr.size; i += 4096) {
-                       cx18_setup_page(cx, seghdr.addr + i);
-                       for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
-                               /* no need for endianness conversion on the ppc */
-                               cx18_raw_writel(cx, src[(offset + j) / 4],
-                                               dst + seghdr.addr + j);
-                               if (cx18_raw_readl(cx, dst + seghdr.addr + j)
-                                   != src[(offset + j) / 4]) {
-                                       CX18_ERR("Mismatch at offset %x\n",
-                                                offset + j);
-                                       release_firmware(fw);
-                                       cx18_setup_page(cx, 0);
-                                       return -EIO;
-                               }
-                       }
-               }
-               offset += seghdr.size;
-       }
-       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
-               CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
-                               fn, apu_version, fw->size);
-       size = fw->size;
-       release_firmware(fw);
-       cx18_setup_page(cx, 0);
-       return size;
-}
-
-void cx18_halt_firmware(struct cx18 *cx)
-{
-       CX18_DEBUG_INFO("Preparing for firmware halt.\n");
-       cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
-                                 0x0000000F, 0x000F000F);
-       cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
-                                 0x00000002, 0x00020002);
-}
-
-void cx18_init_power(struct cx18 *cx, int lowpwr)
-{
-       /* power-down Spare and AOM PLLs */
-       /* power-up fast, slow and mpeg PLLs */
-       cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
-
-       /* ADEC out of sleep */
-       cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
-                                 0x00000000, 0x00020002);
-
-       /*
-        * The PLL parameters are based on the external crystal frequency that
-        * would ideally be:
-        *
-        * NTSC Color subcarrier freq * 8 =
-        *      4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
-        *
-        * The accidents of history and rationale that explain from where this
-        * combination of magic numbers originate can be found in:
-        *
-        * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
-        * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
-        *
-        * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
-        * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
-        *
-        * As Mike Bradley has rightly pointed out, it's not the exact crystal
-        * frequency that matters, only that all parts of the driver and
-        * firmware are using the same value (close to the ideal value).
-        *
-        * Since I have a strong suspicion that, if the firmware ever assumes a
-        * crystal value at all, it will assume 28.636360 MHz, the crystal
-        * freq used in calculations in this driver will be:
-        *
-        *      xtal_freq = 28.636360 MHz
-        *
-        * an error of less than 0.13 ppm which is way, way better than any off
-        * the shelf crystal will have for accuracy anyway.
-        *
-        * Below I aim to run the PLLs' VCOs near 400 MHz to minimze errors.
-        *
-        * Many thanks to Jeff Campbell and Mike Bradley for their extensive
-        * investigation, experimentation, testing, and suggested solutions of
-        * of audio/video sync problems with SVideo and CVBS captures.
-        */
-
-       /* the fast clock is at 200/245 MHz */
-       /* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/
-       /* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/
-       cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
-       cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
-                                               CX18_FAST_CLOCK_PLL_FRAC);
-
-       cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
-       cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
-       cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
-
-       /* set slow clock to 125/120 MHz */
-       /* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */
-       /* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */
-       cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);
-       cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,
-                                               CX18_SLOW_CLOCK_PLL_FRAC);
-       cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);
-
-       /* mpeg clock pll 54MHz */
-       /* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */
-       cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
-       cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
-       cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
-
-       /* Defaults */
-       /* APU = SC or SC/2 = 125/62.5 */
-       /* EPU = SC = 125 */
-       /* DDR = FC = 180 */
-       /* ENC = SC = 125 */
-       /* AI1 = SC = 125 */
-       /* VIM2 = disabled */
-       /* PCI = FC/2 = 90 */
-       /* AI2 = disabled */
-       /* DEMUX = disabled */
-       /* AO = SC/2 = 62.5 */
-       /* SER = 54MHz */
-       /* VFC = disabled */
-       /* USB = disabled */
-
-       if (lowpwr) {
-               cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
-                                         0x00000020, 0xFFFFFFFF);
-               cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
-                                         0x00000004, 0xFFFFFFFF);
-       } else {
-               /* This doesn't explicitly set every clock select */
-               cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
-                                         0x00000004, 0x00060006);
-               cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
-                                         0x00000006, 0x00060006);
-       }
-
-       cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
-                                 0x00000002, 0xFFFFFFFF);
-       cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
-                                 0x00000104, 0xFFFFFFFF);
-       cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
-                                 0x00009026, 0xFFFFFFFF);
-       cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
-                                 0x00003105, 0xFFFFFFFF);
-}
-
-void cx18_init_memory(struct cx18 *cx)
-{
-       cx18_msleep_timeout(10, 0);
-       cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
-                                 0x00000000, 0x00010001);
-       cx18_msleep_timeout(10, 0);
-
-       cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
-
-       cx18_msleep_timeout(10, 0);
-
-       cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
-       cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
-       cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
-
-       cx18_msleep_timeout(10, 0);
-
-       /* Initialize DQS pad time */
-       cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
-       cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
-
-       cx18_msleep_timeout(10, 0);
-
-       cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
-                                 0x00000000, 0x00020002);
-       cx18_msleep_timeout(10, 0);
-
-       /* use power-down mode when idle */
-       cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
-
-       cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
-                                 0x00000001, 0x00010001);
-
-       cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
-       cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
-
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);  /* AO */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);  /* AI2 */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);  /* AI1 */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);  /* ME */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);  /* ENC */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);  /* PK */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);  /* RC */
-       cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);  /* AVO */
-}
-
-#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"
-#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"
-
-int cx18_firmware_init(struct cx18 *cx)
-{
-       u32 fw_entry_addr;
-       int sz, retries;
-       u32 api_args[MAX_MB_ARGUMENTS];
-
-       /* Allow chip to control CLKRUN */
-       cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
-
-       /* Stop the firmware */
-       cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
-                                 0x0000000F, 0x000F000F);
-
-       cx18_msleep_timeout(1, 0);
-
-       /* If the CPU is still running */
-       if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
-               CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
-               return -EIO;
-       }
-
-       cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
-       cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
-
-       sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);
-       if (sz <= 0)
-               return sz;
-
-       /* The SCB & IPC area *must* be correct before starting the firmwares */
-       cx18_init_scb(cx);
-
-       fw_entry_addr = 0;
-       sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,
-                               &fw_entry_addr);
-       if (sz <= 0)
-               return sz;
-
-       /* Start the CPU. The CPU will take care of the APU for us. */
-       cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
-                                 0x00000000, 0x00080008);
-
-       /* Wait up to 500 ms for the APU to come out of reset */
-       for (retries = 0;
-            retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
-            retries++)
-               cx18_msleep_timeout(10, 0);
-
-       cx18_msleep_timeout(200, 0);
-
-       if (retries == 50 &&
-           (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
-               CX18_ERR("Could not start the CPU\n");
-               return -EIO;
-       }
-
-       /*
-        * The CPU had once before set up to receive an interrupt for it's
-        * outgoing IRQ_CPU_TO_EPU_ACK to us.  If it ever does this, we get an
-        * interrupt when it sends us an ack, but by the time we process it,
-        * that flag in the SW2 status register has been cleared by the CPU
-        * firmware.  We'll prevent that not so useful condition from happening
-        * by clearing the CPU's interrupt enables for Ack IRQ's we want to
-        * process.
-        */
-       cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
-
-       /* Try a benign command to see if the CPU is alive and well */
-       sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
-       if (sz < 0)
-               return sz;
-
-       /* initialize GPIO */
-       cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
-       return 0;
-}
-
-MODULE_FIRMWARE(CX18_CPU_FIRMWARE);
-MODULE_FIRMWARE(CX18_APU_FIRMWARE);
diff --git a/drivers/media/video/cx18/cx18-firmware.h b/drivers/media/video/cx18/cx18-firmware.h
deleted file mode 100644 (file)
index 38d4c05..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  cx18 firmware functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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
- */
-
-int cx18_firmware_init(struct cx18 *cx);
-void cx18_halt_firmware(struct cx18 *cx);
-void cx18_init_memory(struct cx18 *cx);
-void cx18_init_power(struct cx18 *cx, int lowpwr);
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c
deleted file mode 100644 (file)
index 5374aeb..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- *  cx18 gpio functions
- *
- *  Derived from ivtv-gpio.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-cards.h"
-#include "cx18-gpio.h"
-#include "tuner-xc2028.h"
-
-/********************* GPIO stuffs *********************/
-
-/* GPIO registers */
-#define CX18_REG_GPIO_IN     0xc72010
-#define CX18_REG_GPIO_OUT1   0xc78100
-#define CX18_REG_GPIO_DIR1   0xc78108
-#define CX18_REG_GPIO_OUT2   0xc78104
-#define CX18_REG_GPIO_DIR2   0xc7810c
-
-/*
- * HVR-1600 GPIO pins, courtesy of Hauppauge:
- *
- * gpio0: zilog ir process reset pin
- * gpio1: zilog programming pin (you should never use this)
- * gpio12: cx24227 reset pin
- * gpio13: cs5345 reset pin
-*/
-
-/*
- * File scope utility functions
- */
-static void gpio_write(struct cx18 *cx)
-{
-       u32 dir_lo = cx->gpio_dir & 0xffff;
-       u32 val_lo = cx->gpio_val & 0xffff;
-       u32 dir_hi = cx->gpio_dir >> 16;
-       u32 val_hi = cx->gpio_val >> 16;
-
-       cx18_write_reg_expect(cx, dir_lo << 16,
-                                       CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo);
-       cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo,
-                                       CX18_REG_GPIO_OUT1, val_lo, dir_lo);
-       cx18_write_reg_expect(cx, dir_hi << 16,
-                                       CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi);
-       cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi,
-                                       CX18_REG_GPIO_OUT2, val_hi, dir_hi);
-}
-
-static void gpio_update(struct cx18 *cx, u32 mask, u32 data)
-{
-       if (mask == 0)
-               return;
-
-       mutex_lock(&cx->gpio_lock);
-       cx->gpio_val = (cx->gpio_val & ~mask) | (data & mask);
-       gpio_write(cx);
-       mutex_unlock(&cx->gpio_lock);
-}
-
-static void gpio_reset_seq(struct cx18 *cx, u32 active_lo, u32 active_hi,
-                          unsigned int assert_msecs,
-                          unsigned int recovery_msecs)
-{
-       u32 mask;
-
-       mask = active_lo | active_hi;
-       if (mask == 0)
-               return;
-
-       /*
-        * Assuming that active_hi and active_lo are a subsets of the bits in
-        * gpio_dir.  Also assumes that active_lo and active_hi don't overlap
-        * in any bit position
-        */
-
-       /* Assert */
-       gpio_update(cx, mask, ~active_lo);
-       schedule_timeout_uninterruptible(msecs_to_jiffies(assert_msecs));
-
-       /* Deassert */
-       gpio_update(cx, mask, ~active_hi);
-       schedule_timeout_uninterruptible(msecs_to_jiffies(recovery_msecs));
-}
-
-/*
- * GPIO Multiplexer - logical device
- */
-static int gpiomux_log_status(struct v4l2_subdev *sd)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       mutex_lock(&cx->gpio_lock);
-       CX18_INFO_DEV(sd, "GPIO:  direction 0x%08x, value 0x%08x\n",
-                     cx->gpio_dir, cx->gpio_val);
-       mutex_unlock(&cx->gpio_lock);
-       return 0;
-}
-
-static int gpiomux_s_radio(struct v4l2_subdev *sd)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       /*
-        * FIXME - work out the cx->active/audio_input mess - this is
-        * intended to handle the switch to radio mode and set the
-        * audio routing, but we need to update the state in cx
-        */
-       gpio_update(cx, cx->card->gpio_audio_input.mask,
-                       cx->card->gpio_audio_input.radio);
-       return 0;
-}
-
-static int gpiomux_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       u32 data;
-
-       switch (cx->card->audio_inputs[cx->audio_input].muxer_input) {
-       case 1:
-               data = cx->card->gpio_audio_input.linein;
-               break;
-       case 0:
-               data = cx->card->gpio_audio_input.tuner;
-               break;
-       default:
-               /*
-                * FIXME - work out the cx->active/audio_input mess - this is
-                * intended to handle the switch from radio mode and set the
-                * audio routing, but we need to update the state in cx
-                */
-               data = cx->card->gpio_audio_input.tuner;
-               break;
-       }
-       gpio_update(cx, cx->card->gpio_audio_input.mask, data);
-       return 0;
-}
-
-static int gpiomux_s_audio_routing(struct v4l2_subdev *sd,
-                                  u32 input, u32 output, u32 config)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       u32 data;
-
-       switch (input) {
-       case 0:
-               data = cx->card->gpio_audio_input.tuner;
-               break;
-       case 1:
-               data = cx->card->gpio_audio_input.linein;
-               break;
-       case 2:
-               data = cx->card->gpio_audio_input.radio;
-               break;
-       default:
-               return -EINVAL;
-       }
-       gpio_update(cx, cx->card->gpio_audio_input.mask, data);
-       return 0;
-}
-
-static const struct v4l2_subdev_core_ops gpiomux_core_ops = {
-       .log_status = gpiomux_log_status,
-       .s_std = gpiomux_s_std,
-};
-
-static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = {
-       .s_radio = gpiomux_s_radio,
-};
-
-static const struct v4l2_subdev_audio_ops gpiomux_audio_ops = {
-       .s_routing = gpiomux_s_audio_routing,
-};
-
-static const struct v4l2_subdev_ops gpiomux_ops = {
-       .core = &gpiomux_core_ops,
-       .tuner = &gpiomux_tuner_ops,
-       .audio = &gpiomux_audio_ops,
-};
-
-/*
- * GPIO Reset Controller - logical device
- */
-static int resetctrl_log_status(struct v4l2_subdev *sd)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-       mutex_lock(&cx->gpio_lock);
-       CX18_INFO_DEV(sd, "GPIO:  direction 0x%08x, value 0x%08x\n",
-                     cx->gpio_dir, cx->gpio_val);
-       mutex_unlock(&cx->gpio_lock);
-       return 0;
-}
-
-static int resetctrl_reset(struct v4l2_subdev *sd, u32 val)
-{
-       struct cx18 *cx = v4l2_get_subdevdata(sd);
-       const struct cx18_gpio_i2c_slave_reset *p;
-
-       p = &cx->card->gpio_i2c_slave_reset;
-       switch (val) {
-       case CX18_GPIO_RESET_I2C:
-               gpio_reset_seq(cx, p->active_lo_mask, p->active_hi_mask,
-                              p->msecs_asserted, p->msecs_recovery);
-               break;
-       case CX18_GPIO_RESET_Z8F0811:
-               /*
-                * Assert timing for the Z8F0811 on HVR-1600 boards:
-                * 1. Assert RESET for min of 4 clock cycles at 18.432 MHz to
-                *    initiate
-                * 2. Reset then takes 66 WDT cycles at 10 kHz + 16 xtal clock
-                *    cycles (6,601,085 nanoseconds ~= 7 milliseconds)
-                * 3. DBG pin must be high before chip exits reset for normal
-                *    operation.  DBG is open drain and hopefully pulled high
-                *    since we don't normally drive it (GPIO 1?) for the
-                *    HVR-1600
-                * 4. Z8F0811 won't exit reset until RESET is deasserted
-                * 5. Zilog comes out of reset, loads reset vector address and
-                *    executes from there. Required recovery delay unknown.
-                */
-               gpio_reset_seq(cx, p->ir_reset_mask, 0,
-                              p->msecs_asserted, p->msecs_recovery);
-               break;
-       case CX18_GPIO_RESET_XC2028:
-               if (cx->card->tuners[0].tuner == TUNER_XC2028)
-                       gpio_reset_seq(cx, (1 << cx->card->xceive_pin), 0,
-                                      1, 1);
-               break;
-       }
-       return 0;
-}
-
-static const struct v4l2_subdev_core_ops resetctrl_core_ops = {
-       .log_status = resetctrl_log_status,
-       .reset = resetctrl_reset,
-};
-
-static const struct v4l2_subdev_ops resetctrl_ops = {
-       .core = &resetctrl_core_ops,
-};
-
-/*
- * External entry points
- */
-void cx18_gpio_init(struct cx18 *cx)
-{
-       mutex_lock(&cx->gpio_lock);
-       cx->gpio_dir = cx->card->gpio_init.direction;
-       cx->gpio_val = cx->card->gpio_init.initial_value;
-
-       if (cx->card->tuners[0].tuner == TUNER_XC2028) {
-               cx->gpio_dir |= 1 << cx->card->xceive_pin;
-               cx->gpio_val |= 1 << cx->card->xceive_pin;
-       }
-
-       if (cx->gpio_dir == 0) {
-               mutex_unlock(&cx->gpio_lock);
-               return;
-       }
-
-       CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
-                       cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
-                       cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
-                       cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
-                       cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
-
-       gpio_write(cx);
-       mutex_unlock(&cx->gpio_lock);
-}
-
-int cx18_gpio_register(struct cx18 *cx, u32 hw)
-{
-       struct v4l2_subdev *sd;
-       const struct v4l2_subdev_ops *ops;
-       char *str;
-
-       switch (hw) {
-       case CX18_HW_GPIO_MUX:
-               sd = &cx->sd_gpiomux;
-               ops = &gpiomux_ops;
-               str = "gpio-mux";
-               break;
-       case CX18_HW_GPIO_RESET_CTRL:
-               sd = &cx->sd_resetctrl;
-               ops = &resetctrl_ops;
-               str = "gpio-reset-ctrl";
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       v4l2_subdev_init(sd, ops);
-       v4l2_set_subdevdata(sd, cx);
-       snprintf(sd->name, sizeof(sd->name), "%s %s", cx->v4l2_dev.name, str);
-       sd->grp_id = hw;
-       return v4l2_device_register_subdev(&cx->v4l2_dev, sd);
-}
-
-void cx18_reset_ir_gpio(void *data)
-{
-       struct cx18 *cx = to_cx18((struct v4l2_device *)data);
-
-       if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0)
-               return;
-
-       CX18_DEBUG_INFO("Resetting IR microcontroller\n");
-
-       v4l2_subdev_call(&cx->sd_resetctrl,
-                        core, reset, CX18_GPIO_RESET_Z8F0811);
-}
-EXPORT_SYMBOL(cx18_reset_ir_gpio);
-/* This symbol is exported for use by lirc_pvr150 for the IR-blaster */
-
-/* Xceive tuner reset function */
-int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
-{
-       struct i2c_algo_bit_data *algo = dev;
-       struct cx18_i2c_algo_callback_data *cb_data = algo->data;
-       struct cx18 *cx = cb_data->cx;
-
-       if (cmd != XC2028_TUNER_RESET ||
-           cx->card->tuners[0].tuner != TUNER_XC2028)
-               return 0;
-
-       CX18_DEBUG_INFO("Resetting XCeive tuner\n");
-       return v4l2_subdev_call(&cx->sd_resetctrl,
-                               core, reset, CX18_GPIO_RESET_XC2028);
-}
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h
deleted file mode 100644 (file)
index 4aea2ef..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  cx18 gpio functions
- *
- *  Derived from ivtv-gpio.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-void cx18_gpio_init(struct cx18 *cx);
-int cx18_gpio_register(struct cx18 *cx, u32 hw);
-
-enum cx18_gpio_reset_type {
-       CX18_GPIO_RESET_I2C     = 0,
-       CX18_GPIO_RESET_Z8F0811 = 1,
-       CX18_GPIO_RESET_XC2028  = 2,
-};
-
-void cx18_reset_ir_gpio(void *data);
-int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
deleted file mode 100644 (file)
index 51609d5..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- *  cx18 I2C functions
- *
- *  Derived from ivtv-i2c.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-cards.h"
-#include "cx18-gpio.h"
-#include "cx18-i2c.h"
-#include "cx18-irq.h"
-
-#define CX18_REG_I2C_1_WR   0xf15000
-#define CX18_REG_I2C_1_RD   0xf15008
-#define CX18_REG_I2C_2_WR   0xf25100
-#define CX18_REG_I2C_2_RD   0xf25108
-
-#define SETSCL_BIT      0x0001
-#define SETSDL_BIT      0x0002
-#define GETSCL_BIT      0x0004
-#define GETSDL_BIT      0x0008
-
-#define CX18_CS5345_I2C_ADDR           0x4c
-#define CX18_Z8F0811_IR_TX_I2C_ADDR    0x70
-#define CX18_Z8F0811_IR_RX_I2C_ADDR    0x71
-
-/* This array should match the CX18_HW_ defines */
-static const u8 hw_addrs[] = {
-       0,                              /* CX18_HW_TUNER */
-       0,                              /* CX18_HW_TVEEPROM */
-       CX18_CS5345_I2C_ADDR,           /* CX18_HW_CS5345 */
-       0,                              /* CX18_HW_DVB */
-       0,                              /* CX18_HW_418_AV */
-       0,                              /* CX18_HW_GPIO_MUX */
-       0,                              /* CX18_HW_GPIO_RESET_CTRL */
-       CX18_Z8F0811_IR_TX_I2C_ADDR,    /* CX18_HW_Z8F0811_IR_TX_HAUP */
-       CX18_Z8F0811_IR_RX_I2C_ADDR,    /* CX18_HW_Z8F0811_IR_RX_HAUP */
-};
-
-/* This array should match the CX18_HW_ defines */
-/* This might well become a card-specific array */
-static const u8 hw_bus[] = {
-       1,      /* CX18_HW_TUNER */
-       0,      /* CX18_HW_TVEEPROM */
-       0,      /* CX18_HW_CS5345 */
-       0,      /* CX18_HW_DVB */
-       0,      /* CX18_HW_418_AV */
-       0,      /* CX18_HW_GPIO_MUX */
-       0,      /* CX18_HW_GPIO_RESET_CTRL */
-       0,      /* CX18_HW_Z8F0811_IR_TX_HAUP */
-       0,      /* CX18_HW_Z8F0811_IR_RX_HAUP */
-};
-
-/* This array should match the CX18_HW_ defines */
-static const char * const hw_devicenames[] = {
-       "tuner",
-       "tveeprom",
-       "cs5345",
-       "cx23418_DTV",
-       "cx23418_AV",
-       "gpio_mux",
-       "gpio_reset_ctrl",
-       "ir_tx_z8f0811_haup",
-       "ir_rx_z8f0811_haup",
-};
-
-static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
-                          const char *type, u8 addr)
-{
-       struct i2c_board_info info;
-       struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data;
-       unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       strlcpy(info.type, type, I2C_NAME_SIZE);
-
-       /* Our default information for ir-kbd-i2c.c to use */
-       switch (hw) {
-       case CX18_HW_Z8F0811_IR_RX_HAUP:
-               init_data->ir_codes = RC_MAP_HAUPPAUGE;
-               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-               init_data->type = RC_TYPE_RC5;
-               init_data->name = cx->card_name;
-               info.platform_data = init_data;
-               break;
-       }
-
-       return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
-              -1 : 0;
-}
-
-int cx18_i2c_register(struct cx18 *cx, unsigned idx)
-{
-       struct v4l2_subdev *sd;
-       int bus = hw_bus[idx];
-       struct i2c_adapter *adap = &cx->i2c_adap[bus];
-       const char *type = hw_devicenames[idx];
-       u32 hw = 1 << idx;
-
-       if (idx >= ARRAY_SIZE(hw_addrs))
-               return -1;
-
-       if (hw == CX18_HW_TUNER) {
-               /* special tuner group handling */
-               sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
-                               adap, type, 0, cx->card_i2c->radio);
-               if (sd != NULL)
-                       sd->grp_id = hw;
-               sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
-                               adap, type, 0, cx->card_i2c->demod);
-               if (sd != NULL)
-                       sd->grp_id = hw;
-               sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
-                               adap, type, 0, cx->card_i2c->tv);
-               if (sd != NULL)
-                       sd->grp_id = hw;
-               return sd != NULL ? 0 : -1;
-       }
-
-       if (hw & CX18_HW_IR_ANY)
-               return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]);
-
-       /* Is it not an I2C device or one we do not wish to register? */
-       if (!hw_addrs[idx])
-               return -1;
-
-       /* It's an I2C device other than an analog tuner or IR chip */
-       sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx],
-                                NULL);
-       if (sd != NULL)
-               sd->grp_id = hw;
-       return sd != NULL ? 0 : -1;
-}
-
-/* Find the first member of the subdev group id in hw */
-struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw)
-{
-       struct v4l2_subdev *result = NULL;
-       struct v4l2_subdev *sd;
-
-       spin_lock(&cx->v4l2_dev.lock);
-       v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) {
-               if (sd->grp_id == hw) {
-                       result = sd;
-                       break;
-               }
-       }
-       spin_unlock(&cx->v4l2_dev.lock);
-       return result;
-}
-
-static void cx18_setscl(void *data, int state)
-{
-       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
-       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
-       u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
-       u32 r = cx18_read_reg(cx, addr);
-
-       if (state)
-               cx18_write_reg(cx, r | SETSCL_BIT, addr);
-       else
-               cx18_write_reg(cx, r & ~SETSCL_BIT, addr);
-}
-
-static void cx18_setsda(void *data, int state)
-{
-       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
-       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
-       u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
-       u32 r = cx18_read_reg(cx, addr);
-
-       if (state)
-               cx18_write_reg(cx, r | SETSDL_BIT, addr);
-       else
-               cx18_write_reg(cx, r & ~SETSDL_BIT, addr);
-}
-
-static int cx18_getscl(void *data)
-{
-       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
-       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
-       u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
-
-       return cx18_read_reg(cx, addr) & GETSCL_BIT;
-}
-
-static int cx18_getsda(void *data)
-{
-       struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
-       int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
-       u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
-
-       return cx18_read_reg(cx, addr) & GETSDL_BIT;
-}
-
-/* template for i2c-bit-algo */
-static struct i2c_adapter cx18_i2c_adap_template = {
-       .name = "cx18 i2c driver",
-       .algo = NULL,                   /* set by i2c-algo-bit */
-       .algo_data = NULL,              /* filled from template */
-       .owner = THIS_MODULE,
-};
-
-#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
-#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
-
-static struct i2c_algo_bit_data cx18_i2c_algo_template = {
-       .setsda         = cx18_setsda,
-       .setscl         = cx18_setscl,
-       .getsda         = cx18_getsda,
-       .getscl         = cx18_getscl,
-       .udelay         = CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/
-       .timeout        = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
-};
-
-/* init + register i2c adapter */
-int init_cx18_i2c(struct cx18 *cx)
-{
-       int i, err;
-       CX18_DEBUG_I2C("i2c init\n");
-
-       for (i = 0; i < 2; i++) {
-               /* Setup algorithm for adapter */
-               memcpy(&cx->i2c_algo[i], &cx18_i2c_algo_template,
-                       sizeof(struct i2c_algo_bit_data));
-               cx->i2c_algo_cb_data[i].cx = cx;
-               cx->i2c_algo_cb_data[i].bus_index = i;
-               cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
-
-               /* Setup adapter */
-               memcpy(&cx->i2c_adap[i], &cx18_i2c_adap_template,
-                       sizeof(struct i2c_adapter));
-               cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
-               sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
-                               " #%d-%d", cx->instance, i);
-               i2c_set_adapdata(&cx->i2c_adap[i], &cx->v4l2_dev);
-               cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev;
-       }
-
-       if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
-               /* Reset/Unreset I2C hardware block */
-               /* Clock select 220MHz */
-               cx18_write_reg_expect(cx, 0x10000000, 0xc71004,
-                                         0x00000000, 0x10001000);
-               /* Clock Enable */
-               cx18_write_reg_expect(cx, 0x10001000, 0xc71024,
-                                         0x00001000, 0x10001000);
-       }
-       /* courtesy of Steven Toth <stoth@hauppauge.com> */
-       cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
-       mdelay(10);
-       cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);
-       mdelay(10);
-       cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
-       mdelay(10);
-
-       /* Set to edge-triggered intrs. */
-       cx18_write_reg(cx, 0x00c00000, 0xc730c8);
-       /* Clear any stale intrs */
-       cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,
-                      ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);
-
-       /* Hw I2C1 Clock Freq ~100kHz */
-       cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
-       cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
-       cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
-
-       /* Hw I2C2 Clock Freq ~100kHz */
-       cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
-       cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
-       cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
-
-       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
-                    core, reset, (u32) CX18_GPIO_RESET_I2C);
-
-       err = i2c_bit_add_bus(&cx->i2c_adap[0]);
-       if (err)
-               goto err;
-       err = i2c_bit_add_bus(&cx->i2c_adap[1]);
-       if (err)
-               goto err_del_bus_0;
-       return 0;
-
- err_del_bus_0:
-       i2c_del_adapter(&cx->i2c_adap[0]);
- err:
-       return err;
-}
-
-void exit_cx18_i2c(struct cx18 *cx)
-{
-       int i;
-       CX18_DEBUG_I2C("i2c exit\n");
-       cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
-                                                       CX18_REG_I2C_1_WR);
-       cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
-                                                       CX18_REG_I2C_2_WR);
-
-       for (i = 0; i < 2; i++) {
-               i2c_del_adapter(&cx->i2c_adap[i]);
-       }
-}
-
-/*
-   Hauppauge HVR1600 should have:
-   32 cx24227
-   98 unknown
-   a0 eeprom
-   c2 tuner
-   e? zilog ir
-   */
diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h
deleted file mode 100644 (file)
index 1180fdc..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *  cx18 I2C functions
- *
- *  Derived from ivtv-i2c.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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
- */
-
-int cx18_i2c_register(struct cx18 *cx, unsigned idx);
-struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw);
-
-/* init + register i2c adapter */
-int init_cx18_i2c(struct cx18 *cx);
-void exit_cx18_i2c(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c
deleted file mode 100644 (file)
index 49b9dbd..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- *  cx18 driver PCI memory mapped IO access routines
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-irq.h"
-
-void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
-{
-       u8 __iomem *dst = addr;
-       u16 val2 = val | (val << 8);
-       u32 val4 = val2 | (val2 << 16);
-
-       /* Align writes on the CX23418's addresses */
-       if ((count > 0) && ((unsigned long)dst & 1)) {
-               cx18_writeb(cx, (u8) val, dst);
-               count--;
-               dst++;
-       }
-       if ((count > 1) && ((unsigned long)dst & 2)) {
-               cx18_writew(cx, val2, dst);
-               count -= 2;
-               dst += 2;
-       }
-       while (count > 3) {
-               cx18_writel(cx, val4, dst);
-               count -= 4;
-               dst += 4;
-       }
-       if (count > 1) {
-               cx18_writew(cx, val2, dst);
-               count -= 2;
-               dst += 2;
-       }
-       if (count > 0)
-               cx18_writeb(cx, (u8) val, dst);
-}
-
-void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
-{
-       cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val);
-       cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | val;
-       cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
-}
-
-void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
-{
-       cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) & ~val;
-       cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
-}
-
-void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
-{
-       cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val);
-       cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | val;
-       cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
-}
-
-void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
-{
-       cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) & ~val;
-       cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
-}
-
-void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val)
-{
-       u32 r;
-       r = cx18_read_reg(cx, SW2_INT_ENABLE_CPU);
-       cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_CPU);
-}
-
-void cx18_setup_page(struct cx18 *cx, u32 addr)
-{
-       u32 val;
-       val = cx18_read_reg(cx, 0xD000F8);
-       val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
-       cx18_write_reg(cx, val, 0xD000F8);
-}
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
deleted file mode 100644 (file)
index 18974d8..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- *  cx18 driver PCI memory mapped IO access routines
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#ifndef CX18_IO_H
-#define CX18_IO_H
-
-#include "cx18-driver.h"
-
-/*
- * Readback and retry of MMIO access for reliability:
- * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
- * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
- *
- * *write* functions are implied to retry the mmio unless suffixed with _noretry
- * *read* functions never retry the mmio (it never helps to do so)
- */
-
-/* Non byteswapping memory mapped IO */
-static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
-{
-       return __raw_readl(addr);
-}
-
-static inline
-void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
-{
-       __raw_writel(val, addr);
-}
-
-static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
-               cx18_raw_writel_noretry(cx, val, addr);
-               if (val == cx18_raw_readl(cx, addr))
-                       break;
-       }
-}
-
-/* Normal memory mapped IO */
-static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
-{
-       return readl(addr);
-}
-
-static inline
-void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
-{
-       writel(val, addr);
-}
-
-static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
-               cx18_writel_noretry(cx, val, addr);
-               if (val == cx18_readl(cx, addr))
-                       break;
-       }
-}
-
-static inline
-void cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
-                       u32 eval, u32 mask)
-{
-       int i;
-       u32 r;
-       eval &= mask;
-       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
-               cx18_writel_noretry(cx, val, addr);
-               r = cx18_readl(cx, addr);
-               if (r == 0xffffffff && eval != 0xffffffff)
-                       continue;
-               if (eval == (r & mask))
-                       break;
-       }
-}
-
-static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr)
-{
-       return readw(addr);
-}
-
-static inline
-void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
-{
-       writew(val, addr);
-}
-
-static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
-               cx18_writew_noretry(cx, val, addr);
-               if (val == cx18_readw(cx, addr))
-                       break;
-       }
-}
-
-static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr)
-{
-       return readb(addr);
-}
-
-static inline
-void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr)
-{
-       writeb(val, addr);
-}
-
-static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr)
-{
-       int i;
-       for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
-               cx18_writeb_noretry(cx, val, addr);
-               if (val == cx18_readb(cx, addr))
-                       break;
-       }
-}
-
-static inline
-void cx18_memcpy_fromio(struct cx18 *cx, void *to,
-                       const void __iomem *from, unsigned int len)
-{
-       memcpy_fromio(to, from, len);
-}
-
-void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
-
-
-/* Access "register" region of CX23418 memory mapped I/O */
-static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg)
-{
-       cx18_writel_noretry(cx, val, cx->reg_mem + reg);
-}
-
-static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
-{
-       cx18_writel(cx, val, cx->reg_mem + reg);
-}
-
-static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
-                                        u32 eval, u32 mask)
-{
-       cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask);
-}
-
-static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg)
-{
-       return cx18_readl(cx, cx->reg_mem + reg);
-}
-
-
-/* Access "encoder memory" region of CX23418 memory mapped I/O */
-static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
-{
-       cx18_writel(cx, val, cx->enc_mem + addr);
-}
-
-static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr)
-{
-       return cx18_readl(cx, cx->enc_mem + addr);
-}
-
-void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
-void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
-void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
-void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
-void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val);
-void cx18_setup_page(struct cx18 *cx, u32 addr);
-
-#endif /* CX18_IO_H */
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
deleted file mode 100644 (file)
index e9912db..0000000
+++ /dev/null
@@ -1,1194 +0,0 @@
-/*
- *  cx18 ioctl system call
- *
- *  Derived from ivtv-ioctl.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-version.h"
-#include "cx18-mailbox.h"
-#include "cx18-i2c.h"
-#include "cx18-queue.h"
-#include "cx18-fileops.h"
-#include "cx18-vbi.h"
-#include "cx18-audio.h"
-#include "cx18-video.h"
-#include "cx18-streams.h"
-#include "cx18-ioctl.h"
-#include "cx18-gpio.h"
-#include "cx18-controls.h"
-#include "cx18-cards.h"
-#include "cx18-av-core.h"
-#include <media/tveeprom.h>
-#include <media/v4l2-chip-ident.h>
-
-u16 cx18_service2vbi(int type)
-{
-       switch (type) {
-       case V4L2_SLICED_TELETEXT_B:
-               return CX18_SLICED_TYPE_TELETEXT_B;
-       case V4L2_SLICED_CAPTION_525:
-               return CX18_SLICED_TYPE_CAPTION_525;
-       case V4L2_SLICED_WSS_625:
-               return CX18_SLICED_TYPE_WSS_625;
-       case V4L2_SLICED_VPS:
-               return CX18_SLICED_TYPE_VPS;
-       default:
-               return 0;
-       }
-}
-
-/* Check if VBI services are allowed on the (field, line) for the video std */
-static int valid_service_line(int field, int line, int is_pal)
-{
-       return (is_pal && line >= 6 &&
-               ((field == 0 && line <= 23) || (field == 1 && line <= 22))) ||
-              (!is_pal && line >= 10 && line < 22);
-}
-
-/*
- * For a (field, line, std) and inbound potential set of services for that line,
- * return the first valid service of those passed in the incoming set for that
- * line in priority order:
- * CC, VPS, or WSS over TELETEXT for well known lines
- * TELETEXT, before VPS, before CC, before WSS, for other lines
- */
-static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
-{
-       u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
-       int i;
-
-       set = set & valid_set;
-       if (set == 0 || !valid_service_line(field, line, is_pal))
-               return 0;
-       if (!is_pal) {
-               if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
-                       return V4L2_SLICED_CAPTION_525;
-       } else {
-               if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
-                       return V4L2_SLICED_VPS;
-               if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
-                       return V4L2_SLICED_WSS_625;
-               if (line == 23)
-                       return 0;
-       }
-       for (i = 0; i < 32; i++) {
-               if ((1 << i) & set)
-                       return 1 << i;
-       }
-       return 0;
-}
-
-/*
- * Expand the service_set of *fmt into valid service_lines for the std,
- * and clear the passed in fmt->service_set
- */
-void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
-{
-       u16 set = fmt->service_set;
-       int f, l;
-
-       fmt->service_set = 0;
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++)
-                       fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
-       }
-}
-
-/*
- * Sanitize the service_lines in *fmt per the video std, and return 1
- * if any service_line is left as valid after santization
- */
-static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
-{
-       int f, l;
-       u16 set = 0;
-
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++) {
-                       fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
-                       set |= fmt->service_lines[f][l];
-               }
-       }
-       return set != 0;
-}
-
-/* Compute the service_set from the assumed valid service_lines of *fmt */
-u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt)
-{
-       int f, l;
-       u16 set = 0;
-
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++)
-                       set |= fmt->service_lines[f][l];
-       }
-       return set;
-}
-
-static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
-
-       pixfmt->width = cx->cxhdl.width;
-       pixfmt->height = cx->cxhdl.height;
-       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
-       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
-               pixfmt->pixelformat = s->pixelformat;
-               pixfmt->sizeimage = s->vb_bytes_per_frame;
-               pixfmt->bytesperline = 720;
-       } else {
-               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
-               pixfmt->sizeimage = 128 * 1024;
-               pixfmt->bytesperline = 0;
-       }
-       return 0;
-}
-
-static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
-
-       vbifmt->sampling_rate = 27000000;
-       vbifmt->offset = 248; /* FIXME - slightly wrong for both 50 & 60 Hz */
-       vbifmt->samples_per_line = vbi_active_samples - 4;
-       vbifmt->sample_format = V4L2_PIX_FMT_GREY;
-       vbifmt->start[0] = cx->vbi.start[0];
-       vbifmt->start[1] = cx->vbi.start[1];
-       vbifmt->count[0] = vbifmt->count[1] = cx->vbi.count;
-       vbifmt->flags = 0;
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       return 0;
-}
-
-static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
-                                       struct v4l2_format *fmt)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-
-       /* sane, V4L2 spec compliant, defaults */
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
-       memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
-       vbifmt->service_set = 0;
-
-       /*
-        * Fetch the configured service_lines and total service_set from the
-        * digitizer/slicer.  Note, cx18_av_vbi() wipes the passed in
-        * fmt->fmt.sliced under valid calling conditions
-        */
-       if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced))
-               return -EINVAL;
-
-       /* Ensure V4L2 spec compliant output */
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
-       vbifmt->service_set = cx18_get_service_set(vbifmt);
-       return 0;
-}
-
-static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       int w = fmt->fmt.pix.width;
-       int h = fmt->fmt.pix.height;
-       int min_h = 2;
-
-       w = min(w, 720);
-       w = max(w, 2);
-       if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
-               /* YUV height must be a multiple of 32 */
-               h &= ~0x1f;
-               min_h = 32;
-       }
-       h = min(h, cx->is_50hz ? 576 : 480);
-       h = max(h, min_h);
-
-       fmt->fmt.pix.width = w;
-       fmt->fmt.pix.height = h;
-       return 0;
-}
-
-static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       return cx18_g_fmt_vbi_cap(file, fh, fmt);
-}
-
-static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
-                                       struct v4l2_format *fmt)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-
-       /* If given a service set, expand it validly & clear passed in set */
-       if (vbifmt->service_set)
-               cx18_expand_service_set(vbifmt, cx->is_50hz);
-       /* Sanitize the service_lines, and compute the new set if any valid */
-       if (check_service_set(vbifmt, cx->is_50hz))
-               vbifmt->service_set = cx18_get_service_set(vbifmt);
-       return 0;
-}
-
-static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       struct cx18_stream *s = &cx->streams[id->type];
-       int ret;
-       int w, h;
-
-       ret = cx18_try_fmt_vid_cap(file, fh, fmt);
-       if (ret)
-               return ret;
-       w = fmt->fmt.pix.width;
-       h = fmt->fmt.pix.height;
-
-       if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
-           s->pixelformat == fmt->fmt.pix.pixelformat)
-               return 0;
-
-       if (atomic_read(&cx->ana_capturing) > 0)
-               return -EBUSY;
-
-       s->pixelformat = fmt->fmt.pix.pixelformat;
-       /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-          UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-       if (s->pixelformat == V4L2_PIX_FMT_HM12)
-               s->vb_bytes_per_frame = h * 720 * 3 / 2;
-       else
-               s->vb_bytes_per_frame = h * 720 * 2;
-
-       mbus_fmt.width = cx->cxhdl.width = w;
-       mbus_fmt.height = cx->cxhdl.height = h;
-       mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
-       v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
-       return cx18_g_fmt_vid_cap(file, fh, fmt);
-}
-
-static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
-                               struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       int ret;
-
-       /*
-        * Changing the Encoder's Raw VBI parameters won't have any effect
-        * if any analog capture is ongoing
-        */
-       if (!cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
-               return -EBUSY;
-
-       /*
-        * Set the digitizer registers for raw active VBI.
-        * Note cx18_av_vbi_wipes out a lot of the passed in fmt under valid
-        * calling conditions
-        */
-       ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi);
-       if (ret)
-               return ret;
-
-       /* Store our new v4l2 (non-)sliced VBI state */
-       cx->vbi.sliced_in->service_set = 0;
-       cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
-
-       return cx18_g_fmt_vbi_cap(file, fh, fmt);
-}
-
-static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
-                                       struct v4l2_format *fmt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       int ret;
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-
-       cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
-
-       /*
-        * Changing the Encoder's Raw VBI parameters won't have any effect
-        * if any analog capture is ongoing
-        */
-       if (cx18_raw_vbi(cx) && atomic_read(&cx->ana_capturing) > 0)
-               return -EBUSY;
-
-       /*
-        * Set the service_lines requested in the digitizer/slicer registers.
-        * Note, cx18_av_vbi() wipes some "impossible" service lines in the
-        * passed in fmt->fmt.sliced under valid calling conditions
-        */
-       ret = v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &fmt->fmt.sliced);
-       if (ret)
-               return ret;
-       /* Store our current v4l2 sliced VBI settings */
-       cx->vbi.in.type =  V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
-       memcpy(cx->vbi.sliced_in, vbifmt, sizeof(*cx->vbi.sliced_in));
-       return 0;
-}
-
-static int cx18_g_chip_ident(struct file *file, void *fh,
-                               struct v4l2_dbg_chip_ident *chip)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       int err = 0;
-
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-       switch (chip->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               switch (chip->match.addr) {
-               case 0:
-                       chip->ident = V4L2_IDENT_CX23418;
-                       chip->revision = cx18_read_reg(cx, 0xC72028);
-                       break;
-               case 1:
-                       /*
-                        * The A/V decoder is always present, but in the rare
-                        * case that the card doesn't have analog, we don't
-                        * use it.  We find it w/o using the cx->sd_av pointer
-                        */
-                       cx18_call_hw(cx, CX18_HW_418_AV,
-                                    core, g_chip_ident, chip);
-                       break;
-               default:
-                       /*
-                        * Could return ident = V4L2_IDENT_UNKNOWN if we had
-                        * other host chips at higher addresses, but we don't
-                        */
-                       err = -EINVAL; /* per V4L2 spec */
-                       break;
-               }
-               break;
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
-               cx18_call_all(cx, core, g_chip_ident, chip);
-               break;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               /*
-                * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
-                * to look if a chip is at the address with no driver.  That's a
-                * dangerous thing to do with EEPROMs anyway.
-                */
-               cx18_call_all(cx, core, g_chip_ident, chip);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-       return err;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx18_cxc(struct cx18 *cx, unsigned int cmd, void *arg)
-{
-       struct v4l2_dbg_register *regs = arg;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
-               return -EINVAL;
-
-       regs->size = 4;
-       if (cmd == VIDIOC_DBG_S_REGISTER)
-               cx18_write_enc(cx, regs->val, regs->reg);
-       else
-               regs->val = cx18_read_enc(cx, regs->reg);
-       return 0;
-}
-
-static int cx18_g_register(struct file *file, void *fh,
-                               struct v4l2_dbg_register *reg)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (v4l2_chip_match_host(&reg->match))
-               return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
-       /* FIXME - errors shouldn't be ignored */
-       cx18_call_all(cx, core, g_register, reg);
-       return 0;
-}
-
-static int cx18_s_register(struct file *file, void *fh,
-                               struct v4l2_dbg_register *reg)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (v4l2_chip_match_host(&reg->match))
-               return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
-       /* FIXME - errors shouldn't be ignored */
-       cx18_call_all(cx, core, s_register, reg);
-       return 0;
-}
-#endif
-
-static int cx18_querycap(struct file *file, void *fh,
-                               struct v4l2_capability *vcap)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
-       strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
-       snprintf(vcap->bus_info, sizeof(vcap->bus_info),
-                "PCI:%s", pci_name(cx->pci_dev));
-       vcap->capabilities = cx->v4l2_cap;          /* capabilities */
-       if (id->type == CX18_ENC_STREAM_TYPE_YUV)
-               vcap->capabilities |= V4L2_CAP_STREAMING;
-       return 0;
-}
-
-static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       return cx18_get_audio_input(cx, vin->index, vin);
-}
-
-static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       vin->index = cx->audio_input;
-       return cx18_get_audio_input(cx, vin->index, vin);
-}
-
-static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (vout->index >= cx->nof_audio_inputs)
-               return -EINVAL;
-       cx->audio_input = vout->index;
-       cx18_audio_set_io(cx);
-       return 0;
-}
-
-static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       /* set it to defaults from our table */
-       return cx18_get_input(cx, vin->index, vin);
-}
-
-static int cx18_cropcap(struct file *file, void *fh,
-                       struct v4l2_cropcap *cropcap)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       cropcap->bounds.top = cropcap->bounds.left = 0;
-       cropcap->bounds.width = 720;
-       cropcap->bounds.height = cx->is_50hz ? 576 : 480;
-       cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
-       cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
-       cropcap->defrect = cropcap->bounds;
-       return 0;
-}
-
-static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       CX18_DEBUG_WARN("VIDIOC_S_CROP not implemented\n");
-       return -EINVAL;
-}
-
-static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
-       return -EINVAL;
-}
-
-static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
-                                       struct v4l2_fmtdesc *fmt)
-{
-       static const struct v4l2_fmtdesc formats[] = {
-               { 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
-                 "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
-               },
-               { 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
-                 "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
-               },
-               { 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
-                 "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 }
-               },
-       };
-
-       if (fmt->index > ARRAY_SIZE(formats) - 1)
-               return -EINVAL;
-       *fmt = formats[fmt->index];
-       return 0;
-}
-
-static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       *i = cx->active_input;
-       return 0;
-}
-
-int cx18_s_input(struct file *file, void *fh, unsigned int inp)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       if (inp >= cx->nof_inputs)
-               return -EINVAL;
-
-       if (inp == cx->active_input) {
-               CX18_DEBUG_INFO("Input unchanged\n");
-               return 0;
-       }
-
-       CX18_DEBUG_INFO("Changing input from %d to %d\n",
-                       cx->active_input, inp);
-
-       cx->active_input = inp;
-       /* Set the audio input to whatever is appropriate for the input type. */
-       cx->audio_input = cx->card->video_inputs[inp].audio_index;
-
-       /* prevent others from messing with the streams until
-          we're finished changing inputs. */
-       cx18_mute(cx);
-       cx18_video_set_io(cx);
-       cx18_audio_set_io(cx);
-       cx18_unmute(cx);
-       return 0;
-}
-
-static int cx18_g_frequency(struct file *file, void *fh,
-                               struct v4l2_frequency *vf)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (vf->tuner != 0)
-               return -EINVAL;
-
-       cx18_call_all(cx, tuner, g_frequency, vf);
-       return 0;
-}
-
-int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       if (vf->tuner != 0)
-               return -EINVAL;
-
-       cx18_mute(cx);
-       CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
-       cx18_call_all(cx, tuner, s_frequency, vf);
-       cx18_unmute(cx);
-       return 0;
-}
-
-static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       *std = cx->std;
-       return 0;
-}
-
-int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       if ((*std & V4L2_STD_ALL) == 0)
-               return -EINVAL;
-
-       if (*std == cx->std)
-               return 0;
-
-       if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
-           atomic_read(&cx->ana_capturing) > 0) {
-               /* Switching standard would turn off the radio or mess
-                  with already running streams, prevent that by
-                  returning EBUSY. */
-               return -EBUSY;
-       }
-
-       cx->std = *std;
-       cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
-       cx->is_50hz = !cx->is_60hz;
-       cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
-       cx->cxhdl.width = 720;
-       cx->cxhdl.height = cx->is_50hz ? 576 : 480;
-       cx->vbi.count = cx->is_50hz ? 18 : 12;
-       cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
-       cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
-       CX18_DEBUG_INFO("Switching standard to %llx.\n",
-                       (unsigned long long) cx->std);
-
-       /* Tuner */
-       cx18_call_all(cx, core, s_std, cx->std);
-       return 0;
-}
-
-static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-
-       if (vt->index != 0)
-               return -EINVAL;
-
-       cx18_call_all(cx, tuner, s_tuner, vt);
-       return 0;
-}
-
-static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       if (vt->index != 0)
-               return -EINVAL;
-
-       cx18_call_all(cx, tuner, g_tuner, vt);
-
-       if (vt->type == V4L2_TUNER_RADIO)
-               strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
-       else
-               strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
-       return 0;
-}
-
-static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
-                                       struct v4l2_sliced_vbi_cap *cap)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
-       int f, l;
-
-       if (cap->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
-               return -EINVAL;
-
-       cap->service_set = 0;
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++) {
-                       if (valid_service_line(f, l, cx->is_50hz)) {
-                               /*
-                                * We can find all v4l2 supported vbi services
-                                * for the standard, on a valid line for the std
-                                */
-                               cap->service_lines[f][l] = set;
-                               cap->service_set |= set;
-                       } else
-                               cap->service_lines[f][l] = 0;
-               }
-       }
-       for (f = 0; f < 3; f++)
-               cap->reserved[f] = 0;
-       return 0;
-}
-
-static int _cx18_process_idx_data(struct cx18_buffer *buf,
-                                 struct v4l2_enc_idx *idx)
-{
-       int consumed, remaining;
-       struct v4l2_enc_idx_entry *e_idx;
-       struct cx18_enc_idx_entry *e_buf;
-
-       /* Frame type lookup: 1=I, 2=P, 4=B */
-       const int mapping[8] = {
-               -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P,
-               -1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1
-       };
-
-       /*
-        * Assumption here is that a buf holds an integral number of
-        * struct cx18_enc_idx_entry objects and is properly aligned.
-        * This is enforced by the module options on IDX buffer sizes.
-        */
-       remaining = buf->bytesused - buf->readpos;
-       consumed = 0;
-       e_idx = &idx->entry[idx->entries];
-       e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos];
-
-       while (remaining >= sizeof(struct cx18_enc_idx_entry) &&
-              idx->entries < V4L2_ENC_IDX_ENTRIES) {
-
-               e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32)
-                               | le32_to_cpu(e_buf->offset_low);
-
-               e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32)
-                            | le32_to_cpu(e_buf->pts_low);
-
-               e_idx->length = le32_to_cpu(e_buf->length);
-
-               e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7];
-
-               e_idx->reserved[0] = 0;
-               e_idx->reserved[1] = 0;
-
-               idx->entries++;
-               e_idx = &idx->entry[idx->entries];
-               e_buf++;
-
-               remaining -= sizeof(struct cx18_enc_idx_entry);
-               consumed += sizeof(struct cx18_enc_idx_entry);
-       }
-
-       /* Swallow any partial entries at the end, if there are any */
-       if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry))
-               consumed += remaining;
-
-       buf->readpos += consumed;
-       return consumed;
-}
-
-static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl,
-                                struct v4l2_enc_idx *idx)
-{
-       if (s->type != CX18_ENC_STREAM_TYPE_IDX)
-               return -EINVAL;
-
-       if (mdl->curr_buf == NULL)
-               mdl->curr_buf = list_first_entry(&mdl->buf_list,
-                                                struct cx18_buffer, list);
-
-       if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
-               /*
-                * For some reason we've exhausted the buffers, but the MDL
-                * object still said some data was unread.
-                * Fix that and bail out.
-                */
-               mdl->readpos = mdl->bytesused;
-               return 0;
-       }
-
-       list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
-
-               /* Skip any empty buffers in the MDL */
-               if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
-                       continue;
-
-               mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx);
-
-               /* exit when MDL drained or request satisfied */
-               if (idx->entries >= V4L2_ENC_IDX_ENTRIES ||
-                   mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
-                   mdl->readpos >= mdl->bytesused)
-                       break;
-       }
-       return 0;
-}
-
-static int cx18_g_enc_index(struct file *file, void *fh,
-                               struct v4l2_enc_idx *idx)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-       s32 tmp;
-       struct cx18_mdl *mdl;
-
-       if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */
-               return -EINVAL;
-
-       /* Compute the best case number of entries we can buffer */
-       tmp = s->buffers -
-                         s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN;
-       if (tmp <= 0)
-               tmp = 1;
-       tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry);
-
-       /* Fill out the header of the return structure */
-       idx->entries = 0;
-       idx->entries_cap = tmp;
-       memset(idx->reserved, 0, sizeof(idx->reserved));
-
-       /* Pull IDX MDLs and buffers from q_full and populate the entries */
-       do {
-               mdl = cx18_dequeue(s, &s->q_full);
-               if (mdl == NULL) /* No more IDX data right now */
-                       break;
-
-               /* Extract the Index entry data from the MDL and buffers */
-               cx18_process_idx_data(s, mdl, idx);
-               if (mdl->readpos < mdl->bytesused) {
-                       /* We finished with data remaining, push the MDL back */
-                       cx18_push(s, mdl, &s->q_full);
-                       break;
-               }
-
-               /* We drained this MDL, schedule it to go to the firmware */
-               cx18_enqueue(s, mdl, &s->q_free);
-
-       } while (idx->entries < V4L2_ENC_IDX_ENTRIES);
-
-       /* Tell the work handler to send free IDX MDLs to the firmware */
-       cx18_stream_load_fw_queue(s);
-       return 0;
-}
-
-static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
-{
-       struct videobuf_queue *q = NULL;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       switch (s->vb_type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               q = &s->vbuf_q;
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               break;
-       default:
-               break;
-       }
-       return q;
-}
-
-static int cx18_streamon(struct file *file, void *priv,
-       enum v4l2_buf_type type)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       /* Start the hardware only if we're the video device */
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       if (id->type != CX18_ENC_STREAM_TYPE_YUV)
-               return -EINVAL;
-
-       /* Establish a buffer timeout */
-       mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
-
-       return videobuf_streamon(cx18_vb_queue(id));
-}
-
-static int cx18_streamoff(struct file *file, void *priv,
-       enum v4l2_buf_type type)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       /* Start the hardware only if we're the video device */
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       if (id->type != CX18_ENC_STREAM_TYPE_YUV)
-               return -EINVAL;
-
-       return videobuf_streamoff(cx18_vb_queue(id));
-}
-
-static int cx18_reqbufs(struct file *file, void *priv,
-       struct v4l2_requestbuffers *rb)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_reqbufs(cx18_vb_queue(id), rb);
-}
-
-static int cx18_querybuf(struct file *file, void *priv,
-       struct v4l2_buffer *b)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_querybuf(cx18_vb_queue(id), b);
-}
-
-static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_qbuf(cx18_vb_queue(id), b);
-}
-
-static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx18_open_id *id = file->private_data;
-       struct cx18 *cx = id->cx;
-       struct cx18_stream *s = &cx->streams[id->type];
-
-       if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
-}
-
-static int cx18_encoder_cmd(struct file *file, void *fh,
-                               struct v4l2_encoder_cmd *enc)
-{
-       struct cx18_open_id *id = fh2id(fh);
-       struct cx18 *cx = id->cx;
-       u32 h;
-
-       switch (enc->cmd) {
-       case V4L2_ENC_CMD_START:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
-               enc->flags = 0;
-               return cx18_start_capture(id);
-
-       case V4L2_ENC_CMD_STOP:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
-               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
-               cx18_stop_capture(id,
-                                 enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
-               break;
-
-       case V4L2_ENC_CMD_PAUSE:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
-               enc->flags = 0;
-               if (!atomic_read(&cx->ana_capturing))
-                       return -EPERM;
-               if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
-                       return 0;
-               h = cx18_find_handle(cx);
-               if (h == CX18_INVALID_TASK_HANDLE) {
-                       CX18_ERR("Can't find valid task handle for "
-                                "V4L2_ENC_CMD_PAUSE\n");
-                       return -EBADFD;
-               }
-               cx18_mute(cx);
-               cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
-               break;
-
-       case V4L2_ENC_CMD_RESUME:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
-               enc->flags = 0;
-               if (!atomic_read(&cx->ana_capturing))
-                       return -EPERM;
-               if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
-                       return 0;
-               h = cx18_find_handle(cx);
-               if (h == CX18_INVALID_TASK_HANDLE) {
-                       CX18_ERR("Can't find valid task handle for "
-                                "V4L2_ENC_CMD_RESUME\n");
-                       return -EBADFD;
-               }
-               cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
-               cx18_unmute(cx);
-               break;
-
-       default:
-               CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int cx18_try_encoder_cmd(struct file *file, void *fh,
-                               struct v4l2_encoder_cmd *enc)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       switch (enc->cmd) {
-       case V4L2_ENC_CMD_START:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
-               enc->flags = 0;
-               break;
-
-       case V4L2_ENC_CMD_STOP:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
-               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
-               break;
-
-       case V4L2_ENC_CMD_PAUSE:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
-               enc->flags = 0;
-               break;
-
-       case V4L2_ENC_CMD_RESUME:
-               CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
-               enc->flags = 0;
-               break;
-
-       default:
-               CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int cx18_log_status(struct file *file, void *fh)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-       struct v4l2_input vidin;
-       struct v4l2_audio audin;
-       int i;
-
-       CX18_INFO("Version: %s  Card: %s\n", CX18_VERSION, cx->card_name);
-       if (cx->hw_flags & CX18_HW_TVEEPROM) {
-               struct tveeprom tv;
-
-               cx18_read_eeprom(cx, &tv);
-       }
-       cx18_call_all(cx, core, log_status);
-       cx18_get_input(cx, cx->active_input, &vidin);
-       cx18_get_audio_input(cx, cx->audio_input, &audin);
-       CX18_INFO("Video Input: %s\n", vidin.name);
-       CX18_INFO("Audio Input: %s\n", audin.name);
-       mutex_lock(&cx->gpio_lock);
-       CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
-               cx->gpio_dir, cx->gpio_val);
-       mutex_unlock(&cx->gpio_lock);
-       CX18_INFO("Tuner: %s\n",
-               test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
-       v4l2_ctrl_handler_log_status(&cx->cxhdl.hdl, cx->v4l2_dev.name);
-       CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
-       for (i = 0; i < CX18_MAX_STREAMS; i++) {
-               struct cx18_stream *s = &cx->streams[i];
-
-               if (s->video_dev == NULL || s->buffers == 0)
-                       continue;
-               CX18_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n",
-                         s->name, s->s_flags,
-                         atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
-                          / s->buffers,
-                         (s->buffers * s->buf_size) / 1024, s->buffers);
-       }
-       CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
-                       (long long)cx->mpg_data_received,
-                       (long long)cx->vbi_data_inserted);
-       return 0;
-}
-
-static long cx18_default(struct file *file, void *fh, bool valid_prio,
-                                                       int cmd, void *arg)
-{
-       struct cx18 *cx = fh2id(fh)->cx;
-
-       switch (cmd) {
-       case VIDIOC_INT_RESET: {
-               u32 val = *(u32 *)arg;
-
-               if ((val == 0) || (val & 0x01))
-                       cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
-                                    (u32) CX18_GPIO_RESET_Z8F0811);
-               break;
-       }
-
-       default:
-               return -ENOTTY;
-       }
-       return 0;
-}
-
-static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
-       .vidioc_querycap                = cx18_querycap,
-       .vidioc_s_audio                 = cx18_s_audio,
-       .vidioc_g_audio                 = cx18_g_audio,
-       .vidioc_enumaudio               = cx18_enumaudio,
-       .vidioc_enum_input              = cx18_enum_input,
-       .vidioc_cropcap                 = cx18_cropcap,
-       .vidioc_s_crop                  = cx18_s_crop,
-       .vidioc_g_crop                  = cx18_g_crop,
-       .vidioc_g_input                 = cx18_g_input,
-       .vidioc_s_input                 = cx18_s_input,
-       .vidioc_g_frequency             = cx18_g_frequency,
-       .vidioc_s_frequency             = cx18_s_frequency,
-       .vidioc_s_tuner                 = cx18_s_tuner,
-       .vidioc_g_tuner                 = cx18_g_tuner,
-       .vidioc_g_enc_index             = cx18_g_enc_index,
-       .vidioc_g_std                   = cx18_g_std,
-       .vidioc_s_std                   = cx18_s_std,
-       .vidioc_log_status              = cx18_log_status,
-       .vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap,
-       .vidioc_encoder_cmd             = cx18_encoder_cmd,
-       .vidioc_try_encoder_cmd         = cx18_try_encoder_cmd,
-       .vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap,
-       .vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap,
-       .vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap,
-       .vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap,
-       .vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap,
-       .vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap,
-       .vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap,
-       .vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap,
-       .vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap,
-       .vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap,
-       .vidioc_g_chip_ident            = cx18_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register              = cx18_g_register,
-       .vidioc_s_register              = cx18_s_register,
-#endif
-       .vidioc_default                 = cx18_default,
-       .vidioc_streamon                = cx18_streamon,
-       .vidioc_streamoff               = cx18_streamoff,
-       .vidioc_reqbufs                 = cx18_reqbufs,
-       .vidioc_querybuf                = cx18_querybuf,
-       .vidioc_qbuf                    = cx18_qbuf,
-       .vidioc_dqbuf                   = cx18_dqbuf,
-};
-
-void cx18_set_funcs(struct video_device *vdev)
-{
-       vdev->ioctl_ops = &cx18_ioctl_ops;
-}
diff --git a/drivers/media/video/cx18/cx18-ioctl.h b/drivers/media/video/cx18/cx18-ioctl.h
deleted file mode 100644 (file)
index 2f9dd59..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  cx18 ioctl system call
- *
- *  Derived from ivtv-ioctl.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-u16 cx18_service2vbi(int type);
-void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
-u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
-void cx18_set_funcs(struct video_device *vdev);
-int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
-int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
-int cx18_s_input(struct file *file, void *fh, unsigned int inp);
diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c
deleted file mode 100644 (file)
index 80edfe9..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  cx18 interrupt handling
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-irq.h"
-#include "cx18-mailbox.h"
-#include "cx18-scb.h"
-
-static void xpu_ack(struct cx18 *cx, u32 sw2)
-{
-       if (sw2 & IRQ_CPU_TO_EPU_ACK)
-               wake_up(&cx->mb_cpu_waitq);
-       if (sw2 & IRQ_APU_TO_EPU_ACK)
-               wake_up(&cx->mb_apu_waitq);
-}
-
-static void epu_cmd(struct cx18 *cx, u32 sw1)
-{
-       if (sw1 & IRQ_CPU_TO_EPU)
-               cx18_api_epu_cmd_irq(cx, CPU);
-       if (sw1 & IRQ_APU_TO_EPU)
-               cx18_api_epu_cmd_irq(cx, APU);
-}
-
-irqreturn_t cx18_irq_handler(int irq, void *dev_id)
-{
-       struct cx18 *cx = (struct cx18 *)dev_id;
-       u32 sw1, sw2, hw2;
-
-       sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;
-       sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask;
-       hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask;
-
-       if (sw1)
-               cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
-       if (sw2)
-               cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
-       if (hw2)
-               cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
-
-       if (sw1 || sw2 || hw2)
-               CX18_DEBUG_HI_IRQ("received interrupts "
-                                 "SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
-
-       /*
-        * SW1 responses have to happen first.  The sending XPU times out the
-        * incoming mailboxes on us rather rapidly.
-        */
-       if (sw1)
-               epu_cmd(cx, sw1);
-
-       /* To do: interrupt-based I2C handling
-       if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
-       }
-       */
-
-       if (sw2)
-               xpu_ack(cx, sw2);
-
-       return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
-}
diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h
deleted file mode 100644 (file)
index 30e7eaf..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  cx18 interrupt handling
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#define HW2_I2C1_INT                   (1 << 22)
-#define HW2_I2C2_INT                   (1 << 23)
-#define HW2_INT_CLR_STATUS             0xc730c4
-#define HW2_INT_MASK5_PCI              0xc730e4
-#define SW1_INT_SET                     0xc73100
-#define SW1_INT_STATUS                  0xc73104
-#define SW1_INT_ENABLE_PCI              0xc7311c
-#define SW2_INT_SET                     0xc73140
-#define SW2_INT_STATUS                  0xc73144
-#define SW2_INT_ENABLE_CPU              0xc73158
-#define SW2_INT_ENABLE_PCI              0xc7315c
-
-irqreturn_t cx18_irq_handler(int irq, void *dev_id);
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
deleted file mode 100644 (file)
index eabf00c..0000000
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- *  cx18 mailbox functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include <stdarg.h>
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-scb.h"
-#include "cx18-irq.h"
-#include "cx18-mailbox.h"
-#include "cx18-queue.h"
-#include "cx18-streams.h"
-#include "cx18-alsa-pcm.h" /* FIXME make configurable */
-
-static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" };
-
-#define API_FAST (1 << 2) /* Short timeout */
-#define API_SLOW (1 << 3) /* Additional 300ms timeout */
-
-struct cx18_api_info {
-       u32 cmd;
-       u8 flags;               /* Flags, see above */
-       u8 rpu;                 /* Processing unit */
-       const char *name;       /* The name of the command */
-};
-
-#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
-
-static const struct cx18_api_info api_info[] = {
-       /* MPEG encoder API */
-       API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
-       API_ENTRY(CPU, CX18_EPU_DEBUG,                          0),
-       API_ENTRY(CPU, CX18_CREATE_TASK,                        0),
-       API_ENTRY(CPU, CX18_DESTROY_TASK,                       0),
-       API_ENTRY(CPU, CX18_CPU_CAPTURE_START,                  API_SLOW),
-       API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP,                   API_SLOW),
-       API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE,                  0),
-       API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME,                 0),
-       API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
-       API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE,         0),
-       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN,                   0),
-       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE,                 0),
-       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION,           0),
-       API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM,               0),
-       API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE,        0),
-       API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING,              0),
-       API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE,                 0),
-       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS,           0),
-       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE,                 0),
-       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE,                 0),
-       API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS,            0),
-       API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM,              API_SLOW),
-       API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO,            0),
-       API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT,                  0),
-       API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID,                  0),
-       API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID,                  0),
-       API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE,              0),
-       API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE,              0),
-       API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION,     0),
-       API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO,               0),
-       API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME,           0),
-       API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM,           0),
-       API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER,      0),
-       API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS,                    0),
-       API_ENTRY(CPU, CX18_CPU_SET_VFC_PARAM,                  0),
-       API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK,                 0),
-       API_ENTRY(CPU, CX18_CPU_DE_SET_MDL,                     API_FAST),
-       API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL,                 API_SLOW),
-       API_ENTRY(APU, CX18_APU_START,                          0),
-       API_ENTRY(APU, CX18_APU_STOP,                           0),
-       API_ENTRY(APU, CX18_APU_RESETAI,                        0),
-       API_ENTRY(CPU, CX18_CPU_DEBUG_PEEK32,                   0),
-       API_ENTRY(0, 0,                                         0),
-};
-
-static const struct cx18_api_info *find_api_info(u32 cmd)
-{
-       int i;
-
-       for (i = 0; api_info[i].cmd; i++)
-               if (api_info[i].cmd == cmd)
-                       return &api_info[i];
-       return NULL;
-}
-
-/* Call with buf of n*11+1 bytes */
-static char *u32arr2hex(u32 data[], int n, char *buf)
-{
-       char *p;
-       int i;
-
-       for (i = 0, p = buf; i < n; i++, p += 11) {
-               /* kernel snprintf() appends '\0' always */
-               snprintf(p, 12, " %#010x", data[i]);
-       }
-       *p = '\0';
-       return buf;
-}
-
-static void dump_mb(struct cx18 *cx, struct cx18_mailbox *mb, char *name)
-{
-       char argstr[MAX_MB_ARGUMENTS*11+1];
-
-       if (!(cx18_debug & CX18_DBGFLG_API))
-               return;
-
-       CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s"
-                      "\n", name, mb->request, mb->ack, mb->cmd, mb->error,
-                      u32arr2hex(mb->args, MAX_MB_ARGUMENTS, argstr));
-}
-
-
-/*
- * Functions that run in a work_queue work handling context
- */
-
-static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
-{
-       struct cx18_buffer *buf;
-
-       if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0)
-               return;
-
-       /* We ignore mdl and buf readpos accounting here - it doesn't matter */
-
-       /* The likely case */
-       if (list_is_singular(&mdl->buf_list)) {
-               buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
-                                      list);
-               if (buf->bytesused)
-                       dvb_dmx_swfilter(&s->dvb->demux,
-                                        buf->buf, buf->bytesused);
-               return;
-       }
-
-       list_for_each_entry(buf, &mdl->buf_list, list) {
-               if (buf->bytesused == 0)
-                       break;
-               dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused);
-       }
-}
-
-static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
-       struct cx18_mdl *mdl)
-{
-       struct cx18_videobuf_buffer *vb_buf;
-       struct cx18_buffer *buf;
-       u8 *p;
-       u32 offset = 0;
-       int dispatch = 0;
-
-       if (mdl->bytesused == 0)
-               return;
-
-       /* Acquire a videobuf buffer, clone to and and release it */
-       spin_lock(&s->vb_lock);
-       if (list_empty(&s->vb_capture))
-               goto out;
-
-       vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer,
-               vb.queue);
-
-       p = videobuf_to_vmalloc(&vb_buf->vb);
-       if (!p)
-               goto out;
-
-       offset = vb_buf->bytes_used;
-       list_for_each_entry(buf, &mdl->buf_list, list) {
-               if (buf->bytesused == 0)
-                       break;
-
-               if ((offset + buf->bytesused) <= vb_buf->vb.bsize) {
-                       memcpy(p + offset, buf->buf, buf->bytesused);
-                       offset += buf->bytesused;
-                       vb_buf->bytes_used += buf->bytesused;
-               }
-       }
-
-       /* If we've filled the buffer as per the callers res then dispatch it */
-       if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
-               dispatch = 1;
-               vb_buf->bytes_used = 0;
-       }
-
-       if (dispatch) {
-               vb_buf->vb.ts = ktime_to_timeval(ktime_get());
-               list_del(&vb_buf->vb.queue);
-               vb_buf->vb.state = VIDEOBUF_DONE;
-               wake_up(&vb_buf->vb.done);
-       }
-
-       mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
-
-out:
-       spin_unlock(&s->vb_lock);
-}
-
-static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s,
-                                 struct cx18_mdl *mdl)
-{
-       struct cx18_buffer *buf;
-
-       if (mdl->bytesused == 0)
-               return;
-
-       /* We ignore mdl and buf readpos accounting here - it doesn't matter */
-
-       /* The likely case */
-       if (list_is_singular(&mdl->buf_list)) {
-               buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
-                                      list);
-               if (buf->bytesused)
-                       cx->pcm_announce_callback(cx->alsa, buf->buf,
-                                                 buf->bytesused);
-               return;
-       }
-
-       list_for_each_entry(buf, &mdl->buf_list, list) {
-               if (buf->bytesused == 0)
-                       break;
-               cx->pcm_announce_callback(cx->alsa, buf->buf, buf->bytesused);
-       }
-}
-
-static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       u32 handle, mdl_ack_count, id;
-       struct cx18_mailbox *mb;
-       struct cx18_mdl_ack *mdl_ack;
-       struct cx18_stream *s;
-       struct cx18_mdl *mdl;
-       int i;
-
-       mb = &order->mb;
-       handle = mb->args[0];
-       s = cx18_handle_to_stream(cx, handle);
-
-       if (s == NULL) {
-               CX18_WARN("Got DMA done notification for unknown/inactive"
-                         " handle %d, %s mailbox seq no %d\n", handle,
-                         (order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) ?
-                         "stale" : "good", mb->request);
-               return;
-       }
-
-       mdl_ack_count = mb->args[2];
-       mdl_ack = order->mdl_ack;
-       for (i = 0; i < mdl_ack_count; i++, mdl_ack++) {
-               id = mdl_ack->id;
-               /*
-                * Simple integrity check for processing a stale (and possibly
-                * inconsistent mailbox): make sure the MDL id is in the
-                * valid range for the stream.
-                *
-                * We go through the trouble of dealing with stale mailboxes
-                * because most of the time, the mailbox data is still valid and
-                * unchanged (and in practice the firmware ping-pongs the
-                * two mdl_ack buffers so mdl_acks are not stale).
-                *
-                * There are occasions when we get a half changed mailbox,
-                * which this check catches for a handle & id mismatch.  If the
-                * handle and id do correspond, the worst case is that we
-                * completely lost the old MDL, but pick up the new MDL
-                * early (but the new mdl_ack is guaranteed to be good in this
-                * case as the firmware wouldn't point us to a new mdl_ack until
-                * it's filled in).
-                *
-                * cx18_queue_get_mdl() will detect the lost MDLs
-                * and send them back to q_free for fw rotation eventually.
-                */
-               if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) &&
-                   !(id >= s->mdl_base_idx &&
-                     id < (s->mdl_base_idx + s->buffers))) {
-                       CX18_WARN("Fell behind! Ignoring stale mailbox with "
-                                 " inconsistent data. Lost MDL for mailbox "
-                                 "seq no %d\n", mb->request);
-                       break;
-               }
-               mdl = cx18_queue_get_mdl(s, id, mdl_ack->data_used);
-
-               CX18_DEBUG_HI_DMA("DMA DONE for %s (MDL %d)\n", s->name, id);
-               if (mdl == NULL) {
-                       CX18_WARN("Could not find MDL %d for stream %s\n",
-                                 id, s->name);
-                       continue;
-               }
-
-               CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
-                                 s->name, mdl->bytesused);
-
-               if (s->type == CX18_ENC_STREAM_TYPE_TS) {
-                       cx18_mdl_send_to_dvb(s, mdl);
-                       cx18_enqueue(s, mdl, &s->q_free);
-               } else if (s->type == CX18_ENC_STREAM_TYPE_PCM) {
-                       /* Pass the data to cx18-alsa */
-                       if (cx->pcm_announce_callback != NULL) {
-                               cx18_mdl_send_to_alsa(cx, s, mdl);
-                               cx18_enqueue(s, mdl, &s->q_free);
-                       } else {
-                               cx18_enqueue(s, mdl, &s->q_full);
-                       }
-               } else if (s->type == CX18_ENC_STREAM_TYPE_YUV) {
-                       cx18_mdl_send_to_videobuf(s, mdl);
-                       cx18_enqueue(s, mdl, &s->q_free);
-               } else {
-                       cx18_enqueue(s, mdl, &s->q_full);
-                       if (s->type == CX18_ENC_STREAM_TYPE_IDX)
-                               cx18_stream_rotate_idx_mdls(cx);
-               }
-       }
-       /* Put as many MDLs as possible back into fw use */
-       cx18_stream_load_fw_queue(s);
-
-       wake_up(&cx->dma_waitq);
-       if (s->id != -1)
-               wake_up(&s->waitq);
-}
-
-static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       char *p;
-       char *str = order->str;
-
-       CX18_DEBUG_INFO("%x %s\n", order->mb.args[0], str);
-       p = strchr(str, '.');
-       if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
-               CX18_INFO("FW version: %s\n", p - 1);
-}
-
-static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       switch (order->rpu) {
-       case CPU:
-       {
-               switch (order->mb.cmd) {
-               case CX18_EPU_DMA_DONE:
-                       epu_dma_done(cx, order);
-                       break;
-               case CX18_EPU_DEBUG:
-                       epu_debug(cx, order);
-                       break;
-               default:
-                       CX18_WARN("Unknown CPU to EPU mailbox command %#0x\n",
-                                 order->mb.cmd);
-                       break;
-               }
-               break;
-       }
-       case APU:
-               CX18_WARN("Unknown APU to EPU mailbox command %#0x\n",
-                         order->mb.cmd);
-               break;
-       default:
-               break;
-       }
-}
-
-static
-void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       atomic_set(&order->pending, 0);
-}
-
-void cx18_in_work_handler(struct work_struct *work)
-{
-       struct cx18_in_work_order *order =
-                       container_of(work, struct cx18_in_work_order, work);
-       struct cx18 *cx = order->cx;
-       epu_cmd(cx, order);
-       free_in_work_order(cx, order);
-}
-
-
-/*
- * Functions that run in an interrupt handling context
- */
-
-static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       struct cx18_mailbox __iomem *ack_mb;
-       u32 ack_irq, req;
-
-       switch (order->rpu) {
-       case APU:
-               ack_irq = IRQ_EPU_TO_APU_ACK;
-               ack_mb = &cx->scb->apu2epu_mb;
-               break;
-       case CPU:
-               ack_irq = IRQ_EPU_TO_CPU_ACK;
-               ack_mb = &cx->scb->cpu2epu_mb;
-               break;
-       default:
-               CX18_WARN("Unhandled RPU (%d) for command %x ack\n",
-                         order->rpu, order->mb.cmd);
-               return;
-       }
-
-       req = order->mb.request;
-       /* Don't ack if the RPU has gotten impatient and timed us out */
-       if (req != cx18_readl(cx, &ack_mb->request) ||
-           req == cx18_readl(cx, &ack_mb->ack)) {
-               CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
-                               "incoming %s to EPU mailbox (sequence no. %u) "
-                               "while processing\n",
-                               rpu_str[order->rpu], rpu_str[order->rpu], req);
-               order->flags |= CX18_F_EWO_MB_STALE_WHILE_PROC;
-               return;
-       }
-       cx18_writel(cx, req, &ack_mb->ack);
-       cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq);
-       return;
-}
-
-static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       u32 handle, mdl_ack_offset, mdl_ack_count;
-       struct cx18_mailbox *mb;
-       int i;
-
-       mb = &order->mb;
-       handle = mb->args[0];
-       mdl_ack_offset = mb->args[1];
-       mdl_ack_count = mb->args[2];
-
-       if (handle == CX18_INVALID_TASK_HANDLE ||
-           mdl_ack_count == 0 || mdl_ack_count > CX18_MAX_MDL_ACKS) {
-               if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
-                       mb_ack_irq(cx, order);
-               return -1;
-       }
-
-       for (i = 0; i < sizeof(struct cx18_mdl_ack) * mdl_ack_count; i += sizeof(u32))
-               ((u32 *)order->mdl_ack)[i / sizeof(u32)] =
-                       cx18_readl(cx, cx->enc_mem + mdl_ack_offset + i);
-
-       if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
-               mb_ack_irq(cx, order);
-       return 1;
-}
-
-static
-int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       u32 str_offset;
-       char *str = order->str;
-
-       str[0] = '\0';
-       str_offset = order->mb.args[1];
-       if (str_offset) {
-               cx18_setup_page(cx, str_offset);
-               cx18_memcpy_fromio(cx, str, cx->enc_mem + str_offset, 252);
-               str[252] = '\0';
-               cx18_setup_page(cx, SCB_OFFSET);
-       }
-
-       if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
-               mb_ack_irq(cx, order);
-
-       return str_offset ? 1 : 0;
-}
-
-static inline
-int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order)
-{
-       int ret = -1;
-
-       switch (order->rpu) {
-       case CPU:
-       {
-               switch (order->mb.cmd) {
-               case CX18_EPU_DMA_DONE:
-                       ret = epu_dma_done_irq(cx, order);
-                       break;
-               case CX18_EPU_DEBUG:
-                       ret = epu_debug_irq(cx, order);
-                       break;
-               default:
-                       CX18_WARN("Unknown CPU to EPU mailbox command %#0x\n",
-                                 order->mb.cmd);
-                       break;
-               }
-               break;
-       }
-       case APU:
-               CX18_WARN("Unknown APU to EPU mailbox command %#0x\n",
-                         order->mb.cmd);
-               break;
-       default:
-               break;
-       }
-       return ret;
-}
-
-static inline
-struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx)
-{
-       int i;
-       struct cx18_in_work_order *order = NULL;
-
-       for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
-               /*
-                * We only need "pending" atomic to inspect its contents,
-                * and need not do a check and set because:
-                * 1. Any work handler thread only clears "pending" and only
-                * on one, particular work order at a time, per handler thread.
-                * 2. "pending" is only set here, and we're serialized because
-                * we're called in an IRQ handler context.
-                */
-               if (atomic_read(&cx->in_work_order[i].pending) == 0) {
-                       order = &cx->in_work_order[i];
-                       atomic_set(&order->pending, 1);
-                       break;
-               }
-       }
-       return order;
-}
-
-void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
-{
-       struct cx18_mailbox __iomem *mb;
-       struct cx18_mailbox *order_mb;
-       struct cx18_in_work_order *order;
-       int submit;
-       int i;
-
-       switch (rpu) {
-       case CPU:
-               mb = &cx->scb->cpu2epu_mb;
-               break;
-       case APU:
-               mb = &cx->scb->apu2epu_mb;
-               break;
-       default:
-               return;
-       }
-
-       order = alloc_in_work_order_irq(cx);
-       if (order == NULL) {
-               CX18_WARN("Unable to find blank work order form to schedule "
-                         "incoming mailbox command processing\n");
-               return;
-       }
-
-       order->flags = 0;
-       order->rpu = rpu;
-       order_mb = &order->mb;
-
-       /* mb->cmd and mb->args[0] through mb->args[2] */
-       for (i = 0; i < 4; i++)
-               (&order_mb->cmd)[i] = cx18_readl(cx, &mb->cmd + i);
-
-       /* mb->request and mb->ack.  N.B. we want to read mb->ack last */
-       for (i = 0; i < 2; i++)
-               (&order_mb->request)[i] = cx18_readl(cx, &mb->request + i);
-
-       if (order_mb->request == order_mb->ack) {
-               CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
-                               "incoming %s to EPU mailbox (sequence no. %u)"
-                               "\n",
-                               rpu_str[rpu], rpu_str[rpu], order_mb->request);
-               if (cx18_debug & CX18_DBGFLG_WARN)
-                       dump_mb(cx, order_mb, "incoming");
-               order->flags = CX18_F_EWO_MB_STALE_UPON_RECEIPT;
-       }
-
-       /*
-        * Individual EPU command processing is responsible for ack-ing
-        * a non-stale mailbox as soon as possible
-        */
-       submit = epu_cmd_irq(cx, order);
-       if (submit > 0) {
-               queue_work(cx->in_work_queue, &order->work);
-       }
-}
-
-
-/*
- * Functions called from a non-interrupt, non work_queue context
- */
-
-static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
-{
-       const struct cx18_api_info *info = find_api_info(cmd);
-       u32 irq, req, ack, err;
-       struct cx18_mailbox __iomem *mb;
-       wait_queue_head_t *waitq;
-       struct mutex *mb_lock;
-       unsigned long int t0, timeout, ret;
-       int i;
-       char argstr[MAX_MB_ARGUMENTS*11+1];
-       DEFINE_WAIT(w);
-
-       if (info == NULL) {
-               CX18_WARN("unknown cmd %x\n", cmd);
-               return -EINVAL;
-       }
-
-       if (cx18_debug & CX18_DBGFLG_API) { /* only call u32arr2hex if needed */
-               if (cmd == CX18_CPU_DE_SET_MDL) {
-                       if (cx18_debug & CX18_DBGFLG_HIGHVOL)
-                               CX18_DEBUG_HI_API("%s\tcmd %#010x args%s\n",
-                                               info->name, cmd,
-                                               u32arr2hex(data, args, argstr));
-               } else
-                       CX18_DEBUG_API("%s\tcmd %#010x args%s\n",
-                                      info->name, cmd,
-                                      u32arr2hex(data, args, argstr));
-       }
-
-       switch (info->rpu) {
-       case APU:
-               waitq = &cx->mb_apu_waitq;
-               mb_lock = &cx->epu2apu_mb_lock;
-               irq = IRQ_EPU_TO_APU;
-               mb = &cx->scb->epu2apu_mb;
-               break;
-       case CPU:
-               waitq = &cx->mb_cpu_waitq;
-               mb_lock = &cx->epu2cpu_mb_lock;
-               irq = IRQ_EPU_TO_CPU;
-               mb = &cx->scb->epu2cpu_mb;
-               break;
-       default:
-               CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu);
-               return -EINVAL;
-       }
-
-       mutex_lock(mb_lock);
-       /*
-        * Wait for an in-use mailbox to complete
-        *
-        * If the XPU is responding with Ack's, the mailbox shouldn't be in
-        * a busy state, since we serialize access to it on our end.
-        *
-        * If the wait for ack after sending a previous command was interrupted
-        * by a signal, we may get here and find a busy mailbox.  After waiting,
-        * mark it "not busy" from our end, if the XPU hasn't ack'ed it still.
-        */
-       req = cx18_readl(cx, &mb->request);
-       timeout = msecs_to_jiffies(10);
-       ret = wait_event_timeout(*waitq,
-                                (ack = cx18_readl(cx, &mb->ack)) == req,
-                                timeout);
-       if (req != ack) {
-               /* waited long enough, make the mbox "not busy" from our end */
-               cx18_writel(cx, req, &mb->ack);
-               CX18_ERR("mbox was found stuck busy when setting up for %s; "
-                        "clearing busy and trying to proceed\n", info->name);
-       } else if (ret != timeout)
-               CX18_DEBUG_API("waited %u msecs for busy mbox to be acked\n",
-                              jiffies_to_msecs(timeout-ret));
-
-       /* Build the outgoing mailbox */
-       req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1;
-
-       cx18_writel(cx, cmd, &mb->cmd);
-       for (i = 0; i < args; i++)
-               cx18_writel(cx, data[i], &mb->args[i]);
-       cx18_writel(cx, 0, &mb->error);
-       cx18_writel(cx, req, &mb->request);
-       cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */
-
-       /*
-        * Notify the XPU and wait for it to send an Ack back
-        */
-       timeout = msecs_to_jiffies((info->flags & API_FAST) ? 10 : 20);
-
-       CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
-                         irq, info->name);
-
-       /* So we don't miss the wakeup, prepare to wait before notifying fw */
-       prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE);
-       cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
-
-       t0 = jiffies;
-       ack = cx18_readl(cx, &mb->ack);
-       if (ack != req) {
-               schedule_timeout(timeout);
-               ret = jiffies - t0;
-               ack = cx18_readl(cx, &mb->ack);
-       } else {
-               ret = jiffies - t0;
-       }
-
-       finish_wait(waitq, &w);
-
-       if (req != ack) {
-               mutex_unlock(mb_lock);
-               if (ret >= timeout) {
-                       /* Timed out */
-                       CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
-                                       "for RPU acknowledgement\n",
-                                       info->name, jiffies_to_msecs(ret));
-               } else {
-                       CX18_DEBUG_WARN("woken up before mailbox ack was ready "
-                                       "after submitting %s to RPU.  only "
-                                       "waited %d msecs on req %u but awakened"
-                                       " with unmatched ack %u\n",
-                                       info->name,
-                                       jiffies_to_msecs(ret),
-                                       req, ack);
-               }
-               return -EINVAL;
-       }
-
-       if (ret >= timeout)
-               CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
-                               "sending %s; timed out waiting %d msecs\n",
-                               info->name, jiffies_to_msecs(ret));
-       else
-               CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
-                                 jiffies_to_msecs(ret), info->name);
-
-       /* Collect data returned by the XPU */
-       for (i = 0; i < MAX_MB_ARGUMENTS; i++)
-               data[i] = cx18_readl(cx, &mb->args[i]);
-       err = cx18_readl(cx, &mb->error);
-       mutex_unlock(mb_lock);
-
-       /*
-        * Wait for XPU to perform extra actions for the caller in some cases.
-        * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all MDLs
-        * back in a burst shortly thereafter
-        */
-       if (info->flags & API_SLOW)
-               cx18_msleep_timeout(300, 0);
-
-       if (err)
-               CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
-                               info->name);
-       return err ? -EIO : 0;
-}
-
-int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
-{
-       return cx18_api_call(cx, cmd, args, data);
-}
-
-static int cx18_set_filter_param(struct cx18_stream *s)
-{
-       struct cx18 *cx = s->cx;
-       u32 mode;
-       int ret;
-
-       mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
-       ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
-                       s->handle, 1, mode, cx->spatial_strength);
-       mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
-       ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
-                       s->handle, 0, mode, cx->temporal_strength);
-       ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
-                       s->handle, 2, cx->filter_mode >> 2, 0);
-       return ret;
-}
-
-int cx18_api_func(void *priv, u32 cmd, int in, int out,
-               u32 data[CX2341X_MBOX_MAX_DATA])
-{
-       struct cx18_stream *s = priv;
-       struct cx18 *cx = s->cx;
-
-       switch (cmd) {
-       case CX2341X_ENC_SET_OUTPUT_PORT:
-               return 0;
-       case CX2341X_ENC_SET_FRAME_RATE:
-               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
-                               s->handle, 0, 0, 0, 0, data[0]);
-       case CX2341X_ENC_SET_FRAME_SIZE:
-               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
-                               s->handle, data[1], data[0]);
-       case CX2341X_ENC_SET_STREAM_TYPE:
-               return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
-                               s->handle, data[0]);
-       case CX2341X_ENC_SET_ASPECT_RATIO:
-               return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
-                               s->handle, data[0]);
-
-       case CX2341X_ENC_SET_GOP_PROPERTIES:
-               return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
-                               s->handle, data[0], data[1]);
-       case CX2341X_ENC_SET_GOP_CLOSURE:
-               return 0;
-       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
-               return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
-                               s->handle, data[0]);
-       case CX2341X_ENC_MUTE_AUDIO:
-               return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
-                               s->handle, data[0]);
-       case CX2341X_ENC_SET_BIT_RATE:
-               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
-                               s->handle, data[0], data[1], data[2], data[3]);
-       case CX2341X_ENC_MUTE_VIDEO:
-               return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
-                               s->handle, data[0]);
-       case CX2341X_ENC_SET_FRAME_DROP_RATE:
-               return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
-                               s->handle, data[0]);
-       case CX2341X_ENC_MISC:
-               return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
-                               s->handle, data[0], data[1], data[2]);
-       case CX2341X_ENC_SET_DNR_FILTER_MODE:
-               cx->filter_mode = (data[0] & 3) | (data[1] << 2);
-               return cx18_set_filter_param(s);
-       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
-               cx->spatial_strength = data[0];
-               cx->temporal_strength = data[1];
-               return cx18_set_filter_param(s);
-       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
-               return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
-                               s->handle, data[0], data[1]);
-       case CX2341X_ENC_SET_CORING_LEVELS:
-               return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
-                               s->handle, data[0], data[1], data[2], data[3]);
-       }
-       CX18_WARN("Unknown cmd %x\n", cmd);
-       return 0;
-}
-
-int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
-               u32 cmd, int args, ...)
-{
-       va_list ap;
-       int i;
-
-       va_start(ap, args);
-       for (i = 0; i < args; i++)
-               data[i] = va_arg(ap, u32);
-       va_end(ap);
-       return cx18_api(cx, cmd, args, data);
-}
-
-int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
-{
-       u32 data[MAX_MB_ARGUMENTS];
-       va_list ap;
-       int i;
-
-       if (cx == NULL) {
-               CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
-               return 0;
-       }
-       if (args > MAX_MB_ARGUMENTS) {
-               CX18_ERR("args too big (cmd=%x)\n", cmd);
-               args = MAX_MB_ARGUMENTS;
-       }
-       va_start(ap, args);
-       for (i = 0; i < args; i++)
-               data[i] = va_arg(ap, u32);
-       va_end(ap);
-       return cx18_api(cx, cmd, args, data);
-}
diff --git a/drivers/media/video/cx18/cx18-mailbox.h b/drivers/media/video/cx18/cx18-mailbox.h
deleted file mode 100644 (file)
index b63fdfa..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  cx18 mailbox functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#ifndef _CX18_MAILBOX_H_
-#define _CX18_MAILBOX_H_
-
-/* mailbox max args */
-#define MAX_MB_ARGUMENTS 6
-/* compatibility, should be same as the define in cx2341x.h */
-#define CX2341X_MBOX_MAX_DATA 16
-
-#define MB_RESERVED_HANDLE_0 0
-#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
-
-#define APU 0
-#define CPU 1
-#define EPU 2
-#define HPU 3
-
-struct cx18;
-
-/*
- * This structure is used by CPU to provide completed MDL & buffers information.
- * Its structure is dictated by the layout of the SCB, required by the
- * firmware, but its definition needs to be here, instead of in cx18-scb.h,
- * for mailbox work order scheduling
- */
-struct cx18_mdl_ack {
-    u32 id;        /* ID of a completed MDL */
-    u32 data_used; /* Total data filled in the MDL with 'id' */
-};
-
-/* The cx18_mailbox struct is the mailbox structure which is used for passing
-   messages between processors */
-struct cx18_mailbox {
-    /* The sender sets a handle in 'request' after he fills the command. The
-       'request' should be different than 'ack'. The sender, also, generates
-       an interrupt on XPU2YPU_irq where XPU is the sender and YPU is the
-       receiver. */
-    u32       request;
-    /* The receiver detects a new command when 'req' is different than 'ack'.
-       He sets 'ack' to the same value as 'req' to clear the command. He, also,
-       generates an interrupt on YPU2XPU_irq where XPU is the sender and YPU
-       is the receiver. */
-    u32       ack;
-    u32       reserved[6];
-    /* 'cmd' identifies the command. The list of these commands are in
-       cx23418.h */
-    u32       cmd;
-    /* Each command can have up to 6 arguments */
-    u32       args[MAX_MB_ARGUMENTS];
-    /* The return code can be one of the codes in the file cx23418.h. If the
-       command is completed successfully, the error will be ERR_SYS_SUCCESS.
-       If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
-       code would indicate the task from which the error originated and will
-       be one of the errors in cx23418.h. In that case, the following
-       applies ((error & 0xff) != 0).
-       If the command is pending, the return will be passed in a MB from the
-       receiver to the sender. 'req' will be returned in args[0] */
-    u32       error;
-};
-
-struct cx18_stream;
-
-int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
-int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
-               int args, ...);
-int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
-int cx18_api_func(void *priv, u32 cmd, int in, int out,
-               u32 data[CX2341X_MBOX_MAX_DATA]);
-
-void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu);
-
-void cx18_in_work_handler(struct work_struct *work);
-
-#endif
diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c
deleted file mode 100644 (file)
index 8884537..0000000
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- *  cx18 buffer queues
- *
- *  Derived from ivtv-queue.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-queue.h"
-#include "cx18-streams.h"
-#include "cx18-scb.h"
-#include "cx18-io.h"
-
-void cx18_buf_swap(struct cx18_buffer *buf)
-{
-       int i;
-
-       for (i = 0; i < buf->bytesused; i += 4)
-               swab32s((u32 *)(buf->buf + i));
-}
-
-void _cx18_mdl_swap(struct cx18_mdl *mdl)
-{
-       struct cx18_buffer *buf;
-
-       list_for_each_entry(buf, &mdl->buf_list, list) {
-               if (buf->bytesused == 0)
-                       break;
-               cx18_buf_swap(buf);
-       }
-}
-
-void cx18_queue_init(struct cx18_queue *q)
-{
-       INIT_LIST_HEAD(&q->list);
-       atomic_set(&q->depth, 0);
-       q->bytesused = 0;
-}
-
-struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
-                                struct cx18_queue *q, int to_front)
-{
-       /* clear the mdl if it is not to be enqueued to the full queue */
-       if (q != &s->q_full) {
-               mdl->bytesused = 0;
-               mdl->readpos = 0;
-               mdl->m_flags = 0;
-               mdl->skipped = 0;
-               mdl->curr_buf = NULL;
-       }
-
-       /* q_busy is restricted to a max buffer count imposed by firmware */
-       if (q == &s->q_busy &&
-           atomic_read(&q->depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
-               q = &s->q_free;
-
-       spin_lock(&q->lock);
-
-       if (to_front)
-               list_add(&mdl->list, &q->list); /* LIFO */
-       else
-               list_add_tail(&mdl->list, &q->list); /* FIFO */
-       q->bytesused += mdl->bytesused - mdl->readpos;
-       atomic_inc(&q->depth);
-
-       spin_unlock(&q->lock);
-       return q;
-}
-
-struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
-{
-       struct cx18_mdl *mdl = NULL;
-
-       spin_lock(&q->lock);
-       if (!list_empty(&q->list)) {
-               mdl = list_first_entry(&q->list, struct cx18_mdl, list);
-               list_del_init(&mdl->list);
-               q->bytesused -= mdl->bytesused - mdl->readpos;
-               mdl->skipped = 0;
-               atomic_dec(&q->depth);
-       }
-       spin_unlock(&q->lock);
-       return mdl;
-}
-
-static void _cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
-                                         struct cx18_mdl *mdl)
-{
-       struct cx18_buffer *buf;
-       u32 buf_size = s->buf_size;
-       u32 bytesused = mdl->bytesused;
-
-       list_for_each_entry(buf, &mdl->buf_list, list) {
-               buf->readpos = 0;
-               if (bytesused >= buf_size) {
-                       buf->bytesused = buf_size;
-                       bytesused -= buf_size;
-               } else {
-                       buf->bytesused = bytesused;
-                       bytesused = 0;
-               }
-               cx18_buf_sync_for_cpu(s, buf);
-       }
-}
-
-static inline void cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
-                                               struct cx18_mdl *mdl)
-{
-       struct cx18_buffer *buf;
-
-       if (list_is_singular(&mdl->buf_list)) {
-               buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
-                                      list);
-               buf->bytesused = mdl->bytesused;
-               buf->readpos = 0;
-               cx18_buf_sync_for_cpu(s, buf);
-       } else {
-               _cx18_mdl_update_bufs_for_cpu(s, mdl);
-       }
-}
-
-struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
-       u32 bytesused)
-{
-       struct cx18 *cx = s->cx;
-       struct cx18_mdl *mdl;
-       struct cx18_mdl *tmp;
-       struct cx18_mdl *ret = NULL;
-       LIST_HEAD(sweep_up);
-
-       /*
-        * We don't have to acquire multiple q locks here, because we are
-        * serialized by the single threaded work handler.
-        * MDLs from the firmware will thus remain in order as
-        * they are moved from q_busy to q_full or to the dvb ring buffer.
-        */
-       spin_lock(&s->q_busy.lock);
-       list_for_each_entry_safe(mdl, tmp, &s->q_busy.list, list) {
-               /*
-                * We should find what the firmware told us is done,
-                * right at the front of the queue.  If we don't, we likely have
-                * missed an mdl done message from the firmware.
-                * Once we skip an mdl repeatedly, relative to the size of
-                * q_busy, we have high confidence we've missed it.
-                */
-               if (mdl->id != id) {
-                       mdl->skipped++;
-                       if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) {
-                               /* mdl must have fallen out of rotation */
-                               CX18_WARN("Skipped %s, MDL %d, %d "
-                                         "times - it must have dropped out of "
-                                         "rotation\n", s->name, mdl->id,
-                                         mdl->skipped);
-                               /* Sweep it up to put it back into rotation */
-                               list_move_tail(&mdl->list, &sweep_up);
-                               atomic_dec(&s->q_busy.depth);
-                       }
-                       continue;
-               }
-               /*
-                * We pull the desired mdl off of the queue here.  Something
-                * will have to put it back on a queue later.
-                */
-               list_del_init(&mdl->list);
-               atomic_dec(&s->q_busy.depth);
-               ret = mdl;
-               break;
-       }
-       spin_unlock(&s->q_busy.lock);
-
-       /*
-        * We found the mdl for which we were looking.  Get it ready for
-        * the caller to put on q_full or in the dvb ring buffer.
-        */
-       if (ret != NULL) {
-               ret->bytesused = bytesused;
-               ret->skipped = 0;
-               /* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */
-               cx18_mdl_update_bufs_for_cpu(s, ret);
-               if (s->type != CX18_ENC_STREAM_TYPE_TS)
-                       set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags);
-       }
-
-       /* Put any mdls the firmware is ignoring back into normal rotation */
-       list_for_each_entry_safe(mdl, tmp, &sweep_up, list) {
-               list_del_init(&mdl->list);
-               cx18_enqueue(s, mdl, &s->q_free);
-       }
-       return ret;
-}
-
-/* Move all mdls of a queue, while flushing the mdl */
-static void cx18_queue_flush(struct cx18_stream *s,
-                            struct cx18_queue *q_src, struct cx18_queue *q_dst)
-{
-       struct cx18_mdl *mdl;
-
-       /* It only makes sense to flush to q_free or q_idle */
-       if (q_src == q_dst || q_dst == &s->q_full || q_dst == &s->q_busy)
-               return;
-
-       spin_lock(&q_src->lock);
-       spin_lock(&q_dst->lock);
-       while (!list_empty(&q_src->list)) {
-               mdl = list_first_entry(&q_src->list, struct cx18_mdl, list);
-               list_move_tail(&mdl->list, &q_dst->list);
-               mdl->bytesused = 0;
-               mdl->readpos = 0;
-               mdl->m_flags = 0;
-               mdl->skipped = 0;
-               mdl->curr_buf = NULL;
-               atomic_inc(&q_dst->depth);
-       }
-       cx18_queue_init(q_src);
-       spin_unlock(&q_src->lock);
-       spin_unlock(&q_dst->lock);
-}
-
-void cx18_flush_queues(struct cx18_stream *s)
-{
-       cx18_queue_flush(s, &s->q_busy, &s->q_free);
-       cx18_queue_flush(s, &s->q_full, &s->q_free);
-}
-
-/*
- * Note, s->buf_pool is not protected by a lock,
- * the stream better not have *anything* going on when calling this
- */
-void cx18_unload_queues(struct cx18_stream *s)
-{
-       struct cx18_queue *q_idle = &s->q_idle;
-       struct cx18_mdl *mdl;
-       struct cx18_buffer *buf;
-
-       /* Move all MDLS to q_idle */
-       cx18_queue_flush(s, &s->q_busy, q_idle);
-       cx18_queue_flush(s, &s->q_full, q_idle);
-       cx18_queue_flush(s, &s->q_free, q_idle);
-
-       /* Reset MDL id's and move all buffers back to the stream's buf_pool */
-       spin_lock(&q_idle->lock);
-       list_for_each_entry(mdl, &q_idle->list, list) {
-               while (!list_empty(&mdl->buf_list)) {
-                       buf = list_first_entry(&mdl->buf_list,
-                                              struct cx18_buffer, list);
-                       list_move_tail(&buf->list, &s->buf_pool);
-                       buf->bytesused = 0;
-                       buf->readpos = 0;
-               }
-               mdl->id = s->mdl_base_idx; /* reset id to a "safe" value */
-               /* all other mdl fields were cleared by cx18_queue_flush() */
-       }
-       spin_unlock(&q_idle->lock);
-}
-
-/*
- * Note, s->buf_pool is not protected by a lock,
- * the stream better not have *anything* going on when calling this
- */
-void cx18_load_queues(struct cx18_stream *s)
-{
-       struct cx18 *cx = s->cx;
-       struct cx18_mdl *mdl;
-       struct cx18_buffer *buf;
-       int mdl_id;
-       int i;
-       u32 partial_buf_size;
-
-       /*
-        * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free
-        * Excess MDLs are left on q_idle
-        * Excess buffers are left in buf_pool and/or on an MDL in q_idle
-        */
-       mdl_id = s->mdl_base_idx;
-       for (mdl = cx18_dequeue(s, &s->q_idle), i = s->bufs_per_mdl;
-            mdl != NULL && i == s->bufs_per_mdl;
-            mdl = cx18_dequeue(s, &s->q_idle)) {
-
-               mdl->id = mdl_id;
-
-               for (i = 0; i < s->bufs_per_mdl; i++) {
-                       if (list_empty(&s->buf_pool))
-                               break;
-
-                       buf = list_first_entry(&s->buf_pool, struct cx18_buffer,
-                                              list);
-                       list_move_tail(&buf->list, &mdl->buf_list);
-
-                       /* update the firmware's MDL array with this buffer */
-                       cx18_writel(cx, buf->dma_handle,
-                                   &cx->scb->cpu_mdl[mdl_id + i].paddr);
-                       cx18_writel(cx, s->buf_size,
-                                   &cx->scb->cpu_mdl[mdl_id + i].length);
-               }
-
-               if (i == s->bufs_per_mdl) {
-                       /*
-                        * The encoder doesn't honor s->mdl_size.  So in the
-                        * case of a non-integral number of buffers to meet
-                        * mdl_size, we lie about the size of the last buffer
-                        * in the MDL to get the encoder to really only send
-                        * us mdl_size bytes per MDL transfer.
-                        */
-                       partial_buf_size = s->mdl_size % s->buf_size;
-                       if (partial_buf_size) {
-                               cx18_writel(cx, partial_buf_size,
-                                     &cx->scb->cpu_mdl[mdl_id + i - 1].length);
-                       }
-                       cx18_enqueue(s, mdl, &s->q_free);
-               } else {
-                       /* Not enough buffers for this MDL; we won't use it */
-                       cx18_push(s, mdl, &s->q_idle);
-               }
-               mdl_id += i;
-       }
-}
-
-void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl)
-{
-       int dma = s->dma;
-       u32 buf_size = s->buf_size;
-       struct pci_dev *pci_dev = s->cx->pci_dev;
-       struct cx18_buffer *buf;
-
-       list_for_each_entry(buf, &mdl->buf_list, list)
-               pci_dma_sync_single_for_device(pci_dev, buf->dma_handle,
-                                              buf_size, dma);
-}
-
-int cx18_stream_alloc(struct cx18_stream *s)
-{
-       struct cx18 *cx = s->cx;
-       int i;
-
-       if (s->buffers == 0)
-               return 0;
-
-       CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers "
-                       "(%d.%02d kB total)\n",
-               s->name, s->buffers, s->buf_size,
-               s->buffers * s->buf_size / 1024,
-               (s->buffers * s->buf_size * 100 / 1024) % 100);
-
-       if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] -
-                               (char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
-               unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
-                                       ((char __iomem *)cx->scb->cpu_mdl));
-
-               CX18_ERR("Too many buffers, cannot fit in SCB area\n");
-               CX18_ERR("Max buffers = %zd\n",
-                       bufsz / sizeof(struct cx18_mdl_ent));
-               return -ENOMEM;
-       }
-
-       s->mdl_base_idx = cx->free_mdl_idx;
-
-       /* allocate stream buffers and MDLs */
-       for (i = 0; i < s->buffers; i++) {
-               struct cx18_mdl *mdl;
-               struct cx18_buffer *buf;
-
-               /* 1 MDL per buffer to handle the worst & also default case */
-               mdl = kzalloc(sizeof(struct cx18_mdl), GFP_KERNEL|__GFP_NOWARN);
-               if (mdl == NULL)
-                       break;
-
-               buf = kzalloc(sizeof(struct cx18_buffer),
-                               GFP_KERNEL|__GFP_NOWARN);
-               if (buf == NULL) {
-                       kfree(mdl);
-                       break;
-               }
-
-               buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN);
-               if (buf->buf == NULL) {
-                       kfree(mdl);
-                       kfree(buf);
-                       break;
-               }
-
-               INIT_LIST_HEAD(&mdl->list);
-               INIT_LIST_HEAD(&mdl->buf_list);
-               mdl->id = s->mdl_base_idx; /* a somewhat safe value */
-               cx18_enqueue(s, mdl, &s->q_idle);
-
-               INIT_LIST_HEAD(&buf->list);
-               buf->dma_handle = pci_map_single(s->cx->pci_dev,
-                               buf->buf, s->buf_size, s->dma);
-               cx18_buf_sync_for_cpu(s, buf);
-               list_add_tail(&buf->list, &s->buf_pool);
-       }
-       if (i == s->buffers) {
-               cx->free_mdl_idx += s->buffers;
-               return 0;
-       }
-       CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
-       cx18_stream_free(s);
-       return -ENOMEM;
-}
-
-void cx18_stream_free(struct cx18_stream *s)
-{
-       struct cx18_mdl *mdl;
-       struct cx18_buffer *buf;
-       struct cx18 *cx = s->cx;
-
-       CX18_DEBUG_INFO("Deallocating buffers for %s stream\n", s->name);
-
-       /* move all buffers to buf_pool and all MDLs to q_idle */
-       cx18_unload_queues(s);
-
-       /* empty q_idle */
-       while ((mdl = cx18_dequeue(s, &s->q_idle)))
-               kfree(mdl);
-
-       /* empty buf_pool */
-       while (!list_empty(&s->buf_pool)) {
-               buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list);
-               list_del_init(&buf->list);
-
-               pci_unmap_single(s->cx->pci_dev, buf->dma_handle,
-                               s->buf_size, s->dma);
-               kfree(buf->buf);
-               kfree(buf);
-       }
-}
diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h
deleted file mode 100644 (file)
index 4201ddc..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  cx18 buffer queues
- *
- *  Derived from ivtv-queue.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#define CX18_DMA_UNMAPPED      ((u32) -1)
-
-/* cx18_buffer utility functions */
-
-static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
-       struct cx18_buffer *buf)
-{
-       pci_dma_sync_single_for_cpu(s->cx->pci_dev, buf->dma_handle,
-                               s->buf_size, s->dma);
-}
-
-static inline void cx18_buf_sync_for_device(struct cx18_stream *s,
-       struct cx18_buffer *buf)
-{
-       pci_dma_sync_single_for_device(s->cx->pci_dev, buf->dma_handle,
-                               s->buf_size, s->dma);
-}
-
-void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl);
-
-static inline void cx18_mdl_sync_for_device(struct cx18_stream *s,
-                                           struct cx18_mdl *mdl)
-{
-       if (list_is_singular(&mdl->buf_list))
-               cx18_buf_sync_for_device(s, list_first_entry(&mdl->buf_list,
-                                                            struct cx18_buffer,
-                                                            list));
-       else
-               _cx18_mdl_sync_for_device(s, mdl);
-}
-
-void cx18_buf_swap(struct cx18_buffer *buf);
-void _cx18_mdl_swap(struct cx18_mdl *mdl);
-
-static inline void cx18_mdl_swap(struct cx18_mdl *mdl)
-{
-       if (list_is_singular(&mdl->buf_list))
-               cx18_buf_swap(list_first_entry(&mdl->buf_list,
-                                              struct cx18_buffer, list));
-       else
-               _cx18_mdl_swap(mdl);
-}
-
-/* cx18_queue utility functions */
-struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
-                                struct cx18_queue *q, int to_front);
-
-static inline
-struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
-                               struct cx18_queue *q)
-{
-       return _cx18_enqueue(s, mdl, q, 0); /* FIFO */
-}
-
-static inline
-struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_mdl *mdl,
-                            struct cx18_queue *q)
-{
-       return _cx18_enqueue(s, mdl, q, 1); /* LIFO */
-}
-
-void cx18_queue_init(struct cx18_queue *q);
-struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
-struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
-       u32 bytesused);
-void cx18_flush_queues(struct cx18_stream *s);
-
-/* queue MDL reconfiguration helpers */
-void cx18_unload_queues(struct cx18_stream *s);
-void cx18_load_queues(struct cx18_stream *s);
-
-/* cx18_stream utility functions */
-int cx18_stream_alloc(struct cx18_stream *s);
-void cx18_stream_free(struct cx18_stream *s);
diff --git a/drivers/media/video/cx18/cx18-scb.c b/drivers/media/video/cx18/cx18-scb.c
deleted file mode 100644 (file)
index 85cc596..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *  cx18 System Control Block initialization
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-scb.h"
-
-void cx18_init_scb(struct cx18 *cx)
-{
-       cx18_setup_page(cx, SCB_OFFSET);
-       cx18_memset_io(cx, cx->scb, 0, 0x10000);
-
-       cx18_writel(cx, IRQ_APU_TO_CPU,     &cx->scb->apu2cpu_irq);
-       cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
-       cx18_writel(cx, IRQ_HPU_TO_CPU,     &cx->scb->hpu2cpu_irq);
-       cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
-       cx18_writel(cx, IRQ_PPU_TO_CPU,     &cx->scb->ppu2cpu_irq);
-       cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
-       cx18_writel(cx, IRQ_EPU_TO_CPU,     &cx->scb->epu2cpu_irq);
-       cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
-
-       cx18_writel(cx, IRQ_CPU_TO_APU,     &cx->scb->cpu2apu_irq);
-       cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
-       cx18_writel(cx, IRQ_HPU_TO_APU,     &cx->scb->hpu2apu_irq);
-       cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
-       cx18_writel(cx, IRQ_PPU_TO_APU,     &cx->scb->ppu2apu_irq);
-       cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
-       cx18_writel(cx, IRQ_EPU_TO_APU,     &cx->scb->epu2apu_irq);
-       cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
-
-       cx18_writel(cx, IRQ_CPU_TO_HPU,     &cx->scb->cpu2hpu_irq);
-       cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
-       cx18_writel(cx, IRQ_APU_TO_HPU,     &cx->scb->apu2hpu_irq);
-       cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
-       cx18_writel(cx, IRQ_PPU_TO_HPU,     &cx->scb->ppu2hpu_irq);
-       cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
-       cx18_writel(cx, IRQ_EPU_TO_HPU,     &cx->scb->epu2hpu_irq);
-       cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
-
-       cx18_writel(cx, IRQ_CPU_TO_PPU,     &cx->scb->cpu2ppu_irq);
-       cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
-       cx18_writel(cx, IRQ_APU_TO_PPU,     &cx->scb->apu2ppu_irq);
-       cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
-       cx18_writel(cx, IRQ_HPU_TO_PPU,     &cx->scb->hpu2ppu_irq);
-       cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
-       cx18_writel(cx, IRQ_EPU_TO_PPU,     &cx->scb->epu2ppu_irq);
-       cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
-
-       cx18_writel(cx, IRQ_CPU_TO_EPU,     &cx->scb->cpu2epu_irq);
-       cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
-       cx18_writel(cx, IRQ_APU_TO_EPU,     &cx->scb->apu2epu_irq);
-       cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
-       cx18_writel(cx, IRQ_HPU_TO_EPU,     &cx->scb->hpu2epu_irq);
-       cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
-       cx18_writel(cx, IRQ_PPU_TO_EPU,     &cx->scb->ppu2epu_irq);
-       cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
-
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
-                       &cx->scb->apu2cpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
-                       &cx->scb->hpu2cpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
-                       &cx->scb->ppu2cpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
-                       &cx->scb->epu2cpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
-                       &cx->scb->cpu2apu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
-                       &cx->scb->hpu2apu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
-                       &cx->scb->ppu2apu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
-                       &cx->scb->epu2apu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
-                       &cx->scb->cpu2hpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
-                       &cx->scb->apu2hpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
-                       &cx->scb->ppu2hpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
-                       &cx->scb->epu2hpu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
-                       &cx->scb->cpu2ppu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
-                       &cx->scb->apu2ppu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
-                       &cx->scb->hpu2ppu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
-                       &cx->scb->epu2ppu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
-                       &cx->scb->cpu2epu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
-                       &cx->scb->apu2epu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
-                       &cx->scb->hpu2epu_mb_offset);
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
-                       &cx->scb->ppu2epu_mb_offset);
-
-       cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
-                       &cx->scb->ipc_offset);
-
-       cx18_writel(cx, 1, &cx->scb->epu_state);
-}
diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h
deleted file mode 100644 (file)
index 0887765..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- *  cx18 System Control Block initialization
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#ifndef CX18_SCB_H
-#define CX18_SCB_H
-
-#include "cx18-mailbox.h"
-
-/* NOTE: All ACK interrupts are in the SW2 register.  All non-ACK interrupts
-   are in the SW1 register. */
-
-#define IRQ_APU_TO_CPU         0x00000001
-#define IRQ_CPU_TO_APU_ACK     0x00000001
-#define IRQ_HPU_TO_CPU         0x00000002
-#define IRQ_CPU_TO_HPU_ACK     0x00000002
-#define IRQ_PPU_TO_CPU         0x00000004
-#define IRQ_CPU_TO_PPU_ACK     0x00000004
-#define IRQ_EPU_TO_CPU         0x00000008
-#define IRQ_CPU_TO_EPU_ACK     0x00000008
-
-#define IRQ_CPU_TO_APU         0x00000010
-#define IRQ_APU_TO_CPU_ACK     0x00000010
-#define IRQ_HPU_TO_APU         0x00000020
-#define IRQ_APU_TO_HPU_ACK     0x00000020
-#define IRQ_PPU_TO_APU         0x00000040
-#define IRQ_APU_TO_PPU_ACK     0x00000040
-#define IRQ_EPU_TO_APU         0x00000080
-#define IRQ_APU_TO_EPU_ACK     0x00000080
-
-#define IRQ_CPU_TO_HPU         0x00000100
-#define IRQ_HPU_TO_CPU_ACK     0x00000100
-#define IRQ_APU_TO_HPU         0x00000200
-#define IRQ_HPU_TO_APU_ACK     0x00000200
-#define IRQ_PPU_TO_HPU         0x00000400
-#define IRQ_HPU_TO_PPU_ACK     0x00000400
-#define IRQ_EPU_TO_HPU         0x00000800
-#define IRQ_HPU_TO_EPU_ACK     0x00000800
-
-#define IRQ_CPU_TO_PPU         0x00001000
-#define IRQ_PPU_TO_CPU_ACK     0x00001000
-#define IRQ_APU_TO_PPU         0x00002000
-#define IRQ_PPU_TO_APU_ACK     0x00002000
-#define IRQ_HPU_TO_PPU         0x00004000
-#define IRQ_PPU_TO_HPU_ACK     0x00004000
-#define IRQ_EPU_TO_PPU         0x00008000
-#define IRQ_PPU_TO_EPU_ACK     0x00008000
-
-#define IRQ_CPU_TO_EPU         0x00010000
-#define IRQ_EPU_TO_CPU_ACK     0x00010000
-#define IRQ_APU_TO_EPU         0x00020000
-#define IRQ_EPU_TO_APU_ACK     0x00020000
-#define IRQ_HPU_TO_EPU         0x00040000
-#define IRQ_EPU_TO_HPU_ACK     0x00040000
-#define IRQ_PPU_TO_EPU         0x00080000
-#define IRQ_EPU_TO_PPU_ACK     0x00080000
-
-#define SCB_OFFSET  0xDC0000
-
-/* If Firmware uses fixed memory map, it shall not allocate the area
-   between SCB_OFFSET and SCB_OFFSET+SCB_RESERVED_SIZE-1 inclusive */
-#define SCB_RESERVED_SIZE 0x10000
-
-
-/* This structure is used by EPU to provide memory descriptors in its memory */
-struct cx18_mdl_ent {
-    u32 paddr;  /* Physical address of a buffer segment */
-    u32 length; /* Length of the buffer segment */
-};
-
-struct cx18_scb {
-       /* These fields form the System Control Block which is used at boot time
-          for localizing the IPC data as well as the code positions for all
-          processors. The offsets are from the start of this struct. */
-
-       /* Offset where to find the Inter-Processor Communication data */
-       u32 ipc_offset;
-       u32 reserved01[7];
-       /* Offset where to find the start of the CPU code */
-       u32 cpu_code_offset;
-       u32 reserved02[3];
-       /* Offset where to find the start of the APU code */
-       u32 apu_code_offset;
-       u32 reserved03[3];
-       /* Offset where to find the start of the HPU code */
-       u32 hpu_code_offset;
-       u32 reserved04[3];
-       /* Offset where to find the start of the PPU code */
-       u32 ppu_code_offset;
-       u32 reserved05[3];
-
-       /* These fields form Inter-Processor Communication data which is used
-          by all processors to locate the information needed for communicating
-          with other processors */
-
-       /* Fields for CPU: */
-
-       /* bit 0: 1/0 processor ready/not ready. Set other bits to 0. */
-       u32 cpu_state;
-       u32 reserved1[7];
-       /* Offset to the mailbox used for sending commands from APU to CPU */
-       u32 apu2cpu_mb_offset;
-       /* Value to write to register SW1 register set (0xC7003100) after the
-          command is ready */
-       u32 apu2cpu_irq;
-       /* Value to write to register SW2 register set (0xC7003140) after the
-          command is cleared */
-       u32 cpu2apu_irq_ack;
-       u32 reserved2[13];
-
-       u32 hpu2cpu_mb_offset;
-       u32 hpu2cpu_irq;
-       u32 cpu2hpu_irq_ack;
-       u32 reserved3[13];
-
-       u32 ppu2cpu_mb_offset;
-       u32 ppu2cpu_irq;
-       u32 cpu2ppu_irq_ack;
-       u32 reserved4[13];
-
-       u32 epu2cpu_mb_offset;
-       u32 epu2cpu_irq;
-       u32 cpu2epu_irq_ack;
-       u32 reserved5[13];
-       u32 reserved6[8];
-
-       /* Fields for APU: */
-
-       u32 apu_state;
-       u32 reserved11[7];
-       u32 cpu2apu_mb_offset;
-       u32 cpu2apu_irq;
-       u32 apu2cpu_irq_ack;
-       u32 reserved12[13];
-
-       u32 hpu2apu_mb_offset;
-       u32 hpu2apu_irq;
-       u32 apu2hpu_irq_ack;
-       u32 reserved13[13];
-
-       u32 ppu2apu_mb_offset;
-       u32 ppu2apu_irq;
-       u32 apu2ppu_irq_ack;
-       u32 reserved14[13];
-
-       u32 epu2apu_mb_offset;
-       u32 epu2apu_irq;
-       u32 apu2epu_irq_ack;
-       u32 reserved15[13];
-       u32 reserved16[8];
-
-       /* Fields for HPU: */
-
-       u32 hpu_state;
-       u32 reserved21[7];
-       u32 cpu2hpu_mb_offset;
-       u32 cpu2hpu_irq;
-       u32 hpu2cpu_irq_ack;
-       u32 reserved22[13];
-
-       u32 apu2hpu_mb_offset;
-       u32 apu2hpu_irq;
-       u32 hpu2apu_irq_ack;
-       u32 reserved23[13];
-
-       u32 ppu2hpu_mb_offset;
-       u32 ppu2hpu_irq;
-       u32 hpu2ppu_irq_ack;
-       u32 reserved24[13];
-
-       u32 epu2hpu_mb_offset;
-       u32 epu2hpu_irq;
-       u32 hpu2epu_irq_ack;
-       u32 reserved25[13];
-       u32 reserved26[8];
-
-       /* Fields for PPU: */
-
-       u32 ppu_state;
-       u32 reserved31[7];
-       u32 cpu2ppu_mb_offset;
-       u32 cpu2ppu_irq;
-       u32 ppu2cpu_irq_ack;
-       u32 reserved32[13];
-
-       u32 apu2ppu_mb_offset;
-       u32 apu2ppu_irq;
-       u32 ppu2apu_irq_ack;
-       u32 reserved33[13];
-
-       u32 hpu2ppu_mb_offset;
-       u32 hpu2ppu_irq;
-       u32 ppu2hpu_irq_ack;
-       u32 reserved34[13];
-
-       u32 epu2ppu_mb_offset;
-       u32 epu2ppu_irq;
-       u32 ppu2epu_irq_ack;
-       u32 reserved35[13];
-       u32 reserved36[8];
-
-       /* Fields for EPU: */
-
-       u32 epu_state;
-       u32 reserved41[7];
-       u32 cpu2epu_mb_offset;
-       u32 cpu2epu_irq;
-       u32 epu2cpu_irq_ack;
-       u32 reserved42[13];
-
-       u32 apu2epu_mb_offset;
-       u32 apu2epu_irq;
-       u32 epu2apu_irq_ack;
-       u32 reserved43[13];
-
-       u32 hpu2epu_mb_offset;
-       u32 hpu2epu_irq;
-       u32 epu2hpu_irq_ack;
-       u32 reserved44[13];
-
-       u32 ppu2epu_mb_offset;
-       u32 ppu2epu_irq;
-       u32 epu2ppu_irq_ack;
-       u32 reserved45[13];
-       u32 reserved46[8];
-
-       u32 semaphores[8];  /* Semaphores */
-
-       u32 reserved50[32]; /* Reserved for future use */
-
-       struct cx18_mailbox  apu2cpu_mb;
-       struct cx18_mailbox  hpu2cpu_mb;
-       struct cx18_mailbox  ppu2cpu_mb;
-       struct cx18_mailbox  epu2cpu_mb;
-
-       struct cx18_mailbox  cpu2apu_mb;
-       struct cx18_mailbox  hpu2apu_mb;
-       struct cx18_mailbox  ppu2apu_mb;
-       struct cx18_mailbox  epu2apu_mb;
-
-       struct cx18_mailbox  cpu2hpu_mb;
-       struct cx18_mailbox  apu2hpu_mb;
-       struct cx18_mailbox  ppu2hpu_mb;
-       struct cx18_mailbox  epu2hpu_mb;
-
-       struct cx18_mailbox  cpu2ppu_mb;
-       struct cx18_mailbox  apu2ppu_mb;
-       struct cx18_mailbox  hpu2ppu_mb;
-       struct cx18_mailbox  epu2ppu_mb;
-
-       struct cx18_mailbox  cpu2epu_mb;
-       struct cx18_mailbox  apu2epu_mb;
-       struct cx18_mailbox  hpu2epu_mb;
-       struct cx18_mailbox  ppu2epu_mb;
-
-       struct cx18_mdl_ack  cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];
-       struct cx18_mdl_ent  cpu_mdl[1];
-};
-
-void cx18_init_scb(struct cx18 *cx);
-
-#endif
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
deleted file mode 100644 (file)
index 9d598ab..0000000
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*
- *  cx18 init/start/stop/exit stream functions
- *
- *  Derived from ivtv-streams.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-io.h"
-#include "cx18-fileops.h"
-#include "cx18-mailbox.h"
-#include "cx18-i2c.h"
-#include "cx18-queue.h"
-#include "cx18-ioctl.h"
-#include "cx18-streams.h"
-#include "cx18-cards.h"
-#include "cx18-scb.h"
-#include "cx18-dvb.h"
-
-#define CX18_DSP0_INTERRUPT_MASK       0xd0004C
-
-static struct v4l2_file_operations cx18_v4l2_enc_fops = {
-       .owner = THIS_MODULE,
-       .read = cx18_v4l2_read,
-       .open = cx18_v4l2_open,
-       .unlocked_ioctl = video_ioctl2,
-       .release = cx18_v4l2_close,
-       .poll = cx18_v4l2_enc_poll,
-       .mmap = cx18_v4l2_mmap,
-};
-
-/* offset from 0 to register ts v4l2 minors on */
-#define CX18_V4L2_ENC_TS_OFFSET   16
-/* offset from 0 to register pcm v4l2 minors on */
-#define CX18_V4L2_ENC_PCM_OFFSET  24
-/* offset from 0 to register yuv v4l2 minors on */
-#define CX18_V4L2_ENC_YUV_OFFSET  32
-
-static struct {
-       const char *name;
-       int vfl_type;
-       int num_offset;
-       int dma;
-       enum v4l2_buf_type buf_type;
-} cx18_stream_info[] = {
-       {       /* CX18_ENC_STREAM_TYPE_MPG */
-               "encoder MPEG",
-               VFL_TYPE_GRABBER, 0,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-       },
-       {       /* CX18_ENC_STREAM_TYPE_TS */
-               "TS",
-               VFL_TYPE_GRABBER, -1,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-       },
-       {       /* CX18_ENC_STREAM_TYPE_YUV */
-               "encoder YUV",
-               VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-       },
-       {       /* CX18_ENC_STREAM_TYPE_VBI */
-               "encoder VBI",
-               VFL_TYPE_VBI, 0,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
-       },
-       {       /* CX18_ENC_STREAM_TYPE_PCM */
-               "encoder PCM audio",
-               VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
-       },
-       {       /* CX18_ENC_STREAM_TYPE_IDX */
-               "encoder IDX",
-               VFL_TYPE_GRABBER, -1,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-       },
-       {       /* CX18_ENC_STREAM_TYPE_RAD */
-               "encoder radio",
-               VFL_TYPE_RADIO, 0,
-               PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
-       },
-};
-
-
-void cx18_dma_free(struct videobuf_queue *q,
-       struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
-{
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int cx18_prepare_buffer(struct videobuf_queue *q,
-       struct cx18_stream *s,
-       struct cx18_videobuf_buffer *buf,
-       u32 pixelformat,
-       unsigned int width, unsigned int height,
-       enum v4l2_field field)
-{
-        struct cx18 *cx = s->cx;
-       int rc = 0;
-
-       /* check settings */
-       buf->bytes_used = 0;
-
-       if ((width  < 48) || (height < 32))
-               return -EINVAL;
-
-       buf->vb.size = (width * height * 2);
-       if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
-               return -EINVAL;
-
-       /* alloc + fill struct (if changed) */
-       if (buf->vb.width != width || buf->vb.height != height ||
-           buf->vb.field != field || s->pixelformat != pixelformat ||
-           buf->tvnorm != cx->std) {
-
-               buf->vb.width  = width;
-               buf->vb.height = height;
-               buf->vb.field  = field;
-               buf->tvnorm    = cx->std;
-               s->pixelformat = pixelformat;
-
-               /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-                  UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-               if (s->pixelformat == V4L2_PIX_FMT_HM12)
-                       s->vb_bytes_per_frame = height * 720 * 3 / 2;
-               else
-                       s->vb_bytes_per_frame = height * 720 * 2;
-               cx18_dma_free(q, s, buf);
-       }
-
-       if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
-               return -EINVAL;
-
-       if (buf->vb.field == 0)
-               buf->vb.field = V4L2_FIELD_INTERLACED;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               buf->vb.width  = width;
-               buf->vb.height = height;
-               buf->vb.field  = field;
-               buf->tvnorm    = cx->std;
-               s->pixelformat = pixelformat;
-
-               /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
-                  UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
-               if (s->pixelformat == V4L2_PIX_FMT_HM12)
-                       s->vb_bytes_per_frame = height * 720 * 3 / 2;
-               else
-                       s->vb_bytes_per_frame = height * 720 * 2;
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (rc != 0)
-                       goto fail;
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       cx18_dma_free(q, s, buf);
-       return rc;
-
-}
-
-/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)
-   1440 is a single line of 4:2:2 YUV at 720 luma samples wide
-*/
-#define VB_MIN_BUFFERS 32
-#define VB_MIN_BUFSIZE 4147200
-
-static int buffer_setup(struct videobuf_queue *q,
-       unsigned int *count, unsigned int *size)
-{
-       struct cx18_stream *s = q->priv_data;
-       struct cx18 *cx = s->cx;
-
-       *size = 2 * cx->cxhdl.width * cx->cxhdl.height;
-       if (*count == 0)
-               *count = VB_MIN_BUFFERS;
-
-       while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
-               (*count)--;
-
-       q->field = V4L2_FIELD_INTERLACED;
-       q->last = V4L2_FIELD_INTERLACED;
-
-       return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q,
-       struct videobuf_buffer *vb,
-       enum v4l2_field field)
-{
-       struct cx18_videobuf_buffer *buf =
-               container_of(vb, struct cx18_videobuf_buffer, vb);
-       struct cx18_stream *s = q->priv_data;
-       struct cx18 *cx = s->cx;
-
-       return cx18_prepare_buffer(q, s, buf, s->pixelformat,
-               cx->cxhdl.width, cx->cxhdl.height, field);
-}
-
-static void buffer_release(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
-{
-       struct cx18_videobuf_buffer *buf =
-               container_of(vb, struct cx18_videobuf_buffer, vb);
-       struct cx18_stream *s = q->priv_data;
-
-       cx18_dma_free(q, s, buf);
-}
-
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx18_videobuf_buffer *buf =
-               container_of(vb, struct cx18_videobuf_buffer, vb);
-       struct cx18_stream *s = q->priv_data;
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-
-       list_add_tail(&buf->vb.queue, &s->vb_capture);
-}
-
-static struct videobuf_queue_ops cx18_videobuf_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-static void cx18_stream_init(struct cx18 *cx, int type)
-{
-       struct cx18_stream *s = &cx->streams[type];
-       struct video_device *video_dev = s->video_dev;
-
-       /* we need to keep video_dev, so restore it afterwards */
-       memset(s, 0, sizeof(*s));
-       s->video_dev = video_dev;
-
-       /* initialize cx18_stream fields */
-       s->dvb = NULL;
-       s->cx = cx;
-       s->type = type;
-       s->name = cx18_stream_info[type].name;
-       s->handle = CX18_INVALID_TASK_HANDLE;
-
-       s->dma = cx18_stream_info[type].dma;
-       s->buffers = cx->stream_buffers[type];
-       s->buf_size = cx->stream_buf_size[type];
-       INIT_LIST_HEAD(&s->buf_pool);
-       s->bufs_per_mdl = 1;
-       s->mdl_size = s->buf_size * s->bufs_per_mdl;
-
-       init_waitqueue_head(&s->waitq);
-       s->id = -1;
-       spin_lock_init(&s->q_free.lock);
-       cx18_queue_init(&s->q_free);
-       spin_lock_init(&s->q_busy.lock);
-       cx18_queue_init(&s->q_busy);
-       spin_lock_init(&s->q_full.lock);
-       cx18_queue_init(&s->q_full);
-       spin_lock_init(&s->q_idle.lock);
-       cx18_queue_init(&s->q_idle);
-
-       INIT_WORK(&s->out_work_order, cx18_out_work_handler);
-
-       INIT_LIST_HEAD(&s->vb_capture);
-       s->vb_timeout.function = cx18_vb_timeout;
-       s->vb_timeout.data = (unsigned long)s;
-       init_timer(&s->vb_timeout);
-       spin_lock_init(&s->vb_lock);
-       if (type == CX18_ENC_STREAM_TYPE_YUV) {
-               spin_lock_init(&s->vbuf_q_lock);
-
-               s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,
-                       &cx->pci_dev->dev, &s->vbuf_q_lock,
-                       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       V4L2_FIELD_INTERLACED,
-                       sizeof(struct cx18_videobuf_buffer),
-                       s, &cx->serialize_lock);
-
-               /* Assume the previous pixel default */
-               s->pixelformat = V4L2_PIX_FMT_HM12;
-               s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
-       }
-}
-
-static int cx18_prep_dev(struct cx18 *cx, int type)
-{
-       struct cx18_stream *s = &cx->streams[type];
-       u32 cap = cx->v4l2_cap;
-       int num_offset = cx18_stream_info[type].num_offset;
-       int num = cx->instance + cx18_first_minor + num_offset;
-
-       /*
-        * These five fields are always initialized.
-        * For analog capture related streams, if video_dev == NULL then the
-        * stream is not in use.
-        * For the TS stream, if dvb == NULL then the stream is not in use.
-        * In those cases no other fields but these four can be used.
-        */
-       s->video_dev = NULL;
-       s->dvb = NULL;
-       s->cx = cx;
-       s->type = type;
-       s->name = cx18_stream_info[type].name;
-
-       /* Check whether the radio is supported */
-       if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))
-               return 0;
-
-       /* Check whether VBI is supported */
-       if (type == CX18_ENC_STREAM_TYPE_VBI &&
-           !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
-               return 0;
-
-       /* User explicitly selected 0 buffers for these streams, so don't
-          create them. */
-       if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
-           cx->stream_buffers[type] == 0) {
-               CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
-               return 0;
-       }
-
-       cx18_stream_init(cx, type);
-
-       /* Allocate the cx18_dvb struct only for the TS on cards with DTV */
-       if (type == CX18_ENC_STREAM_TYPE_TS) {
-               if (cx->card->hw_all & CX18_HW_DVB) {
-                       s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
-                       if (s->dvb == NULL) {
-                               CX18_ERR("Couldn't allocate cx18_dvb structure"
-                                        " for %s\n", s->name);
-                               return -ENOMEM;
-                       }
-               } else {
-                       /* Don't need buffers for the TS, if there is no DVB */
-                       s->buffers = 0;
-               }
-       }
-
-       if (num_offset == -1)
-               return 0;
-
-       /* allocate and initialize the v4l2 video device structure */
-       s->video_dev = video_device_alloc();
-       if (s->video_dev == NULL) {
-               CX18_ERR("Couldn't allocate v4l2 video_device for %s\n",
-                               s->name);
-               return -ENOMEM;
-       }
-
-       snprintf(s->video_dev->name, sizeof(s->video_dev->name), "%s %s",
-                cx->v4l2_dev.name, s->name);
-
-       s->video_dev->num = num;
-       s->video_dev->v4l2_dev = &cx->v4l2_dev;
-       s->video_dev->fops = &cx18_v4l2_enc_fops;
-       s->video_dev->release = video_device_release;
-       s->video_dev->tvnorms = V4L2_STD_ALL;
-       s->video_dev->lock = &cx->serialize_lock;
-       set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
-       cx18_set_funcs(s->video_dev);
-       return 0;
-}
-
-/* Initialize v4l2 variables and register v4l2 devices */
-int cx18_streams_setup(struct cx18 *cx)
-{
-       int type, ret;
-
-       /* Setup V4L2 Devices */
-       for (type = 0; type < CX18_MAX_STREAMS; type++) {
-               /* Prepare device */
-               ret = cx18_prep_dev(cx, type);
-               if (ret < 0)
-                       break;
-
-               /* Allocate Stream */
-               ret = cx18_stream_alloc(&cx->streams[type]);
-               if (ret < 0)
-                       break;
-       }
-       if (type == CX18_MAX_STREAMS)
-               return 0;
-
-       /* One or more streams could not be initialized. Clean 'em all up. */
-       cx18_streams_cleanup(cx, 0);
-       return ret;
-}
-
-static int cx18_reg_dev(struct cx18 *cx, int type)
-{
-       struct cx18_stream *s = &cx->streams[type];
-       int vfl_type = cx18_stream_info[type].vfl_type;
-       const char *name;
-       int num, ret;
-
-       if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
-               ret = cx18_dvb_register(s);
-               if (ret < 0) {
-                       CX18_ERR("DVB failed to register\n");
-                       return ret;
-               }
-       }
-
-       if (s->video_dev == NULL)
-               return 0;
-
-       num = s->video_dev->num;
-       /* card number + user defined offset + device offset */
-       if (type != CX18_ENC_STREAM_TYPE_MPG) {
-               struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
-
-               if (s_mpg->video_dev)
-                       num = s_mpg->video_dev->num
-                           + cx18_stream_info[type].num_offset;
-       }
-       video_set_drvdata(s->video_dev, s);
-
-       /* Register device. First try the desired minor, then any free one. */
-       ret = video_register_device_no_warn(s->video_dev, vfl_type, num);
-       if (ret < 0) {
-               CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
-                       s->name, num);
-               video_device_release(s->video_dev);
-               s->video_dev = NULL;
-               return ret;
-       }
-
-       name = video_device_node_name(s->video_dev);
-
-       switch (vfl_type) {
-       case VFL_TYPE_GRABBER:
-               CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
-                         name, s->name, cx->stream_buffers[type],
-                         cx->stream_buf_size[type] / 1024,
-                         (cx->stream_buf_size[type] * 100 / 1024) % 100);
-               break;
-
-       case VFL_TYPE_RADIO:
-               CX18_INFO("Registered device %s for %s\n", name, s->name);
-               break;
-
-       case VFL_TYPE_VBI:
-               if (cx->stream_buffers[type])
-                       CX18_INFO("Registered device %s for %s "
-                                 "(%d x %d bytes)\n",
-                                 name, s->name, cx->stream_buffers[type],
-                                 cx->stream_buf_size[type]);
-               else
-                       CX18_INFO("Registered device %s for %s\n",
-                               name, s->name);
-               break;
-       }
-
-       return 0;
-}
-
-/* Register v4l2 devices */
-int cx18_streams_register(struct cx18 *cx)
-{
-       int type;
-       int err;
-       int ret = 0;
-
-       /* Register V4L2 devices */
-       for (type = 0; type < CX18_MAX_STREAMS; type++) {
-               err = cx18_reg_dev(cx, type);
-               if (err && ret == 0)
-                       ret = err;
-       }
-
-       if (ret == 0)
-               return 0;
-
-       /* One or more streams could not be initialized. Clean 'em all up. */
-       cx18_streams_cleanup(cx, 1);
-       return ret;
-}
-
-/* Unregister v4l2 devices */
-void cx18_streams_cleanup(struct cx18 *cx, int unregister)
-{
-       struct video_device *vdev;
-       int type;
-
-       /* Teardown all streams */
-       for (type = 0; type < CX18_MAX_STREAMS; type++) {
-
-               /* The TS has a cx18_dvb structure, not a video_device */
-               if (type == CX18_ENC_STREAM_TYPE_TS) {
-                       if (cx->streams[type].dvb != NULL) {
-                               if (unregister)
-                                       cx18_dvb_unregister(&cx->streams[type]);
-                               kfree(cx->streams[type].dvb);
-                               cx->streams[type].dvb = NULL;
-                               cx18_stream_free(&cx->streams[type]);
-                       }
-                       continue;
-               }
-
-               /* No struct video_device, but can have buffers allocated */
-               if (type == CX18_ENC_STREAM_TYPE_IDX) {
-                       /* If the module params didn't inhibit IDX ... */
-                       if (cx->stream_buffers[type] != 0) {
-                               cx->stream_buffers[type] = 0;
-                               /*
-                                * Before calling cx18_stream_free(),
-                                * check if the IDX stream was actually set up.
-                                * Needed, since the cx18_probe() error path
-                                * exits through here as well as normal clean up
-                                */
-                               if (cx->streams[type].buffers != 0)
-                                       cx18_stream_free(&cx->streams[type]);
-                       }
-                       continue;
-               }
-
-               /* If struct video_device exists, can have buffers allocated */
-               vdev = cx->streams[type].video_dev;
-
-               cx->streams[type].video_dev = NULL;
-               if (vdev == NULL)
-                       continue;
-
-               if (type == CX18_ENC_STREAM_TYPE_YUV)
-                       videobuf_mmap_free(&cx->streams[type].vbuf_q);
-
-               cx18_stream_free(&cx->streams[type]);
-
-               /* Unregister or release device */
-               if (unregister)
-                       video_unregister_device(vdev);
-               else
-                       video_device_release(vdev);
-       }
-}
-
-static void cx18_vbi_setup(struct cx18_stream *s)
-{
-       struct cx18 *cx = s->cx;
-       int raw = cx18_raw_vbi(cx);
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       int lines;
-
-       if (cx->is_60hz) {
-               cx->vbi.count = 12;
-               cx->vbi.start[0] = 10;
-               cx->vbi.start[1] = 273;
-       } else {        /* PAL/SECAM */
-               cx->vbi.count = 18;
-               cx->vbi.start[0] = 6;
-               cx->vbi.start[1] = 318;
-       }
-
-       /* setup VBI registers */
-       if (raw)
-               v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi);
-       else
-               v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced);
-
-       /*
-        * Send the CX18_CPU_SET_RAW_VBI_PARAM API command to setup Encoder Raw
-        * VBI when the first analog capture channel starts, as once it starts
-        * (e.g. MPEG), we can't effect any change in the Encoder Raw VBI setup
-        * (i.e. for the VBI capture channels).  We also send it for each
-        * analog capture channel anyway just to make sure we get the proper
-        * behavior
-        */
-       if (raw) {
-               lines = cx->vbi.count * 2;
-       } else {
-               /*
-                * For 525/60 systems, according to the VIP 2 & BT.656 std:
-                * The EAV RP code's Field bit toggles on line 4, a few lines
-                * after the Vertcal Blank bit has already toggled.
-                * Tell the encoder to capture 21-4+1=18 lines per field,
-                * since we want lines 10 through 21.
-                *
-                * For 625/50 systems, according to the VIP 2 & BT.656 std:
-                * The EAV RP code's Field bit toggles on line 1, a few lines
-                * after the Vertcal Blank bit has already toggled.
-                * (We've actually set the digitizer so that the Field bit
-                * toggles on line 2.) Tell the encoder to capture 23-2+1=22
-                * lines per field, since we want lines 6 through 23.
-                */
-               lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2;
-       }
-
-       data[0] = s->handle;
-       /* Lines per field */
-       data[1] = (lines / 2) | ((lines / 2) << 16);
-       /* bytes per line */
-       data[2] = (raw ? vbi_active_samples
-                      : (cx->is_60hz ? vbi_hblank_samples_60Hz
-                                     : vbi_hblank_samples_50Hz));
-       /* Every X number of frames a VBI interrupt arrives
-          (frames as in 25 or 30 fps) */
-       data[3] = 1;
-       /*
-        * Set the SAV/EAV RP codes to look for as start/stop points
-        * when in VIP-1.1 mode
-        */
-       if (raw) {
-               /*
-                * Start codes for beginning of "active" line in vertical blank
-                * 0x20 (               VerticalBlank                )
-                * 0x60 (     EvenField VerticalBlank                )
-                */
-               data[4] = 0x20602060;
-               /*
-                * End codes for end of "active" raw lines and regular lines
-                * 0x30 (               VerticalBlank HorizontalBlank)
-                * 0x70 (     EvenField VerticalBlank HorizontalBlank)
-                * 0x90 (Task                         HorizontalBlank)
-                * 0xd0 (Task EvenField               HorizontalBlank)
-                */
-               data[5] = 0x307090d0;
-       } else {
-               /*
-                * End codes for active video, we want data in the hblank region
-                * 0xb0 (Task         0 VerticalBlank HorizontalBlank)
-                * 0xf0 (Task EvenField VerticalBlank HorizontalBlank)
-                *
-                * Since the V bit is only allowed to toggle in the EAV RP code,
-                * just before the first active region line, these two
-                * are problematic:
-                * 0x90 (Task                         HorizontalBlank)
-                * 0xd0 (Task EvenField               HorizontalBlank)
-                *
-                * We have set the digitzer such that we don't have to worry
-                * about these problem codes.
-                */
-               data[4] = 0xB0F0B0F0;
-               /*
-                * Start codes for beginning of active line in vertical blank
-                * 0xa0 (Task           VerticalBlank                )
-                * 0xe0 (Task EvenField VerticalBlank                )
-                */
-               data[5] = 0xA0E0A0E0;
-       }
-
-       CX18_DEBUG_INFO("Setup VBI h: %d lines %x bpl %d fr %d %x %x\n",
-                       data[0], data[1], data[2], data[3], data[4], data[5]);
-
-       cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
-}
-
-void cx18_stream_rotate_idx_mdls(struct cx18 *cx)
-{
-       struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-       struct cx18_mdl *mdl;
-
-       if (!cx18_stream_enabled(s))
-               return;
-
-       /* Return if the firmware is not running low on MDLs */
-       if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >=
-                                           CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN)
-               return;
-
-       /* Return if there are no MDLs to rotate back to the firmware */
-       if (atomic_read(&s->q_full.depth) < 2)
-               return;
-
-       /*
-        * Take the oldest IDX MDL still holding data, and discard its index
-        * entries by scheduling the MDL to go back to the firmware
-        */
-       mdl = cx18_dequeue(s, &s->q_full);
-       if (mdl != NULL)
-               cx18_enqueue(s, mdl, &s->q_free);
-}
-
-static
-struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,
-                                          struct cx18_mdl *mdl)
-{
-       struct cx18 *cx = s->cx;
-       struct cx18_queue *q;
-
-       /* Don't give it to the firmware, if we're not running a capture */
-       if (s->handle == CX18_INVALID_TASK_HANDLE ||
-           test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
-           !test_bit(CX18_F_S_STREAMING, &s->s_flags))
-               return cx18_enqueue(s, mdl, &s->q_free);
-
-       q = cx18_enqueue(s, mdl, &s->q_busy);
-       if (q != &s->q_busy)
-               return q; /* The firmware has the max MDLs it can handle */
-
-       cx18_mdl_sync_for_device(s, mdl);
-       cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
-                 (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem,
-                 s->bufs_per_mdl, mdl->id, s->mdl_size);
-       return q;
-}
-
-static
-void _cx18_stream_load_fw_queue(struct cx18_stream *s)
-{
-       struct cx18_queue *q;
-       struct cx18_mdl *mdl;
-
-       if (atomic_read(&s->q_free.depth) == 0 ||
-           atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
-               return;
-
-       /* Move from q_free to q_busy notifying the firmware, until the limit */
-       do {
-               mdl = cx18_dequeue(s, &s->q_free);
-               if (mdl == NULL)
-                       break;
-               q = _cx18_stream_put_mdl_fw(s, mdl);
-       } while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM
-                && q == &s->q_busy);
-}
-
-void cx18_out_work_handler(struct work_struct *work)
-{
-       struct cx18_stream *s =
-                        container_of(work, struct cx18_stream, out_work_order);
-
-       _cx18_stream_load_fw_queue(s);
-}
-
-static void cx18_stream_configure_mdls(struct cx18_stream *s)
-{
-       cx18_unload_queues(s);
-
-       switch (s->type) {
-       case CX18_ENC_STREAM_TYPE_YUV:
-               /*
-                * Height should be a multiple of 32 lines.
-                * Set the MDL size to the exact size needed for one frame.
-                * Use enough buffers per MDL to cover the MDL size
-                */
-               if (s->pixelformat == V4L2_PIX_FMT_HM12)
-                       s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
-               else
-                       s->mdl_size = 720 * s->cx->cxhdl.height * 2;
-               s->bufs_per_mdl = s->mdl_size / s->buf_size;
-               if (s->mdl_size % s->buf_size)
-                       s->bufs_per_mdl++;
-               break;
-       case CX18_ENC_STREAM_TYPE_VBI:
-               s->bufs_per_mdl = 1;
-               if  (cx18_raw_vbi(s->cx)) {
-                       s->mdl_size = (s->cx->is_60hz ? 12 : 18)
-                                                      * 2 * vbi_active_samples;
-               } else {
-                       /*
-                        * See comment in cx18_vbi_setup() below about the
-                        * extra lines we capture in sliced VBI mode due to
-                        * the lines on which EAV RP codes toggle.
-                       */
-                       s->mdl_size = s->cx->is_60hz
-                                  ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz
-                                  : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;
-               }
-               break;
-       default:
-               s->bufs_per_mdl = 1;
-               s->mdl_size = s->buf_size * s->bufs_per_mdl;
-               break;
-       }
-
-       cx18_load_queues(s);
-}
-
-int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
-{
-       u32 data[MAX_MB_ARGUMENTS];
-       struct cx18 *cx = s->cx;
-       int captype = 0;
-       struct cx18_stream *s_idx;
-
-       if (!cx18_stream_enabled(s))
-               return -EINVAL;
-
-       CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
-
-       switch (s->type) {
-       case CX18_ENC_STREAM_TYPE_MPG:
-               captype = CAPTURE_CHANNEL_TYPE_MPEG;
-               cx->mpg_data_received = cx->vbi_data_inserted = 0;
-               cx->dualwatch_jiffies = jiffies;
-               cx->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
-               cx->search_pack_header = 0;
-               break;
-
-       case CX18_ENC_STREAM_TYPE_IDX:
-               captype = CAPTURE_CHANNEL_TYPE_INDEX;
-               break;
-       case CX18_ENC_STREAM_TYPE_TS:
-               captype = CAPTURE_CHANNEL_TYPE_TS;
-               break;
-       case CX18_ENC_STREAM_TYPE_YUV:
-               captype = CAPTURE_CHANNEL_TYPE_YUV;
-               break;
-       case CX18_ENC_STREAM_TYPE_PCM:
-               captype = CAPTURE_CHANNEL_TYPE_PCM;
-               break;
-       case CX18_ENC_STREAM_TYPE_VBI:
-#ifdef CX18_ENCODER_PARSES_SLICED
-               captype = cx18_raw_vbi(cx) ?
-                    CAPTURE_CHANNEL_TYPE_VBI : CAPTURE_CHANNEL_TYPE_SLICED_VBI;
-#else
-               /*
-                * Currently we set things up so that Sliced VBI from the
-                * digitizer is handled as Raw VBI by the encoder
-                */
-               captype = CAPTURE_CHANNEL_TYPE_VBI;
-#endif
-               cx->vbi.frame = 0;
-               cx->vbi.inserted_frame = 0;
-               memset(cx->vbi.sliced_mpeg_size,
-                       0, sizeof(cx->vbi.sliced_mpeg_size));
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* Clear Streamoff flags in case left from last capture */
-       clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
-
-       cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);
-       s->handle = data[0];
-       cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
-
-       /*
-        * For everything but CAPTURE_CHANNEL_TYPE_TS, play it safe and
-        * set up all the parameters, as it is not obvious which parameters the
-        * firmware shares across capture channel types and which it does not.
-        *
-        * Some of the cx18_vapi() calls below apply to only certain capture
-        * channel types.  We're hoping there's no harm in calling most of them
-        * anyway, as long as the values are all consistent.  Setting some
-        * shared parameters will have no effect once an analog capture channel
-        * has started streaming.
-        */
-       if (captype != CAPTURE_CHANNEL_TYPE_TS) {
-               cx18_vapi(cx, CX18_CPU_SET_VER_CROP_LINE, 2, s->handle, 0);
-               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 3, 1);
-               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 8, 0);
-               cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 3, s->handle, 4, 1);
-
-               /*
-                * Audio related reset according to
-                * Documentation/video4linux/cx2341x/fw-encoder-api.txt
-                */
-               if (atomic_read(&cx->ana_capturing) == 0)
-                       cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
-                                 s->handle, 12);
-
-               /*
-                * Number of lines for Field 1 & Field 2 according to
-                * Documentation/video4linux/cx2341x/fw-encoder-api.txt
-                * Field 1 is 312 for 625 line systems in BT.656
-                * Field 2 is 313 for 625 line systems in BT.656
-                */
-               cx18_vapi(cx, CX18_CPU_SET_CAPTURE_LINE_NO, 3,
-                         s->handle, 312, 313);
-
-               if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
-                       cx18_vbi_setup(s);
-
-               /*
-                * Select to receive I, P, and B frame index entries, if the
-                * index stream is enabled.  Otherwise disable index entry
-                * generation.
-                */
-               s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
-               cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2,
-                                s->handle, cx18_stream_enabled(s_idx) ? 7 : 0);
-
-               /* Call out to the common CX2341x API setup for user controls */
-               cx->cxhdl.priv = s;
-               cx2341x_handler_setup(&cx->cxhdl);
-
-               /*
-                * When starting a capture and we're set for radio,
-                * ensure the video is muted, despite the user control.
-                */
-               if (!cx->cxhdl.video_mute &&
-                   test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
-                       cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
-                         (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);
-
-               /* Enable the Video Format Converter for UYVY 4:2:2 support,
-                * rather than the default HM12 Macroblovk 4:2:0 support.
-                */
-               if (captype == CAPTURE_CHANNEL_TYPE_YUV) {
-                       if (s->pixelformat == V4L2_PIX_FMT_UYVY)
-                               cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
-                                       s->handle, 1);
-                       else
-                               /* If in doubt, default to HM12 */
-                               cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
-                                       s->handle, 0);
-               }
-       }
-
-       if (atomic_read(&cx->tot_capturing) == 0) {
-               cx2341x_handler_set_busy(&cx->cxhdl, 1);
-               clear_bit(CX18_F_I_EOS, &cx->i_flags);
-               cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
-       }
-
-       cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
-               (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
-               (void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
-
-       /* Init all the cpu_mdls for this stream */
-       cx18_stream_configure_mdls(s);
-       _cx18_stream_load_fw_queue(s);
-
-       /* begin_capture */
-       if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
-               CX18_DEBUG_WARN("Error starting capture!\n");
-               /* Ensure we're really not capturing before releasing MDLs */
-               set_bit(CX18_F_S_STOPPING, &s->s_flags);
-               if (s->type == CX18_ENC_STREAM_TYPE_MPG)
-                       cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
-               else
-                       cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
-               clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-               /* FIXME - CX18_F_S_STREAMOFF as well? */
-               cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
-               cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
-               s->handle = CX18_INVALID_TASK_HANDLE;
-               clear_bit(CX18_F_S_STOPPING, &s->s_flags);
-               if (atomic_read(&cx->tot_capturing) == 0) {
-                       set_bit(CX18_F_I_EOS, &cx->i_flags);
-                       cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
-               }
-               return -EINVAL;
-       }
-
-       /* you're live! sit back and await interrupts :) */
-       if (captype != CAPTURE_CHANNEL_TYPE_TS)
-               atomic_inc(&cx->ana_capturing);
-       atomic_inc(&cx->tot_capturing);
-       return 0;
-}
-EXPORT_SYMBOL(cx18_start_v4l2_encode_stream);
-
-void cx18_stop_all_captures(struct cx18 *cx)
-{
-       int i;
-
-       for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
-               struct cx18_stream *s = &cx->streams[i];
-
-               if (!cx18_stream_enabled(s))
-                       continue;
-               if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
-                       cx18_stop_v4l2_encode_stream(s, 0);
-       }
-}
-
-int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
-{
-       struct cx18 *cx = s->cx;
-
-       if (!cx18_stream_enabled(s))
-               return -EINVAL;
-
-       /* This function assumes that you are allowed to stop the capture
-          and that we are actually capturing */
-
-       CX18_DEBUG_INFO("Stop Capture\n");
-
-       if (atomic_read(&cx->tot_capturing) == 0)
-               return 0;
-
-       set_bit(CX18_F_S_STOPPING, &s->s_flags);
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG)
-               cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
-       else
-               cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
-
-       if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {
-               CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
-       }
-
-       if (s->type != CX18_ENC_STREAM_TYPE_TS)
-               atomic_dec(&cx->ana_capturing);
-       atomic_dec(&cx->tot_capturing);
-
-       /* Clear capture and no-read bits */
-       clear_bit(CX18_F_S_STREAMING, &s->s_flags);
-
-       /* Tell the CX23418 it can't use our buffers anymore */
-       cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
-
-       cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
-       s->handle = CX18_INVALID_TASK_HANDLE;
-       clear_bit(CX18_F_S_STOPPING, &s->s_flags);
-
-       if (atomic_read(&cx->tot_capturing) > 0)
-               return 0;
-
-       cx2341x_handler_set_busy(&cx->cxhdl, 0);
-       cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
-       wake_up(&s->waitq);
-
-       return 0;
-}
-EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream);
-
-u32 cx18_find_handle(struct cx18 *cx)
-{
-       int i;
-
-       /* find first available handle to be used for global settings */
-       for (i = 0; i < CX18_MAX_STREAMS; i++) {
-               struct cx18_stream *s = &cx->streams[i];
-
-               if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE))
-                       return s->handle;
-       }
-       return CX18_INVALID_TASK_HANDLE;
-}
-
-struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle)
-{
-       int i;
-       struct cx18_stream *s;
-
-       if (handle == CX18_INVALID_TASK_HANDLE)
-               return NULL;
-
-       for (i = 0; i < CX18_MAX_STREAMS; i++) {
-               s = &cx->streams[i];
-               if (s->handle != handle)
-                       continue;
-               if (cx18_stream_enabled(s))
-                       return s;
-       }
-       return NULL;
-}
diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h
deleted file mode 100644 (file)
index 713b0e6..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  cx18 init/start/stop/exit stream functions
- *
- *  Derived from ivtv-streams.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-u32 cx18_find_handle(struct cx18 *cx);
-struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle);
-int cx18_streams_setup(struct cx18 *cx);
-int cx18_streams_register(struct cx18 *cx);
-void cx18_streams_cleanup(struct cx18 *cx, int unregister);
-
-#define CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN (3)
-void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
-
-static inline bool cx18_stream_enabled(struct cx18_stream *s)
-{
-       return s->video_dev ||
-              (s->dvb && s->dvb->enabled) ||
-              (s->type == CX18_ENC_STREAM_TYPE_IDX &&
-               s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
-}
-
-/* Related to submission of mdls to firmware */
-static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
-{
-       schedule_work(&s->out_work_order);
-}
-
-static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s,
-                                         struct cx18_mdl *mdl)
-{
-       /* Put mdl on q_free; the out work handler will move mdl(s) to q_busy */
-       cx18_enqueue(s, mdl, &s->q_free);
-       cx18_stream_load_fw_queue(s);
-}
-
-void cx18_out_work_handler(struct work_struct *work);
-
-/* Capture related */
-int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
-int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
-
-void cx18_stop_all_captures(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx18-vbi.c b/drivers/media/video/cx18/cx18-vbi.c
deleted file mode 100644 (file)
index 6d3121f..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- *  cx18 Vertical Blank Interval support functions
- *
- *  Derived from ivtv-vbi.c
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-vbi.h"
-#include "cx18-ioctl.h"
-#include "cx18-queue.h"
-
-/*
- * Raster Reference/Protection (RP) bytes, used in Start/End Active
- * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start
- * of VBI sample or VBI ancillary data regions in the digitial ratser line.
- *
- * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0
- */
-static const u8 raw_vbi_sav_rp[2] = { 0x20, 0x60 };    /* __V_, _FV_ */
-static const u8 sliced_vbi_eav_rp[2] = { 0xb0, 0xf0 }; /* T_VH, TFVH */
-
-static void copy_vbi_data(struct cx18 *cx, int lines, u32 pts_stamp)
-{
-       int line = 0;
-       int i;
-       u32 linemask[2] = { 0, 0 };
-       unsigned short size;
-       static const u8 mpeg_hdr_data[] = {
-               /* MPEG-2 Program Pack */
-               0x00, 0x00, 0x01, 0xba,             /* Prog Pack start code */
-               0x44, 0x00, 0x0c, 0x66, 0x24, 0x01, /* SCR, SCR Ext, markers */
-               0x01, 0xd1, 0xd3,                   /* Mux Rate, markers */
-               0xfa, 0xff, 0xff,                   /* Res, Suff cnt, Stuff */
-               /* MPEG-2 Private Stream 1 PES Packet */
-               0x00, 0x00, 0x01, 0xbd,             /* Priv Stream 1 start */
-               0x00, 0x1a,                         /* length */
-               0x84, 0x80, 0x07,                   /* flags, hdr data len */
-               0x21, 0x00, 0x5d, 0x63, 0xa7,       /* PTS, markers */
-               0xff, 0xff                          /* stuffing */
-       };
-       const int sd = sizeof(mpeg_hdr_data);   /* start of vbi data */
-       int idx = cx->vbi.frame % CX18_VBI_FRAMES;
-       u8 *dst = &cx->vbi.sliced_mpeg_data[idx][0];
-
-       for (i = 0; i < lines; i++) {
-               struct v4l2_sliced_vbi_data *sdata = cx->vbi.sliced_data + i;
-               int f, l;
-
-               if (sdata->id == 0)
-                       continue;
-
-               l = sdata->line - 6;
-               f = sdata->field;
-               if (f)
-                       l += 18;
-               if (l < 32)
-                       linemask[0] |= (1 << l);
-               else
-                       linemask[1] |= (1 << (l - 32));
-               dst[sd + 12 + line * 43] = cx18_service2vbi(sdata->id);
-               memcpy(dst + sd + 12 + line * 43 + 1, sdata->data, 42);
-               line++;
-       }
-       memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
-       if (line == 36) {
-               /* All lines are used, so there is no space for the linemask
-                  (the max size of the VBI data is 36 * 43 + 4 bytes).
-                  So in this case we use the magic number 'ITV0'. */
-               memcpy(dst + sd, "ITV0", 4);
-               memcpy(dst + sd + 4, dst + sd + 12, line * 43);
-               size = 4 + ((43 * line + 3) & ~3);
-       } else {
-               memcpy(dst + sd, "itv0", 4);
-               cpu_to_le32s(&linemask[0]);
-               cpu_to_le32s(&linemask[1]);
-               memcpy(dst + sd + 4, &linemask[0], 8);
-               size = 12 + ((43 * line + 3) & ~3);
-       }
-       dst[4+16] = (size + 10) >> 8;
-       dst[5+16] = (size + 10) & 0xff;
-       dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
-       dst[10+16] = (pts_stamp >> 22) & 0xff;
-       dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
-       dst[12+16] = (pts_stamp >> 7) & 0xff;
-       dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
-       cx->vbi.sliced_mpeg_size[idx] = sd + size;
-}
-
-/* Compress raw VBI format, removes leading SAV codes and surplus space
-   after the frame.  Returns new compressed size. */
-/* FIXME - this function ignores the input size. */
-static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size)
-{
-       u32 line_size = vbi_active_samples;
-       u32 lines = cx->vbi.count * 2;
-       u8 *q = buf;
-       u8 *p;
-       int i;
-
-       /* Skip the header */
-       buf += hdr_size;
-
-       for (i = 0; i < lines; i++) {
-               p = buf + i * line_size;
-
-               /* Look for SAV code */
-               if (p[0] != 0xff || p[1] || p[2] ||
-                   (p[3] != raw_vbi_sav_rp[0] &&
-                    p[3] != raw_vbi_sav_rp[1]))
-                       break;
-               if (i == lines - 1) {
-                       /* last line is hdr_size bytes short - extrapolate it */
-                       memcpy(q, p + 4, line_size - 4 - hdr_size);
-                       q += line_size - 4 - hdr_size;
-                       p += line_size - hdr_size - 1;
-                       memset(q, (int) *p, hdr_size);
-               } else {
-                       memcpy(q, p + 4, line_size - 4);
-                       q += line_size - 4;
-               }
-       }
-       return lines * (line_size - 4);
-}
-
-static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
-                              const u32 hdr_size)
-{
-       struct v4l2_decode_vbi_line vbi;
-       int i;
-       u32 line = 0;
-       u32 line_size = cx->is_60hz ? vbi_hblank_samples_60Hz
-                                   : vbi_hblank_samples_50Hz;
-
-       /* find the first valid line */
-       for (i = hdr_size, buf += hdr_size; i < size; i++, buf++) {
-               if (buf[0] == 0xff && !buf[1] && !buf[2] &&
-                   (buf[3] == sliced_vbi_eav_rp[0] ||
-                    buf[3] == sliced_vbi_eav_rp[1]))
-                       break;
-       }
-
-       /*
-        * The last line is short by hdr_size bytes, but for the remaining
-        * checks against size, we pretend that it is not, by counting the
-        * header bytes we knowingly skipped
-        */
-       size -= (i - hdr_size);
-       if (size < line_size)
-               return line;
-
-       for (i = 0; i < size / line_size; i++) {
-               u8 *p = buf + i * line_size;
-
-               /* Look for EAV code  */
-               if (p[0] != 0xff || p[1] || p[2] ||
-                   (p[3] != sliced_vbi_eav_rp[0] &&
-                    p[3] != sliced_vbi_eav_rp[1]))
-                       continue;
-               vbi.p = p + 4;
-               v4l2_subdev_call(cx->sd_av, vbi, decode_vbi_line, &vbi);
-               if (vbi.type) {
-                       cx->vbi.sliced_data[line].id = vbi.type;
-                       cx->vbi.sliced_data[line].field = vbi.is_second_field;
-                       cx->vbi.sliced_data[line].line = vbi.line;
-                       memcpy(cx->vbi.sliced_data[line].data, vbi.p, 42);
-                       line++;
-               }
-       }
-       return line;
-}
-
-static void _cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf)
-{
-       /*
-        * The CX23418 provides a 12 byte header in its raw VBI buffers to us:
-        * 0x3fffffff [4 bytes of something] [4 byte presentation time stamp]
-        */
-       struct vbi_data_hdr {
-               __be32 magic;
-               __be32 unknown;
-               __be32 pts;
-       } *hdr = (struct vbi_data_hdr *) buf->buf;
-
-       u8 *p = (u8 *) buf->buf;
-       u32 size = buf->bytesused;
-       u32 pts;
-       int lines;
-
-       /*
-        * The CX23418 sends us data that is 32 bit little-endian swapped,
-        * but we want the raw VBI bytes in the order they were in the raster
-        * line.  This has a side effect of making the header big endian
-        */
-       cx18_buf_swap(buf);
-
-       /* Raw VBI data */
-       if (cx18_raw_vbi(cx)) {
-
-               size = buf->bytesused =
-                    compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr));
-
-               /*
-                * Hack needed for compatibility with old VBI software.
-                * Write the frame # at the last 4 bytes of the frame
-                */
-               p += size - 4;
-               memcpy(p, &cx->vbi.frame, 4);
-               cx->vbi.frame++;
-               return;
-       }
-
-       /* Sliced VBI data with data insertion */
-
-       pts = (be32_to_cpu(hdr->magic) == 0x3fffffff) ? be32_to_cpu(hdr->pts)
-                                                     : 0;
-
-       lines = compress_sliced_buf(cx, p, size, sizeof(struct vbi_data_hdr));
-
-       /* always return at least one empty line */
-       if (lines == 0) {
-               cx->vbi.sliced_data[0].id = 0;
-               cx->vbi.sliced_data[0].line = 0;
-               cx->vbi.sliced_data[0].field = 0;
-               lines = 1;
-       }
-       buf->bytesused = size = lines * sizeof(cx->vbi.sliced_data[0]);
-       memcpy(p, &cx->vbi.sliced_data[0], size);
-
-       if (cx->vbi.insert_mpeg)
-               copy_vbi_data(cx, lines, pts);
-       cx->vbi.frame++;
-}
-
-void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
-                          int streamtype)
-{
-       struct cx18_buffer *buf;
-       u32 orig_used;
-
-       if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
-               return;
-
-       /*
-        * Big assumption here:
-        * Every buffer hooked to the MDL's buf_list is a complete VBI frame
-        * that ends at the end of the buffer.
-        *
-        * To assume anything else would make the code in this file
-        * more complex, or require extra memcpy()'s to make the
-        * buffers satisfy the above assumption.  It's just simpler to set
-        * up the encoder buffer transfers to make the assumption true.
-        */
-       list_for_each_entry(buf, &mdl->buf_list, list) {
-               orig_used = buf->bytesused;
-               if (orig_used == 0)
-                       break;
-               _cx18_process_vbi_data(cx, buf);
-               mdl->bytesused -= (orig_used - buf->bytesused);
-       }
-}
diff --git a/drivers/media/video/cx18/cx18-vbi.h b/drivers/media/video/cx18/cx18-vbi.h
deleted file mode 100644 (file)
index b365cf4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  cx18 Vertical Blank Interval support functions
- *
- *  Derived from ivtv-vbi.h
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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
- */
-
-void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
-                          int streamtype);
-int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/drivers/media/video/cx18/cx18-version.h b/drivers/media/video/cx18/cx18-version.h
deleted file mode 100644 (file)
index fed48b6..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  cx18 driver version information
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#ifndef CX18_VERSION_H
-#define CX18_VERSION_H
-
-#define CX18_DRIVER_NAME "cx18"
-#define CX18_VERSION "1.5.1"
-
-#endif
diff --git a/drivers/media/video/cx18/cx18-video.c b/drivers/media/video/cx18/cx18-video.c
deleted file mode 100644 (file)
index 6dc84aa..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  cx18 video interface functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#include "cx18-driver.h"
-#include "cx18-video.h"
-#include "cx18-cards.h"
-
-void cx18_video_set_io(struct cx18 *cx)
-{
-       int inp = cx->active_input;
-
-       v4l2_subdev_call(cx->sd_av, video, s_routing,
-                       cx->card->video_inputs[inp].video_input, 0, 0);
-}
diff --git a/drivers/media/video/cx18/cx18-video.h b/drivers/media/video/cx18/cx18-video.h
deleted file mode 100644 (file)
index 529006a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  cx18 video interface functions
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  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
- */
-
-void cx18_video_set_io(struct cx18 *cx);
diff --git a/drivers/media/video/cx18/cx23418.h b/drivers/media/video/cx18/cx23418.h
deleted file mode 100644 (file)
index 767a8d2..0000000
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- *  cx18 header containing common defines.
- *
- *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- *  02111-1307  USA
- */
-
-#ifndef CX23418_H
-#define CX23418_H
-
-#include <media/cx2341x.h>
-
-#define MGR_CMD_MASK                           0x40000000
-/* The MSB of the command code indicates that this is the completion of a
-   command */
-#define MGR_CMD_MASK_ACK                       (MGR_CMD_MASK | 0x80000000)
-
-/* Description: This command creates a new instance of a certain task
-   IN[0]  - Task ID. This is one of the XPU_CMD_MASK_YYY where XPU is
-           the processor on which the task YYY will be created
-   OUT[0] - Task handle. This handle is passed along with commands to
-           dispatch to the right instance of the task
-   ReturnCode - One of the ERR_SYS_... */
-#define CX18_CREATE_TASK                       (MGR_CMD_MASK | 0x0001)
-
-/* Description: This command destroys an instance of a task
-   IN[0] - Task handle. Hanlde of the task to destroy
-   ReturnCode - One of the ERR_SYS_... */
-#define CX18_DESTROY_TASK                      (MGR_CMD_MASK | 0x0002)
-
-/* All commands for CPU have the following mask set */
-#define CPU_CMD_MASK                           0x20000000
-#define CPU_CMD_MASK_DEBUG                     (CPU_CMD_MASK | 0x00000000)
-#define CPU_CMD_MASK_ACK                       (CPU_CMD_MASK | 0x80000000)
-#define CPU_CMD_MASK_CAPTURE                   (CPU_CMD_MASK | 0x00020000)
-#define CPU_CMD_MASK_TS                        (CPU_CMD_MASK | 0x00040000)
-
-#define EPU_CMD_MASK                           0x02000000
-#define EPU_CMD_MASK_DEBUG                     (EPU_CMD_MASK | 0x000000)
-#define EPU_CMD_MASK_DE                        (EPU_CMD_MASK | 0x040000)
-
-#define APU_CMD_MASK                           0x10000000
-#define APU_CMD_MASK_ACK                       (APU_CMD_MASK | 0x80000000)
-
-#define CX18_APU_ENCODING_METHOD_MPEG          (0 << 28)
-#define CX18_APU_ENCODING_METHOD_AC3           (1 << 28)
-
-/* Description: Command APU to start audio
-   IN[0] - audio parameters (same as CX18_CPU_SET_AUDIO_PARAMETERS?)
-   IN[1] - caller buffer address, or 0
-   ReturnCode - ??? */
-#define CX18_APU_START                         (APU_CMD_MASK | 0x01)
-
-/* Description: Command APU to stop audio
-   IN[0] - encoding method to stop
-   ReturnCode - ??? */
-#define CX18_APU_STOP                          (APU_CMD_MASK | 0x02)
-
-/* Description: Command APU to reset the AI
-   ReturnCode - ??? */
-#define CX18_APU_RESETAI                       (APU_CMD_MASK | 0x05)
-
-/* Description: This command indicates that a Memory Descriptor List has been
-   filled with the requested channel type
-   IN[0] - Task handle. Handle of the task
-   IN[1] - Offset of the MDL_ACK from the beginning of the local DDR.
-   IN[2] - Number of CNXT_MDL_ACK structures in the array pointed to by IN[1]
-   ReturnCode - One of the ERR_DE_... */
-#define CX18_EPU_DMA_DONE                              (EPU_CMD_MASK_DE | 0x0001)
-
-/* Something interesting happened
-   IN[0] - A value to log
-   IN[1] - An offset of a string in the MiniMe memory;
-          0/zero/NULL means "I have nothing to say" */
-#define CX18_EPU_DEBUG                                 (EPU_CMD_MASK_DEBUG | 0x0003)
-
-/* Reads memory/registers (32-bit)
-   IN[0] - Address
-   OUT[1] - Value */
-#define CX18_CPU_DEBUG_PEEK32                  (CPU_CMD_MASK_DEBUG | 0x0003)
-
-/* Description: This command starts streaming with the set channel type
-   IN[0] - Task handle. Handle of the task to start
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_CAPTURE_START                 (CPU_CMD_MASK_CAPTURE | 0x0002)
-
-/* Description: This command stops streaming with the set channel type
-   IN[0] - Task handle. Handle of the task to stop
-   IN[1] - 0 = stop at end of GOP, 1 = stop at end of frame (MPEG only)
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_CAPTURE_STOP                  (CPU_CMD_MASK_CAPTURE | 0x0003)
-
-/* Description: This command pauses streaming with the set channel type
-   IN[0] - Task handle. Handle of the task to pause
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_CAPTURE_PAUSE                 (CPU_CMD_MASK_CAPTURE | 0x0007)
-
-/* Description: This command resumes streaming with the set channel type
-   IN[0] - Task handle. Handle of the task to resume
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_CAPTURE_RESUME                (CPU_CMD_MASK_CAPTURE | 0x0008)
-
-#define CAPTURE_CHANNEL_TYPE_NONE              0
-#define CAPTURE_CHANNEL_TYPE_MPEG              1
-#define CAPTURE_CHANNEL_TYPE_INDEX             2
-#define CAPTURE_CHANNEL_TYPE_YUV               3
-#define CAPTURE_CHANNEL_TYPE_PCM               4
-#define CAPTURE_CHANNEL_TYPE_VBI               5
-#define CAPTURE_CHANNEL_TYPE_SLICED_VBI                6
-#define CAPTURE_CHANNEL_TYPE_TS                        7
-#define CAPTURE_CHANNEL_TYPE_MAX               15
-
-/* Description: This command sets the channel type. This can only be done
-   when stopped.
-   IN[0] - Task handle. Handle of the task to start
-   IN[1] - Channel Type. See Below.
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_CHANNEL_TYPE                      (CPU_CMD_MASK_CAPTURE + 1)
-
-/* Description: Set stream output type
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - type
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_STREAM_OUTPUT_TYPE                (CPU_CMD_MASK_CAPTURE | 0x0012)
-
-/* Description: Set video input resolution and frame rate
-   IN[0] - task handle
-   IN[1] - reserved
-   IN[2] - reserved
-   IN[3] - reserved
-   IN[4] - reserved
-   IN[5] - frame rate, 0 - 29.97f/s, 1 - 25f/s
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_VIDEO_IN                  (CPU_CMD_MASK_CAPTURE | 0x0004)
-
-/* Description: Set video frame rate
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - video bit rate mode
-   IN[2] - video average rate
-   IN[3] - video peak rate
-   IN[4] - system mux rate
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_VIDEO_RATE                (CPU_CMD_MASK_CAPTURE | 0x0005)
-
-/* Description: Set video output resolution
-   IN[0] - task handle
-   IN[1] - horizontal size
-   IN[2] - vertical size
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_VIDEO_RESOLUTION          (CPU_CMD_MASK_CAPTURE | 0x0006)
-
-/* Description: This command set filter parameters
-   IN[0] - Task handle. Handle of the task
-   IN[1] - type, 0 - temporal, 1 - spatial, 2 - median
-   IN[2] - mode,  temporal/spatial: 0 - disable, 1 - static, 2 - dynamic
-                       median: 0 = disable, 1 = horizontal, 2 = vertical,
-                               3 = horizontal/vertical, 4 = diagonal
-   IN[3] - strength, temporal 0 - 31, spatial 0 - 15
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_FILTER_PARAM              (CPU_CMD_MASK_CAPTURE | 0x0009)
-
-/* Description: This command set spatial filter type
-   IN[0] - Task handle.
-   IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
-                     3 = 2D H/V separable, 4 = 2D symmetric non-separable
-   IN[2] - chroma type: 0 - disable, 1 = 1D horizontal
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_SPATIAL_FILTER_TYPE       (CPU_CMD_MASK_CAPTURE | 0x000C)
-
-/* Description: This command set coring levels for median filter
-   IN[0] - Task handle.
-   IN[1] - luma_high
-   IN[2] - luma_low
-   IN[3] - chroma_high
-   IN[4] - chroma_low
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_MEDIAN_CORING             (CPU_CMD_MASK_CAPTURE | 0x000E)
-
-/* Description: This command set the picture type mask for index file
-   IN[0] - Task handle (ignored by firmware)
-   IN[1] -     0 = disable index file output
-                       1 = output I picture
-                       2 = P picture
-                       4 = B picture
-                       other = illegal */
-#define CX18_CPU_SET_INDEXTABLE                (CPU_CMD_MASK_CAPTURE | 0x0010)
-
-/* Description: Set audio parameters
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - audio parameter
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_AUDIO_PARAMETERS          (CPU_CMD_MASK_CAPTURE | 0x0011)
-
-/* Description: Set video mute
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - bit31-24: muteYvalue
-          bit23-16: muteUvalue
-          bit15-8:  muteVvalue
-          bit0:     1:mute, 0: unmute
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_VIDEO_MUTE                        (CPU_CMD_MASK_CAPTURE | 0x0013)
-
-/* Description: Set audio mute
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - mute/unmute
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_AUDIO_MUTE                        (CPU_CMD_MASK_CAPTURE | 0x0014)
-
-/* Description: Set stream output type
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - subType
-           SET_INITIAL_SCR                     1
-           SET_QUALITY_MODE            2
-           SET_VIM_PROTECT_MODE        3
-           SET_PTS_CORRECTION          4
-           SET_USB_FLUSH_MODE          5
-           SET_MERAQPAR_ENABLE         6
-           SET_NAV_PACK_INSERTION      7
-           SET_SCENE_CHANGE_ENABLE     8
-   IN[2] - parameter 1
-   IN[3] - parameter 2
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_MISC_PARAMETERS           (CPU_CMD_MASK_CAPTURE | 0x0015)
-
-/* Description: Set raw VBI parameters
-   IN[0] - Task handle
-   IN[1] - No. of input lines per field:
-                               bit[15:0]: field 1,
-                               bit[31:16]: field 2
-   IN[2] - No. of input bytes per line
-   IN[3] - No. of output frames per transfer
-   IN[4] - start code
-   IN[5] - stop code
-   ReturnCode */
-#define CX18_CPU_SET_RAW_VBI_PARAM             (CPU_CMD_MASK_CAPTURE | 0x0016)
-
-/* Description: Set capture line No.
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - height1
-   IN[2] - height2
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_CAPTURE_LINE_NO           (CPU_CMD_MASK_CAPTURE | 0x0017)
-
-/* Description: Set copyright
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - copyright
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_COPYRIGHT                 (CPU_CMD_MASK_CAPTURE | 0x0018)
-
-/* Description: Set audio PID
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - PID
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_AUDIO_PID                 (CPU_CMD_MASK_CAPTURE | 0x0019)
-
-/* Description: Set video PID
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - PID
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_VIDEO_PID                 (CPU_CMD_MASK_CAPTURE | 0x001A)
-
-/* Description: Set Vertical Crop Line
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - Line
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_VER_CROP_LINE             (CPU_CMD_MASK_CAPTURE | 0x001B)
-
-/* Description: Set COP structure
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - M
-   IN[2] - N
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_GOP_STRUCTURE             (CPU_CMD_MASK_CAPTURE | 0x001C)
-
-/* Description: Set Scene Change Detection
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - scene change
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_SCENE_CHANGE_DETECTION    (CPU_CMD_MASK_CAPTURE | 0x001D)
-
-/* Description: Set Aspect Ratio
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - AspectRatio
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_ASPECT_RATIO              (CPU_CMD_MASK_CAPTURE | 0x001E)
-
-/* Description: Set Skip Input Frame
-   IN[0] - task handle. Handle of the task to start
-   IN[1] - skip input frames
-   ReturnCode - One of the ERR_CAPTURE_... */
-#define CX18_CPU_SET_SKIP_INPUT_FRAME          (CPU_CMD_MASK_CAPTURE | 0x001F)
-
-/* Description: Set sliced VBI parameters -
-   Note This API will only apply to MPEG and Sliced VBI Channels
-   IN[0] - Task handle
-   IN[1] - output type, 0 - CC, 1 - Moji, 2 - Teletext
-   IN[2] - start / stop line
-                       bit[15:0] start line number
-                       bit[31:16] stop line number
-   IN[3] - number of output frames per interrupt
-   IN[4] - VBI insertion mode
-                       bit 0:  output user data, 1 - enable
-                       bit 1:  output private stream, 1 - enable
-                       bit 2:  mux option, 0 - in GOP, 1 - in picture
-                       bit[7:0]        private stream ID
-   IN[5] - insertion period while mux option is in picture
-   ReturnCode - VBI data offset */
-#define CX18_CPU_SET_SLICED_VBI_PARAM          (CPU_CMD_MASK_CAPTURE | 0x0020)
-
-/* Description: Set the user data place holder
-   IN[0] - type of data (0 for user)
-   IN[1] - Stuffing period
-   IN[2] - ID data size in word (less than 10)
-   IN[3] - Pointer to ID buffer */
-#define CX18_CPU_SET_USERDATA_PLACE_HOLDER     (CPU_CMD_MASK_CAPTURE | 0x0021)
-
-
-/* Description:
-   In[0] Task Handle
-   return parameter:
-   Out[0]  Reserved
-   Out[1]  Video PTS bit[32:2] of last output video frame.
-   Out[2]  Video PTS bit[ 1:0] of last output video frame.
-   Out[3]  Hardware Video PTS counter bit[31:0],
-            these bits get incremented on every 90kHz clock tick.
-   Out[4]  Hardware Video PTS counter bit32,
-            these bits get incremented on every 90kHz clock tick.
-   ReturnCode */
-#define CX18_CPU_GET_ENC_PTS                   (CPU_CMD_MASK_CAPTURE | 0x0022)
-
-/* Description: Set VFC parameters
-   IN[0] - task handle
-   IN[1] - VFC enable flag, 1 - enable, 0 - disable
-*/
-#define CX18_CPU_SET_VFC_PARAM                  (CPU_CMD_MASK_CAPTURE | 0x0023)
-
-/* Below is the list of commands related to the data exchange */
-#define CPU_CMD_MASK_DE                        (CPU_CMD_MASK | 0x040000)
-
-/* Description: This command provides the physical base address of the local
-   DDR as viewed by EPU
-   IN[0] - Physical offset where EPU has the local DDR mapped
-   ReturnCode - One of the ERR_DE_... */
-#define CPU_CMD_DE_SetBase                     (CPU_CMD_MASK_DE | 0x0001)
-
-/* Description: This command provides the offsets in the device memory where
-   the 2 cx18_mdl_ack blocks reside
-   IN[0] - Task handle. Handle of the task to start
-   IN[1] - Offset of the first cx18_mdl_ack from the beginning of the
-          local DDR.
-   IN[2] - Offset of the second cx18_mdl_ack from the beginning of the
-          local DDR.
-   ReturnCode - One of the ERR_DE_... */
-#define CX18_CPU_DE_SET_MDL_ACK                        (CPU_CMD_MASK_DE | 0x0002)
-
-/* Description: This command provides the offset to a Memory Descriptor List
-   IN[0] - Task handle. Handle of the task to start
-   IN[1] - Offset of the MDL from the beginning of the local DDR.
-   IN[2] - Number of cx18_mdl_ent structures in the array pointed to by IN[1]
-   IN[3] - Buffer ID
-   IN[4] - Total buffer length
-   ReturnCode - One of the ERR_DE_... */
-#define CX18_CPU_DE_SET_MDL                    (CPU_CMD_MASK_DE | 0x0005)
-
-/* Description: This command requests return of all current Memory
-   Descriptor Lists to the driver
-   IN[0] - Task handle. Handle of the task to start
-   ReturnCode - One of the ERR_DE_... */
-#define CX18_CPU_DE_RELEASE_MDL                (CPU_CMD_MASK_DE | 0x0006)
-
-/* Description: This command signals the cpu that the dat buffer has been
-   consumed and ready for re-use.
-   IN[0] - Task handle. Handle of the task
-   IN[1] - Offset of the data block from the beginning of the local DDR.
-   IN[2] - Number of bytes in the data block
-   ReturnCode - One of the ERR_DE_... */
-/* #define CX18_CPU_DE_RELEASE_BUFFER           (CPU_CMD_MASK_DE | 0x0007) */
-
-/* No Error / Success */
-#define CNXT_OK                 0x000000
-
-/* Received unknown command */
-#define CXERR_UNK_CMD           0x000001
-
-/* First parameter in the command is invalid */
-#define CXERR_INVALID_PARAM1    0x000002
-
-/* Second parameter in the command is invalid */
-#define CXERR_INVALID_PARAM2    0x000003
-
-/* Device interface is not open/found */
-#define CXERR_DEV_NOT_FOUND     0x000004
-
-/* Requested function is not implemented/available */
-#define CXERR_NOTSUPPORTED      0x000005
-
-/* Invalid pointer is provided */
-#define CXERR_BADPTR            0x000006
-
-/* Unable to allocate memory */
-#define CXERR_NOMEM             0x000007
-
-/* Object/Link not found */
-#define CXERR_LINK              0x000008
-
-/* Device busy, command cannot be executed */
-#define CXERR_BUSY              0x000009
-
-/* File/device/handle is not open. */
-#define CXERR_NOT_OPEN          0x00000A
-
-/* Value is out of range */
-#define CXERR_OUTOFRANGE        0x00000B
-
-/* Buffer overflow */
-#define CXERR_OVERFLOW          0x00000C
-
-/* Version mismatch */
-#define CXERR_BADVER            0x00000D
-
-/* Operation timed out */
-#define CXERR_TIMEOUT           0x00000E
-
-/* Operation aborted */
-#define CXERR_ABORT             0x00000F
-
-/* Specified I2C device not found for read/write */
-#define CXERR_I2CDEV_NOTFOUND   0x000010
-
-/* Error in I2C data xfer (but I2C device is present) */
-#define CXERR_I2CDEV_XFERERR    0x000011
-
-/* Chanel changing component not ready */
-#define CXERR_CHANNELNOTREADY   0x000012
-
-/* PPU (Presensation/Decoder) mail box is corrupted */
-#define CXERR_PPU_MB_CORRUPT    0x000013
-
-/* CPU (Capture/Encoder) mail box is corrupted */
-#define CXERR_CPU_MB_CORRUPT    0x000014
-
-/* APU (Audio) mail box is corrupted */
-#define CXERR_APU_MB_CORRUPT    0x000015
-
-/* Unable to open file for reading */
-#define CXERR_FILE_OPEN_READ    0x000016
-
-/* Unable to open file for writing */
-#define CXERR_FILE_OPEN_WRITE   0x000017
-
-/* Unable to find the I2C section specified */
-#define CXERR_I2C_BADSECTION    0x000018
-
-/* Error in I2C data xfer (but I2C device is present) */
-#define CXERR_I2CDEV_DATALOW    0x000019
-
-/* Error in I2C data xfer (but I2C device is present) */
-#define CXERR_I2CDEV_CLOCKLOW   0x00001A
-
-/* No Interrupt received from HW (for I2C access) */
-#define CXERR_NO_HW_I2C_INTR    0x00001B
-
-/* RPU is not ready to accept commands! */
-#define CXERR_RPU_NOT_READY     0x00001C
-
-/* RPU is not ready to accept commands! */
-#define CXERR_RPU_NO_ACK        0x00001D
-
-/* The are no buffers ready. Try again soon! */
-#define CXERR_NODATA_AGAIN      0x00001E
-
-/* The stream is stopping. Function not allowed now! */
-#define CXERR_STOPPING_STATUS   0x00001F
-
-/* Trying to access hardware when the power is turned OFF */
-#define CXERR_DEVPOWER_OFF      0x000020
-
-#endif /* CX23418_H */
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
deleted file mode 100644 (file)
index b391e9b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-config VIDEO_CX23885
-       tristate "Conexant cx23885 (2388x successor) support"
-       depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
-       select SND_PCM
-       select I2C_ALGOBIT
-       select VIDEO_BTCX
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       depends on RC_CORE
-       select VIDEOBUF_DVB
-       select VIDEOBUF_DMA_SG
-       select VIDEO_CX25840
-       select VIDEO_CX2341X
-       select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_STV6110 if !DVB_FE_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_STV0900 if !DVB_FE_CUSTOMISE
-       select DVB_DS3000 if !DVB_FE_CUSTOMISE
-       select DVB_STV0367 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         This is a video4linux driver for Conexant 23885 based
-         TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx23885
-
-config MEDIA_ALTERA_CI
-       tristate "Altera FPGA based CI module"
-       depends on VIDEO_CX23885 && DVB_CORE
-       select ALTERA_STAPL
-       ---help---
-         An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
-
-         To compile this driver as a module, choose M here: the
-         module will be called altera-ci
diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile
deleted file mode 100644 (file)
index f92cc4c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-cx23885-objs   := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
-                   cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
-                   cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
-                   cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
-                   cx23885-f300.o cx23885-alsa.o
-
-obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
-obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-
-ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/cx23885/altera-ci.c b/drivers/media/video/cx23885/altera-ci.c
deleted file mode 100644 (file)
index 1fa8927..0000000
+++ /dev/null
@@ -1,837 +0,0 @@
-/*
- * altera-ci.c
- *
- *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
- *
- * Copyright (C) 2010,2011 NetUP Inc.
- * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
- *
- * 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.
- */
-
-/*
- * currently cx23885 GPIO's used.
- * GPIO-0 ~INT in
- * GPIO-1 TMS out
- * GPIO-2 ~reset chips out
- * GPIO-3 to GPIO-10 data/addr for CA in/out
- * GPIO-11 ~CS out
- * GPIO-12 AD_RG out
- * GPIO-13 ~WR out
- * GPIO-14 ~RD out
- * GPIO-15 ~RDY in
- * GPIO-16 TCK out
- * GPIO-17 TDO in
- * GPIO-18 TDI out
- */
-/*
- *  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
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * |  TDI  |  TDO  |  TCK  |  RDY# |  #RD  |  #WR  | AD_RG |  #CS  |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- *  bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
-#include <media/videobuf-dma-sg.h>
-#include <media/videobuf-dvb.h>
-#include "altera-ci.h"
-#include "dvb_ca_en50221.h"
-
-/* FPGA regs */
-#define NETUP_CI_INT_CTRL      0x00
-#define NETUP_CI_BUSCTRL2      0x01
-#define NETUP_CI_ADDR0         0x04
-#define NETUP_CI_ADDR1         0x05
-#define NETUP_CI_DATA          0x06
-#define NETUP_CI_BUSCTRL       0x07
-#define NETUP_CI_PID_ADDR0     0x08
-#define NETUP_CI_PID_ADDR1     0x09
-#define NETUP_CI_PID_DATA      0x0a
-#define NETUP_CI_TSA_DIV       0x0c
-#define NETUP_CI_TSB_DIV       0x0d
-#define NETUP_CI_REVISION      0x0f
-
-/* const for ci op */
-#define NETUP_CI_FLG_CTL       1
-#define NETUP_CI_FLG_RD                1
-#define NETUP_CI_FLG_AD                1
-
-static unsigned int ci_dbg;
-module_param(ci_dbg, int, 0644);
-MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
-
-static unsigned int pid_dbg;
-module_param(pid_dbg, int, 0644);
-MODULE_PARM_DESC(pid_dbg, "Enable PID filtering debugging");
-
-MODULE_DESCRIPTION("altera FPGA CI module");
-MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");
-MODULE_LICENSE("GPL");
-
-#define ci_dbg_print(args...) \
-       do { \
-               if (ci_dbg) \
-                       printk(KERN_DEBUG args); \
-       } while (0)
-
-#define pid_dbg_print(args...) \
-       do { \
-               if (pid_dbg) \
-                       printk(KERN_DEBUG args); \
-       } while (0)
-
-struct altera_ci_state;
-struct netup_hw_pid_filter;
-
-struct fpga_internal {
-       void *dev;
-       struct mutex fpga_mutex;/* two CI's on the same fpga */
-       struct netup_hw_pid_filter *pid_filt[2];
-       struct altera_ci_state *state[2];
-       struct work_struct work;
-       int (*fpga_rw) (void *dev, int flag, int data, int rw);
-       int cis_used;
-       int filts_used;
-       int strt_wrk;
-};
-
-/* stores all private variables for communication with CI */
-struct altera_ci_state {
-       struct fpga_internal *internal;
-       struct dvb_ca_en50221 ca;
-       int status;
-       int nr;
-};
-
-/* stores all private variables for hardware pid filtering */
-struct netup_hw_pid_filter {
-       struct fpga_internal *internal;
-       struct dvb_demux *demux;
-       /* save old functions */
-       int (*start_feed)(struct dvb_demux_feed *feed);
-       int (*stop_feed)(struct dvb_demux_feed *feed);
-
-       int status;
-       int nr;
-};
-
-/* internal params node */
-struct fpga_inode {
-       /* pointer for internal params, one for each pair of CI's */
-       struct fpga_internal            *internal;
-       struct fpga_inode               *next_inode;
-};
-
-/* first internal params */
-static struct fpga_inode *fpga_first_inode;
-
-/* find chip by dev */
-static struct fpga_inode *find_inode(void *dev)
-{
-       struct fpga_inode *temp_chip = fpga_first_inode;
-
-       if (temp_chip == NULL)
-               return temp_chip;
-
-       /*
-        Search for the last fpga CI chip or
-        find it by dev */
-       while ((temp_chip != NULL) &&
-                               (temp_chip->internal->dev != dev))
-               temp_chip = temp_chip->next_inode;
-
-       return temp_chip;
-}
-/* check demux */
-static struct fpga_internal *check_filter(struct fpga_internal *temp_int,
-                                               void *demux_dev, int filt_nr)
-{
-       if (temp_int == NULL)
-               return NULL;
-
-       if ((temp_int->pid_filt[filt_nr]) == NULL)
-               return NULL;
-
-       if (temp_int->pid_filt[filt_nr]->demux == demux_dev)
-               return temp_int;
-
-       return NULL;
-}
-
-/* find chip by demux */
-static struct fpga_inode *find_dinode(void *demux_dev)
-{
-       struct fpga_inode *temp_chip = fpga_first_inode;
-       struct fpga_internal *temp_int;
-
-       /*
-        * Search of the last fpga CI chip or
-        * find it by demux
-        */
-       while (temp_chip != NULL) {
-               if (temp_chip->internal != NULL) {
-                       temp_int = temp_chip->internal;
-                       if (check_filter(temp_int, demux_dev, 0))
-                               break;
-                       if (check_filter(temp_int, demux_dev, 1))
-                               break;
-               }
-
-               temp_chip = temp_chip->next_inode;
-       }
-
-       return temp_chip;
-}
-
-/* deallocating chip */
-static void remove_inode(struct fpga_internal *internal)
-{
-       struct fpga_inode *prev_node = fpga_first_inode;
-       struct fpga_inode *del_node = find_inode(internal->dev);
-
-       if (del_node != NULL) {
-               if (del_node == fpga_first_inode) {
-                       fpga_first_inode = del_node->next_inode;
-               } else {
-                       while (prev_node->next_inode != del_node)
-                               prev_node = prev_node->next_inode;
-
-                       if (del_node->next_inode == NULL)
-                               prev_node->next_inode = NULL;
-                       else
-                               prev_node->next_inode =
-                                       prev_node->next_inode->next_inode;
-               }
-
-               kfree(del_node);
-       }
-}
-
-/* allocating new chip */
-static struct fpga_inode *append_internal(struct fpga_internal *internal)
-{
-       struct fpga_inode *new_node = fpga_first_inode;
-
-       if (new_node == NULL) {
-               new_node = kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
-               fpga_first_inode = new_node;
-       } else {
-               while (new_node->next_inode != NULL)
-                       new_node = new_node->next_inode;
-
-               new_node->next_inode =
-                               kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
-               if (new_node->next_inode != NULL)
-                       new_node = new_node->next_inode;
-               else
-                       new_node = NULL;
-       }
-
-       if (new_node != NULL) {
-               new_node->internal = internal;
-               new_node->next_inode = NULL;
-       }
-
-       return new_node;
-}
-
-static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,
-                                                       u8 val, u8 read)
-{
-       inter->fpga_rw(inter->dev, NETUP_CI_FLG_AD, addr, 0);
-       return inter->fpga_rw(inter->dev, 0, val, read);
-}
-
-/* flag - mem/io, read - read/write */
-int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
-                               u8 flag, u8 read, int addr, u8 val)
-{
-
-       struct altera_ci_state *state = en50221->data;
-       struct fpga_internal *inter = state->internal;
-
-       u8 store;
-       int mem = 0;
-
-       if (0 != slot)
-               return -EINVAL;
-
-       mutex_lock(&inter->fpga_mutex);
-
-       netup_fpga_op_rw(inter, NETUP_CI_ADDR0, ((addr << 1) & 0xfe), 0);
-       netup_fpga_op_rw(inter, NETUP_CI_ADDR1, ((addr >> 7) & 0x7f), 0);
-       store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
-
-       store &= 0x0f;
-       store |= ((state->nr << 7) | (flag << 6));
-
-       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, store, 0);
-       mem = netup_fpga_op_rw(inter, NETUP_CI_DATA, val, read);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
-                       (read) ? "read" : "write", addr,
-                       (flag == NETUP_CI_FLG_CTL) ? "ctl" : "mem",
-                       (read) ? mem : val);
-
-       return mem;
-}
-
-int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr)
-{
-       return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);
-}
-
-int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr, u8 data)
-{
-       return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);
-}
-
-int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
-{
-       return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,
-                                               NETUP_CI_FLG_RD, addr, 0);
-}
-
-int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
-                                               u8 addr, u8 data)
-{
-       return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);
-}
-
-int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
-{
-       struct altera_ci_state *state = en50221->data;
-       struct fpga_internal *inter = state->internal;
-       /* reasonable timeout for CI reset is 10 seconds */
-       unsigned long t_out = jiffies + msecs_to_jiffies(9999);
-       int ret;
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (0 != slot)
-               return -EINVAL;
-
-       mutex_lock(&inter->fpga_mutex);
-
-       ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
-       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
-                               (ret & 0xcf) | (1 << (5 - state->nr)), 0);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       for (;;) {
-               mdelay(50);
-
-               mutex_lock(&inter->fpga_mutex);
-
-               ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
-                                               0, NETUP_CI_FLG_RD);
-               mutex_unlock(&inter->fpga_mutex);
-
-               if ((ret & (1 << (5 - state->nr))) == 0)
-                       break;
-               if (time_after(jiffies, t_out))
-                       break;
-       }
-
-
-       ci_dbg_print("%s: %d msecs\n", __func__,
-               jiffies_to_msecs(jiffies + msecs_to_jiffies(9999) - t_out));
-
-       return 0;
-}
-
-int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
-{
-       /* not implemented */
-       return 0;
-}
-
-int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
-{
-       struct altera_ci_state *state = en50221->data;
-       struct fpga_internal *inter = state->internal;
-       int ret;
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (0 != slot)
-               return -EINVAL;
-
-       mutex_lock(&inter->fpga_mutex);
-
-       ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
-       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
-                               (ret & 0x0f) | (1 << (3 - state->nr)), 0);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       return 0;
-}
-
-/* work handler */
-static void netup_read_ci_status(struct work_struct *work)
-{
-       struct fpga_internal *inter =
-                       container_of(work, struct fpga_internal, work);
-       int ret;
-
-       ci_dbg_print("%s\n", __func__);
-
-       mutex_lock(&inter->fpga_mutex);
-       /* ack' irq */
-       ret = netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0, NETUP_CI_FLG_RD);
-       ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       if (inter->state[1] != NULL) {
-               inter->state[1]->status =
-                               ((ret & 1) == 0 ?
-                               DVB_CA_EN50221_POLL_CAM_PRESENT |
-                               DVB_CA_EN50221_POLL_CAM_READY : 0);
-               ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
-                               __func__, inter->state[1]->status);
-       };
-
-       if (inter->state[0] != NULL) {
-               inter->state[0]->status =
-                               ((ret & 2) == 0 ?
-                               DVB_CA_EN50221_POLL_CAM_PRESENT |
-                               DVB_CA_EN50221_POLL_CAM_READY : 0);
-               ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
-                               __func__, inter->state[0]->status);
-       };
-}
-
-/* CI irq handler */
-int altera_ci_irq(void *dev)
-{
-       struct fpga_inode *temp_int = NULL;
-       struct fpga_internal *inter = NULL;
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (dev != NULL) {
-               temp_int = find_inode(dev);
-               if (temp_int != NULL) {
-                       inter = temp_int->internal;
-                       schedule_work(&inter->work);
-               }
-       }
-
-       return 1;
-}
-EXPORT_SYMBOL(altera_ci_irq);
-
-int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
-                                                               int open)
-{
-       struct altera_ci_state *state = en50221->data;
-
-       if (0 != slot)
-               return -EINVAL;
-
-       return state->status;
-}
-
-void altera_hw_filt_release(void *main_dev, int filt_nr)
-{
-       struct fpga_inode *temp_int = find_inode(main_dev);
-       struct netup_hw_pid_filter *pid_filt = NULL;
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (temp_int != NULL) {
-               pid_filt = temp_int->internal->pid_filt[filt_nr - 1];
-               /* stored old feed controls */
-               pid_filt->demux->start_feed = pid_filt->start_feed;
-               pid_filt->demux->stop_feed = pid_filt->stop_feed;
-
-               if (((--(temp_int->internal->filts_used)) <= 0) &&
-                        ((temp_int->internal->cis_used) <= 0)) {
-
-                       ci_dbg_print("%s: Actually removing\n", __func__);
-
-                       remove_inode(temp_int->internal);
-                       kfree(pid_filt->internal);
-               }
-
-               kfree(pid_filt);
-
-       }
-
-}
-EXPORT_SYMBOL(altera_hw_filt_release);
-
-void altera_ci_release(void *dev, int ci_nr)
-{
-       struct fpga_inode *temp_int = find_inode(dev);
-       struct altera_ci_state *state = NULL;
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (temp_int != NULL) {
-               state = temp_int->internal->state[ci_nr - 1];
-               altera_hw_filt_release(dev, ci_nr);
-
-
-               if (((temp_int->internal->filts_used) <= 0) &&
-                               ((--(temp_int->internal->cis_used)) <= 0)) {
-
-                       ci_dbg_print("%s: Actually removing\n", __func__);
-
-                       remove_inode(temp_int->internal);
-                       kfree(state->internal);
-               }
-
-               if (state != NULL) {
-                       if (state->ca.data != NULL)
-                               dvb_ca_en50221_release(&state->ca);
-
-                       kfree(state);
-               }
-       }
-
-}
-EXPORT_SYMBOL(altera_ci_release);
-
-static void altera_pid_control(struct netup_hw_pid_filter *pid_filt,
-               u16 pid, int onoff)
-{
-       struct fpga_internal *inter = pid_filt->internal;
-       u8 store = 0;
-
-       /* pid 0-0x1f always enabled, don't touch them */
-       if ((pid == 0x2000) || (pid < 0x20))
-               return;
-
-       mutex_lock(&inter->fpga_mutex);
-
-       netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, (pid >> 3) & 0xff, 0);
-       netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
-                       ((pid >> 11) & 0x03) | (pid_filt->nr << 2), 0);
-
-       store = netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, 0, NETUP_CI_FLG_RD);
-
-       if (onoff)/* 0 - on, 1 - off */
-               store |= (1 << (pid & 7));
-       else
-               store &= ~(1 << (pid & 7));
-
-       netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, store, 0);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       pid_dbg_print("%s: (%d) set pid: %5d 0x%04x '%s'\n", __func__,
-               pid_filt->nr, pid, pid, onoff ? "off" : "on");
-}
-
-static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,
-                                       int filt_nr, int onoff)
-{
-       struct fpga_internal *inter = pid_filt->internal;
-       u8 store = 0;
-       int i;
-
-       pid_dbg_print("%s: pid_filt->nr[%d]  now %s\n", __func__, pid_filt->nr,
-                       onoff ? "off" : "on");
-
-       if (onoff)/* 0 - on, 1 - off */
-               store = 0xff;/* ignore pid */
-       else
-               store = 0;/* enable pid */
-
-       mutex_lock(&inter->fpga_mutex);
-
-       for (i = 0; i < 1024; i++) {
-               netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, i & 0xff, 0);
-
-               netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
-                               ((i >> 8) & 0x03) | (pid_filt->nr << 2), 0);
-               /* pid 0-0x1f always enabled */
-               netup_fpga_op_rw(inter, NETUP_CI_PID_DATA,
-                               (i > 3 ? store : 0), 0);
-       }
-
-       mutex_unlock(&inter->fpga_mutex);
-}
-
-int altera_pid_feed_control(void *demux_dev, int filt_nr,
-               struct dvb_demux_feed *feed, int onoff)
-{
-       struct fpga_inode *temp_int = find_dinode(demux_dev);
-       struct fpga_internal *inter = temp_int->internal;
-       struct netup_hw_pid_filter *pid_filt = inter->pid_filt[filt_nr - 1];
-
-       altera_pid_control(pid_filt, feed->pid, onoff ? 0 : 1);
-       /* call old feed proc's */
-       if (onoff)
-               pid_filt->start_feed(feed);
-       else
-               pid_filt->stop_feed(feed);
-
-       if (feed->pid == 0x2000)
-               altera_toggle_fullts_streaming(pid_filt, filt_nr,
-                                               onoff ? 0 : 1);
-
-       return 0;
-}
-EXPORT_SYMBOL(altera_pid_feed_control);
-
-int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
-{
-       altera_pid_feed_control(feed->demux, num, feed, 1);
-
-       return 0;
-}
-
-int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
-{
-       altera_pid_feed_control(feed->demux, num, feed, 0);
-
-       return 0;
-}
-
-int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
-{
-       return altera_ci_start_feed(feed, 1);
-}
-
-int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
-{
-       return altera_ci_stop_feed(feed, 1);
-}
-
-int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
-{
-       return altera_ci_start_feed(feed, 2);
-}
-
-int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
-{
-       return altera_ci_stop_feed(feed, 2);
-}
-
-int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
-{
-       struct netup_hw_pid_filter *pid_filt = NULL;
-       struct fpga_inode *temp_int = find_inode(config->dev);
-       struct fpga_internal *inter = NULL;
-       int ret = 0;
-
-       pid_filt = kzalloc(sizeof(struct netup_hw_pid_filter), GFP_KERNEL);
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (!pid_filt) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       if (temp_int != NULL) {
-               inter = temp_int->internal;
-               (inter->filts_used)++;
-               ci_dbg_print("%s: Find Internal Structure!\n", __func__);
-       } else {
-               inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
-               if (!inter) {
-                       ret = -ENOMEM;
-                       goto err;
-               }
-
-               temp_int = append_internal(inter);
-               inter->filts_used = 1;
-               inter->dev = config->dev;
-               inter->fpga_rw = config->fpga_rw;
-               mutex_init(&inter->fpga_mutex);
-               inter->strt_wrk = 1;
-               ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
-       }
-
-       ci_dbg_print("%s: setting hw pid filter = %p for ci = %d\n", __func__,
-                                               pid_filt, hw_filt_nr - 1);
-       inter->pid_filt[hw_filt_nr - 1] = pid_filt;
-       pid_filt->demux = config->demux;
-       pid_filt->internal = inter;
-       pid_filt->nr = hw_filt_nr - 1;
-       /* store old feed controls */
-       pid_filt->start_feed = config->demux->start_feed;
-       pid_filt->stop_feed = config->demux->stop_feed;
-       /* replace with new feed controls */
-       if (hw_filt_nr == 1) {
-               pid_filt->demux->start_feed = altera_ci_start_feed_1;
-               pid_filt->demux->stop_feed = altera_ci_stop_feed_1;
-       } else if (hw_filt_nr == 2) {
-               pid_filt->demux->start_feed = altera_ci_start_feed_2;
-               pid_filt->demux->stop_feed = altera_ci_stop_feed_2;
-       }
-
-       altera_toggle_fullts_streaming(pid_filt, 0, 1);
-
-       return 0;
-err:
-       ci_dbg_print("%s: Can't init hardware filter: Error %d\n",
-                    __func__, ret);
-
-       kfree(pid_filt);
-
-       return ret;
-}
-EXPORT_SYMBOL(altera_hw_filt_init);
-
-int altera_ci_init(struct altera_ci_config *config, int ci_nr)
-{
-       struct altera_ci_state *state;
-       struct fpga_inode *temp_int = find_inode(config->dev);
-       struct fpga_internal *inter = NULL;
-       int ret = 0;
-       u8 store = 0;
-
-       state = kzalloc(sizeof(struct altera_ci_state), GFP_KERNEL);
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (!state) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       if (temp_int != NULL) {
-               inter = temp_int->internal;
-               (inter->cis_used)++;
-               ci_dbg_print("%s: Find Internal Structure!\n", __func__);
-       } else {
-               inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
-               if (!inter) {
-                       ret = -ENOMEM;
-                       goto err;
-               }
-
-               temp_int = append_internal(inter);
-               inter->cis_used = 1;
-               inter->dev = config->dev;
-               inter->fpga_rw = config->fpga_rw;
-               mutex_init(&inter->fpga_mutex);
-               inter->strt_wrk = 1;
-               ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
-       }
-
-       ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__,
-                                               state, ci_nr - 1);
-       inter->state[ci_nr - 1] = state;
-       state->internal = inter;
-       state->nr = ci_nr - 1;
-
-       state->ca.owner = THIS_MODULE;
-       state->ca.read_attribute_mem = altera_ci_read_attribute_mem;
-       state->ca.write_attribute_mem = altera_ci_write_attribute_mem;
-       state->ca.read_cam_control = altera_ci_read_cam_ctl;
-       state->ca.write_cam_control = altera_ci_write_cam_ctl;
-       state->ca.slot_reset = altera_ci_slot_reset;
-       state->ca.slot_shutdown = altera_ci_slot_shutdown;
-       state->ca.slot_ts_enable = altera_ci_slot_ts_ctl;
-       state->ca.poll_slot_status = altera_poll_ci_slot_status;
-       state->ca.data = state;
-
-       ret = dvb_ca_en50221_init(config->adapter,
-                                  &state->ca,
-                                  /* flags */ 0,
-                                  /* n_slots */ 1);
-       if (0 != ret)
-               goto err;
-
-       altera_hw_filt_init(config, ci_nr);
-
-       if (inter->strt_wrk) {
-               INIT_WORK(&inter->work, netup_read_ci_status);
-               inter->strt_wrk = 0;
-       }
-
-       ci_dbg_print("%s: CI initialized!\n", __func__);
-
-       mutex_lock(&inter->fpga_mutex);
-
-       /* Enable div */
-       netup_fpga_op_rw(inter, NETUP_CI_TSA_DIV, 0x0, 0);
-       netup_fpga_op_rw(inter, NETUP_CI_TSB_DIV, 0x0, 0);
-
-       /* enable TS out */
-       store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
-       store |= (3 << 4);
-       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
-
-       ret = netup_fpga_op_rw(inter, NETUP_CI_REVISION, 0, NETUP_CI_FLG_RD);
-       /* enable irq */
-       netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0x44, 0);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       ci_dbg_print("%s: NetUP CI Revision = 0x%x\n", __func__, ret);
-
-       schedule_work(&inter->work);
-
-       return 0;
-err:
-       ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
-
-       kfree(state);
-
-       return ret;
-}
-EXPORT_SYMBOL(altera_ci_init);
-
-int altera_ci_tuner_reset(void *dev, int ci_nr)
-{
-       struct fpga_inode *temp_int = find_inode(dev);
-       struct fpga_internal *inter = NULL;
-       u8 store;
-
-       ci_dbg_print("%s\n", __func__);
-
-       if (temp_int == NULL)
-               return -1;
-
-       if (temp_int->internal == NULL)
-               return -1;
-
-       inter = temp_int->internal;
-
-       mutex_lock(&inter->fpga_mutex);
-
-       store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
-       store &= ~(4 << (2 - ci_nr));
-       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
-       msleep(100);
-       store |= (4 << (2 - ci_nr));
-       netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
-
-       mutex_unlock(&inter->fpga_mutex);
-
-       return 0;
-}
-EXPORT_SYMBOL(altera_ci_tuner_reset);
diff --git a/drivers/media/video/cx23885/altera-ci.h b/drivers/media/video/cx23885/altera-ci.h
deleted file mode 100644 (file)
index 70e4fd6..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * altera-ci.c
- *
- *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
- *
- * Copyright (C) 2010 NetUP Inc.
- * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
- *
- * 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 __ALTERA_CI_H
-#define __ALTERA_CI_H
-
-#define ALT_DATA       0x000000ff
-#define ALT_TDI                0x00008000
-#define ALT_TDO                0x00004000
-#define ALT_TCK                0x00002000
-#define ALT_RDY                0x00001000
-#define ALT_RD         0x00000800
-#define ALT_WR         0x00000400
-#define ALT_AD_RG      0x00000200
-#define ALT_CS         0x00000100
-
-struct altera_ci_config {
-       void *dev;/* main dev, for example cx23885_dev */
-       void *adapter;/* for CI to connect to */
-       struct dvb_demux *demux;/* for hardware PID filter to connect to */
-       int (*fpga_rw) (void *dev, int ad_rg, int val, int rw);
-};
-
-#if defined(CONFIG_MEDIA_ALTERA_CI) || (defined(CONFIG_MEDIA_ALTERA_CI_MODULE) \
-                                                       && defined(MODULE))
-
-extern int altera_ci_init(struct altera_ci_config *config, int ci_nr);
-extern void altera_ci_release(void *dev, int ci_nr);
-extern int altera_ci_irq(void *dev);
-extern int altera_ci_tuner_reset(void *dev, int ci_nr);
-
-#else
-
-static inline int altera_ci_init(struct altera_ci_config *config, int ci_nr)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return 0;
-}
-
-static inline void altera_ci_release(void *dev, int ci_nr)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-
-static inline int altera_ci_irq(void *dev)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return 0;
-}
-
-static inline int altera_ci_tuner_reset(void *dev, int ci_nr)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return 0;
-}
-
-#endif
-#if 0
-static inline int altera_hw_filt_init(struct altera_ci_config *config,
-                                                       int hw_filt_nr)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return 0;
-}
-
-static inline void altera_hw_filt_release(void *dev, int filt_nr)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-
-static inline int altera_pid_feed_control(void *dev, int filt_nr,
-               struct dvb_demux_feed *dvbdmxfeed, int onoff)
-{
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-       return 0;
-}
-
-#endif /* CONFIG_MEDIA_ALTERA_CI */
-
-#endif /* __ALTERA_CI_H */
diff --git a/drivers/media/video/cx23885/cimax2.c b/drivers/media/video/cx23885/cimax2.c
deleted file mode 100644 (file)
index c9f15d6..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * cimax2.c
- *
- * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
- *
- * Copyright (C) 2009 NetUP Inc.
- * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
- * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
- *
- * 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 "cx23885.h"
-#include "dvb_ca_en50221.h"
-/**** 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
-+-------+-------+-------+-------+-------+-------+-------+-------+
-|  WR#  |  RD#  |       |  ACK# |  ADHI |  ADLO |  CS1# |  CS0# |
-+-------+-------+-------+-------+-------+-------+-------+-------+
- bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
-+-------+-------+-------+-------+-------+-------+-------+-------+
-|  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
-+-------+-------+-------+-------+-------+-------+-------+-------+
-***/
-/* MC417 */
-#define NETUP_DATA             0x000000ff
-#define NETUP_WR               0x00008000
-#define NETUP_RD               0x00004000
-#define NETUP_ACK              0x00001000
-#define NETUP_ADHI             0x00000800
-#define NETUP_ADLO             0x00000400
-#define NETUP_CS1              0x00000200
-#define NETUP_CS0              0x00000100
-#define NETUP_EN_ALL           0x00001000
-#define NETUP_CTRL_OFF         (NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD)
-#define NETUP_CI_CTL           0x04
-#define NETUP_CI_RD            1
-
-#define NETUP_IRQ_DETAM        0x1
-#define NETUP_IRQ_IRQAM                0x4
-
-static unsigned int ci_dbg;
-module_param(ci_dbg, int, 0644);
-MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
-
-static unsigned int ci_irq_enable;
-module_param(ci_irq_enable, int, 0644);
-MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");
-
-#define ci_dbg_print(args...) \
-       do { \
-               if (ci_dbg) \
-                       printk(KERN_DEBUG args); \
-       } while (0)
-
-#define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0)
-
-/* stores all private variables for communication with CI */
-struct netup_ci_state {
-       struct dvb_ca_en50221 ca;
-       struct mutex ca_mutex;
-       struct i2c_adapter *i2c_adap;
-       u8 ci_i2c_addr;
-       int status;
-       struct work_struct work;
-       void *priv;
-       u8 current_irq_mode;
-       int current_ci_flag;
-       unsigned long next_status_checked_time;
-};
-
-
-int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
-                                               u8 *buf, int len)
-{
-       int ret;
-       struct i2c_msg msg[] = {
-               {
-                       .addr   = addr,
-                       .flags  = 0,
-                       .buf    = &reg,
-                       .len    = 1
-               }, {
-                       .addr   = addr,
-                       .flags  = I2C_M_RD,
-                       .buf    = buf,
-                       .len    = len
-               }
-       };
-
-       ret = i2c_transfer(i2c_adap, msg, 2);
-
-       if (ret != 2) {
-               ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n",
-                                               __func__, reg, ret);
-
-               return -1;
-       }
-
-       ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n",
-                                               __func__, addr, reg, buf[0]);
-
-       return 0;
-}
-
-int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
-                                               u8 *buf, int len)
-{
-       int ret;
-       u8 buffer[len + 1];
-
-       struct i2c_msg msg = {
-               .addr   = addr,
-               .flags  = 0,
-               .buf    = &buffer[0],
-               .len    = len + 1
-       };
-
-       buffer[0] = reg;
-       memcpy(&buffer[1], buf, len);
-
-       ret = i2c_transfer(i2c_adap, &msg, 1);
-
-       if (ret != 1) {
-               ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n",
-                                               __func__, reg, ret);
-               return -1;
-       }
-
-       return 0;
-}
-
-int netup_ci_get_mem(struct cx23885_dev *dev)
-{
-       int mem;
-       unsigned long timeout = jiffies + msecs_to_jiffies(1);
-
-       for (;;) {
-               mem = cx_read(MC417_RWD);
-               if ((mem & NETUP_ACK) == 0)
-                       break;
-               if (time_after(jiffies, timeout))
-                       break;
-               udelay(1);
-       }
-
-       cx_set(MC417_RWD, NETUP_CTRL_OFF);
-
-       return mem & 0xff;
-}
-
-int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
-                               u8 flag, u8 read, int addr, u8 data)
-{
-       struct netup_ci_state *state = en50221->data;
-       struct cx23885_tsport *port = state->priv;
-       struct cx23885_dev *dev = port->dev;
-
-       u8 store;
-       int mem;
-       int ret;
-
-       if (0 != slot)
-               return -EINVAL;
-
-       if (state->current_ci_flag != flag) {
-               ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
-                               0, &store, 1);
-               if (ret != 0)
-                       return ret;
-
-               store &= ~0x0c;
-               store |= flag;
-
-               ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                               0, &store, 1);
-               if (ret != 0)
-                       return ret;
-       };
-       state->current_ci_flag = flag;
-
-       mutex_lock(&dev->gpio_lock);
-
-       /* write addr */
-       cx_write(MC417_OEN, NETUP_EN_ALL);
-       cx_write(MC417_RWD, NETUP_CTRL_OFF |
-                               NETUP_ADLO | (0xff & addr));
-       cx_clear(MC417_RWD, NETUP_ADLO);
-       cx_write(MC417_RWD, NETUP_CTRL_OFF |
-                               NETUP_ADHI | (0xff & (addr >> 8)));
-       cx_clear(MC417_RWD, NETUP_ADHI);
-
-       if (read) { /* data in */
-               cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);
-       } else /* data out */
-               cx_write(MC417_RWD, NETUP_CTRL_OFF | data);
-
-       /* choose chip */
-       cx_clear(MC417_RWD,
-                       (state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1);
-       /* read/write */
-       cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR);
-       mem = netup_ci_get_mem(dev);
-
-       mutex_unlock(&dev->gpio_lock);
-
-       if (!read)
-               if (mem < 0)
-                       return -EREMOTEIO;
-
-       ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
-                       (read) ? "read" : "write", state->ci_i2c_addr, addr,
-                       (flag == NETUP_CI_CTL) ? "ctl" : "mem",
-                       (read) ? mem : data);
-
-       if (read)
-               return mem;
-
-       return 0;
-}
-
-int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr)
-{
-       return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0);
-}
-
-int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr, u8 data)
-{
-       return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);
-}
-
-int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
-{
-       return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,
-                                                       NETUP_CI_RD, addr, 0);
-}
-
-int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
-                                                       u8 addr, u8 data)
-{
-       return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data);
-}
-
-int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
-{
-       struct netup_ci_state *state = en50221->data;
-       u8 buf =  0x80;
-       int ret;
-
-       if (0 != slot)
-               return -EINVAL;
-
-       udelay(500);
-       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                                       0, &buf, 1);
-
-       if (ret != 0)
-               return ret;
-
-       udelay(500);
-
-       buf = 0x00;
-       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                                       0, &buf, 1);
-
-       msleep(1000);
-       dvb_ca_en50221_camready_irq(&state->ca, 0);
-
-       return 0;
-
-}
-
-int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
-{
-       /* not implemented */
-       return 0;
-}
-
-int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
-{
-       struct netup_ci_state *state = en50221->data;
-       int ret;
-
-       if (irq_mode == state->current_irq_mode)
-               return 0;
-
-       ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
-                       __func__, state->ci_i2c_addr, irq_mode);
-       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                                       0x1b, &irq_mode, 1);
-
-       if (ret != 0)
-               return ret;
-
-       state->current_irq_mode = irq_mode;
-
-       return 0;
-}
-
-int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
-{
-       struct netup_ci_state *state = en50221->data;
-       u8 buf;
-
-       if (0 != slot)
-               return -EINVAL;
-
-       netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
-                       0, &buf, 1);
-       buf |= 0x60;
-
-       return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                                       0, &buf, 1);
-}
-
-/* work handler */
-static void netup_read_ci_status(struct work_struct *work)
-{
-       struct netup_ci_state *state =
-                       container_of(work, struct netup_ci_state, work);
-       u8 buf[33];
-       int ret;
-
-       /* CAM module IRQ processing. fast operation */
-       dvb_ca_en50221_frda_irq(&state->ca, 0);
-
-       /* CAM module INSERT/REMOVE processing. slow operation because of i2c
-        * transfers */
-       if (time_after(jiffies, state->next_status_checked_time)
-                       || !state->status) {
-               ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
-                               0, &buf[0], 33);
-
-               state->next_status_checked_time = jiffies
-                       + msecs_to_jiffies(1000);
-
-               if (ret != 0)
-                       return;
-
-               ci_dbg_print("%s: Slot Status Addr=[0x%04x], "
-                               "Reg=[0x%02x], data=%02x, "
-                               "TS config = %02x\n", __func__,
-                               state->ci_i2c_addr, 0, buf[0],
-                               buf[0]);
-
-
-               if (buf[0] & 1)
-                       state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
-                               DVB_CA_EN50221_POLL_CAM_READY;
-               else
-                       state->status = 0;
-       }
-}
-
-/* CI irq handler */
-int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)
-{
-       struct cx23885_tsport *port = NULL;
-       struct netup_ci_state *state = NULL;
-
-       ci_dbg_print("%s:\n", __func__);
-
-       if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1)))
-               return 0;
-
-       if (pci_status & PCI_MSK_GPIO0) {
-               port = &dev->ts1;
-               state = port->port_priv;
-               schedule_work(&state->work);
-               ci_dbg_print("%s: Wakeup CI0\n", __func__);
-       }
-
-       if (pci_status & PCI_MSK_GPIO1) {
-               port = &dev->ts2;
-               state = port->port_priv;
-               schedule_work(&state->work);
-               ci_dbg_print("%s: Wakeup CI1\n", __func__);
-       }
-
-       return 1;
-}
-
-int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
-{
-       struct netup_ci_state *state = en50221->data;
-
-       if (0 != slot)
-               return -EINVAL;
-
-       netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags())
-                       : NETUP_IRQ_DETAM);
-
-       return state->status;
-}
-
-int netup_ci_init(struct cx23885_tsport *port)
-{
-       struct netup_ci_state *state;
-       u8 cimax_init[34] = {
-               0x00, /* module A control*/
-               0x00, /* auto select mask high A */
-               0x00, /* auto select mask low A */
-               0x00, /* auto select pattern high A */
-               0x00, /* auto select pattern low A */
-               0x44, /* memory access time A */
-               0x00, /* invert input A */
-               0x00, /* RFU */
-               0x00, /* RFU */
-               0x00, /* module B control*/
-               0x00, /* auto select mask high B */
-               0x00, /* auto select mask low B */
-               0x00, /* auto select pattern high B */
-               0x00, /* auto select pattern low B */
-               0x44, /* memory access time B */
-               0x00, /* invert input B */
-               0x00, /* RFU */
-               0x00, /* RFU */
-               0x00, /* auto select mask high Ext */
-               0x00, /* auto select mask low Ext */
-               0x00, /* auto select pattern high Ext */
-               0x00, /* auto select pattern low Ext */
-               0x00, /* RFU */
-               0x02, /* destination - module A */
-               0x01, /* power on (use it like store place) */
-               0x00, /* RFU */
-               0x00, /* int status read only */
-               ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
-               0x05, /* EXTINT=active-high, INT=push-pull */
-               0x00, /* USCG1 */
-               0x04, /* ack active low */
-               0x00, /* LOCK = 0 */
-               0x33, /* serial mode, rising in, rising out, MSB first*/
-               0x31, /* synchronization */
-       };
-       int ret;
-
-       ci_dbg_print("%s\n", __func__);
-       state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL);
-       if (!state) {
-               ci_dbg_print("%s: Unable create CI structure!\n", __func__);
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       port->port_priv = state;
-
-       switch (port->nr) {
-       case 1:
-               state->ci_i2c_addr = 0x40;
-               break;
-       case 2:
-               state->ci_i2c_addr = 0x41;
-               break;
-       }
-
-       state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap;
-       state->ca.owner = THIS_MODULE;
-       state->ca.read_attribute_mem = netup_ci_read_attribute_mem;
-       state->ca.write_attribute_mem = netup_ci_write_attribute_mem;
-       state->ca.read_cam_control = netup_ci_read_cam_ctl;
-       state->ca.write_cam_control = netup_ci_write_cam_ctl;
-       state->ca.slot_reset = netup_ci_slot_reset;
-       state->ca.slot_shutdown = netup_ci_slot_shutdown;
-       state->ca.slot_ts_enable = netup_ci_slot_ts_ctl;
-       state->ca.poll_slot_status = netup_poll_ci_slot_status;
-       state->ca.data = state;
-       state->priv = port;
-       state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM;
-
-       ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                               0, &cimax_init[0], 34);
-       /* lock registers */
-       ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                               0x1f, &cimax_init[0x18], 1);
-       /* power on slots */
-       ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
-                                               0x18, &cimax_init[0x18], 1);
-
-       if (0 != ret)
-               goto err;
-
-       ret = dvb_ca_en50221_init(&port->frontends.adapter,
-                                  &state->ca,
-                                  /* flags */ 0,
-                                  /* n_slots */ 1);
-       if (0 != ret)
-               goto err;
-
-       INIT_WORK(&state->work, netup_read_ci_status);
-       schedule_work(&state->work);
-
-       ci_dbg_print("%s: CI initialized!\n", __func__);
-
-       return 0;
-err:
-       ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
-       kfree(state);
-       return ret;
-}
-
-void netup_ci_exit(struct cx23885_tsport *port)
-{
-       struct netup_ci_state *state;
-
-       if (NULL == port)
-               return;
-
-       state = (struct netup_ci_state *)port->port_priv;
-       if (NULL == state)
-               return;
-
-       if (NULL == state->ca.data)
-               return;
-
-       dvb_ca_en50221_release(&state->ca);
-       kfree(state);
-}
diff --git a/drivers/media/video/cx23885/cimax2.h b/drivers/media/video/cx23885/cimax2.h
deleted file mode 100644 (file)
index 518744a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * cimax2.h
- *
- * CIMax(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
- *
- * Copyright (C) 2009 NetUP Inc.
- * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
- * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
- *
- * 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 CIMAX2_H
-#define CIMAX2_H
-#include "dvb_ca_en50221.h"
-
-extern int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr);
-extern int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
-                                               int slot, int addr, u8 data);
-extern int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
-                                               int slot, u8 addr);
-extern int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
-                                               int slot, u8 addr, u8 data);
-extern int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot);
-extern int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot);
-extern int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot);
-extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status);
-extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
-                                               int slot, int open);
-extern int netup_ci_init(struct cx23885_tsport *port);
-extern void netup_ci_exit(struct cx23885_tsport *port);
-
-#endif
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c
deleted file mode 100644 (file)
index 5d5052d..0000000
+++ /dev/null
@@ -1,1790 +0,0 @@
-/*
- *
- *  Support for a cx23417 mpeg encoder via cx23885 host port.
- *
- *    (c) 2004 Jelle Foks <jelle@foks.us>
- *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
- *    (c) 2008 Steven Toth <stoth@linuxtv.org>
- *      - CX23885/7/8 support
- *
- *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
- *
- *  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 <linux/slab.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/cx2341x.h>
-
-#include "cx23885.h"
-#include "cx23885-ioctl.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) ? dev->name : "cx23885[?]", ## 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);
-       }
-}
-
-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);
-}
-
-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;
-}
-
-void mc417_gpio_set(struct cx23885_dev *dev, u32 mask)
-{
-       u32 val;
-
-       /* Set the gpio value */
-       mc417_register_read(dev, 0x900C, &val);
-       val |= (mask & 0x000ffff);
-       mc417_register_write(dev, 0x900C, val);
-}
-
-void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask)
-{
-       u32 val;
-
-       /* Clear the gpio value */
-       mc417_register_read(dev, 0x900C, &val);
-       val &= ~(mask & 0x0000ffff);
-       mc417_register_write(dev, 0x900C, val);
-}
-
-void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
-{
-       u32 val;
-
-       /* Enable GPIO direction bits */
-       mc417_register_read(dev, 0x9020, &val);
-       if (asoutput)
-               val |= (mask & 0x0000ffff);
-       else
-               val &= ~(mask & 0x0000ffff);
-
-       mc417_register_write(dev, 0x9020, val);
-}
-/* ------------------------------------------------------------------ */
-
-/* MPEG encoder API */
-static 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_ID";
-       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_MODE";
-       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 gpio_value;
-       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, &gpio_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",
-                       CX23885_FIRM_IMAGE_NAME);
-               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);
-
-       /* F/W power up disturbs the GPIOs, restore state */
-       retval |= mc417_register_write(dev, 0x9020, gpio_output);
-       retval |= mc417_register_write(dev, 0x900C, gpio_value);
-
-       retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
-       retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
-
-       /* Hardcoded GPIO's here */
-       retval |= mc417_register_write(dev, 0x9020, 0x4000);
-       retval |= mc417_register_write(dev, 0x900C, 0x4000);
-
-       mc417_register_read(dev, 0x9020, &gpio_output);
-       mc417_register_read(dev, 0x900C, &gpio_value);
-
-       if (retval < 0)
-               printk(KERN_ERR "%s: Error with mc417_register_write\n",
-                       __func__);
-       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__);
-
-       /* Dynamically change the height based on video standard */
-       if (dev->encodernorm.id & V4L2_STD_525_60)
-               dev->ts1.height = 480;
-       else
-               dev->ts1.height = 576;
-
-       /* assign frame size */
-       cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-                               dev->ts1.height, dev->ts1.width);
-
-       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 startencoder)
-{
-       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;
-               }
-               retval = cx23885_find_mailbox(dev);
-               if (retval < 0) {
-                       printk(KERN_ERR "%s() mailbox < 0, error\n",
-                               __func__);
-                       return -1;
-               }
-               dev->cx23417_mailbox = retval;
-               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 */
-       if (startencoder) {
-               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(&dev->mpeg_params, qmenu->id));
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       call_all(dev, core, g_std, id);
-
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-       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];
-
-       /* Have the drier core notify the subdevices */
-       mutex_lock(&dev->lock);
-       cx23885_set_tvnorm(dev, *id);
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-       struct v4l2_input *i)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __func__);
-       return cx23885_enum_input(dev, i);
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       return cx23885_get_input(file, priv, i);
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       return cx23885_set_input(file, priv, i);
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-       strcpy(t->name, "Television");
-       call_all(dev, tuner, g_tuner, t);
-
-       dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-
-       /* Update the A/V core */
-       call_all(dev, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-       f->type = V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->freq;
-
-       call_all(dev, tuner, g_frequency, f);
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       return cx23885_set_frequency(file, priv, f);
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-       struct v4l2_control *ctl)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       return cx23885_get_control(dev, ctl);
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-       struct v4l2_control *ctl)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       return cx23885_set_control(dev, ctl);
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                               struct v4l2_capability *cap)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-       struct cx23885_tsport  *tsport = &dev->ts1;
-
-       strlcpy(cap->driver, dev->name, sizeof(cap->driver));
-       strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
-               sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       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;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, "MPEG", sizeof(f->description));
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       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;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       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_TRY_FMT: w: %d, h: %d, f: %d\n",
-               dev->ts1.width, dev->ts1.height, fh->mpegq.field);
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       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;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                               struct v4l2_requestbuffers *p)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-
-       return videobuf_reqbufs(&fh->mpegq, p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                               struct v4l2_buffer *p)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-
-       return videobuf_querybuf(&fh->mpegq, p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv,
-                               struct v4l2_buffer *p)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-
-       return videobuf_qbuf(&fh->mpegq, p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx23885_fh  *fh  = priv;
-
-       return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);
-}
-
-
-static int vidioc_streamon(struct file *file, void *priv,
-                               enum v4l2_buf_type i)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-
-       return videobuf_streamon(&fh->mpegq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx23885_fh  *fh  = file->private_data;
-
-       return videobuf_streamoff(&fh->mpegq);
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-
-       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-       return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-       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, VIDIOC_S_EXT_CTRLS);
-
-       if (err == 0) {
-               err = cx2341x_update(dev, cx23885_mbox_func,
-                       &dev->mpeg_params, &p);
-               dev->mpeg_params = p;
-       }
-       return err;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-       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, VIDIOC_TRY_EXT_CTRLS);
-       return err;
-}
-
-static int vidioc_log_status(struct file *file, void *priv)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-       char name[32 + 2];
-
-       snprintf(name, sizeof(name), "%s/2", dev->name);
-       printk(KERN_INFO
-               "%s/2: ============  START LOG STATUS  ============\n",
-              dev->name);
-       call_all(dev, core, log_status);
-       cx2341x_log_status(&dev->mpeg_params, name);
-       printk(KERN_INFO
-               "%s/2: =============  END LOG STATUS  =============\n",
-              dev->name);
-       return 0;
-}
-
-static int vidioc_querymenu(struct file *file, void *priv,
-                               struct v4l2_querymenu *a)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-
-       return cx23885_querymenu(dev, a);
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *c)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-
-       return cx23885_queryctrl(dev, c);
-}
-
-static int mpeg_open(struct file *file)
-{
-       struct cx23885_dev *dev = video_drvdata(file);
-       struct cx23885_fh *fh;
-
-       dprintk(2, "%s()\n", __func__);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (!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, NULL);
-       return 0;
-}
-
-static int mpeg_release(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, 1) < 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 v4l2_file_operations mpeg_fops = {
-       .owner         = THIS_MODULE,
-       .open          = mpeg_open,
-       .release       = mpeg_release,
-       .read          = mpeg_read,
-       .poll          = mpeg_poll,
-       .mmap          = mpeg_mmap,
-       .ioctl         = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
-       .vidioc_querystd         = vidioc_g_std,
-       .vidioc_g_std            = vidioc_g_std,
-       .vidioc_s_std            = vidioc_s_std,
-       .vidioc_enum_input       = vidioc_enum_input,
-       .vidioc_g_input          = vidioc_g_input,
-       .vidioc_s_input          = vidioc_s_input,
-       .vidioc_g_tuner          = vidioc_g_tuner,
-       .vidioc_s_tuner          = vidioc_s_tuner,
-       .vidioc_g_frequency      = vidioc_g_frequency,
-       .vidioc_s_frequency      = vidioc_s_frequency,
-       .vidioc_s_ctrl           = vidioc_s_ctrl,
-       .vidioc_g_ctrl           = vidioc_g_ctrl,
-       .vidioc_querycap         = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_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_g_ext_ctrls      = vidioc_g_ext_ctrls,
-       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
-       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
-       .vidioc_log_status       = vidioc_log_status,
-       .vidioc_querymenu        = vidioc_querymenu,
-       .vidioc_queryctrl        = vidioc_queryctrl,
-       .vidioc_g_chip_ident     = cx23885_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register       = cx23885_g_register,
-       .vidioc_s_register       = cx23885_s_register,
-#endif
-};
-
-static struct video_device cx23885_mpeg_template = {
-       .name          = "cx23885",
-       .fops          = &mpeg_fops,
-       .ioctl_ops     = &mpeg_ioctl_ops,
-       .tvnorms       = CX23885_NORMS,
-       .current_norm  = V4L2_STD_NTSC_M,
-};
-
-void cx23885_417_unregister(struct cx23885_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       if (dev->v4l_device) {
-               if (video_is_registered(dev->v4l_device))
-                       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;
-       snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
-               cx23885_boards[tsport->dev->board].name, type);
-       vfd->parent  = &pci->dev;
-       vfd->release = video_device_release;
-       return vfd;
-}
-
-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");
-       video_set_drvdata(dev->v4l_device, dev);
-       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;
-       }
-
-       printk(KERN_INFO "%s: registered device %s [mpeg]\n",
-              dev->name, video_device_node_name(dev->v4l_device));
-
-       /* ST: Configure the encoder paramaters, but don't begin
-        * encoding, this resolves an issue where the first time the
-        * encoder is started video can be choppy.
-        */
-       cx23885_initialize_codec(dev, 0);
-
-       return 0;
-}
-
-MODULE_FIRMWARE(CX23885_FIRM_IMAGE_NAME);
diff --git a/drivers/media/video/cx23885/cx23885-alsa.c b/drivers/media/video/cx23885/cx23885-alsa.c
deleted file mode 100644 (file)
index 7951692..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- *
- *  Support for CX23885 analog audio capture
- *
- *    (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
- *    Adapted from cx88-alsa.c
- *    (c) 2009 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/dma-mapping.h>
-#include <linux/pci.h>
-
-#include <asm/delay.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-
-#include <sound/tlv.h>
-
-
-#include "cx23885.h"
-#include "cx23885-reg.h"
-
-#define AUDIO_SRAM_CHANNEL     SRAM_CH07
-
-#define dprintk(level, fmt, arg...)    if (audio_debug >= level) \
-       printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
-
-#define dprintk_core(level, fmt, arg...)       if (audio_debug >= level) \
-       printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
-
-/****************************************************************************
-                       Module global static vars
- ****************************************************************************/
-
-static unsigned int disable_analog_audio;
-module_param(disable_analog_audio, int, 0644);
-MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
-
-static unsigned int audio_debug;
-module_param(audio_debug, int, 0644);
-MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
-
-/****************************************************************************
-                       Board specific funtions
- ****************************************************************************/
-
-/* Constants taken from cx88-reg.h */
-#define AUD_INT_DN_RISCI1       (1 <<  0)
-#define AUD_INT_UP_RISCI1       (1 <<  1)
-#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
-#define AUD_INT_DN_RISCI2       (1 <<  4) /* yes, 3 is skipped */
-#define AUD_INT_UP_RISCI2       (1 <<  5)
-#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
-#define AUD_INT_DN_SYNC         (1 << 12)
-#define AUD_INT_UP_SYNC         (1 << 13)
-#define AUD_INT_RDS_DN_SYNC     (1 << 14)
-#define AUD_INT_OPC_ERR         (1 << 16)
-#define AUD_INT_BER_IRQ         (1 << 20)
-#define AUD_INT_MCHG_IRQ        (1 << 21)
-#define GP_COUNT_CONTROL_RESET 0x3
-
-/*
- * BOARD Specific: Sets audio DMA
- */
-
-static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
-{
-       struct cx23885_audio_buffer *buf = chip->buf;
-       struct cx23885_dev *dev  = chip->dev;
-       struct sram_channel *audio_ch =
-               &dev->sram_channels[AUDIO_SRAM_CHANNEL];
-
-       dprintk(1, "%s()\n", __func__);
-
-       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
-       cx_clear(AUD_INT_DMA_CTL, 0x11);
-
-       /* setup fifo + format - out channel */
-       cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
-               buf->risc.dma);
-
-       /* sets bpl size */
-       cx_write(AUD_INT_A_LNGTH, buf->bpl);
-
-       /* This is required to get good audio (1 seems to be ok) */
-       cx_write(AUD_INT_A_MODE, 1);
-
-       /* reset counter */
-       cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
-       atomic_set(&chip->count, 0);
-
-       dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
-               "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
-               chip->num_periods, buf->bpl * chip->num_periods);
-
-       /* Enables corresponding bits at AUD_INT_STAT */
-       cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
-                                   AUD_INT_DN_RISCI1);
-
-       /* Clean any pending interrupt bits already set */
-       cx_write(AUDIO_INT_INT_STAT, ~0);
-
-       /* enable audio irqs */
-       cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
-
-       /* start dma */
-       cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
-       cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
-                                         RISC enable */
-       if (audio_debug)
-               cx23885_sram_channel_dump(chip->dev, audio_ch);
-
-       return 0;
-}
-
-/*
- * BOARD Specific: Resets audio DMA
- */
-static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
-{
-       struct cx23885_dev *dev = chip->dev;
-       dprintk(1, "Stopping audio DMA\n");
-
-       /* stop dma */
-       cx_clear(AUD_INT_DMA_CTL, 0x11);
-
-       /* disable irqs */
-       cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
-       cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
-                                   AUD_INT_DN_RISCI1);
-
-       if (audio_debug)
-               cx23885_sram_channel_dump(chip->dev,
-                       &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
-
-       return 0;
-}
-
-/*
- * BOARD Specific: Handles audio IRQ
- */
-int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
-{
-       struct cx23885_audio_dev *chip = dev->audio_dev;
-
-       if (0 == (status & mask))
-               return 0;
-
-       cx_write(AUDIO_INT_INT_STAT, status);
-
-       /* risc op code error */
-       if (status & AUD_INT_OPC_ERR) {
-               printk(KERN_WARNING "%s/1: Audio risc op code error\n",
-                       dev->name);
-               cx_clear(AUD_INT_DMA_CTL, 0x11);
-               cx23885_sram_channel_dump(dev,
-                       &dev->sram_channels[AUDIO_SRAM_CHANNEL]);
-       }
-       if (status & AUD_INT_DN_SYNC) {
-               dprintk(1, "Downstream sync error\n");
-               cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
-               return 1;
-       }
-       /* risc1 downstream */
-       if (status & AUD_INT_DN_RISCI1) {
-               atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
-               snd_pcm_period_elapsed(chip->substream);
-       }
-       /* FIXME: Any other status should deserve a special handling? */
-
-       return 1;
-}
-
-static int dsp_buffer_free(struct cx23885_audio_dev *chip)
-{
-       BUG_ON(!chip->dma_size);
-
-       dprintk(2, "Freeing buffer\n");
-       videobuf_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);
-
-       chip->dma_risc = NULL;
-       chip->dma_size = 0;
-
-       return 0;
-}
-
-/****************************************************************************
-                               ALSA PCM Interface
- ****************************************************************************/
-
-/*
- * Digital hardware definition
- */
-#define DEFAULT_FIFO_SIZE      4096
-
-static struct snd_pcm_hardware snd_cx23885_digital_hw = {
-       .info = SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP_VALID,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates =                SNDRV_PCM_RATE_48000,
-       .rate_min =             48000,
-       .rate_max =             48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       /* Analog audio output will be full of clicks and pops if there
-          are not exactly four lines in the SRAM FIFO buffer.  */
-       .period_bytes_min = DEFAULT_FIFO_SIZE/4,
-       .period_bytes_max = DEFAULT_FIFO_SIZE/4,
-       .periods_min = 1,
-       .periods_max = 1024,
-       .buffer_bytes_max = (1024*1024),
-};
-
-/*
- * audio pcm capture open callback
- */
-static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int err;
-
-       if (!chip) {
-               printk(KERN_ERR "BUG: cx23885 can't find device struct."
-                               " Can't proceed with open\n");
-               return -ENODEV;
-       }
-
-       err = snd_pcm_hw_constraint_pow2(runtime, 0,
-               SNDRV_PCM_HW_PARAM_PERIODS);
-       if (err < 0)
-               goto _error;
-
-       chip->substream = substream;
-
-       runtime->hw = snd_cx23885_digital_hw;
-
-       if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
-               DEFAULT_FIFO_SIZE) {
-               unsigned int bpl = chip->dev->
-                       sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
-               bpl &= ~7; /* must be multiple of 8 */
-               runtime->hw.period_bytes_min = bpl;
-               runtime->hw.period_bytes_max = bpl;
-       }
-
-       return 0;
-_error:
-       dprintk(1, "Error opening PCM!\n");
-       return err;
-}
-
-/*
- * audio close callback
- */
-static int snd_cx23885_close(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
-/*
- * hw_params callback
- */
-static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *hw_params)
-{
-       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
-       struct videobuf_dmabuf *dma;
-
-       struct cx23885_audio_buffer *buf;
-       int ret;
-
-       if (substream->runtime->dma_area) {
-               dsp_buffer_free(chip);
-               substream->runtime->dma_area = NULL;
-       }
-
-       chip->period_size = params_period_bytes(hw_params);
-       chip->num_periods = params_periods(hw_params);
-       chip->dma_size = chip->period_size * params_periods(hw_params);
-
-       BUG_ON(!chip->dma_size);
-       BUG_ON(chip->num_periods & (chip->num_periods-1));
-
-       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
-       if (NULL == buf)
-               return -ENOMEM;
-
-       buf->bpl = chip->period_size;
-
-       dma = &buf->dma;
-       videobuf_dma_init(dma);
-       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
-                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
-       if (ret < 0)
-               goto error;
-
-       ret = videobuf_dma_map(&chip->pci->dev, dma);
-       if (ret < 0)
-               goto error;
-
-       ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
-                                  chip->period_size, chip->num_periods, 1);
-       if (ret < 0)
-               goto error;
-
-       /* Loop back to start of program */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
-
-       chip->buf = buf;
-       chip->dma_risc = dma;
-
-       substream->runtime->dma_area = chip->dma_risc->vaddr;
-       substream->runtime->dma_bytes = chip->dma_size;
-       substream->runtime->dma_addr = 0;
-
-       return 0;
-
-error:
-       kfree(buf);
-       return ret;
-}
-
-/*
- * hw free callback
- */
-static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
-{
-
-       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
-
-       if (substream->runtime->dma_area) {
-               dsp_buffer_free(chip);
-               substream->runtime->dma_area = NULL;
-       }
-
-       return 0;
-}
-
-/*
- * prepare callback
- */
-static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
-/*
- * trigger callback
- */
-static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
-       int cmd)
-{
-       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
-       int err;
-
-       /* Local interrupts are already disabled by ALSA */
-       spin_lock(&chip->lock);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               err = cx23885_start_audio_dma(chip);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               err = cx23885_stop_audio_dma(chip);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-
-       spin_unlock(&chip->lock);
-
-       return err;
-}
-
-/*
- * pointer callback
- */
-static snd_pcm_uframes_t snd_cx23885_pointer(
-       struct snd_pcm_substream *substream)
-{
-       struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       u16 count;
-
-       count = atomic_read(&chip->count);
-
-       return runtime->period_size * (count & (runtime->periods-1));
-}
-
-/*
- * page callback (needed for mmap)
- */
-static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
-                               unsigned long offset)
-{
-       void *pageptr = substream->runtime->dma_area + offset;
-       return vmalloc_to_page(pageptr);
-}
-
-/*
- * operators
- */
-static struct snd_pcm_ops snd_cx23885_pcm_ops = {
-       .open = snd_cx23885_pcm_open,
-       .close = snd_cx23885_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_cx23885_hw_params,
-       .hw_free = snd_cx23885_hw_free,
-       .prepare = snd_cx23885_prepare,
-       .trigger = snd_cx23885_card_trigger,
-       .pointer = snd_cx23885_pointer,
-       .page = snd_cx23885_page,
-};
-
-/*
- * create a PCM device
- */
-static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
-       char *name)
-{
-       int err;
-       struct snd_pcm *pcm;
-
-       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
-       if (err < 0)
-               return err;
-       pcm->private_data = chip;
-       strcpy(pcm->name, name);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
-
-       return 0;
-}
-
-/****************************************************************************
-                       Basic Flow for Sound Devices
- ****************************************************************************/
-
-/*
- * Alsa Constructor - Component probe
- */
-
-struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
-{
-       struct snd_card *card;
-       struct cx23885_audio_dev *chip;
-       int err;
-
-       if (disable_analog_audio)
-               return NULL;
-
-       if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
-               printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
-                       "for analog TV Audio\n", __func__);
-               return NULL;
-       }
-
-       err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-                       THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
-       if (err < 0)
-               goto error;
-
-       chip = (struct cx23885_audio_dev *) card->private_data;
-       chip->dev = dev;
-       chip->pci = dev->pci;
-       chip->card = card;
-       spin_lock_init(&chip->lock);
-
-       snd_card_set_dev(card, &dev->pci->dev);
-
-       err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
-       if (err < 0)
-               goto error;
-
-       strcpy(card->driver, "CX23885");
-       sprintf(card->shortname, "Conexant CX23885");
-       sprintf(card->longname, "%s at %s", card->shortname, dev->name);
-
-       err = snd_card_register(card);
-       if (err < 0)
-               goto error;
-
-       dprintk(0, "registered ALSA audio device\n");
-
-       return chip;
-
-error:
-       snd_card_free(card);
-       printk(KERN_ERR "%s(): Failed to register analog "
-                       "audio adapter\n", __func__);
-
-       return NULL;
-}
-
-/*
- * ALSA destructor
- */
-void cx23885_audio_unregister(struct cx23885_dev *dev)
-{
-       struct cx23885_audio_dev *chip = dev->audio_dev;
-
-       snd_card_free(chip->card);
-}
diff --git a/drivers/media/video/cx23885/cx23885-av.c b/drivers/media/video/cx23885/cx23885-av.c
deleted file mode 100644 (file)
index 134ebdd..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  AV device support routines - non-input, non-vl42_subdev routines
- *
- *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include "cx23885.h"
-
-void cx23885_av_work_handler(struct work_struct *work)
-{
-       struct cx23885_dev *dev =
-                          container_of(work, struct cx23885_dev, cx25840_work);
-       bool handled;
-
-       v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
-                        PCI_MSK_AV_CORE, &handled);
-       cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
-}
diff --git a/drivers/media/video/cx23885/cx23885-av.h b/drivers/media/video/cx23885/cx23885-av.h
deleted file mode 100644 (file)
index d2915c3..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  AV device support routines - non-input, non-vl42_subdev routines
- *
- *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#ifndef _CX23885_AV_H_
-#define _CX23885_AV_H_
-void cx23885_av_work_handler(struct work_struct *work);
-#endif
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c
deleted file mode 100644 (file)
index d365e9a..0000000
+++ /dev/null
@@ -1,1684 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <media/cx25840.h>
-#include <linux/firmware.h>
-#include <misc/altera.h>
-
-#include "cx23885.h"
-#include "tuner-xc2028.h"
-#include "netup-eeprom.h"
-#include "netup-init.h"
-#include "altera-ci.h"
-#include "xc4000.h"
-#include "xc5000.h"
-#include "cx23888-ir.h"
-
-static unsigned int netup_card_rev = 1;
-module_param(netup_card_rev, int, 0644);
-MODULE_PARM_DESC(netup_card_rev,
-               "NetUP Dual DVB-T/C CI card revision");
-static unsigned int enable_885_ir;
-module_param(enable_885_ir, int, 0644);
-MODULE_PARM_DESC(enable_885_ir,
-                "Enable integrated IR controller for supported\n"
-                "\t\t    CX2388[57] boards that are wired for it:\n"
-                "\t\t\tHVR-1250 (reported safe)\n"
-                "\t\t\tTerraTec Cinergy T PCIe Dual (not well tested, appears to be safe)\n"
-                "\t\t\tTeVii S470 (reported unsafe)\n"
-                "\t\t    This can cause an interrupt storm with some cards.\n"
-                "\t\t    Default: 0 [Disabled]");
-
-/* ------------------------------------------------------------------ */
-/* board config info                                                  */
-
-struct cx23885_board cx23885_boards[] = {
-       [CX23885_BOARD_UNKNOWN] = {
-               .name           = "UNKNOWN/GENERIC",
-               /* Ensure safe default for unknown boards */
-               .clk_freq       = 0,
-               .input          = {{
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = 0,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE2,
-                       .vmux   = 1,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE3,
-                       .vmux   = 2,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE4,
-                       .vmux   = 3,
-               } },
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1800lp] = {
-               .name           = "Hauppauge WinTV-HVR1800lp",
-               .portc          = CX23885_MPEG_DVB,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xff00,
-               }, {
-                       .type   = CX23885_VMUX_DEBUG,
-                       .vmux   = 0,
-                       .gpio0  = 0xff01,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xff02,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xff02,
-               } },
-       },
-       [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 */
-               .tuner_bus      = 1,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN5_CH2 |
-                                       CX25840_VIN2_CH1,
-                       .amux   = CX25840_AUDIO8,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN6_CH1,
-                       .amux   = CX25840_AUDIO7,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN8_CH1 |
-                                       CX25840_SVIDEO_ON,
-                       .amux   = CX25840_AUDIO7,
-                       .gpio0  = 0,
-               } },
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1250] = {
-               .name           = "Hauppauge WinTV-HVR1250",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portc          = CX23885_MPEG_DVB,
-#ifdef MT2131_NO_ANALOG_SUPPORT_YET
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .tuner_addr     = 0x42, /* 0x84 >> 1 */
-               .tuner_bus      = 1,
-#endif
-               .force_bff      = 1,
-               .input          = {{
-#ifdef MT2131_NO_ANALOG_SUPPORT_YET
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN5_CH2 |
-                                       CX25840_VIN2_CH1,
-                       .amux   = CX25840_AUDIO8,
-                       .gpio0  = 0xff00,
-               }, {
-#endif
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN6_CH1,
-                       .amux   = CX25840_AUDIO7,
-                       .gpio0  = 0xff02,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN8_CH1 |
-                                       CX25840_SVIDEO_ON,
-                       .amux   = CX25840_AUDIO7,
-                       .gpio0  = 0xff02,
-               } },
-       },
-       [CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = {
-               .name           = "DViCO FusionHDTV5 Express",
-               .portb          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1500Q] = {
-               .name           = "Hauppauge WinTV-HVR1500Q",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1500] = {
-               .name           = "Hauppauge WinTV-HVR1500",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portc          = CX23885_MPEG_DVB,
-               .tuner_type     = TUNER_XC2028,
-               .tuner_addr     = 0x61, /* 0xc2 >> 1 */
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN5_CH2 |
-                                       CX25840_VIN2_CH1,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN6_CH1,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN8_CH1 |
-                                       CX25840_SVIDEO_ON,
-                       .gpio0  = 0,
-               } },
-       },
-       [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,
-       },
-       [CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
-               .name           = "DViCO FusionHDTV7 Dual Express",
-               .portb          = CX23885_MPEG_DVB,
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = {
-               .name           = "DViCO FusionHDTV DVB-T Dual Express",
-               .portb          = CX23885_MPEG_DVB,
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = {
-               .name           = "Leadtek Winfast PxDVR3200 H",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
-               .name           = "Leadtek Winfast PxDVR3200 H XC4000",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portc          = CX23885_MPEG_DVB,
-               .tuner_type     = TUNER_XC4000,
-               .tuner_addr     = 0x61,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   = CX25840_VIN2_CH1 |
-                                 CX25840_VIN5_CH2 |
-                                 CX25840_NONE0_CH3,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = CX25840_COMPOSITE1,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   = CX25840_SVIDEO_LUMA3 |
-                                 CX25840_SVIDEO_CHROMA4,
-               }, {
-                       .type   = CX23885_VMUX_COMPONENT,
-                       .vmux   = CX25840_VIN7_CH1 |
-                                 CX25840_VIN6_CH2 |
-                                 CX25840_VIN8_CH3 |
-                                 CX25840_COMPONENT_ON,
-               } },
-       },
-       [CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
-               .name           = "Compro VideoMate E650F",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_TBS_6920] = {
-               .name           = "TurboSight TBS 6920",
-               .portb          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_TEVII_S470] = {
-               .name           = "TeVii S470",
-               .portb          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_DVBWORLD_2005] = {
-               .name           = "DVBWorld DVB-S2 2005",
-               .portb          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = {
-               .ci_type        = 1,
-               .name           = "NetUP Dual DVB-S2 CI",
-               .portb          = CX23885_MPEG_DVB,
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1270] = {
-               .name           = "Hauppauge WinTV-HVR1270",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1275] = {
-               .name           = "Hauppauge WinTV-HVR1275",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1255] = {
-               .name           = "Hauppauge WinTV-HVR1255",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portc          = CX23885_MPEG_DVB,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = 0x42, /* 0x84 >> 1 */
-               .force_bff      = 1,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN5_CH2 |
-                                       CX25840_VIN2_CH1 |
-                                       CX25840_DIF_ON,
-                       .amux   = CX25840_AUDIO8,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN6_CH1,
-                       .amux   = CX25840_AUDIO7,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN8_CH1 |
-                                       CX25840_SVIDEO_ON,
-                       .amux   = CX25840_AUDIO7,
-               } },
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1255_22111] = {
-               .name           = "Hauppauge WinTV-HVR1255",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portc          = CX23885_MPEG_DVB,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = 0x42, /* 0x84 >> 1 */
-               .force_bff      = 1,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN5_CH2 |
-                                       CX25840_VIN2_CH1 |
-                                       CX25840_DIF_ON,
-                       .amux   = CX25840_AUDIO8,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN8_CH1 |
-                                       CX25840_SVIDEO_ON,
-                       .amux   = CX25840_AUDIO7,
-               } },
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1210] = {
-               .name           = "Hauppauge WinTV-HVR1210",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_MYGICA_X8506] = {
-               .name           = "Mygica X8506 DMB-TH",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_bus      = 1,
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portb          = CX23885_MPEG_DVB,
-               .input          = {
-                       {
-                               .type   = CX23885_VMUX_TELEVISION,
-                               .vmux   = CX25840_COMPOSITE2,
-                       },
-                       {
-                               .type   = CX23885_VMUX_COMPOSITE1,
-                               .vmux   = CX25840_COMPOSITE8,
-                       },
-                       {
-                               .type   = CX23885_VMUX_SVIDEO,
-                               .vmux   = CX25840_SVIDEO_LUMA3 |
-                                               CX25840_SVIDEO_CHROMA4,
-                       },
-                       {
-                               .type   = CX23885_VMUX_COMPONENT,
-                               .vmux   = CX25840_COMPONENT_ON |
-                                       CX25840_VIN1_CH1 |
-                                       CX25840_VIN6_CH2 |
-                                       CX25840_VIN7_CH3,
-                       },
-               },
-       },
-       [CX23885_BOARD_MAGICPRO_PROHDTVE2] = {
-               .name           = "Magic-Pro ProHDTV Extreme 2",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_bus      = 1,
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portb          = CX23885_MPEG_DVB,
-               .input          = {
-                       {
-                               .type   = CX23885_VMUX_TELEVISION,
-                               .vmux   = CX25840_COMPOSITE2,
-                       },
-                       {
-                               .type   = CX23885_VMUX_COMPOSITE1,
-                               .vmux   = CX25840_COMPOSITE8,
-                       },
-                       {
-                               .type   = CX23885_VMUX_SVIDEO,
-                               .vmux   = CX25840_SVIDEO_LUMA3 |
-                                               CX25840_SVIDEO_CHROMA4,
-                       },
-                       {
-                               .type   = CX23885_VMUX_COMPONENT,
-                               .vmux   = CX25840_COMPONENT_ON |
-                                       CX25840_VIN1_CH1 |
-                                       CX25840_VIN6_CH2 |
-                                       CX25840_VIN7_CH3,
-                       },
-               },
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1850] = {
-               .name           = "Hauppauge WinTV-HVR1850",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portb          = CX23885_MPEG_ENCODER,
-               .portc          = CX23885_MPEG_DVB,
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_addr     = 0x42, /* 0x84 >> 1 */
-               .force_bff      = 1,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN5_CH2 |
-                                       CX25840_VIN2_CH1 |
-                                       CX25840_DIF_ON,
-                       .amux   = CX25840_AUDIO8,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN6_CH1,
-                       .amux   = CX25840_AUDIO7,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   =       CX25840_VIN7_CH3 |
-                                       CX25840_VIN4_CH2 |
-                                       CX25840_VIN8_CH1 |
-                                       CX25840_SVIDEO_ON,
-                       .amux   = CX25840_AUDIO7,
-               } },
-       },
-       [CX23885_BOARD_COMPRO_VIDEOMATE_E800] = {
-               .name           = "Compro VideoMate E800",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_HAUPPAUGE_HVR1290] = {
-               .name           = "Hauppauge WinTV-HVR1290",
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_MYGICA_X8558PRO] = {
-               .name           = "Mygica X8558 PRO DMB-TH",
-               .portb          = CX23885_MPEG_DVB,
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_LEADTEK_WINFAST_PXTV1200] = {
-               .name           = "LEADTEK WinFast PxTV1200",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .tuner_type     = TUNER_XC2028,
-               .tuner_addr     = 0x61,
-               .tuner_bus      = 1,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   = CX25840_VIN2_CH1 |
-                                 CX25840_VIN5_CH2 |
-                                 CX25840_NONE0_CH3,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = CX25840_COMPOSITE1,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   = CX25840_SVIDEO_LUMA3 |
-                                 CX25840_SVIDEO_CHROMA4,
-               }, {
-                       .type   = CX23885_VMUX_COMPONENT,
-                       .vmux   = CX25840_VIN7_CH1 |
-                                 CX25840_VIN6_CH2 |
-                                 CX25840_VIN8_CH3 |
-                                 CX25840_COMPONENT_ON,
-               } },
-       },
-       [CX23885_BOARD_GOTVIEW_X5_3D_HYBRID] = {
-               .name           = "GoTView X5 3D Hybrid",
-               .tuner_type     = TUNER_XC5000,
-               .tuner_addr     = 0x64,
-               .tuner_bus      = 1,
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portb          = CX23885_MPEG_DVB,
-               .input          = {{
-                       .type   = CX23885_VMUX_TELEVISION,
-                       .vmux   = CX25840_VIN2_CH1 |
-                                 CX25840_VIN5_CH2,
-                       .gpio0  = 0x02,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = CX23885_VMUX_COMPOSITE1,
-               }, {
-                       .type   = CX23885_VMUX_SVIDEO,
-                       .vmux   = CX25840_SVIDEO_LUMA3 |
-                                 CX25840_SVIDEO_CHROMA4,
-               } },
-       },
-       [CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF] = {
-               .ci_type        = 2,
-               .name           = "NetUP Dual DVB-T/C-CI RF",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .portb          = CX23885_MPEG_DVB,
-               .portc          = CX23885_MPEG_DVB,
-               .num_fds_portb  = 2,
-               .num_fds_portc  = 2,
-               .tuner_type     = TUNER_XC5000,
-               .tuner_addr     = 0x64,
-               .input          = { {
-                               .type   = CX23885_VMUX_TELEVISION,
-                               .vmux   = CX25840_COMPOSITE1,
-               } },
-       },
-       [CX23885_BOARD_MPX885] = {
-               .name           = "MPX-885",
-               .porta          = CX23885_ANALOG_VIDEO,
-               .input          = {{
-                       .type   = CX23885_VMUX_COMPOSITE1,
-                       .vmux   = CX25840_COMPOSITE1,
-                       .amux   = CX25840_AUDIO6,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE2,
-                       .vmux   = CX25840_COMPOSITE2,
-                       .amux   = CX25840_AUDIO6,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE3,
-                       .vmux   = CX25840_COMPOSITE3,
-                       .amux   = CX25840_AUDIO7,
-                       .gpio0  = 0,
-               }, {
-                       .type   = CX23885_VMUX_COMPOSITE4,
-                       .vmux   = CX25840_COMPOSITE4,
-                       .amux   = CX25840_AUDIO7,
-                       .gpio0  = 0,
-               } },
-       },
-       [CX23885_BOARD_MYGICA_X8507] = {
-               .name           = "Mygica X8507",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_bus      = 1,
-               .porta          = CX23885_ANALOG_VIDEO,
-               .input          = {
-                       {
-                               .type   = CX23885_VMUX_TELEVISION,
-                               .vmux   = CX25840_COMPOSITE2,
-                               .amux   = CX25840_AUDIO8,
-                       },
-                       {
-                               .type   = CX23885_VMUX_COMPOSITE1,
-                               .vmux   = CX25840_COMPOSITE8,
-                       },
-                       {
-                               .type   = CX23885_VMUX_SVIDEO,
-                               .vmux   = CX25840_SVIDEO_LUMA3 |
-                                               CX25840_SVIDEO_CHROMA4,
-                       },
-                       {
-                               .type   = CX23885_VMUX_COMPONENT,
-                               .vmux   = CX25840_COMPONENT_ON |
-                                       CX25840_VIN1_CH1 |
-                                       CX25840_VIN6_CH2 |
-                                       CX25840_VIN7_CH3,
-                       },
-               },
-       },
-       [CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL] = {
-               .name           = "TerraTec Cinergy T PCIe Dual",
-               .portb          = CX23885_MPEG_DVB,
-               .portc          = CX23885_MPEG_DVB,
-       },
-       [CX23885_BOARD_TEVII_S471] = {
-               .name           = "TeVii S471",
-               .portb          = CX23885_MPEG_DVB,
-       }
-};
-const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
-
-/* ------------------------------------------------------------------ */
-/* PCI subsystem IDs                                                  */
-
-struct cx23885_subid cx23885_subids[] = {
-       {
-               .subvendor = 0x0070,
-               .subdevice = 0x3400,
-               .card      = CX23885_BOARD_UNKNOWN,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7600,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800lp,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7800,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7801,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7809,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7911,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1250,
-       }, {
-               .subvendor = 0x18ac,
-               .subdevice = 0xd500,
-               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7790,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7797,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7710,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x7717,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x71d1,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x71d3,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8101,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1700,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8010,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
-       }, {
-               .subvendor = 0x18ac,
-               .subdevice = 0xd618,
-               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
-       }, {
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb78,
-               .card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
-       }, {
-               .subvendor = 0x107d,
-               .subdevice = 0x6681,
-               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
-       }, {
-               .subvendor = 0x107d,
-               .subdevice = 0x6f39,
-               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000,
-       }, {
-               .subvendor = 0x185b,
-               .subdevice = 0xe800,
-               .card      = CX23885_BOARD_COMPRO_VIDEOMATE_E650F,
-       }, {
-               .subvendor = 0x6920,
-               .subdevice = 0x8888,
-               .card      = CX23885_BOARD_TBS_6920,
-       }, {
-               .subvendor = 0xd470,
-               .subdevice = 0x9022,
-               .card      = CX23885_BOARD_TEVII_S470,
-       }, {
-               .subvendor = 0x0001,
-               .subdevice = 0x2005,
-               .card      = CX23885_BOARD_DVBWORLD_2005,
-       }, {
-               .subvendor = 0x1b55,
-               .subdevice = 0x2a2c,
-               .card      = CX23885_BOARD_NETUP_DUAL_DVBS2_CI,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2211,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1270,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2215,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x221d,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2251,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2259,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255_22111,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2291,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2295,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x2299,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x229d,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x22f0,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x22f1,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x22f2,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x22f3,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x22f4,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x22f5,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
-       }, {
-               .subvendor = 0x14f1,
-               .subdevice = 0x8651,
-               .card      = CX23885_BOARD_MYGICA_X8506,
-       }, {
-               .subvendor = 0x14f1,
-               .subdevice = 0x8657,
-               .card      = CX23885_BOARD_MAGICPRO_PROHDTVE2,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8541,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1850,
-       }, {
-               .subvendor = 0x1858,
-               .subdevice = 0xe800,
-               .card      = CX23885_BOARD_COMPRO_VIDEOMATE_E800,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8551,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1290,
-       }, {
-               .subvendor = 0x14f1,
-               .subdevice = 0x8578,
-               .card      = CX23885_BOARD_MYGICA_X8558PRO,
-       }, {
-               .subvendor = 0x107d,
-               .subdevice = 0x6f22,
-               .card      = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200,
-       }, {
-               .subvendor = 0x5654,
-               .subdevice = 0x2390,
-               .card      = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID,
-       }, {
-               .subvendor = 0x1b55,
-               .subdevice = 0xe2e4,
-               .card      = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF,
-       }, {
-               .subvendor = 0x14f1,
-               .subdevice = 0x8502,
-               .card      = CX23885_BOARD_MYGICA_X8507,
-       }, {
-               .subvendor = 0x153b,
-               .subdevice = 0x117e,
-               .card      = CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL,
-       }, {
-               .subvendor = 0xd471,
-               .subdevice = 0x9022,
-               .card      = CX23885_BOARD_TEVII_S471,
-       },
-};
-const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
-
-void cx23885_card_list(struct cx23885_dev *dev)
-{
-       int i;
-
-       if (0 == dev->pci->subsystem_vendor &&
-           0 == dev->pci->subsystem_device) {
-               printk(KERN_INFO
-                       "%s: Board has no valid PCIe Subsystem ID and can't\n"
-                      "%s: be autodetected. Pass card=<n> insmod option\n"
-                      "%s: to workaround that. Redirect complaints to the\n"
-                      "%s: vendor of the TV card.  Best regards,\n"
-                      "%s:         -- tux\n",
-                      dev->name, dev->name, dev->name, dev->name, dev->name);
-       } else {
-               printk(KERN_INFO
-                       "%s: Your board isn't known (yet) to the driver.\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",
-                      dev->name, dev->name, dev->name, dev->name);
-       }
-       printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
-              dev->name);
-       for (i = 0; i < cx23885_bcount; i++)
-               printk(KERN_INFO "%s:    card=%d -> %s\n",
-                      dev->name, i, cx23885_boards[i].name);
-}
-
-static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
-{
-       struct tveeprom tv;
-
-       tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
-               eeprom_data);
-
-       /* Make sure we support the board model */
-       switch (tv.model) {
-       case 22001:
-               /* WinTV-HVR1270 (PCIe, Retail, half height)
-                * ATSC/QAM and basic analog, IR Blast */
-       case 22009:
-               /* WinTV-HVR1210 (PCIe, Retail, half height)
-                * DVB-T and basic analog, IR Blast */
-       case 22011:
-               /* WinTV-HVR1270 (PCIe, Retail, half height)
-                * ATSC/QAM and basic analog, IR Recv */
-       case 22019:
-               /* WinTV-HVR1210 (PCIe, Retail, half height)
-                * DVB-T and basic analog, IR Recv */
-       case 22021:
-               /* WinTV-HVR1275 (PCIe, Retail, half height)
-                * ATSC/QAM and basic analog, IR Recv */
-       case 22029:
-               /* WinTV-HVR1210 (PCIe, Retail, half height)
-                * DVB-T and basic analog, IR Recv */
-       case 22101:
-               /* WinTV-HVR1270 (PCIe, Retail, full height)
-                * ATSC/QAM and basic analog, IR Blast */
-       case 22109:
-               /* WinTV-HVR1210 (PCIe, Retail, full height)
-                * DVB-T and basic analog, IR Blast */
-       case 22111:
-               /* WinTV-HVR1270 (PCIe, Retail, full height)
-                * ATSC/QAM and basic analog, IR Recv */
-       case 22119:
-               /* WinTV-HVR1210 (PCIe, Retail, full height)
-                * DVB-T and basic analog, IR Recv */
-       case 22121:
-               /* WinTV-HVR1275 (PCIe, Retail, full height)
-                * ATSC/QAM and basic analog, IR Recv */
-       case 22129:
-               /* WinTV-HVR1210 (PCIe, Retail, full height)
-                * DVB-T and basic analog, IR Recv */
-       case 71009:
-               /* WinTV-HVR1200 (PCIe, Retail, full height)
-                * DVB-T and basic analog */
-       case 71359:
-               /* WinTV-HVR1200 (PCIe, OEM, half height)
-                * DVB-T and basic analog */
-       case 71439:
-               /* WinTV-HVR1200 (PCIe, OEM, half height)
-                * DVB-T and basic analog */
-       case 71449:
-               /* WinTV-HVR1200 (PCIe, OEM, full height)
-                * DVB-T and basic analog */
-       case 71939:
-               /* WinTV-HVR1200 (PCIe, OEM, half height)
-                * DVB-T and basic analog */
-       case 71949:
-               /* WinTV-HVR1200 (PCIe, OEM, full height)
-                * DVB-T and basic analog */
-       case 71959:
-               /* WinTV-HVR1200 (PCIe, OEM, full height)
-                * DVB-T and basic analog */
-       case 71979:
-               /* WinTV-HVR1200 (PCIe, OEM, half height)
-                * DVB-T and basic analog */
-       case 71999:
-               /* WinTV-HVR1200 (PCIe, OEM, full height)
-                * DVB-T and basic analog */
-       case 76601:
-               /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual
-                       channel ATSC and MPEG2 HW Encoder */
-       case 77001:
-               /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC
-                       and Basic analog */
-       case 77011:
-               /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC
-                       and Basic analog */
-       case 77041:
-               /* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM
-                       and Basic analog */
-       case 77051:
-               /* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM
-                       and Basic analog */
-       case 78011:
-               /* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM,
-                       Dual channel ATSC and MPEG2 HW Encoder */
-       case 78501:
-               /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
-                       Dual channel ATSC and MPEG2 HW Encoder */
-       case 78521:
-               /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
-                       Dual channel ATSC and MPEG2 HW Encoder */
-       case 78531:
-               /* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM,
-                       Dual channel ATSC and MPEG2 HW Encoder */
-       case 78631:
-               /* WinTV-HVR1800 (PCIe, OEM, No IR, No FM,
-                       Dual channel ATSC and MPEG2 HW Encoder */
-       case 79001:
-               /* WinTV-HVR1250 (PCIe, Retail, IR, full height,
-                       ATSC and Basic analog */
-       case 79101:
-               /* WinTV-HVR1250 (PCIe, Retail, IR, half height,
-                       ATSC and Basic analog */
-       case 79501:
-               /* WinTV-HVR1250 (PCIe, No IR, half height,
-                       ATSC [at least] and Basic analog) */
-       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 81509:
-               /* WinTV-HVR1700 (PCIe, OEM, No IR, half height)
-                * DVB-T and MPEG2 HW Encoder */
-       case 81519:
-               /* WinTV-HVR1700 (PCIe, OEM, No IR, full height)
-                * DVB-T and MPEG2 HW Encoder */
-               break;
-       case 85021:
-               /* WinTV-HVR1850 (PCIe, Retail, 3.5mm in, IR, FM,
-                       Dual channel ATSC and MPEG2 HW Encoder */
-               break;
-       case 85721:
-               /* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
-                       Dual channel ATSC and Basic analog */
-               break;
-       default:
-               printk(KERN_WARNING "%s: warning: "
-                       "unknown hauppauge model #%d\n",
-                       dev->name, tv.model);
-               break;
-       }
-
-       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-                       dev->name, tv.model);
-}
-
-int cx23885_tuner_callback(void *priv, int component, int command, int arg)
-{
-       struct cx23885_tsport *port = priv;
-       struct cx23885_dev *dev = port->dev;
-       u32 bitmask = 0;
-
-       if ((command == XC2028_RESET_CLK) || (command == XC2028_I2C_FLUSH))
-               return 0;
-
-       if (command != 0) {
-               printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
-                       __func__, command);
-               return -EINVAL;
-       }
-
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1400:
-       case CX23885_BOARD_HAUPPAUGE_HVR1500:
-       case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
-               /* Tuner Reset Command */
-               bitmask = 0x04;
-               break;
-       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
-       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
-               /* Two identical tuners on two different i2c buses,
-                * we need to reset the correct gpio. */
-               if (port->nr == 1)
-                       bitmask = 0x01;
-               else if (port->nr == 2)
-                       bitmask = 0x04;
-               break;
-       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
-               /* Tuner Reset Command */
-               bitmask = 0x02;
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-               altera_ci_tuner_reset(dev, port->nr);
-               break;
-       }
-
-       if (bitmask) {
-               /* Drive the tuner into reset and back out */
-               cx_clear(GP0_IO, bitmask);
-               mdelay(200);
-               cx_set(GP0_IO, bitmask);
-       }
-
-       return 0;
-}
-
-void cx23885_gpio_setup(struct cx23885_dev *dev)
-{
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               /* GPIO-0 cx24227 demodulator reset */
-               cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1500:
-               /* GPIO-0 cx24227 demodulator */
-               /* GPIO-2 xc3028 tuner */
-
-               /* Put the parts into reset */
-               cx_set(GP0_IO, 0x00050000);
-               cx_clear(GP0_IO, 0x00000005);
-               msleep(5);
-
-               /* Bring the parts out of reset */
-               cx_set(GP0_IO, 0x00050005);
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-               /* GPIO-0 cx24227 demodulator reset */
-               /* GPIO-2 xc5000 tuner reset */
-               cx_set(GP0_IO, 0x00050005); /* Bring the part out of reset */
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1800:
-               /* GPIO-0 656_CLK */
-               /* GPIO-1 656_D0 */
-               /* GPIO-2 8295A Reset */
-               /* GPIO-3-10 cx23417 data0-7 */
-               /* GPIO-11-14 cx23417 addr0-3 */
-               /* GPIO-15-18 cx23417 READY, CS, RD, WR */
-               /* GPIO-19 IR_RX */
-
-               /* CX23417 GPIO's */
-               /* EIO15 Zilog Reset */
-               /* EIO14 S5H1409/CX24227 Reset */
-               mc417_gpio_enable(dev, GPIO_15 | GPIO_14, 1);
-
-               /* Put the demod into reset and protect the eeprom */
-               mc417_gpio_clear(dev, GPIO_15 | GPIO_14);
-               mdelay(100);
-
-               /* Bring the demod and blaster out of reset */
-               mc417_gpio_set(dev, GPIO_15 | GPIO_14);
-               mdelay(100);
-
-               /* Force the TDA8295A into reset and back */
-               cx23885_gpio_enable(dev, GPIO_2, 1);
-               cx23885_gpio_set(dev, GPIO_2);
-               mdelay(20);
-               cx23885_gpio_clear(dev, GPIO_2);
-               mdelay(20);
-               cx23885_gpio_set(dev, GPIO_2);
-               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;
-       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
-               /* GPIO-0 xc5000 tuner reset i2c bus 0 */
-               /* GPIO-1 s5h1409 demod reset i2c bus 0 */
-               /* GPIO-2 xc5000 tuner reset i2c bus 1 */
-               /* GPIO-3 s5h1409 demod reset i2c bus 0 */
-
-               /* Put the parts into reset and back */
-               cx_set(GP0_IO, 0x000f0000);
-               mdelay(20);
-               cx_clear(GP0_IO, 0x0000000f);
-               mdelay(20);
-               cx_set(GP0_IO, 0x000f000f);
-               break;
-       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
-               /* GPIO-0 portb xc3028 reset */
-               /* GPIO-1 portb zl10353 reset */
-               /* GPIO-2 portc xc3028 reset */
-               /* GPIO-3 portc zl10353 reset */
-
-               /* Put the parts into reset and back */
-               cx_set(GP0_IO, 0x000f0000);
-               mdelay(20);
-               cx_clear(GP0_IO, 0x0000000f);
-               mdelay(20);
-               cx_set(GP0_IO, 0x000f000f);
-               break;
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
-               /* GPIO-2  xc3028 tuner reset */
-
-               /* The following GPIO's are on the internal AVCore (cx25840) */
-               /* GPIO-?  zl10353 demod reset */
-
-               /* Put the parts into reset and back */
-               cx_set(GP0_IO, 0x00040000);
-               mdelay(20);
-               cx_clear(GP0_IO, 0x00000004);
-               mdelay(20);
-               cx_set(GP0_IO, 0x00040004);
-               break;
-       case CX23885_BOARD_TBS_6920:
-               cx_write(MC417_CTL, 0x00000036);
-               cx_write(MC417_OEN, 0x00001000);
-               cx_set(MC417_RWD, 0x00000002);
-               mdelay(200);
-               cx_clear(MC417_RWD, 0x00000800);
-               mdelay(200);
-               cx_set(MC417_RWD, 0x00000800);
-               mdelay(200);
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-               /* GPIO-0 INTA from CiMax1
-                  GPIO-1 INTB from CiMax2
-                  GPIO-2 reset chips
-                  GPIO-3 to GPIO-10 data/addr for CA
-                  GPIO-11 ~CS0 to CiMax1
-                  GPIO-12 ~CS1 to CiMax2
-                  GPIO-13 ADL0 load LSB addr
-                  GPIO-14 ADL1 load MSB addr
-                  GPIO-15 ~RDY from CiMax
-                  GPIO-17 ~RD to CiMax
-                  GPIO-18 ~WR to CiMax
-                */
-               cx_set(GP0_IO, 0x00040000); /* GPIO as out */
-               /* GPIO1 and GPIO2 as INTA and INTB from CiMaxes, reset low */
-               cx_clear(GP0_IO, 0x00030004);
-               mdelay(100);/* reset delay */
-               cx_set(GP0_IO, 0x00040004); /* GPIO as out, reset high */
-               cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */
-               /* GPIO-15 IN as ~ACK, rest as OUT */
-               cx_write(MC417_OEN, 0x00001000);
-               /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
-               cx_write(MC417_RWD, 0x0000c300);
-               /* enable irq */
-               cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1275:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-       case CX23885_BOARD_HAUPPAUGE_HVR1210:
-               /* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */
-               /* GPIO-6 I2C Gate which can isolate the demod from the bus */
-               /* GPIO-9 Demod reset */
-
-               /* Put the parts into reset and back */
-               cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1);
-               cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5);
-               cx23885_gpio_clear(dev, GPIO_9);
-               mdelay(20);
-               cx23885_gpio_set(dev, GPIO_9);
-               break;
-       case CX23885_BOARD_MYGICA_X8506:
-       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
-       case CX23885_BOARD_MYGICA_X8507:
-               /* GPIO-0 (0)Analog / (1)Digital TV */
-               /* GPIO-1 reset XC5000 */
-               /* GPIO-2 reset LGS8GL5 / LGS8G75 */
-               cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1);
-               cx23885_gpio_clear(dev, GPIO_1 | GPIO_2);
-               mdelay(100);
-               cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2);
-               mdelay(100);
-               break;
-       case CX23885_BOARD_MYGICA_X8558PRO:
-               /* GPIO-0 reset first ATBM8830 */
-               /* GPIO-1 reset second ATBM8830 */
-               cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1);
-               cx23885_gpio_clear(dev, GPIO_0 | GPIO_1);
-               mdelay(100);
-               cx23885_gpio_set(dev, GPIO_0 | GPIO_1);
-               mdelay(100);
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               /* GPIO-0 656_CLK */
-               /* GPIO-1 656_D0 */
-               /* GPIO-2 Wake# */
-               /* GPIO-3-10 cx23417 data0-7 */
-               /* GPIO-11-14 cx23417 addr0-3 */
-               /* GPIO-15-18 cx23417 READY, CS, RD, WR */
-               /* GPIO-19 IR_RX */
-               /* GPIO-20 C_IR_TX */
-               /* GPIO-21 I2S DAT */
-               /* GPIO-22 I2S WCLK */
-               /* GPIO-23 I2S BCLK */
-               /* ALT GPIO: EXP GPIO LATCH */
-
-               /* CX23417 GPIO's */
-               /* GPIO-14 S5H1411/CX24228 Reset */
-               /* GPIO-13 EEPROM write protect */
-               mc417_gpio_enable(dev, GPIO_14 | GPIO_13, 1);
-
-               /* Put the demod into reset and protect the eeprom */
-               mc417_gpio_clear(dev, GPIO_14 | GPIO_13);
-               mdelay(100);
-
-               /* Bring the demod out of reset */
-               mc417_gpio_set(dev, GPIO_14);
-               mdelay(100);
-
-               /* CX24228 GPIO */
-               /* Connected to IF / Mux */
-               break;
-       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
-               cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-               /* GPIO-0 ~INT in
-                  GPIO-1 TMS out
-                  GPIO-2 ~reset chips out
-                  GPIO-3 to GPIO-10 data/addr for CA in/out
-                  GPIO-11 ~CS out
-                  GPIO-12 ADDR out
-                  GPIO-13 ~WR out
-                  GPIO-14 ~RD out
-                  GPIO-15 ~RDY in
-                  GPIO-16 TCK out
-                  GPIO-17 TDO in
-                  GPIO-18 TDI out
-                */
-               cx_set(GP0_IO, 0x00060000); /* GPIO-1,2 as out */
-               /* GPIO-0 as INT, reset & TMS low */
-               cx_clear(GP0_IO, 0x00010006);
-               mdelay(100);/* reset delay */
-               cx_set(GP0_IO, 0x00000004); /* reset high */
-               cx_write(MC417_CTL, 0x00000037);/* enable GPIO-3..18 pins */
-               /* GPIO-17 is TDO in, GPIO-15 is ~RDY in, rest is out */
-               cx_write(MC417_OEN, 0x00005000);
-               /* ~RD, ~WR high; ADDR low; ~CS high */
-               cx_write(MC417_RWD, 0x00000d00);
-               /* enable irq */
-               cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
-               break;
-       }
-}
-
-int cx23885_ir_init(struct cx23885_dev *dev)
-{
-       static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = {
-               {
-                       .flags    = V4L2_SUBDEV_IO_PIN_INPUT,
-                       .pin      = CX23885_PIN_IR_RX_GPIO19,
-                       .function = CX23885_PAD_IR_RX,
-                       .value    = 0,
-                       .strength = CX25840_PIN_DRIVE_MEDIUM,
-               }, {
-                       .flags    = V4L2_SUBDEV_IO_PIN_OUTPUT,
-                       .pin      = CX23885_PIN_IR_TX_GPIO20,
-                       .function = CX23885_PAD_IR_TX,
-                       .value    = 0,
-                       .strength = CX25840_PIN_DRIVE_MEDIUM,
-               }
-       };
-       const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg);
-
-       static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = {
-               {
-                       .flags    = V4L2_SUBDEV_IO_PIN_INPUT,
-                       .pin      = CX23885_PIN_IR_RX_GPIO19,
-                       .function = CX23885_PAD_IR_RX,
-                       .value    = 0,
-                       .strength = CX25840_PIN_DRIVE_MEDIUM,
-               }
-       };
-       const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg);
-
-       struct v4l2_subdev_ir_parameters params;
-       int ret = 0;
-       switch (dev->board) {
-       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:
-       case CX23885_BOARD_HAUPPAUGE_HVR1275:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-       case CX23885_BOARD_HAUPPAUGE_HVR1210:
-               /* FIXME: Implement me */
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-               ret = cx23888_ir_probe(dev);
-               if (ret)
-                       break;
-               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
-               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
-                                ir_rx_pin_cfg_count, ir_rx_pin_cfg);
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               ret = cx23888_ir_probe(dev);
-               if (ret)
-                       break;
-               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
-               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
-                                ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
-               /*
-                * For these boards we need to invert the Tx output via the
-                * IR controller to have the LED off while idle
-                */
-               v4l2_subdev_call(dev->sd_ir, ir, tx_g_parameters, &params);
-               params.enable = false;
-               params.shutdown = false;
-               params.invert_level = true;
-               v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
-               params.shutdown = true;
-               v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
-               break;
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-       case CX23885_BOARD_TEVII_S470:
-               if (!enable_885_ir)
-                       break;
-               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
-               if (dev->sd_ir == NULL) {
-                       ret = -ENODEV;
-                       break;
-               }
-               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
-                                ir_rx_pin_cfg_count, ir_rx_pin_cfg);
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               if (!enable_885_ir)
-                       break;
-               dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
-               if (dev->sd_ir == NULL) {
-                       ret = -ENODEV;
-                       break;
-               }
-               v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
-                                ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
-               break;
-       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
-               request_module("ir-kbd-i2c");
-               break;
-       }
-
-       return ret;
-}
-
-void cx23885_ir_fini(struct cx23885_dev *dev)
-{
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               cx23885_irq_remove(dev, PCI_MSK_IR);
-               cx23888_ir_remove(dev);
-               dev->sd_ir = NULL;
-               break;
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-       case CX23885_BOARD_TEVII_S470:
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
-               /* sd_ir is a duplicate pointer to the AV Core, just clear it */
-               dev->sd_ir = NULL;
-               break;
-       }
-}
-
-int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
-{
-       int data;
-       int tdo = 0;
-       struct cx23885_dev *dev = (struct cx23885_dev *)device;
-       /*TMS*/
-       data = ((cx_read(GP0_IO)) & (~0x00000002));
-       data |= (tms ? 0x00020002 : 0x00020000);
-       cx_write(GP0_IO, data);
-
-       /*TDI*/
-       data = ((cx_read(MC417_RWD)) & (~0x0000a000));
-       data |= (tdi ? 0x00008000 : 0);
-       cx_write(MC417_RWD, data);
-       if (read_tdo)
-               tdo = (data & 0x00004000) ? 1 : 0; /*TDO*/
-
-       cx_write(MC417_RWD, data | 0x00002000);
-       udelay(1);
-       /*TCK*/
-       cx_write(MC417_RWD, data);
-
-       return tdo;
-}
-
-void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
-{
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               if (dev->sd_ir)
-                       cx23885_irq_add_enable(dev, PCI_MSK_IR);
-               break;
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-       case CX23885_BOARD_TEVII_S470:
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               if (dev->sd_ir)
-                       cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
-               break;
-       }
-}
-
-void cx23885_card_setup(struct cx23885_dev *dev)
-{
-       struct cx23885_tsport *ts1 = &dev->ts1;
-       struct cx23885_tsport *ts2 = &dev->ts2;
-
-       static u8 eeprom[256];
-
-       if (dev->i2c_bus[0].i2c_rc == 0) {
-               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-               tveeprom_read(&dev->i2c_bus[0].i2c_client,
-                             eeprom, sizeof(eeprom));
-       }
-
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               if (dev->i2c_bus[0].i2c_rc == 0) {
-                       if (eeprom[0x80] != 0x84)
-                               hauppauge_eeprom(dev, eeprom+0xc0);
-                       else
-                               hauppauge_eeprom(dev, eeprom+0x80);
-               }
-               break;
-       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:
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1275:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-       case CX23885_BOARD_HAUPPAUGE_HVR1210:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               if (dev->i2c_bus[0].i2c_rc == 0)
-                       hauppauge_eeprom(dev, eeprom+0xc0);
-               break;
-       }
-
-       switch (dev->board) {
-       case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
-       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
-               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 omitted intentionally */
-       case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
-               ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
-               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1800:
-               /* Defaults for VID B - Analog encoder */
-               /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
-               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);
-               cx_write(0x130184, 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_TBS_6920:
-               ts1->gen_ctrl_val  = 0x4; /* Parallel */
-               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-               break;
-       case CX23885_BOARD_TEVII_S470:
-       case CX23885_BOARD_TEVII_S471:
-       case CX23885_BOARD_DVBWORLD_2005:
-               ts1->gen_ctrl_val  = 0x5; /* Parallel */
-               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-               ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
-               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-               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_MYGICA_X8506:
-       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
-               ts1->gen_ctrl_val  = 0x5; /* Parallel */
-               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-               break;
-       case CX23885_BOARD_MYGICA_X8558PRO:
-               ts1->gen_ctrl_val  = 0x5; /* Parallel */
-               ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
-               ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
-               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_HVR1800lp:
-       case CX23885_BOARD_HAUPPAUGE_HVR1200:
-       case CX23885_BOARD_HAUPPAUGE_HVR1700:
-       case CX23885_BOARD_HAUPPAUGE_HVR1400:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1275:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-       case CX23885_BOARD_HAUPPAUGE_HVR1210:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
-       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_TEVII_S470:
-               /* Currently only enabled for the integrated IR controller */
-               if (!enable_885_ir)
-                       break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-       case CX23885_BOARD_HAUPPAUGE_HVR1800:
-       case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
-       case CX23885_BOARD_HAUPPAUGE_HVR1700:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_MYGICA_X8506:
-       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-       case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
-       case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
-       case CX23885_BOARD_HAUPPAUGE_HVR1500:
-       case CX23885_BOARD_MPX885:
-       case CX23885_BOARD_MYGICA_X8507:
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-               dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_bus[2].i2c_adap,
-                               "cx25840", 0x88 >> 1, NULL);
-               if (dev->sd_cx25840) {
-                       dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
-                       v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
-               }
-               break;
-       }
-
-       /* AUX-PLL 27MHz CLK */
-       switch (dev->board) {
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-               netup_initialize(dev);
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
-               int ret;
-               const struct firmware *fw;
-               const char *filename = "dvb-netup-altera-01.fw";
-               char *action = "configure";
-               static struct netup_card_info cinfo;
-               struct altera_config netup_config = {
-                       .dev = dev,
-                       .action = action,
-                       .jtag_io = netup_jtag_io,
-               };
-
-               netup_initialize(dev);
-
-               netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
-               if (netup_card_rev)
-                       cinfo.rev = netup_card_rev;
-
-               switch (cinfo.rev) {
-               case 0x4:
-                       filename = "dvb-netup-altera-04.fw";
-                       break;
-               default:
-                       filename = "dvb-netup-altera-01.fw";
-                       break;
-               }
-               printk(KERN_INFO "NetUP card rev=0x%x fw_filename=%s\n",
-                               cinfo.rev, filename);
-
-               ret = request_firmware(&fw, filename, &dev->pci->dev);
-               if (ret != 0)
-                       printk(KERN_ERR "did not find the firmware file. (%s) "
-                       "Please see linux/Documentation/dvb/ for more details "
-                       "on firmware-problems.", filename);
-               else
-                       altera_init(&netup_config, fw);
-
-               release_firmware(fw);
-               break;
-       }
-       }
-}
-
-/* ------------------------------------------------------------------ */
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
deleted file mode 100644 (file)
index 697728f..0000000
+++ /dev/null
@@ -1,2234 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/div64.h>
-#include <linux/firmware.h>
-
-#include "cx23885.h"
-#include "cimax2.h"
-#include "altera-ci.h"
-#include "cx23888-ir.h"
-#include "cx23885-ir.h"
-#include "cx23885-av.h"
-#include "cx23885-input.h"
-
-MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CX23885_VERSION);
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-static unsigned int card[]  = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-module_param_array(card,  int, NULL, 0444);
-MODULE_PARM_DESC(card, "card type");
-
-#define dprintk(level, fmt, arg...)\
-       do { if (debug >= level)\
-               printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
-       } while (0)
-
-static unsigned int cx23885_devcount;
-
-#define NO_SYNC_LINE (-1U)
-
-/* FIXME, these allocations will change when
- * analog arrives. The be reviewed.
- * CX23887 Assumptions
- * 1 line = 16 bytes of CDT
- * cmds size = 80
- * cdt size = 16 * linesize
- * iqsize = 64
- * maxlines = 6
- *
- * Address Space:
- * 0x00000000 0x00008fff FIFO clusters
- * 0x00010000 0x000104af Channel Management Data Structures
- * 0x000104b0 0x000104ff Free
- * 0x00010500 0x000108bf 15 channels * iqsize
- * 0x000108c0 0x000108ff Free
- * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables
- *                       15 channels * (iqsize + (maxlines * linesize))
- * 0x00010ea0 0x00010xxx Free
- */
-
-static struct sram_channel cx23885_sram_channels[] = {
-       [SRAM_CH01] = {
-               .name           = "VID A",
-               .cmds_start     = 0x10000,
-               .ctrl_start     = 0x10380,
-               .cdt            = 0x104c0,
-               .fifo_start     = 0x40,
-               .fifo_size      = 0x2800,
-               .ptr1_reg       = DMA1_PTR1,
-               .ptr2_reg       = DMA1_PTR2,
-               .cnt1_reg       = DMA1_CNT1,
-               .cnt2_reg       = DMA1_CNT2,
-       },
-       [SRAM_CH02] = {
-               .name           = "ch2",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA2_PTR1,
-               .ptr2_reg       = DMA2_PTR2,
-               .cnt1_reg       = DMA2_CNT1,
-               .cnt2_reg       = DMA2_CNT2,
-       },
-       [SRAM_CH03] = {
-               .name           = "TS1 B",
-               .cmds_start     = 0x100A0,
-               .ctrl_start     = 0x10400,
-               .cdt            = 0x10580,
-               .fifo_start     = 0x5000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA3_PTR1,
-               .ptr2_reg       = DMA3_PTR2,
-               .cnt1_reg       = DMA3_CNT1,
-               .cnt2_reg       = DMA3_CNT2,
-       },
-       [SRAM_CH04] = {
-               .name           = "ch4",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA4_PTR1,
-               .ptr2_reg       = DMA4_PTR2,
-               .cnt1_reg       = DMA4_CNT1,
-               .cnt2_reg       = DMA4_CNT2,
-       },
-       [SRAM_CH05] = {
-               .name           = "ch5",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA5_PTR1,
-               .ptr2_reg       = DMA5_PTR2,
-               .cnt1_reg       = DMA5_CNT1,
-               .cnt2_reg       = DMA5_CNT2,
-       },
-       [SRAM_CH06] = {
-               .name           = "TS2 C",
-               .cmds_start     = 0x10140,
-               .ctrl_start     = 0x10440,
-               .cdt            = 0x105e0,
-               .fifo_start     = 0x6000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA5_PTR1,
-               .ptr2_reg       = DMA5_PTR2,
-               .cnt1_reg       = DMA5_CNT1,
-               .cnt2_reg       = DMA5_CNT2,
-       },
-       [SRAM_CH07] = {
-               .name           = "TV Audio",
-               .cmds_start     = 0x10190,
-               .ctrl_start     = 0x10480,
-               .cdt            = 0x10a00,
-               .fifo_start     = 0x7000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA6_PTR1,
-               .ptr2_reg       = DMA6_PTR2,
-               .cnt1_reg       = DMA6_CNT1,
-               .cnt2_reg       = DMA6_CNT2,
-       },
-       [SRAM_CH08] = {
-               .name           = "ch8",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA7_PTR1,
-               .ptr2_reg       = DMA7_PTR2,
-               .cnt1_reg       = DMA7_CNT1,
-               .cnt2_reg       = DMA7_CNT2,
-       },
-       [SRAM_CH09] = {
-               .name           = "ch9",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA8_PTR1,
-               .ptr2_reg       = DMA8_PTR2,
-               .cnt1_reg       = DMA8_CNT1,
-               .cnt2_reg       = DMA8_CNT2,
-       },
-};
-
-static struct sram_channel cx23887_sram_channels[] = {
-       [SRAM_CH01] = {
-               .name           = "VID A",
-               .cmds_start     = 0x10000,
-               .ctrl_start     = 0x105b0,
-               .cdt            = 0x107b0,
-               .fifo_start     = 0x40,
-               .fifo_size      = 0x2800,
-               .ptr1_reg       = DMA1_PTR1,
-               .ptr2_reg       = DMA1_PTR2,
-               .cnt1_reg       = DMA1_CNT1,
-               .cnt2_reg       = DMA1_CNT2,
-       },
-       [SRAM_CH02] = {
-               .name           = "VID A (VBI)",
-               .cmds_start     = 0x10050,
-               .ctrl_start     = 0x105F0,
-               .cdt            = 0x10810,
-               .fifo_start     = 0x3000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA2_PTR1,
-               .ptr2_reg       = DMA2_PTR2,
-               .cnt1_reg       = DMA2_CNT1,
-               .cnt2_reg       = DMA2_CNT2,
-       },
-       [SRAM_CH03] = {
-               .name           = "TS1 B",
-               .cmds_start     = 0x100A0,
-               .ctrl_start     = 0x10630,
-               .cdt            = 0x10870,
-               .fifo_start     = 0x5000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA3_PTR1,
-               .ptr2_reg       = DMA3_PTR2,
-               .cnt1_reg       = DMA3_CNT1,
-               .cnt2_reg       = DMA3_CNT2,
-       },
-       [SRAM_CH04] = {
-               .name           = "ch4",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA4_PTR1,
-               .ptr2_reg       = DMA4_PTR2,
-               .cnt1_reg       = DMA4_CNT1,
-               .cnt2_reg       = DMA4_CNT2,
-       },
-       [SRAM_CH05] = {
-               .name           = "ch5",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA5_PTR1,
-               .ptr2_reg       = DMA5_PTR2,
-               .cnt1_reg       = DMA5_CNT1,
-               .cnt2_reg       = DMA5_CNT2,
-       },
-       [SRAM_CH06] = {
-               .name           = "TS2 C",
-               .cmds_start     = 0x10140,
-               .ctrl_start     = 0x10670,
-               .cdt            = 0x108d0,
-               .fifo_start     = 0x6000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA5_PTR1,
-               .ptr2_reg       = DMA5_PTR2,
-               .cnt1_reg       = DMA5_CNT1,
-               .cnt2_reg       = DMA5_CNT2,
-       },
-       [SRAM_CH07] = {
-               .name           = "TV Audio",
-               .cmds_start     = 0x10190,
-               .ctrl_start     = 0x106B0,
-               .cdt            = 0x10930,
-               .fifo_start     = 0x7000,
-               .fifo_size      = 0x1000,
-               .ptr1_reg       = DMA6_PTR1,
-               .ptr2_reg       = DMA6_PTR2,
-               .cnt1_reg       = DMA6_CNT1,
-               .cnt2_reg       = DMA6_CNT2,
-       },
-       [SRAM_CH08] = {
-               .name           = "ch8",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA7_PTR1,
-               .ptr2_reg       = DMA7_PTR2,
-               .cnt1_reg       = DMA7_CNT1,
-               .cnt2_reg       = DMA7_CNT2,
-       },
-       [SRAM_CH09] = {
-               .name           = "ch9",
-               .cmds_start     = 0x0,
-               .ctrl_start     = 0x0,
-               .cdt            = 0x0,
-               .fifo_start     = 0x0,
-               .fifo_size      = 0x0,
-               .ptr1_reg       = DMA8_PTR1,
-               .ptr2_reg       = DMA8_PTR2,
-               .cnt1_reg       = DMA8_CNT1,
-               .cnt2_reg       = DMA8_CNT2,
-       },
-};
-
-void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
-
-       dev->pci_irqmask |= mask;
-
-       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
-}
-
-void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
-
-       dev->pci_irqmask |= mask;
-       cx_set(PCI_INT_MSK, mask);
-
-       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
-}
-
-void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask)
-{
-       u32 v;
-       unsigned long flags;
-       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
-
-       v = mask & dev->pci_irqmask;
-       if (v)
-               cx_set(PCI_INT_MSK, v);
-
-       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
-}
-
-static inline void cx23885_irq_enable_all(struct cx23885_dev *dev)
-{
-       cx23885_irq_enable(dev, 0xffffffff);
-}
-
-void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
-
-       cx_clear(PCI_INT_MSK, mask);
-
-       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
-}
-
-static inline void cx23885_irq_disable_all(struct cx23885_dev *dev)
-{
-       cx23885_irq_disable(dev, 0xffffffff);
-}
-
-void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
-
-       dev->pci_irqmask &= ~mask;
-       cx_clear(PCI_INT_MSK, mask);
-
-       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
-}
-
-static u32 cx23885_irq_get_mask(struct cx23885_dev *dev)
-{
-       u32 v;
-       unsigned long flags;
-       spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
-
-       v = cx_read(PCI_INT_MSK);
-
-       spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
-       return v;
-}
-
-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",
-       };
-       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,
-       };
-       static char *bits[] = {
-               "12",   "13",   "14",   "resync",
-               "cnt0", "cnt1", "18",   "19",
-               "20",   "21",   "22",   "23",
-               "irq1", "irq2", "eol",  "sol",
-       };
-       int i;
-
-       printk("0x%08x [ %s", risc,
-              instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
-       for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)
-               if (risc & (1 << (i + 12)))
-                       printk(" %s", bits[i]);
-       printk(" count=%d ]\n", risc & 0xfff);
-       return incr[risc >> 28] ? incr[risc >> 28] : 1;
-}
-
-void cx23885_wakeup(struct cx23885_tsport *port,
-                          struct cx23885_dmaqueue *q, u32 count)
-{
-       struct cx23885_dev *dev = port->dev;
-       struct cx23885_buffer *buf;
-       int bc;
-
-       for (bc = 0;; bc++) {
-               if (list_empty(&q->active))
-                       break;
-               buf = list_entry(q->active.next,
-                                struct cx23885_buffer, vb.queue);
-
-               /* count comes from the hw and is is 16bit wide --
-                * this trick handles wrap-arounds correctly for
-                * up to 32767 buffers in flight... */
-               if ((s16) (count - buf->count) < 0)
-                       break;
-
-               do_gettimeofday(&buf->vb.ts);
-               dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
-                       count, buf->count);
-               buf->vb.state = VIDEOBUF_DONE;
-               list_del(&buf->vb.queue);
-               wake_up(&buf->vb.done);
-       }
-       if (list_empty(&q->active))
-               del_timer(&q->timeout);
-       else
-               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-       if (bc != 1)
-               printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
-                      __func__, bc);
-}
-
-int cx23885_sram_channel_setup(struct cx23885_dev *dev,
-                                     struct sram_channel *ch,
-                                     unsigned int bpl, u32 risc)
-{
-       unsigned int i, lines;
-       u32 cdt;
-
-       if (ch->cmds_start == 0) {
-               dprintk(1, "%s() Erasing channel [%s]\n", __func__,
-                       ch->name);
-               cx_write(ch->ptr1_reg, 0);
-               cx_write(ch->ptr2_reg, 0);
-               cx_write(ch->cnt2_reg, 0);
-               cx_write(ch->cnt1_reg, 0);
-               return 0;
-       } else {
-               dprintk(1, "%s() Configuring channel [%s]\n", __func__,
-                       ch->name);
-       }
-
-       bpl   = (bpl + 7) & ~7; /* alignment */
-       cdt   = ch->cdt;
-       lines = ch->fifo_size / bpl;
-       if (lines > 6)
-               lines = 6;
-       BUG_ON(lines < 2);
-
-       cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       cx_write(8 + 4, 8);
-       cx_write(8 + 8, 0);
-
-       /* write CDT */
-       for (i = 0; i < lines; 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);
-               cx_write(cdt + 16*i +  8, 0);
-               cx_write(cdt + 16*i + 12, 0);
-       }
-
-       /* write CMDS */
-       if (ch->jumponly)
-               cx_write(ch->cmds_start + 0, 8);
-       else
-               cx_write(ch->cmds_start + 0, risc);
-       cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */
-       cx_write(ch->cmds_start +  8, cdt);
-       cx_write(ch->cmds_start + 12, (lines*16) >> 3);
-       cx_write(ch->cmds_start + 16, ch->ctrl_start);
-       if (ch->jumponly)
-               cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
-       else
-               cx_write(ch->cmds_start + 20, 64 >> 2);
-       for (i = 24; i < 80; i += 4)
-               cx_write(ch->cmds_start + i, 0);
-
-       /* fill registers */
-       cx_write(ch->ptr1_reg, ch->fifo_start);
-       cx_write(ch->ptr2_reg, cdt);
-       cx_write(ch->cnt2_reg, (lines*16) >> 3);
-       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
-
-       dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
-               dev->bridge,
-               ch->name,
-               bpl,
-               lines);
-
-       return 0;
-}
-
-void cx23885_sram_channel_dump(struct cx23885_dev *dev,
-                                     struct sram_channel *ch)
-{
-       static char *name[] = {
-               "init risc lo",
-               "init risc hi",
-               "cdt base",
-               "cdt size",
-               "iq base",
-               "iq size",
-               "risc pc lo",
-               "risc pc hi",
-               "iq wr ptr",
-               "iq rd ptr",
-               "cdt current",
-               "pci target lo",
-               "pci target hi",
-               "line / byte",
-       };
-       u32 risc;
-       unsigned int i, j, n;
-
-       printk(KERN_WARNING "%s: %s - dma channel status dump\n",
-              dev->name, ch->name);
-       for (i = 0; i < ARRAY_SIZE(name); i++)
-               printk(KERN_WARNING "%s:   cmds: %-15s: 0x%08x\n",
-                      dev->name, name[i],
-                      cx_read(ch->cmds_start + 4*i));
-
-       for (i = 0; i < 4; i++) {
-               risc = cx_read(ch->cmds_start + 4 * (i + 14));
-               printk(KERN_WARNING "%s:   risc%d: ", dev->name, i);
-               cx23885_risc_decode(risc);
-       }
-       for (i = 0; i < (64 >> 2); i += n) {
-               risc = cx_read(ch->ctrl_start + 4 * i);
-               /* No consideration for bits 63-32 */
-
-               printk(KERN_WARNING "%s:   (0x%08x) iq %x: ", dev->name,
-                      ch->ctrl_start + 4 * i, i);
-               n = cx23885_risc_decode(risc);
-               for (j = 1; j < n; j++) {
-                       risc = cx_read(ch->ctrl_start + 4 * (i + j));
-                       printk(KERN_WARNING "%s:   iq %x: 0x%08x [ arg #%d ]\n",
-                              dev->name, i+j, risc, j);
-               }
-       }
-
-       printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
-              dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
-       printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
-              dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
-       printk(KERN_WARNING "%s:   ptr1_reg: 0x%08x\n",
-              dev->name, cx_read(ch->ptr1_reg));
-       printk(KERN_WARNING "%s:   ptr2_reg: 0x%08x\n",
-              dev->name, cx_read(ch->ptr2_reg));
-       printk(KERN_WARNING "%s:   cnt1_reg: 0x%08x\n",
-              dev->name, cx_read(ch->cnt1_reg));
-       printk(KERN_WARNING "%s:   cnt2_reg: 0x%08x\n",
-              dev->name, cx_read(ch->cnt2_reg));
-}
-
-static void cx23885_risc_disasm(struct cx23885_tsport *port,
-                               struct btcx_riscmem *risc)
-{
-       struct cx23885_dev *dev = port->dev;
-       unsigned int i, j, n;
-
-       printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
-              dev->name, risc->cpu, (unsigned long)risc->dma);
-       for (i = 0; i < (risc->size >> 2); i += n) {
-               printk(KERN_INFO "%s:   %04d: ", dev->name, i);
-               n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
-               for (j = 1; j < n; j++)
-                       printk(KERN_INFO "%s:   %04d: 0x%08x [ arg #%d ]\n",
-                              dev->name, i + j, risc->cpu[i + j], j);
-               if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
-                       break;
-       }
-}
-
-static void cx23885_shutdown(struct cx23885_dev *dev)
-{
-       /* disable RISC controller */
-       cx_write(DEV_CNTRL2, 0);
-
-       /* Disable all IR activity */
-       cx_write(IR_CNTRL_REG, 0);
-
-       /* Disable Video A/B activity */
-       cx_write(VID_A_DMA_CTL, 0);
-       cx_write(VID_B_DMA_CTL, 0);
-       cx_write(VID_C_DMA_CTL, 0);
-
-       /* Disable Audio activity */
-       cx_write(AUD_INT_DMA_CTL, 0);
-       cx_write(AUD_EXT_DMA_CTL, 0);
-
-       /* Disable Serial port */
-       cx_write(UART_CTL, 0);
-
-       /* Disable Interrupts */
-       cx23885_irq_disable_all(dev);
-       cx_write(VID_A_INT_MSK, 0);
-       cx_write(VID_B_INT_MSK, 0);
-       cx_write(VID_C_INT_MSK, 0);
-       cx_write(AUDIO_INT_INT_MSK, 0);
-       cx_write(AUDIO_EXT_INT_MSK, 0);
-
-}
-
-static void cx23885_reset(struct cx23885_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       cx23885_shutdown(dev);
-
-       cx_write(PCI_INT_STAT, 0xffffffff);
-       cx_write(VID_A_INT_STAT, 0xffffffff);
-       cx_write(VID_B_INT_STAT, 0xffffffff);
-       cx_write(VID_C_INT_STAT, 0xffffffff);
-       cx_write(AUDIO_INT_INT_STAT, 0xffffffff);
-       cx_write(AUDIO_EXT_INT_STAT, 0xffffffff);
-       cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
-       cx_write(PAD_CTRL, 0x00500300);
-
-       mdelay(100);
-
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
-               720*4, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03],
-               188*4, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06],
-               188*4, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0);
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0);
-
-       cx23885_gpio_setup(dev);
-}
-
-
-static int cx23885_pci_quirks(struct cx23885_dev *dev)
-{
-       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
-        * occur on the cx23887 bridge.
-        */
-       if (dev->bridge == CX23885_BRIDGE_885)
-               cx_clear(RDR_TLCTL0, 1 << 4);
-
-       return 0;
-}
-
-static int get_resources(struct cx23885_dev *dev)
-{
-       if (request_mem_region(pci_resource_start(dev->pci, 0),
-                              pci_resource_len(dev->pci, 0),
-                              dev->name))
-               return 0;
-
-       printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
-               dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
-
-       return -EBUSY;
-}
-
-static void cx23885_timeout(unsigned long data);
-int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-                               u32 reg, u32 mask, u32 value);
-
-static int cx23885_init_tsport(struct cx23885_dev *dev,
-       struct cx23885_tsport *port, int 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;
-       port->nr = portno;
-
-       INIT_LIST_HEAD(&port->mpegq.active);
-       INIT_LIST_HEAD(&port->mpegq.queued);
-       port->mpegq.timeout.function = cx23885_timeout;
-       port->mpegq.timeout.data = (unsigned long)port;
-       init_timer(&port->mpegq.timeout);
-
-       mutex_init(&port->frontends.lock);
-       INIT_LIST_HEAD(&port->frontends.felist);
-       port->frontends.active_fe_id = 0;
-
-       /* This should be hardcoded allow a single frontend
-        * attachment to this tsport, keeping the -dvb.c
-        * code clean and safe.
-        */
-       if (!port->num_frontends)
-               port->num_frontends = 1;
-
-       switch (portno) {
-       case 1:
-               port->reg_gpcnt          = VID_B_GPCNT;
-               port->reg_gpcnt_ctl      = VID_B_GPCNT_CTL;
-               port->reg_dma_ctl        = VID_B_DMA_CTL;
-               port->reg_lngth          = VID_B_LNGTH;
-               port->reg_hw_sop_ctrl    = VID_B_HW_SOP_CTL;
-               port->reg_gen_ctrl       = VID_B_GEN_CTL;
-               port->reg_bd_pkt_status  = VID_B_BD_PKT_STATUS;
-               port->reg_sop_status     = VID_B_SOP_STATUS;
-               port->reg_fifo_ovfl_stat = VID_B_FIFO_OVFL_STAT;
-               port->reg_vld_misc       = VID_B_VLD_MISC;
-               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->sram_chno          = SRAM_CH03; /* VID_B */
-               port->pci_irqmask        = 0x02; /* VID_B bit1 */
-               break;
-       case 2:
-               port->reg_gpcnt          = VID_C_GPCNT;
-               port->reg_gpcnt_ctl      = VID_C_GPCNT_CTL;
-               port->reg_dma_ctl        = VID_C_DMA_CTL;
-               port->reg_lngth          = VID_C_LNGTH;
-               port->reg_hw_sop_ctrl    = VID_C_HW_SOP_CTL;
-               port->reg_gen_ctrl       = VID_C_GEN_CTL;
-               port->reg_bd_pkt_status  = VID_C_BD_PKT_STATUS;
-               port->reg_sop_status     = VID_C_SOP_STATUS;
-               port->reg_fifo_ovfl_stat = VID_C_FIFO_OVFL_STAT;
-               port->reg_vld_misc       = VID_C_VLD_MISC;
-               port->reg_ts_clk_en      = VID_C_TS_CLK_EN;
-               port->reg_src_sel        = 0;
-               port->reg_ts_int_msk     = VID_C_INT_MSK;
-               port->reg_ts_int_stat    = VID_C_INT_STAT;
-               port->sram_chno          = SRAM_CH06; /* VID_C */
-               port->pci_irqmask        = 0x04; /* VID_C bit2 */
-               break;
-       default:
-               BUG();
-       }
-
-       cx23885_risc_stopper(dev->pci, &port->mpegq.stopper,
-                    port->reg_dma_ctl, port->dma_ctl_val, 0x00);
-
-       return 0;
-}
-
-static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
-{
-       switch (cx_read(RDR_CFG2) & 0xff) {
-       case 0x00:
-               /* cx23885 */
-               dev->hwrevision = 0xa0;
-               break;
-       case 0x01:
-               /* CX23885-12Z */
-               dev->hwrevision = 0xa1;
-               break;
-       case 0x02:
-               /* CX23885-13Z/14Z */
-               dev->hwrevision = 0xb0;
-               break;
-       case 0x03:
-               if (dev->pci->device == 0x8880) {
-                       /* CX23888-21Z/22Z */
-                       dev->hwrevision = 0xc0;
-               } else {
-                       /* CX23885-14Z */
-                       dev->hwrevision = 0xa4;
-               }
-               break;
-       case 0x04:
-               if (dev->pci->device == 0x8880) {
-                       /* CX23888-31Z */
-                       dev->hwrevision = 0xd0;
-               } else {
-                       /* CX23885-15Z, CX23888-31Z */
-                       dev->hwrevision = 0xa5;
-               }
-               break;
-       case 0x0e:
-               /* CX23887-15Z */
-               dev->hwrevision = 0xc0;
-               break;
-       case 0x0f:
-               /* CX23887-14Z */
-               dev->hwrevision = 0xb1;
-               break;
-       default:
-               printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
-                       __func__, dev->hwrevision);
-       }
-       if (dev->hwrevision)
-               printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
-                       __func__, dev->hwrevision);
-       else
-               printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
-                       __func__, dev->hwrevision);
-}
-
-/* Find the first v4l2_subdev member of the group id in hw */
-struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw)
-{
-       struct v4l2_subdev *result = NULL;
-       struct v4l2_subdev *sd;
-
-       spin_lock(&dev->v4l2_dev.lock);
-       v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) {
-               if (sd->grp_id == hw) {
-                       result = sd;
-                       break;
-               }
-       }
-       spin_unlock(&dev->v4l2_dev.lock);
-       return result;
-}
-
-static int cx23885_dev_setup(struct cx23885_dev *dev)
-{
-       int i;
-
-       spin_lock_init(&dev->pci_irqmask_lock);
-
-       mutex_init(&dev->lock);
-       mutex_init(&dev->gpio_lock);
-
-       atomic_inc(&dev->refcount);
-
-       dev->nr = cx23885_devcount++;
-       sprintf(dev->name, "cx23885[%d]", dev->nr);
-
-       /* Configure the internal memory */
-       if (dev->pci->device == 0x8880) {
-               /* Could be 887 or 888, assume a default */
-               dev->bridge = CX23885_BRIDGE_887;
-               /* Apply a sensible clock frequency for the PCIe bridge */
-               dev->clk_freq = 25000000;
-               dev->sram_channels = cx23887_sram_channels;
-       } else
-       if (dev->pci->device == 0x8852) {
-               dev->bridge = CX23885_BRIDGE_885;
-               /* Apply a sensible clock frequency for the PCIe bridge */
-               dev->clk_freq = 28000000;
-               dev->sram_channels = cx23885_sram_channels;
-       } else
-               BUG();
-
-       dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
-               __func__, dev->bridge);
-
-       /* board config */
-       dev->board = UNSET;
-       if (card[dev->nr] < cx23885_bcount)
-               dev->board = card[dev->nr];
-       for (i = 0; UNSET == dev->board  &&  i < cx23885_idcount; i++)
-               if (dev->pci->subsystem_vendor == cx23885_subids[i].subvendor &&
-                   dev->pci->subsystem_device == cx23885_subids[i].subdevice)
-                       dev->board = cx23885_subids[i].card;
-       if (UNSET == dev->board) {
-               dev->board = CX23885_BOARD_UNKNOWN;
-               cx23885_card_list(dev);
-       }
-
-       /* If the user specific a clk freq override, apply it */
-       if (cx23885_boards[dev->board].clk_freq > 0)
-               dev->clk_freq = cx23885_boards[dev->board].clk_freq;
-
-       dev->pci_bus  = dev->pci->bus->number;
-       dev->pci_slot = PCI_SLOT(dev->pci->devfn);
-       cx23885_irq_add(dev, 0x001f00);
-
-       /* External Master 1 Bus */
-       dev->i2c_bus[0].nr = 0;
-       dev->i2c_bus[0].dev = dev;
-       dev->i2c_bus[0].reg_stat  = I2C1_STAT;
-       dev->i2c_bus[0].reg_ctrl  = I2C1_CTRL;
-       dev->i2c_bus[0].reg_addr  = I2C1_ADDR;
-       dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
-       dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
-       dev->i2c_bus[0].i2c_period = (0x9d << 24); /* 100kHz */
-
-       /* External Master 2 Bus */
-       dev->i2c_bus[1].nr = 1;
-       dev->i2c_bus[1].dev = dev;
-       dev->i2c_bus[1].reg_stat  = I2C2_STAT;
-       dev->i2c_bus[1].reg_ctrl  = I2C2_CTRL;
-       dev->i2c_bus[1].reg_addr  = I2C2_ADDR;
-       dev->i2c_bus[1].reg_rdata = I2C2_RDATA;
-       dev->i2c_bus[1].reg_wdata = I2C2_WDATA;
-       dev->i2c_bus[1].i2c_period = (0x9d << 24); /* 100kHz */
-
-       /* Internal Master 3 Bus */
-       dev->i2c_bus[2].nr = 2;
-       dev->i2c_bus[2].dev = dev;
-       dev->i2c_bus[2].reg_stat  = I2C3_STAT;
-       dev->i2c_bus[2].reg_ctrl  = I2C3_CTRL;
-       dev->i2c_bus[2].reg_addr  = I2C3_ADDR;
-       dev->i2c_bus[2].reg_rdata = I2C3_RDATA;
-       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) ||
-               (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
-               cx23885_init_tsport(dev, &dev->ts1, 1);
-
-       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) {
-               printk(KERN_ERR "CORE %s No more PCIe resources for "
-                      "subsystem: %04x:%04x\n",
-                      dev->name, dev->pci->subsystem_vendor,
-                      dev->pci->subsystem_device);
-
-               cx23885_devcount--;
-               return -ENODEV;
-       }
-
-       /* PCIe stuff */
-       dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
-                            pci_resource_len(dev->pci, 0));
-
-       dev->bmmio = (u8 __iomem *)dev->lmmio;
-
-       printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-              dev->name, dev->pci->subsystem_vendor,
-              dev->pci->subsystem_device, cx23885_boards[dev->board].name,
-              dev->board, card[dev->nr] == dev->board ?
-              "insmod option" : "autodetected");
-
-       cx23885_pci_quirks(dev);
-
-       /* Assume some sensible defaults */
-       dev->tuner_type = cx23885_boards[dev->board].tuner_type;
-       dev->tuner_addr = cx23885_boards[dev->board].tuner_addr;
-       dev->tuner_bus = cx23885_boards[dev->board].tuner_bus;
-       dev->radio_type = cx23885_boards[dev->board].radio_type;
-       dev->radio_addr = cx23885_boards[dev->board].radio_addr;
-
-       dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x tuner_bus = %d\n",
-               __func__, dev->tuner_type, dev->tuner_addr, dev->tuner_bus);
-       dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
-               __func__, dev->radio_type, dev->radio_addr);
-
-       /* The cx23417 encoder has GPIO's that need to be initialised
-        * before DVB, so that demodulators and tuners are out of
-        * reset before DVB uses them.
-        */
-       if ((cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) ||
-               (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
-                       cx23885_mc417_init(dev);
-
-       /* init hardware */
-       cx23885_reset(dev);
-
-       cx23885_i2c_register(&dev->i2c_bus[0]);
-       cx23885_i2c_register(&dev->i2c_bus[1]);
-       cx23885_i2c_register(&dev->i2c_bus[2]);
-       cx23885_card_setup(dev);
-       call_all(dev, core, s_power, 0);
-       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", __func__);
-               }
-       }
-
-       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
-               if (cx23885_boards[dev->board].num_fds_portb)
-                       dev->ts1.num_frontends =
-                               cx23885_boards[dev->board].num_fds_portb;
-               if (cx23885_dvb_register(&dev->ts1) < 0) {
-                       printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
-                              __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_boards[dev->board].num_fds_portc)
-                       dev->ts2.num_frontends =
-                               cx23885_boards[dev->board].num_fds_portc;
-               if (cx23885_dvb_register(&dev->ts2) < 0) {
-                       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__);
-               }
-       }
-
-       cx23885_dev_checkrevision(dev);
-
-       /* disable MSI for NetUP cards, otherwise CI is not working */
-       if (cx23885_boards[dev->board].ci_type > 0)
-               cx_clear(RDR_RDRCTL1, 1 << 8);
-
-       switch (dev->board) {
-       case CX23885_BOARD_TEVII_S470:
-       case CX23885_BOARD_TEVII_S471:
-               cx_clear(RDR_RDRCTL1, 1 << 8);
-               break;
-       }
-
-       return 0;
-}
-
-static void cx23885_dev_unregister(struct cx23885_dev *dev)
-{
-       release_mem_region(pci_resource_start(dev->pci, 0),
-                          pci_resource_len(dev->pci, 0));
-
-       if (!atomic_dec_and_test(&dev->refcount))
-               return;
-
-       if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
-               cx23885_video_unregister(dev);
-
-       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
-               cx23885_dvb_unregister(&dev->ts1);
-
-       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]);
-
-       iounmap(dev->lmmio);
-}
-
-static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
-                              unsigned int offset, u32 sync_line,
-                              unsigned int bpl, unsigned int padding,
-                              unsigned int lines,  unsigned int lpi)
-{
-       struct scatterlist *sg;
-       unsigned int line, todo, sol;
-
-       /* sync instruction */
-       if (sync_line != NO_SYNC_LINE)
-               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       /* scan lines */
-       sg = sglist;
-       for (line = 0; line < lines; line++) {
-               while (offset && offset >= sg_dma_len(sg)) {
-                       offset -= sg_dma_len(sg);
-                       sg++;
-               }
-
-               if (lpi && line > 0 && !(line % lpi))
-                       sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
-               else
-                       sol = RISC_SOL;
-
-               if (bpl <= sg_dma_len(sg)-offset) {
-                       /* fits into current chunk */
-                       *(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
-                       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
-                       offset += bpl;
-               } else {
-                       /* scanline needs to be split */
-                       todo = bpl;
-                       *(rp++) = cpu_to_le32(RISC_WRITE|sol|
-                                           (sg_dma_len(sg)-offset));
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
-                       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
-                       todo -= (sg_dma_len(sg)-offset);
-                       offset = 0;
-                       sg++;
-                       while (todo > sg_dma_len(sg)) {
-                               *(rp++) = cpu_to_le32(RISC_WRITE|
-                                                   sg_dma_len(sg));
-                               *(rp++) = cpu_to_le32(sg_dma_address(sg));
-                               *(rp++) = cpu_to_le32(0); /* bits 63-32 */
-                               todo -= sg_dma_len(sg);
-                               sg++;
-                       }
-                       *(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg));
-                       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
-                       offset += todo;
-               }
-               offset += padding;
-       }
-
-       return rp;
-}
-
-int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                       struct scatterlist *sglist, unsigned int top_offset,
-                       unsigned int bottom_offset, unsigned int bpl,
-                       unsigned int padding, unsigned int lines)
-{
-       u32 instructions, fields;
-       __le32 *rp;
-       int rc;
-
-       fields = 0;
-       if (UNSET != top_offset)
-               fields++;
-       if (UNSET != bottom_offset)
-               fields++;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Padding
-          can cause next bpl to start close to a page border.  First DMA
-          region may be smaller than PAGE_SIZE */
-       /* write and jump need and extra dword */
-       instructions  = fields * (1 + ((bpl + padding) * lines)
-               / PAGE_SIZE + lines);
-       instructions += 2;
-       rc = btcx_riscmem_alloc(pci, risc, instructions*12);
-       if (rc < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       if (UNSET != top_offset)
-               rp = cx23885_risc_field(rp, sglist, top_offset, 0,
-                                       bpl, padding, lines, 0);
-       if (UNSET != bottom_offset)
-               rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
-                                       bpl, padding, lines, 0);
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       return 0;
-}
-
-int cx23885_risc_databuffer(struct pci_dev *pci,
-                                  struct btcx_riscmem *risc,
-                                  struct scatterlist *sglist,
-                                  unsigned int bpl,
-                                  unsigned int lines, unsigned int lpi)
-{
-       u32 instructions;
-       __le32 *rp;
-       int rc;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Here
-          there is no padding and no sync.  First DMA region may be smaller
-          than PAGE_SIZE */
-       /* Jump and write need an extra dword */
-       instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
-       instructions += 1;
-
-       rc = btcx_riscmem_alloc(pci, risc, instructions*12);
-       if (rc < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
-                               bpl, 0, lines, lpi);
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       return 0;
-}
-
-int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                       struct scatterlist *sglist, unsigned int top_offset,
-                       unsigned int bottom_offset, unsigned int bpl,
-                       unsigned int padding, unsigned int lines)
-{
-       u32 instructions, fields;
-       __le32 *rp;
-       int rc;
-
-       fields = 0;
-       if (UNSET != top_offset)
-               fields++;
-       if (UNSET != bottom_offset)
-               fields++;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Padding
-          can cause next bpl to start close to a page border.  First DMA
-          region may be smaller than PAGE_SIZE */
-       /* write and jump need and extra dword */
-       instructions  = fields * (1 + ((bpl + padding) * lines)
-               / PAGE_SIZE + lines);
-       instructions += 2;
-       rc = btcx_riscmem_alloc(pci, risc, instructions*12);
-       if (rc < 0)
-               return rc;
-       /* write risc instructions */
-       rp = risc->cpu;
-
-       /* Sync to line 6, so US CC line 21 will appear in line '12'
-        * in the userland vbi payload */
-       if (UNSET != top_offset)
-               rp = cx23885_risc_field(rp, sglist, top_offset, 6,
-                                       bpl, padding, lines, 0);
-
-       if (UNSET != bottom_offset)
-               rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
-                                       bpl, padding, lines, 0);
-
-
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       return 0;
-}
-
-
-int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-                               u32 reg, u32 mask, u32 value)
-{
-       __le32 *rp;
-       int rc;
-
-       rc = btcx_riscmem_alloc(pci, risc, 4*16);
-       if (rc < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2);
-       *(rp++) = cpu_to_le32(reg);
-       *(rp++) = cpu_to_le32(value);
-       *(rp++) = cpu_to_le32(mask);
-       *(rp++) = cpu_to_le32(RISC_JUMP);
-       *(rp++) = cpu_to_le32(risc->dma);
-       *(rp++) = cpu_to_le32(0); /* bits 63-32 */
-       return 0;
-}
-
-void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
-{
-       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-
-       BUG_ON(in_interrupt());
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_dma_unmap(q->dev, dma);
-       videobuf_dma_free(dma);
-       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
-{
-       struct cx23885_dev *dev = port->dev;
-
-       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", __func__,
-               cx23885_irq_get_mask(dev));
-       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", __func__,
-               cx_read(AUD_INT_DMA_CTL));
-       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", __func__,
-               cx_read(AUD_EXT_DMA_CTL));
-       dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,
-               cx_read(PAD_CTRL));
-       dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,
-               cx_read(ALT_PIN_OUT_SEL));
-       dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,
-               cx_read(GPIO2));
-       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", __func__,
-               port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
-       dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
-               port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
-       if (port->reg_src_sel)
-               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", __func__,
-               port->reg_lngth, cx_read(port->reg_lngth));
-       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", __func__,
-               port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
-       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", __func__,
-               port->reg_sop_status, cx_read(port->reg_sop_status));
-       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", __func__,
-               port->reg_vld_misc, cx_read(port->reg_vld_misc));
-       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", __func__,
-               port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
-}
-
-static int cx23885_start_dma(struct cx23885_tsport *port,
-                            struct cx23885_dmaqueue *q,
-                            struct cx23885_buffer   *buf)
-{
-       struct cx23885_dev *dev = port->dev;
-       u32 reg;
-
-       dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
-               buf->vb.width, buf->vb.height, buf->vb.field);
-
-       /* Stop the fifo and risc engine for this port */
-       cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
-
-       /* setup fifo + format */
-       cx23885_sram_channel_setup(dev,
-                                  &dev->sram_channels[port->sram_chno],
-                                  port->ts_packet_size, buf->risc.dma);
-       if (debug > 5) {
-               cx23885_sram_channel_dump(dev,
-                       &dev->sram_channels[port->sram_chno]);
-               cx23885_risc_disasm(port, &buf->risc);
-       }
-
-       /* write TS length to chip */
-       cx_write(port->reg_lngth, buf->vb.width);
-
-       if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
-               (!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
-               printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
-                       __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, port->hw_sop_ctrl_val);
-       cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
-       cx_write(port->reg_vld_misc, port->vld_misc_val);
-       cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
-       udelay(100);
-
-       /* NOTE: this is 2 (reserved) for portb, does it matter? */
-       /* reset counter to zero */
-       cx_write(port->reg_gpcnt_ctl, 3);
-       q->count = 1;
-
-       /* Set VIDB pins to input */
-       if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
-               reg = cx_read(PAD_CTRL);
-               reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */
-               cx_write(PAD_CTRL, reg);
-       }
-
-       /* Set VIDC pins to input */
-       if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
-               reg = cx_read(PAD_CTRL);
-               reg &= ~0x4; /* Clear TS2_SOP_OE */
-               cx_write(PAD_CTRL, reg);
-       }
-
-       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:
-       case CX23885_BRIDGE_888:
-               /* enable irqs */
-               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);
-               cx23885_irq_add(dev, port->pci_irqmask);
-               cx23885_irq_enable_all(dev);
-               break;
-       default:
-               BUG();
-       }
-
-       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);
-
-       return 0;
-}
-
-static int cx23885_stop_dma(struct cx23885_tsport *port)
-{
-       struct cx23885_dev *dev = port->dev;
-       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;
-}
-
-int cx23885_restart_queue(struct cx23885_tsport *port,
-                               struct cx23885_dmaqueue *q)
-{
-       struct cx23885_dev *dev = port->dev;
-       struct cx23885_buffer *buf;
-
-       dprintk(5, "%s()\n", __func__);
-       if (list_empty(&q->active)) {
-               struct cx23885_buffer *prev;
-               prev = NULL;
-
-               dprintk(5, "%s() queue is empty\n", __func__);
-
-               for (;;) {
-                       if (list_empty(&q->queued))
-                               return 0;
-                       buf = list_entry(q->queued.next, struct cx23885_buffer,
-                                        vb.queue);
-                       if (NULL == prev) {
-                               list_del(&buf->vb.queue);
-                               list_add_tail(&buf->vb.queue, &q->active);
-                               cx23885_start_dma(port, q, buf);
-                               buf->vb.state = VIDEOBUF_ACTIVE;
-                               buf->count    = q->count++;
-                               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-                               dprintk(5, "[%p/%d] restart_queue - f/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, &q->active);
-                               buf->vb.state = VIDEOBUF_ACTIVE;
-                               buf->count    = q->count++;
-                               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                               /* 64 bit bits 63-32 */
-                               prev->risc.jmp[2] = cpu_to_le32(0);
-                               dprintk(5, "[%p/%d] restart_queue - m/active\n",
-                                       buf, buf->vb.i);
-                       } else {
-                               return 0;
-                       }
-                       prev = buf;
-               }
-               return 0;
-       }
-
-       buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
-       dprintk(2, "restart_queue [%p/%d]: restart dma\n",
-               buf, buf->vb.i);
-       cx23885_start_dma(port, q, buf);
-       list_for_each_entry(buf, &q->active, vb.queue)
-               buf->count = q->count++;
-       mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
-                       struct cx23885_buffer *buf, enum v4l2_field field)
-{
-       struct cx23885_dev *dev = port->dev;
-       int size = port->ts_packet_size * port->ts_packet_count;
-       int rc;
-
-       dprintk(1, "%s: %p\n", __func__, buf);
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               buf->vb.width  = port->ts_packet_size;
-               buf->vb.height = port->ts_packet_count;
-               buf->vb.size   = size;
-               buf->vb.field  = field /*V4L2_FIELD_TOP*/;
-
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (0 != rc)
-                       goto fail;
-               cx23885_risc_databuffer(dev->pci, &buf->risc,
-                                       videobuf_to_dma(&buf->vb)->sglist,
-                                       buf->vb.width, buf->vb.height, 0);
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       cx23885_free_buffer(q, buf);
-       return rc;
-}
-
-void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
-{
-       struct cx23885_buffer    *prev;
-       struct cx23885_dev *dev = port->dev;
-       struct cx23885_dmaqueue  *cx88q = &port->mpegq;
-
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
-       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
-
-       if (list_empty(&cx88q->active)) {
-               dprintk(1, "queue is empty - first active\n");
-               list_add_tail(&buf->vb.queue, &cx88q->active);
-               cx23885_start_dma(port, cx88q, buf);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = cx88q->count++;
-               mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
-               dprintk(1, "[%p/%d] %s - first active\n",
-                       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,
-                                 vb.queue);
-               list_add_tail(&buf->vb.queue, &cx88q->active);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = cx88q->count++;
-               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, __func__);
-       }
-}
-
-/* ----------------------------------------------------------- */
-
-static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
-                             int restart)
-{
-       struct cx23885_dev *dev = port->dev;
-       struct cx23885_dmaqueue *q = &port->mpegq;
-       struct cx23885_buffer *buf;
-       unsigned long flags;
-
-       spin_lock_irqsave(&port->slock, flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx23885_buffer,
-                                vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
-                       buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
-       }
-       if (restart) {
-               dprintk(1, "restarting queue\n");
-               cx23885_restart_queue(port, q);
-       }
-       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", __func__);
-       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", __func__);
-
-       if (debug > 5)
-               cx23885_sram_channel_dump(dev,
-                       &dev->sram_channels[port->sram_chno]);
-
-       cx23885_stop_dma(port);
-       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)
-                       dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
-                               VID_BC_MSK_OPC_ERR);
-
-               if (status & VID_BC_MSK_BAD_PKT)
-                       dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
-                               VID_BC_MSK_BAD_PKT);
-
-               if (status & VID_BC_MSK_SYNC)
-                       dprintk(7, " (VID_BC_MSK_SYNC    0x%08x)\n",
-                               VID_BC_MSK_SYNC);
-
-               if (status & VID_BC_MSK_OF)
-                       dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n",
-                               VID_BC_MSK_OF);
-
-               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]);
-
-       } else if (status & VID_BC_MSK_RISCI1) {
-
-               dprintk(7, " (RISCI1            0x%08x)\n", VID_BC_MSK_RISCI1);
-
-               spin_lock(&port->slock);
-               count = cx_read(port->reg_gpcnt);
-               cx23885_wakeup(port, &port->mpegq, count);
-               spin_unlock(&port->slock);
-
-       } else if (status & VID_BC_MSK_RISCI2) {
-
-               dprintk(7, " (RISCI2            0x%08x)\n", VID_BC_MSK_RISCI2);
-
-               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 irqreturn_t cx23885_irq(int irq, void *dev_id)
-{
-       struct cx23885_dev *dev = dev_id;
-       struct cx23885_tsport *ts1 = &dev->ts1;
-       struct cx23885_tsport *ts2 = &dev->ts2;
-       u32 pci_status, pci_mask;
-       u32 vida_status, vida_mask;
-       u32 audint_status, audint_mask;
-       u32 ts1_status, ts1_mask;
-       u32 ts2_status, ts2_mask;
-       int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
-       int audint_count = 0;
-       bool subdev_handled;
-
-       pci_status = cx_read(PCI_INT_STAT);
-       pci_mask = cx23885_irq_get_mask(dev);
-       vida_status = cx_read(VID_A_INT_STAT);
-       vida_mask = cx_read(VID_A_INT_MSK);
-       audint_status = cx_read(AUDIO_INT_INT_STAT);
-       audint_mask = cx_read(AUDIO_INT_INT_MSK);
-       ts1_status = cx_read(VID_B_INT_STAT);
-       ts1_mask = cx_read(VID_B_INT_MSK);
-       ts2_status = cx_read(VID_C_INT_STAT);
-       ts2_mask = cx_read(VID_C_INT_MSK);
-
-       if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
-               goto out;
-
-       vida_count = cx_read(VID_A_GPCNT);
-       audint_count = cx_read(AUD_INT_A_GPCNT);
-       ts1_count = cx_read(ts1->reg_gpcnt);
-       ts2_count = cx_read(ts2->reg_gpcnt);
-       dprintk(7, "pci_status: 0x%08x  pci_mask: 0x%08x\n",
-               pci_status, pci_mask);
-       dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
-               vida_status, vida_mask, vida_count);
-       dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
-               audint_status, audint_mask, audint_count);
-       dprintk(7, "ts1_status: 0x%08x  ts1_mask: 0x%08x count: 0x%x\n",
-               ts1_status, ts1_mask, ts1_count);
-       dprintk(7, "ts2_status: 0x%08x  ts2_mask: 0x%08x count: 0x%x\n",
-               ts2_status, ts2_mask, ts2_count);
-
-       if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
-                         PCI_MSK_AL_RD   | PCI_MSK_AL_WR   | PCI_MSK_APB_DMA |
-                         PCI_MSK_VID_C   | PCI_MSK_VID_B   | PCI_MSK_VID_A   |
-                         PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
-                         PCI_MSK_GPIO0   | PCI_MSK_GPIO1   |
-                         PCI_MSK_AV_CORE | PCI_MSK_IR)) {
-
-               if (pci_status & PCI_MSK_RISC_RD)
-                       dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n",
-                               PCI_MSK_RISC_RD);
-
-               if (pci_status & PCI_MSK_RISC_WR)
-                       dprintk(7, " (PCI_MSK_RISC_WR   0x%08x)\n",
-                               PCI_MSK_RISC_WR);
-
-               if (pci_status & PCI_MSK_AL_RD)
-                       dprintk(7, " (PCI_MSK_AL_RD     0x%08x)\n",
-                               PCI_MSK_AL_RD);
-
-               if (pci_status & PCI_MSK_AL_WR)
-                       dprintk(7, " (PCI_MSK_AL_WR     0x%08x)\n",
-                               PCI_MSK_AL_WR);
-
-               if (pci_status & PCI_MSK_APB_DMA)
-                       dprintk(7, " (PCI_MSK_APB_DMA   0x%08x)\n",
-                               PCI_MSK_APB_DMA);
-
-               if (pci_status & PCI_MSK_VID_C)
-                       dprintk(7, " (PCI_MSK_VID_C     0x%08x)\n",
-                               PCI_MSK_VID_C);
-
-               if (pci_status & PCI_MSK_VID_B)
-                       dprintk(7, " (PCI_MSK_VID_B     0x%08x)\n",
-                               PCI_MSK_VID_B);
-
-               if (pci_status & PCI_MSK_VID_A)
-                       dprintk(7, " (PCI_MSK_VID_A     0x%08x)\n",
-                               PCI_MSK_VID_A);
-
-               if (pci_status & PCI_MSK_AUD_INT)
-                       dprintk(7, " (PCI_MSK_AUD_INT   0x%08x)\n",
-                               PCI_MSK_AUD_INT);
-
-               if (pci_status & PCI_MSK_AUD_EXT)
-                       dprintk(7, " (PCI_MSK_AUD_EXT   0x%08x)\n",
-                               PCI_MSK_AUD_EXT);
-
-               if (pci_status & PCI_MSK_GPIO0)
-                       dprintk(7, " (PCI_MSK_GPIO0     0x%08x)\n",
-                               PCI_MSK_GPIO0);
-
-               if (pci_status & PCI_MSK_GPIO1)
-                       dprintk(7, " (PCI_MSK_GPIO1     0x%08x)\n",
-                               PCI_MSK_GPIO1);
-
-               if (pci_status & PCI_MSK_AV_CORE)
-                       dprintk(7, " (PCI_MSK_AV_CORE   0x%08x)\n",
-                               PCI_MSK_AV_CORE);
-
-               if (pci_status & PCI_MSK_IR)
-                       dprintk(7, " (PCI_MSK_IR        0x%08x)\n",
-                               PCI_MSK_IR);
-       }
-
-       if (cx23885_boards[dev->board].ci_type == 1 &&
-                       (pci_status & (PCI_MSK_GPIO1 | PCI_MSK_GPIO0)))
-               handled += netup_ci_slot_status(dev, pci_status);
-
-       if (cx23885_boards[dev->board].ci_type == 2 &&
-                       (pci_status & PCI_MSK_GPIO0))
-               handled += altera_ci_irq(dev);
-
-       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)
-               handled += cx23885_video_irq(dev, vida_status);
-
-       if (audint_status)
-               handled += cx23885_audio_irq(dev, audint_status, audint_mask);
-
-       if (pci_status & PCI_MSK_IR) {
-               subdev_handled = false;
-               v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
-                                pci_status, &subdev_handled);
-               if (subdev_handled)
-                       handled++;
-       }
-
-       if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) {
-               cx23885_irq_disable(dev, PCI_MSK_AV_CORE);
-               if (!schedule_work(&dev->cx25840_work))
-                       printk(KERN_ERR "%s: failed to set up deferred work for"
-                              " AV Core/IR interrupt. Interrupt is disabled"
-                              " and won't be re-enabled\n", dev->name);
-               handled++;
-       }
-
-       if (handled)
-               cx_write(PCI_INT_STAT, pci_status);
-out:
-       return IRQ_RETVAL(handled);
-}
-
-static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
-                                   unsigned int notification, void *arg)
-{
-       struct cx23885_dev *dev;
-
-       if (sd == NULL)
-               return;
-
-       dev = to_cx23885(sd->v4l2_dev);
-
-       switch (notification) {
-       case V4L2_SUBDEV_IR_RX_NOTIFY: /* Possibly called in an IRQ context */
-               if (sd == dev->sd_ir)
-                       cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
-               break;
-       case V4L2_SUBDEV_IR_TX_NOTIFY: /* Possibly called in an IRQ context */
-               if (sd == dev->sd_ir)
-                       cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
-               break;
-       }
-}
-
-static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
-{
-       INIT_WORK(&dev->cx25840_work, cx23885_av_work_handler);
-       INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
-       INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
-       dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
-}
-
-static inline int encoder_on_portb(struct cx23885_dev *dev)
-{
-       return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
-}
-
-static inline int encoder_on_portc(struct cx23885_dev *dev)
-{
-       return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER;
-}
-
-/* Mask represents 32 different GPIOs, GPIO's are split into multiple
- * registers depending on the board configuration (and whether the
- * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will
- * be pushed into the correct hardware register, regardless of the
- * physical location. Certain registers are shared so we sanity check
- * and report errors if we think we're tampering with a GPIo that might
- * be assigned to the encoder (and used for the host bus).
- *
- * GPIO  2 thru  0 - On the cx23885 bridge
- * GPIO 18 thru  3 - On the cx23417 host bus interface
- * GPIO 23 thru 19 - On the cx25840 a/v core
- */
-void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask)
-{
-       if (mask & 0x7)
-               cx_set(GP0_IO, mask & 0x7);
-
-       if (mask & 0x0007fff8) {
-               if (encoder_on_portb(dev) || encoder_on_portc(dev))
-                       printk(KERN_ERR
-                               "%s: Setting GPIO on encoder ports\n",
-                               dev->name);
-               cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3);
-       }
-
-       /* TODO: 23-19 */
-       if (mask & 0x00f80000)
-               printk(KERN_INFO "%s: Unsupported\n", dev->name);
-}
-
-void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
-{
-       if (mask & 0x00000007)
-               cx_clear(GP0_IO, mask & 0x7);
-
-       if (mask & 0x0007fff8) {
-               if (encoder_on_portb(dev) || encoder_on_portc(dev))
-                       printk(KERN_ERR
-                               "%s: Clearing GPIO moving on encoder ports\n",
-                               dev->name);
-               cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3);
-       }
-
-       /* TODO: 23-19 */
-       if (mask & 0x00f80000)
-               printk(KERN_INFO "%s: Unsupported\n", dev->name);
-}
-
-u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
-{
-       if (mask & 0x00000007)
-               return (cx_read(GP0_IO) >> 8) & mask & 0x7;
-
-       if (mask & 0x0007fff8) {
-               if (encoder_on_portb(dev) || encoder_on_portc(dev))
-                       printk(KERN_ERR
-                               "%s: Reading GPIO moving on encoder ports\n",
-                               dev->name);
-               return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
-       }
-
-       /* TODO: 23-19 */
-       if (mask & 0x00f80000)
-               printk(KERN_INFO "%s: Unsupported\n", dev->name);
-
-       return 0;
-}
-
-void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
-{
-       if ((mask & 0x00000007) && asoutput)
-               cx_set(GP0_IO, (mask & 0x7) << 16);
-       else if ((mask & 0x00000007) && !asoutput)
-               cx_clear(GP0_IO, (mask & 0x7) << 16);
-
-       if (mask & 0x0007fff8) {
-               if (encoder_on_portb(dev) || encoder_on_portc(dev))
-                       printk(KERN_ERR
-                               "%s: Enabling GPIO on encoder ports\n",
-                               dev->name);
-       }
-
-       /* MC417_OEN is active low for output, write 1 for an input */
-       if ((mask & 0x0007fff8) && asoutput)
-               cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3);
-
-       else if ((mask & 0x0007fff8) && !asoutput)
-               cx_set(MC417_OEN, (mask & 0x7fff8) >> 3);
-
-       /* TODO: 23-19 */
-}
-
-static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
-{
-       struct cx23885_dev *dev;
-       int err;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (NULL == dev)
-               return -ENOMEM;
-
-       err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
-       if (err < 0)
-               goto fail_free;
-
-       /* Prepare to handle notifications from subdevices */
-       cx23885_v4l2_dev_notify_init(dev);
-
-       /* pci init */
-       dev->pci = pci_dev;
-       if (pci_enable_device(pci_dev)) {
-               err = -EIO;
-               goto fail_unreg;
-       }
-
-       if (cx23885_dev_setup(dev) < 0) {
-               err = -EINVAL;
-               goto fail_unreg;
-       }
-
-       /* print pci info */
-       dev->pci_rev = pci_dev->revision;
-       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-       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));
-
-       pci_set_master(pci_dev);
-       if (!pci_dma_supported(pci_dev, 0xffffffff)) {
-               printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
-               goto fail_irq;
-       }
-
-       err = request_irq(pci_dev->irq, cx23885_irq,
-                         IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
-       if (err < 0) {
-               printk(KERN_ERR "%s: can't get IRQ %d\n",
-                      dev->name, pci_dev->irq);
-               goto fail_irq;
-       }
-
-       switch (dev->board) {
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-               cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0);
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-               cx23885_irq_add_enable(dev, PCI_MSK_GPIO0);
-               break;
-       }
-
-       /*
-        * The CX2388[58] IR controller can start firing interrupts when
-        * enabled, so these have to take place after the cx23885_irq() handler
-        * is hooked up by the call to request_irq() above.
-        */
-       cx23885_ir_pci_int_enable(dev);
-       cx23885_input_init(dev);
-
-       return 0;
-
-fail_irq:
-       cx23885_dev_unregister(dev);
-fail_unreg:
-       v4l2_device_unregister(&dev->v4l2_dev);
-fail_free:
-       kfree(dev);
-       return err;
-}
-
-static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct cx23885_dev *dev = to_cx23885(v4l2_dev);
-
-       cx23885_input_fini(dev);
-       cx23885_ir_fini(dev);
-
-       cx23885_shutdown(dev);
-
-       pci_disable_device(pci_dev);
-
-       /* unregister stuff */
-       free_irq(pci_dev->irq, dev);
-
-       cx23885_dev_unregister(dev);
-       v4l2_device_unregister(v4l2_dev);
-       kfree(dev);
-}
-
-static struct pci_device_id cx23885_pci_tbl[] = {
-       {
-               /* CX23885 */
-               .vendor       = 0x14f1,
-               .device       = 0x8852,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       }, {
-               /* CX23887 Rev 2 */
-               .vendor       = 0x14f1,
-               .device       = 0x8880,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       }, {
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, cx23885_pci_tbl);
-
-static struct pci_driver cx23885_pci_driver = {
-       .name     = "cx23885",
-       .id_table = cx23885_pci_tbl,
-       .probe    = cx23885_initdev,
-       .remove   = __devexit_p(cx23885_finidev),
-       /* TODO */
-       .suspend  = NULL,
-       .resume   = NULL,
-};
-
-static int __init cx23885_init(void)
-{
-       printk(KERN_INFO "cx23885 driver version %s loaded\n",
-               CX23885_VERSION);
-       return pci_register_driver(&cx23885_pci_driver);
-}
-
-static void __exit cx23885_fini(void)
-{
-       pci_unregister_driver(&cx23885_pci_driver);
-}
-
-module_init(cx23885_init);
-module_exit(cx23885_fini);
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c
deleted file mode 100644 (file)
index f3202a5..0000000
+++ /dev/null
@@ -1,1356 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/kthread.h>
-#include <linux/file.h>
-#include <linux/suspend.h>
-
-#include "cx23885.h"
-#include <media/v4l2-common.h>
-
-#include "dvb_ca_en50221.h"
-#include "s5h1409.h"
-#include "s5h1411.h"
-#include "mt2131.h"
-#include "tda8290.h"
-#include "tda18271.h"
-#include "lgdt330x.h"
-#include "xc4000.h"
-#include "xc5000.h"
-#include "max2165.h"
-#include "tda10048.h"
-#include "tuner-xc2028.h"
-#include "tuner-simple.h"
-#include "dib7000p.h"
-#include "dibx000_common.h"
-#include "zl10353.h"
-#include "stv0900.h"
-#include "stv0900_reg.h"
-#include "stv6110.h"
-#include "lnbh24.h"
-#include "cx24116.h"
-#include "cimax2.h"
-#include "lgs8gxx.h"
-#include "netup-eeprom.h"
-#include "netup-init.h"
-#include "lgdt3305.h"
-#include "atbm8830.h"
-#include "ds3000.h"
-#include "cx23885-f300.h"
-#include "altera-ci.h"
-#include "stv0367.h"
-#include "drxk.h"
-#include "mt2063.h"
-
-static unsigned int debug;
-
-#define dprintk(level, fmt, arg...)\
-       do { if (debug >= level)\
-               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
-       } while (0)
-
-/* ------------------------------------------------------------------ */
-
-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,
-                        unsigned int *count, unsigned int *size)
-{
-       struct cx23885_tsport *port = q->priv_data;
-
-       port->ts_packet_size  = 188 * 4;
-       port->ts_packet_count = 32;
-
-       *size  = port->ts_packet_size * port->ts_packet_count;
-       *count = 32;
-       return 0;
-}
-
-static int dvb_buf_prepare(struct videobuf_queue *q,
-                          struct videobuf_buffer *vb, enum v4l2_field field)
-{
-       struct cx23885_tsport *port = q->priv_data;
-       return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
-}
-
-static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx23885_tsport *port = q->priv_data;
-       cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
-}
-
-static void dvb_buf_release(struct videobuf_queue *q,
-                           struct videobuf_buffer *vb)
-{
-       cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
-}
-
-static int cx23885_dvb_set_frontend(struct dvb_frontend *fe);
-
-static void cx23885_dvb_gate_ctrl(struct cx23885_tsport  *port, int open)
-{
-       struct videobuf_dvb_frontends *f;
-       struct videobuf_dvb_frontend *fe;
-
-       f = &port->frontends;
-
-       if (f->gate <= 1) /* undefined or fe0 */
-               fe = videobuf_dvb_get_frontend(f, 1);
-       else
-               fe = videobuf_dvb_get_frontend(f, f->gate);
-
-       if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
-               fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
-
-       /*
-        * FIXME: Improve this path to avoid calling the
-        * cx23885_dvb_set_frontend() every time it passes here.
-        */
-       cx23885_dvb_set_frontend(fe->dvb.frontend);
-}
-
-static struct videobuf_queue_ops dvb_qops = {
-       .buf_setup    = dvb_buf_setup,
-       .buf_prepare  = dvb_buf_prepare,
-       .buf_queue    = dvb_buf_queue,
-       .buf_release  = dvb_buf_release,
-};
-
-static struct s5h1409_config hauppauge_generic_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_SERIAL_OUTPUT,
-       .gpio          = S5H1409_GPIO_ON,
-       .qam_if        = 44000,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .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,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3800,
-       .dtv8_if_freq_khz = TDA10048_IF_4300,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-};
-
-static struct tda10048_config hauppauge_hvr1210_config = {
-       .demod_address    = 0x10 >> 1,
-       .output_mode      = TDA10048_SERIAL_OUTPUT,
-       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
-       .inversion        = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3500,
-       .dtv8_if_freq_khz = TDA10048_IF_4000,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-};
-
-static struct s5h1409_config hauppauge_ezqam_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_SERIAL_OUTPUT,
-       .gpio          = S5H1409_GPIO_OFF,
-       .qam_if        = 4000,
-       .inversion     = S5H1409_INVERSION_ON,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1409_config hauppauge_hvr1800lp_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_SERIAL_OUTPUT,
-       .gpio          = S5H1409_GPIO_OFF,
-       .qam_if        = 44000,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1409_config hauppauge_hvr1500_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 mt2131_config hauppauge_generic_tunerconfig = {
-       0x61
-};
-
-static struct lgdt330x_config fusionhdtv_5_express = {
-       .demod_address = 0x0e,
-       .demod_chip = LGDT3303,
-       .serial_mpeg = 0x40,
-};
-
-static struct s5h1409_config hauppauge_hvr1500q_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_SERIAL_OUTPUT,
-       .gpio          = S5H1409_GPIO_ON,
-       .qam_if        = 44000,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1409_config dvico_s5h1409_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_SERIAL_OUTPUT,
-       .gpio          = S5H1409_GPIO_ON,
-       .qam_if        = 44000,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1411_config dvico_s5h1411_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_ON,
-       .qam_if        = S5H1411_IF_44000,
-       .vsb_if        = S5H1411_IF_44000,
-       .inversion     = S5H1411_INVERSION_OFF,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct s5h1411_config hcw_s5h1411_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_OFF,
-       .vsb_if        = S5H1411_IF_44000,
-       .qam_if        = S5H1411_IF_4000,
-       .inversion     = S5H1411_INVERSION_ON,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
-       .i2c_address      = 0x61,
-       .if_khz           = 5380,
-};
-
-static struct xc5000_config dvico_xc5000_tunerconfig = {
-       .i2c_address      = 0x64,
-       .if_khz           = 5380,
-};
-
-static struct tda829x_config tda829x_no_probe = {
-       .probe_tuner = TDA829X_DONT_PROBE,
-};
-
-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_std_map hauppauge_hvr1200_tda18271_std_map = {
-       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config hauppauge_tda18271_config = {
-       .std_map = &hauppauge_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static struct tda18271_config hauppauge_hvr1200_tuner_config = {
-       .std_map = &hauppauge_hvr1200_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static struct tda18271_config hauppauge_hvr1210_tuner_config = {
-       .gate    = TDA18271_GATE_DIGITAL,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static struct tda18271_std_map hauppauge_hvr127x_std_map = {
-       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
-                     .if_lvl = 1, .rfagc_top = 0x58 },
-       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
-                     .if_lvl = 1, .rfagc_top = 0x58 },
-};
-
-static struct tda18271_config hauppauge_hvr127x_config = {
-       .std_map = &hauppauge_hvr127x_std_map,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static struct lgdt3305_config hauppauge_lgdt3305_config = {
-       .i2c_addr           = 0x0e,
-       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
-       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
-       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 1,
-       .qam_if_khz         = 4000,
-       .vsb_if_khz         = 3250,
-};
-
-static 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 */
-static 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 struct zl10353_config dvico_fusionhdtv_xc3028 = {
-       .demod_address = 0x0f,
-       .if2           = 45600,
-       .no_tuner      = 1,
-       .disable_i2c_gate_ctrl = 1,
-};
-
-static struct stv0900_reg stv0900_ts_regs[] = {
-       { R0900_TSGENERAL, 0x00 },
-       { R0900_P1_TSSPEED, 0x40 },
-       { R0900_P2_TSSPEED, 0x40 },
-       { R0900_P1_TSCFGM, 0xc0 },
-       { R0900_P2_TSCFGM, 0xc0 },
-       { R0900_P1_TSCFGH, 0xe0 },
-       { R0900_P2_TSCFGH, 0xe0 },
-       { R0900_P1_TSCFGL, 0x20 },
-       { R0900_P2_TSCFGL, 0x20 },
-       { 0xffff, 0xff }, /* terminate */
-};
-
-static struct stv0900_config netup_stv0900_config = {
-       .demod_address = 0x68,
-       .demod_mode = 1, /* dual */
-       .xtal = 8000000,
-       .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
-       .diseqc_mode = 2,/* 2/3 PWM */
-       .ts_config_regs = stv0900_ts_regs,
-       .tun1_maddress = 0,/* 0x60 */
-       .tun2_maddress = 3,/* 0x63 */
-       .tun1_adc = 1,/* 1 Vpp */
-       .tun2_adc = 1,/* 1 Vpp */
-};
-
-static struct stv6110_config netup_stv6110_tunerconfig_a = {
-       .i2c_address = 0x60,
-       .mclk = 16000000,
-       .clk_div = 1,
-       .gain = 8, /* +16 dB  - maximum gain */
-};
-
-static struct stv6110_config netup_stv6110_tunerconfig_b = {
-       .i2c_address = 0x63,
-       .mclk = 16000000,
-       .clk_div = 1,
-       .gain = 8, /* +16 dB  - maximum gain */
-};
-
-static struct cx24116_config tbs_cx24116_config = {
-       .demod_address = 0x55,
-};
-
-static struct ds3000_config tevii_ds3000_config = {
-       .demod_address = 0x68,
-};
-
-static struct cx24116_config dvbworld_cx24116_config = {
-       .demod_address = 0x05,
-};
-
-static struct lgs8gxx_config mygica_x8506_lgs8gl5_config = {
-       .prod = LGS8GXX_PROD_LGS8GL5,
-       .demod_address = 0x19,
-       .serial_ts = 0,
-       .ts_clk_pol = 1,
-       .ts_clk_gated = 1,
-       .if_clk_freq = 30400, /* 30.4 MHz */
-       .if_freq = 5380, /* 5.38 MHz */
-       .if_neg_center = 1,
-       .ext_adc = 0,
-       .adc_signed = 0,
-       .if_neg_edge = 0,
-};
-
-static struct xc5000_config mygica_x8506_xc5000_config = {
-       .i2c_address = 0x61,
-       .if_khz = 5380,
-};
-
-static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
-{
-       struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-       struct cx23885_tsport *port = fe->dvb->priv;
-       struct cx23885_dev *dev = port->dev;
-
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1275:
-               switch (p->modulation) {
-               case VSB_8:
-                       cx23885_gpio_clear(dev, GPIO_5);
-                       break;
-               case QAM_64:
-               case QAM_256:
-               default:
-                       cx23885_gpio_set(dev, GPIO_5);
-                       break;
-               }
-               break;
-       case CX23885_BOARD_MYGICA_X8506:
-       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
-               /* Select Digital TV */
-               cx23885_gpio_set(dev, GPIO_0);
-               break;
-       }
-       return 0;
-}
-
-static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
-       .prod = LGS8GXX_PROD_LGS8G75,
-       .demod_address = 0x19,
-       .serial_ts = 0,
-       .ts_clk_pol = 1,
-       .ts_clk_gated = 1,
-       .if_clk_freq = 30400, /* 30.4 MHz */
-       .if_freq = 6500, /* 6.50 MHz */
-       .if_neg_center = 1,
-       .ext_adc = 0,
-       .adc_signed = 1,
-       .adc_vpp = 2, /* 1.6 Vpp */
-       .if_neg_edge = 1,
-};
-
-static struct xc5000_config magicpro_prohdtve2_xc5000_config = {
-       .i2c_address = 0x61,
-       .if_khz = 6500,
-};
-
-static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = {
-       .prod = ATBM8830_PROD_8830,
-       .demod_address = 0x44,
-       .serial_ts = 0,
-       .ts_sampling_edge = 1,
-       .ts_clk_gated = 0,
-       .osc_clk_freq = 30400, /* in kHz */
-       .if_freq = 0, /* zero IF */
-       .zif_swap_iq = 1,
-       .agc_min = 0x2E,
-       .agc_max = 0xFF,
-       .agc_hold_loop = 0,
-};
-
-static struct max2165_config mygic_x8558pro_max2165_cfg1 = {
-       .i2c_address = 0x60,
-       .osc_clk = 20
-};
-
-static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = {
-       .prod = ATBM8830_PROD_8830,
-       .demod_address = 0x44,
-       .serial_ts = 1,
-       .ts_sampling_edge = 1,
-       .ts_clk_gated = 0,
-       .osc_clk_freq = 30400, /* in kHz */
-       .if_freq = 0, /* zero IF */
-       .zif_swap_iq = 1,
-       .agc_min = 0x2E,
-       .agc_max = 0xFF,
-       .agc_hold_loop = 0,
-};
-
-static struct max2165_config mygic_x8558pro_max2165_cfg2 = {
-       .i2c_address = 0x60,
-       .osc_clk = 20
-};
-static struct stv0367_config netup_stv0367_config[] = {
-       {
-               .demod_address = 0x1c,
-               .xtal = 27000000,
-               .if_khz = 4500,
-               .if_iq_mode = 0,
-               .ts_mode = 1,
-               .clk_pol = 0,
-       }, {
-               .demod_address = 0x1d,
-               .xtal = 27000000,
-               .if_khz = 4500,
-               .if_iq_mode = 0,
-               .ts_mode = 1,
-               .clk_pol = 0,
-       },
-};
-
-static struct xc5000_config netup_xc5000_config[] = {
-       {
-               .i2c_address = 0x61,
-               .if_khz = 4500,
-       }, {
-               .i2c_address = 0x64,
-               .if_khz = 4500,
-       },
-};
-
-static struct drxk_config terratec_drxk_config[] = {
-       {
-               .adr = 0x29,
-               .no_i2c_bridge = 1,
-       }, {
-               .adr = 0x2a,
-               .no_i2c_bridge = 1,
-       },
-};
-
-static struct mt2063_config terratec_mt2063_config[] = {
-       {
-               .tuner_address = 0x60,
-       }, {
-               .tuner_address = 0x67,
-       },
-};
-
-int netup_altera_fpga_rw(void *device, int flag, int data, int read)
-{
-       struct cx23885_dev *dev = (struct cx23885_dev *)device;
-       unsigned long timeout = jiffies + msecs_to_jiffies(1);
-       uint32_t mem = 0;
-
-       mem = cx_read(MC417_RWD);
-       if (read)
-               cx_set(MC417_OEN, ALT_DATA);
-       else {
-               cx_clear(MC417_OEN, ALT_DATA);/* D0-D7 out */
-               mem &= ~ALT_DATA;
-               mem |= (data & ALT_DATA);
-       }
-
-       if (flag)
-               mem |= ALT_AD_RG;
-       else
-               mem &= ~ALT_AD_RG;
-
-       mem &= ~ALT_CS;
-       if (read)
-               mem = (mem & ~ALT_RD) | ALT_WR;
-       else
-               mem = (mem & ~ALT_WR) | ALT_RD;
-
-       cx_write(MC417_RWD, mem);  /* start RW cycle */
-
-       for (;;) {
-               mem = cx_read(MC417_RWD);
-               if ((mem & ALT_RDY) == 0)
-                       break;
-               if (time_after(jiffies, timeout))
-                       break;
-               udelay(1);
-       }
-
-       cx_set(MC417_RWD, ALT_RD | ALT_WR | ALT_CS);
-       if (read)
-               return mem & ALT_DATA;
-
-       return 0;
-};
-
-static int dvb_register(struct cx23885_tsport *port)
-{
-       struct cx23885_dev *dev = port->dev;
-       struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
-       struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
-       int mfe_shared = 0; /* bus not shared by default */
-       int ret;
-
-       /* Get the first frontend */
-       fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
-       if (!fe0)
-               return -EINVAL;
-
-       /* init struct videobuf_dvb */
-       fe0->dvb.name = dev->name;
-
-       /* multi-frontend gate control is undefined or defaults to fe0 */
-       port->frontends.gate = 0;
-
-       /* Sets the gate control callback to be used by i2c command calls */
-       port->gate_ctrl = cx23885_dvb_gate_ctrl;
-
-       /* init frontend */
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                               &hauppauge_generic_config,
-                                               &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(mt2131_attach, fe0->dvb.frontend,
-                                  &i2c_bus->i2c_adap,
-                                  &hauppauge_generic_tunerconfig, 0);
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1275:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
-                                              &hauppauge_lgdt3305_config,
-                                              &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_bus[1].i2c_adap,
-                                  &hauppauge_hvr127x_config);
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
-                                              &hcw_s5h1411_config,
-                                              &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_bus[1].i2c_adap,
-                                  &hauppauge_tda18271_config);
-               }
-
-               tda18271_attach(&dev->ts1.analog_fe,
-                       0x60, &dev->i2c_bus[1].i2c_adap,
-                       &hauppauge_tda18271_config);
-
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1800:
-               i2c_bus = &dev->i2c_bus[0];
-               switch (alt_tuner) {
-               case 1:
-                       fe0->dvb.frontend =
-                               dvb_attach(s5h1409_attach,
-                                          &hauppauge_ezqam_config,
-                                          &i2c_bus->i2c_adap);
-                       if (fe0->dvb.frontend != NULL) {
-                               dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                          &dev->i2c_bus[1].i2c_adap, 0x42,
-                                          &tda829x_no_probe);
-                               dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                          0x60, &dev->i2c_bus[1].i2c_adap,
-                                          &hauppauge_tda18271_config);
-                       }
-                       break;
-               case 0:
-               default:
-                       fe0->dvb.frontend =
-                               dvb_attach(s5h1409_attach,
-                                          &hauppauge_generic_config,
-                                          &i2c_bus->i2c_adap);
-                       if (fe0->dvb.frontend != NULL)
-                               dvb_attach(mt2131_attach, fe0->dvb.frontend,
-                                          &i2c_bus->i2c_adap,
-                                          &hauppauge_generic_tunerconfig, 0);
-                       break;
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                               &hauppauge_hvr1800lp_config,
-                                               &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(mt2131_attach, fe0->dvb.frontend,
-                                  &i2c_bus->i2c_adap,
-                                  &hauppauge_generic_tunerconfig, 0);
-               }
-               break;
-       case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
-                                               &fusionhdtv_5_express,
-                                               &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &i2c_bus->i2c_adap, 0x61,
-                                  TUNER_LG_TDVS_H06XF);
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
-               i2c_bus = &dev->i2c_bus[1];
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                               &hauppauge_hvr1500q_config,
-                                               &dev->i2c_bus[0].i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
-                                  &i2c_bus->i2c_adap,
-                                  &hauppauge_hvr1500q_tunerconfig);
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1500:
-               i2c_bus = &dev->i2c_bus[1];
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                               &hauppauge_hvr1500_config,
-                                               &dev->i2c_bus[0].i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       struct dvb_frontend *fe;
-                       struct xc2028_config cfg = {
-                               .i2c_adap  = &i2c_bus->i2c_adap,
-                               .i2c_addr  = 0x61,
-                       };
-                       static struct xc2028_ctrl ctl = {
-                               .fname       = XC2028_DEFAULT_FIRMWARE,
-                               .max_len     = 64,
-                               .demod       = XC3028_FE_OREN538,
-                       };
-
-                       fe = dvb_attach(xc2028_attach,
-                                       fe0->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];
-               fe0->dvb.frontend = dvb_attach(tda10048_attach,
-                       &hauppauge_hvr1200_config,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                               &dev->i2c_bus[1].i2c_adap, 0x42,
-                               &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                               0x60, &dev->i2c_bus[1].i2c_adap,
-                               &hauppauge_hvr1200_tuner_config);
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1210:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(tda10048_attach,
-                       &hauppauge_hvr1210_config,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                               0x60, &dev->i2c_bus[1].i2c_adap,
-                               &hauppauge_hvr1210_tuner_config);
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1400:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(dib7000p_attach,
-                       &i2c_bus->i2c_adap,
-                       0x12, &hauppauge_hvr1400_dib7000_config);
-               if (fe0->dvb.frontend != NULL) {
-                       struct dvb_frontend *fe;
-                       struct xc2028_config cfg = {
-                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
-                               .i2c_addr  = 0x64,
-                       };
-                       static struct xc2028_ctrl ctl = {
-                               .fname   = XC3028L_DEFAULT_FIRMWARE,
-                               .max_len = 64,
-                               .demod   = XC3028_FE_DIBCOM52,
-                               /* This is true for all demods with
-                                       v36 firmware? */
-                               .type    = XC2028_D2633,
-                       };
-
-                       fe = dvb_attach(xc2028_attach,
-                                       fe0->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_DVICO_FUSIONHDTV_7_DUAL_EXP:
-               i2c_bus = &dev->i2c_bus[port->nr - 1];
-
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                               &dvico_s5h1409_config,
-                                               &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend == NULL)
-                       fe0->dvb.frontend = dvb_attach(s5h1411_attach,
-                                                       &dvico_s5h1411_config,
-                                                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
-                                  &i2c_bus->i2c_adap,
-                                  &dvico_xc5000_tunerconfig);
-               break;
-       case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
-               i2c_bus = &dev->i2c_bus[port->nr - 1];
-
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &dvico_fusionhdtv_xc3028,
-                                              &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       struct dvb_frontend      *fe;
-                       struct xc2028_config      cfg = {
-                               .i2c_adap  = &i2c_bus->i2c_adap,
-                               .i2c_addr  = 0x61,
-                       };
-                       static struct xc2028_ctrl ctl = {
-                               .fname       = XC2028_DEFAULT_FIRMWARE,
-                               .max_len     = 64,
-                               .demod       = XC3028_FE_ZARLINK456,
-                       };
-
-                       fe = dvb_attach(xc2028_attach, fe0->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_LEADTEK_WINFAST_PXDVR3200_H:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
-       case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
-               i2c_bus = &dev->i2c_bus[0];
-
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                       &dvico_fusionhdtv_xc3028,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       struct dvb_frontend      *fe;
-                       struct xc2028_config      cfg = {
-                               .i2c_adap  = &dev->i2c_bus[1].i2c_adap,
-                               .i2c_addr  = 0x61,
-                       };
-                       static struct xc2028_ctrl ctl = {
-                               .fname       = XC2028_DEFAULT_FIRMWARE,
-                               .max_len     = 64,
-                               .demod       = XC3028_FE_ZARLINK456,
-                       };
-
-                       fe = dvb_attach(xc2028_attach, fe0->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_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
-               i2c_bus = &dev->i2c_bus[0];
-
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &dvico_fusionhdtv_xc3028,
-                                              &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       struct dvb_frontend     *fe;
-                       struct xc4000_config    cfg = {
-                               .i2c_address      = 0x61,
-                               .default_pm       = 0,
-                               .dvb_amplitude    = 134,
-                               .set_smoothedcvbs = 1,
-                               .if_khz           = 4560
-                       };
-
-                       fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
-                                       &dev->i2c_bus[1].i2c_adap, &cfg);
-                       if (!fe) {
-                               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
-                                      dev->name);
-                               goto frontend_detach;
-                       }
-               }
-               break;
-       case CX23885_BOARD_TBS_6920:
-               i2c_bus = &dev->i2c_bus[1];
-
-               fe0->dvb.frontend = dvb_attach(cx24116_attach,
-                                       &tbs_cx24116_config,
-                                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
-
-               break;
-       case CX23885_BOARD_TEVII_S470:
-               i2c_bus = &dev->i2c_bus[1];
-
-               fe0->dvb.frontend = dvb_attach(ds3000_attach,
-                                       &tevii_ds3000_config,
-                                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
-
-               break;
-       case CX23885_BOARD_DVBWORLD_2005:
-               i2c_bus = &dev->i2c_bus[1];
-
-               fe0->dvb.frontend = dvb_attach(cx24116_attach,
-                       &dvbworld_cx24116_config,
-                       &i2c_bus->i2c_adap);
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-               i2c_bus = &dev->i2c_bus[0];
-               switch (port->nr) {
-               /* port B */
-               case 1:
-                       fe0->dvb.frontend = dvb_attach(stv0900_attach,
-                                                       &netup_stv0900_config,
-                                                       &i2c_bus->i2c_adap, 0);
-                       if (fe0->dvb.frontend != NULL) {
-                               if (dvb_attach(stv6110_attach,
-                                               fe0->dvb.frontend,
-                                               &netup_stv6110_tunerconfig_a,
-                                               &i2c_bus->i2c_adap)) {
-                                       if (!dvb_attach(lnbh24_attach,
-                                                       fe0->dvb.frontend,
-                                                       &i2c_bus->i2c_adap,
-                                                       LNBH24_PCL | LNBH24_TTX,
-                                                       LNBH24_TEN, 0x09))
-                                               printk(KERN_ERR
-                                                       "No LNBH24 found!\n");
-
-                               }
-                       }
-                       break;
-               /* port C */
-               case 2:
-                       fe0->dvb.frontend = dvb_attach(stv0900_attach,
-                                                       &netup_stv0900_config,
-                                                       &i2c_bus->i2c_adap, 1);
-                       if (fe0->dvb.frontend != NULL) {
-                               if (dvb_attach(stv6110_attach,
-                                               fe0->dvb.frontend,
-                                               &netup_stv6110_tunerconfig_b,
-                                               &i2c_bus->i2c_adap)) {
-                                       if (!dvb_attach(lnbh24_attach,
-                                                       fe0->dvb.frontend,
-                                                       &i2c_bus->i2c_adap,
-                                                       LNBH24_PCL | LNBH24_TTX,
-                                                       LNBH24_TEN, 0x0a))
-                                               printk(KERN_ERR
-                                                       "No LNBH24 found!\n");
-
-                               }
-                       }
-                       break;
-               }
-               break;
-       case CX23885_BOARD_MYGICA_X8506:
-               i2c_bus = &dev->i2c_bus[0];
-               i2c_bus2 = &dev->i2c_bus[1];
-               fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
-                       &mygica_x8506_lgs8gl5_config,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(xc5000_attach,
-                               fe0->dvb.frontend,
-                               &i2c_bus2->i2c_adap,
-                               &mygica_x8506_xc5000_config);
-               }
-               break;
-       case CX23885_BOARD_MAGICPRO_PROHDTVE2:
-               i2c_bus = &dev->i2c_bus[0];
-               i2c_bus2 = &dev->i2c_bus[1];
-               fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
-                       &magicpro_prohdtve2_lgs8g75_config,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(xc5000_attach,
-                               fe0->dvb.frontend,
-                               &i2c_bus2->i2c_adap,
-                               &magicpro_prohdtve2_xc5000_config);
-               }
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
-                       &hcw_s5h1411_config,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                               0x60, &dev->i2c_bus[0].i2c_adap,
-                               &hauppauge_tda18271_config);
-
-               tda18271_attach(&dev->ts1.analog_fe,
-                       0x60, &dev->i2c_bus[1].i2c_adap,
-                       &hauppauge_tda18271_config);
-
-               break;
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-               i2c_bus = &dev->i2c_bus[0];
-               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
-                       &hcw_s5h1411_config,
-                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                               0x60, &dev->i2c_bus[0].i2c_adap,
-                               &hauppauge_tda18271_config);
-               break;
-       case CX23885_BOARD_MYGICA_X8558PRO:
-               switch (port->nr) {
-               /* port B */
-               case 1:
-                       i2c_bus = &dev->i2c_bus[0];
-                       fe0->dvb.frontend = dvb_attach(atbm8830_attach,
-                               &mygica_x8558pro_atbm8830_cfg1,
-                               &i2c_bus->i2c_adap);
-                       if (fe0->dvb.frontend != NULL) {
-                               dvb_attach(max2165_attach,
-                                       fe0->dvb.frontend,
-                                       &i2c_bus->i2c_adap,
-                                       &mygic_x8558pro_max2165_cfg1);
-                       }
-                       break;
-               /* port C */
-               case 2:
-                       i2c_bus = &dev->i2c_bus[1];
-                       fe0->dvb.frontend = dvb_attach(atbm8830_attach,
-                               &mygica_x8558pro_atbm8830_cfg2,
-                               &i2c_bus->i2c_adap);
-                       if (fe0->dvb.frontend != NULL) {
-                               dvb_attach(max2165_attach,
-                                       fe0->dvb.frontend,
-                                       &i2c_bus->i2c_adap,
-                                       &mygic_x8558pro_max2165_cfg2);
-                       }
-                       break;
-               }
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-               i2c_bus = &dev->i2c_bus[0];
-               mfe_shared = 1;/* MFE */
-               port->frontends.gate = 0;/* not clear for me yet */
-               /* ports B, C */
-               /* MFE frontend 1 DVB-T */
-               fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
-                                       &netup_stv0367_config[port->nr - 1],
-                                       &i2c_bus->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (NULL == dvb_attach(xc5000_attach,
-                                       fe0->dvb.frontend,
-                                       &i2c_bus->i2c_adap,
-                                       &netup_xc5000_config[port->nr - 1]))
-                               goto frontend_detach;
-                       /* load xc5000 firmware */
-                       fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
-               }
-               /* MFE frontend 2 */
-               fe1 = videobuf_dvb_get_frontend(&port->frontends, 2);
-               if (fe1 == NULL)
-                       goto frontend_detach;
-               /* DVB-C init */
-               fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
-                                       &netup_stv0367_config[port->nr - 1],
-                                       &i2c_bus->i2c_adap);
-               if (fe1->dvb.frontend != NULL) {
-                       fe1->dvb.frontend->id = 1;
-                       if (NULL == dvb_attach(xc5000_attach,
-                                       fe1->dvb.frontend,
-                                       &i2c_bus->i2c_adap,
-                                       &netup_xc5000_config[port->nr - 1]))
-                               goto frontend_detach;
-               }
-               break;
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-               i2c_bus = &dev->i2c_bus[0];
-               i2c_bus2 = &dev->i2c_bus[1];
-
-               switch (port->nr) {
-               /* port b */
-               case 1:
-                       fe0->dvb.frontend = dvb_attach(drxk_attach,
-                                       &terratec_drxk_config[0],
-                                       &i2c_bus->i2c_adap);
-                       if (fe0->dvb.frontend != NULL) {
-                               if (!dvb_attach(mt2063_attach,
-                                               fe0->dvb.frontend,
-                                               &terratec_mt2063_config[0],
-                                               &i2c_bus2->i2c_adap))
-                                       goto frontend_detach;
-                       }
-                       break;
-               /* port c */
-               case 2:
-                       fe0->dvb.frontend = dvb_attach(drxk_attach,
-                                       &terratec_drxk_config[1],
-                                       &i2c_bus->i2c_adap);
-                       if (fe0->dvb.frontend != NULL) {
-                               if (!dvb_attach(mt2063_attach,
-                                               fe0->dvb.frontend,
-                                               &terratec_mt2063_config[1],
-                                               &i2c_bus2->i2c_adap))
-                                       goto frontend_detach;
-                       }
-                       break;
-               }
-               break;
-       case CX23885_BOARD_TEVII_S471:
-               i2c_bus = &dev->i2c_bus[1];
-
-               fe0->dvb.frontend = dvb_attach(ds3000_attach,
-                                       &tevii_ds3000_config,
-                                       &i2c_bus->i2c_adap);
-               break;
-       default:
-               printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
-                       " isn't supported yet\n",
-                      dev->name);
-               break;
-       }
-
-       if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
-               printk(KERN_ERR "%s: frontend initialization failed\n",
-                      dev->name);
-               goto frontend_detach;
-       }
-
-       /* define general-purpose callback pointer */
-       fe0->dvb.frontend->callback = cx23885_tuner_callback;
-       if (fe1)
-               fe1->dvb.frontend->callback = cx23885_tuner_callback;
-#if 0
-       /* Ensure all frontends negotiate bus access */
-       fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
-       if (fe1)
-               fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
-#endif
-
-       /* Put the analog decoder in standby to keep it quiet */
-       call_all(dev, core, s_power, 0);
-
-       if (fe0->dvb.frontend->ops.analog_ops.standby)
-               fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
-
-       /* register everything */
-       ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
-                                       &dev->pci->dev, adapter_nr, mfe_shared);
-       if (ret)
-               goto frontend_detach;
-
-       /* init CI & MAC */
-       switch (dev->board) {
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
-               static struct netup_card_info cinfo;
-
-               netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
-               memcpy(port->frontends.adapter.proposed_mac,
-                               cinfo.port[port->nr - 1].mac, 6);
-               printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
-                       port->nr, port->frontends.adapter.proposed_mac);
-
-               netup_ci_init(port);
-               break;
-               }
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
-               struct altera_ci_config netup_ci_cfg = {
-                       .dev = dev,/* magic number to identify*/
-                       .adapter = &port->frontends.adapter,/* for CI */
-                       .demux = &fe0->dvb.demux,/* for hw pid filter */
-                       .fpga_rw = netup_altera_fpga_rw,
-               };
-
-               altera_ci_init(&netup_ci_cfg, port->nr);
-               break;
-               }
-       case CX23885_BOARD_TEVII_S470: {
-               u8 eeprom[256]; /* 24C02 i2c eeprom */
-
-               if (port->nr != 1)
-                       break;
-
-               /* Read entire EEPROM */
-               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-               tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
-               printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
-               memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
-               break;
-               }
-       }
-
-       return ret;
-
-frontend_detach:
-       port->gate_ctrl = NULL;
-       videobuf_dvb_dealloc_frontends(&port->frontends);
-       return -EINVAL;
-}
-
-int cx23885_dvb_register(struct cx23885_tsport *port)
-{
-
-       struct videobuf_dvb_frontend *fe0;
-       struct cx23885_dev *dev = port->dev;
-       int err, i;
-
-       /* Here we need to allocate the correct number of frontends,
-        * as reflected in the cards struct. The reality is that currently
-        * no cx23885 boards support this - yet. But, if we don't modify this
-        * code then the second frontend would never be allocated (later)
-        * and fail with error before the attach in dvb_register().
-        * Without these changes we risk an OOPS later. The changes here
-        * are for safety, and should provide a good foundation for the
-        * future addition of any multi-frontend cx23885 based boards.
-        */
-       printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
-               port->num_frontends);
-
-       for (i = 1; i <= port->num_frontends; i++) {
-               if (videobuf_dvb_alloc_frontend(
-                       &port->frontends, i) == NULL) {
-                       printk(KERN_ERR "%s() failed to alloc\n", __func__);
-                       return -ENOMEM;
-               }
-
-               fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
-               if (!fe0)
-                       err = -EINVAL;
-
-               dprintk(1, "%s\n", __func__);
-               dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
-                       dev->board,
-                       dev->name,
-                       dev->pci_bus,
-                       dev->pci_slot);
-
-               err = -ENODEV;
-
-               /* dvb stuff */
-               /* We have to init the queue for each frontend on a port. */
-               printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
-               videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
-                           &dev->pci->dev, &port->slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
-                           sizeof(struct cx23885_buffer), port, NULL);
-       }
-       err = dvb_register(port);
-       if (err != 0)
-               printk(KERN_ERR "%s() dvb_register failed err = %d\n",
-                       __func__, err);
-
-       return err;
-}
-
-int cx23885_dvb_unregister(struct cx23885_tsport *port)
-{
-       struct videobuf_dvb_frontend *fe0;
-
-       /* FIXME: in an error condition where the we have
-        * an expected number of frontends (attach problem)
-        * then this might not clean up correctly, if 1
-        * is invalid.
-        * This comment only applies to future boards IF they
-        * implement MFE support.
-        */
-       fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
-       if (fe0 && fe0->dvb.frontend)
-               videobuf_dvb_unregister_bus(&port->frontends);
-
-       switch (port->dev->board) {
-       case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-               netup_ci_exit(port);
-               break;
-       case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
-               altera_ci_release(port->dev, port->nr);
-               break;
-       }
-
-       port->gate_ctrl = NULL;
-
-       return 0;
-}
-
diff --git a/drivers/media/video/cx23885/cx23885-f300.c b/drivers/media/video/cx23885/cx23885-f300.c
deleted file mode 100644 (file)
index 93998f2..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Driver for Silicon Labs C8051F300 microcontroller.
- *
- * It is used for LNB power control in TeVii S470,
- * TBS 6920 PCIe DVB-S2 cards.
- *
- * Microcontroller connected to cx23885 GPIO pins:
- * GPIO0 - data                - P0.3 F300
- * GPIO1 - reset       - P0.2 F300
- * GPIO2 - clk         - P0.1 F300
- * GPIO3 - busy                - P0.0 F300
- *
- * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
- *
- * 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 "cx23885.h"
-
-#define F300_DATA      GPIO_0
-#define F300_RESET     GPIO_1
-#define F300_CLK       GPIO_2
-#define F300_BUSY      GPIO_3
-
-static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
-{
-       cx23885_gpio_enable(dev, line, 1);
-       if (lvl == 1)
-               cx23885_gpio_set(dev, line);
-       else
-               cx23885_gpio_clear(dev, line);
-}
-
-static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
-{
-       cx23885_gpio_enable(dev, line, 0);
-
-       return cx23885_gpio_get(dev, line);
-}
-
-static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
-{
-       u8 i;
-
-       for (i = 0; i < 8; i++) {
-               f300_set_line(dev, F300_CLK, 0);
-               udelay(30);
-               f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
-               udelay(30);
-               dta <<= 1;
-               f300_set_line(dev, F300_CLK, 1);
-               udelay(30);
-       }
-}
-
-static u8 f300_get_byte(struct cx23885_dev *dev)
-{
-       u8 i, dta = 0;
-
-       for (i = 0; i < 8; i++) {
-               f300_set_line(dev, F300_CLK, 0);
-               udelay(30);
-               dta <<= 1;
-               f300_set_line(dev, F300_CLK, 1);
-               udelay(30);
-               dta |= f300_get_line(dev, F300_DATA);/* msb first */
-
-       }
-
-       return dta;
-}
-
-static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
-{
-       struct cx23885_tsport *port = fe->dvb->priv;
-       struct cx23885_dev *dev = port->dev;
-       u8 i, temp, ret = 0;
-
-       temp = buf[0];
-       for (i = 0; i < buf[0]; i++)
-               temp += buf[i + 1];
-       temp = (~temp + 1);/* get check sum */
-       buf[1 + buf[0]] = temp;
-
-       f300_set_line(dev, F300_RESET, 1);
-       f300_set_line(dev, F300_CLK, 1);
-       udelay(30);
-       f300_set_line(dev, F300_DATA, 1);
-       msleep(1);
-
-       /* question: */
-       f300_set_line(dev, F300_RESET, 0);/* begin to send data */
-       msleep(1);
-
-       f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
-       msleep(1);
-
-       temp = buf[0];
-       temp += 2;
-       for (i = 0; i < temp; i++)
-               f300_send_byte(dev, buf[i]);
-
-       f300_set_line(dev, F300_RESET, 1);/* sent data over */
-       f300_set_line(dev, F300_DATA, 1);
-
-       /* answer: */
-       temp = 0;
-       for (i = 0; ((i < 8) & (temp == 0)); i++) {
-               msleep(1);
-               if (f300_get_line(dev, F300_BUSY) == 0)
-                       temp = 1;
-       }
-
-       if (i > 7) {
-               printk(KERN_ERR "%s: timeout, the slave no response\n",
-                                                               __func__);
-               ret = 1; /* timeout, the slave no response */
-       } else { /* the slave not busy, prepare for getting data */
-               f300_set_line(dev, F300_RESET, 0);/*ready...*/
-               msleep(1);
-               f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
-               msleep(1);
-               temp = f300_get_byte(dev);/*get the data length */
-               if (temp > 14)
-                       temp = 14;
-
-               for (i = 0; i < (temp + 1); i++)
-                       f300_get_byte(dev);/* get data to empty buffer */
-
-               f300_set_line(dev, F300_RESET, 1);/* received data over */
-               f300_set_line(dev, F300_DATA, 1);
-       }
-
-       return ret;
-}
-
-int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-       u8 buf[16];
-
-       buf[0] = 0x05;
-       buf[1] = 0x38;/* write port */
-       buf[2] = 0x01;/* A port, lnb power */
-
-       switch (voltage) {
-       case SEC_VOLTAGE_13:
-               buf[3] = 0x01;/* power on */
-               buf[4] = 0x02;/* B port, H/V */
-               buf[5] = 0x00;/*13V v*/
-               break;
-       case SEC_VOLTAGE_18:
-               buf[3] = 0x01;
-               buf[4] = 0x02;
-               buf[5] = 0x01;/* 18V h*/
-               break;
-       case SEC_VOLTAGE_OFF:
-               buf[3] = 0x00;/* power off */
-               buf[4] = 0x00;
-               buf[5] = 0x00;
-               break;
-       }
-
-       return f300_xfer(fe, buf);
-}
diff --git a/drivers/media/video/cx23885/cx23885-f300.h b/drivers/media/video/cx23885/cx23885-f300.h
deleted file mode 100644 (file)
index e73344c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-extern int f300_set_voltage(struct dvb_frontend *fe,
-                               fe_sec_voltage_t voltage);
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
deleted file mode 100644 (file)
index 4887314..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-
-#include "cx23885.h"
-
-#include <media/v4l2-common.h>
-
-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;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-
-#define dprintk(level, fmt, arg...)\
-       do { if (i2c_debug >= level)\
-               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
-       } while (0)
-
-#define I2C_WAIT_DELAY 32
-#define I2C_WAIT_RETRY 64
-
-#define I2C_EXTEND  (1 << 3)
-#define I2C_NOSTOP  (1 << 4)
-
-static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
-{
-       struct cx23885_i2c *bus = i2c_adap->algo_data;
-       struct cx23885_dev *dev = bus->dev;
-       return cx_read(bus->reg_stat) & 0x01;
-}
-
-static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
-{
-       struct cx23885_i2c *bus = i2c_adap->algo_data;
-       struct cx23885_dev *dev = bus->dev;
-       return cx_read(bus->reg_stat) & 0x02 ? 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;
-}
-
-static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
-                        const struct i2c_msg *msg, int joined_rlen)
-{
-       struct cx23885_i2c *bus = i2c_adap->algo_data;
-       struct cx23885_dev *dev = bus->dev;
-       u32 wdata, addr, ctrl;
-       int retval, cnt;
-
-       if (joined_rlen)
-               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
-                       msg->len, joined_rlen);
-       else
-               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
-
-       /* Deal with i2c probe functions with zero payload */
-       if (msg->len == 0) {
-               cx_write(bus->reg_addr, msg->addr << 25);
-               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
-               if (!i2c_wait_done(i2c_adap))
-                       return -EIO;
-               if (!i2c_slave_did_ack(i2c_adap))
-                       return -ENXIO;
-
-               dprintk(1, "%s() returns 0\n", __func__);
-               return 0;
-       }
-
-
-       /* dev, reg + first byte */
-       addr = (msg->addr << 25) | msg->buf[0];
-       wdata = msg->buf[0];
-       ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
-
-       if (msg->len > 1)
-               ctrl |= I2C_NOSTOP | I2C_EXTEND;
-       else if (joined_rlen)
-               ctrl |= I2C_NOSTOP;
-
-       cx_write(bus->reg_addr, addr);
-       cx_write(bus->reg_wdata, wdata);
-       cx_write(bus->reg_ctrl, ctrl);
-
-       if (!i2c_wait_done(i2c_adap))
-               goto eio;
-       if (i2c_debug) {
-               printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
-               if (!(ctrl & I2C_NOSTOP))
-                       printk(" >\n");
-       }
-
-       for (cnt = 1; cnt < msg->len; cnt++) {
-               /* following bytes */
-               wdata = msg->buf[cnt];
-               ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
-
-               if (cnt < msg->len - 1)
-                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
-               else if (joined_rlen)
-                       ctrl |= I2C_NOSTOP;
-
-               cx_write(bus->reg_addr, addr);
-               cx_write(bus->reg_wdata, wdata);
-               cx_write(bus->reg_ctrl, ctrl);
-
-               if (!i2c_wait_done(i2c_adap))
-                       goto eio;
-               if (i2c_debug) {
-                       dprintk(1, " %02x", msg->buf[cnt]);
-                       if (!(ctrl & I2C_NOSTOP))
-                               dprintk(1, " >\n");
-               }
-       }
-       return msg->len;
-
- eio:
-       retval = -EIO;
-       if (i2c_debug)
-               printk(KERN_ERR " ERR: %d\n", retval);
-       return retval;
-}
-
-static int i2c_readbytes(struct i2c_adapter *i2c_adap,
-                        const struct i2c_msg *msg, int joined)
-{
-       struct cx23885_i2c *bus = i2c_adap->algo_data;
-       struct cx23885_dev *dev = bus->dev;
-       u32 ctrl, cnt;
-       int retval;
-
-
-       if (i2c_debug && !joined)
-               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
-
-       /* Deal with i2c probe functions with zero payload */
-       if (msg->len == 0) {
-               cx_write(bus->reg_addr, msg->addr << 25);
-               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
-               if (!i2c_wait_done(i2c_adap))
-                       return -EIO;
-               if (!i2c_slave_did_ack(i2c_adap))
-                       return -ENXIO;
-
-
-               dprintk(1, "%s() returns 0\n", __func__);
-               return 0;
-       }
-
-       if (i2c_debug) {
-               if (joined)
-                       dprintk(1, " R");
-               else
-                       dprintk(1, " <R %02x", (msg->addr << 1) + 1);
-       }
-
-       for (cnt = 0; cnt < msg->len; cnt++) {
-
-               ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
-
-               if (cnt < msg->len - 1)
-                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
-
-               cx_write(bus->reg_addr, msg->addr << 25);
-               cx_write(bus->reg_ctrl, ctrl);
-
-               if (!i2c_wait_done(i2c_adap))
-                       goto eio;
-               msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
-               if (i2c_debug) {
-                       dprintk(1, " %02x", msg->buf[cnt]);
-                       if (!(ctrl & I2C_NOSTOP))
-                               dprintk(1, " >\n");
-               }
-       }
-       return msg->len;
-
- eio:
-       retval = -EIO;
-       if (i2c_debug)
-               printk(KERN_ERR " ERR: %d\n", retval);
-       return retval;
-}
-
-static int i2c_xfer(struct i2c_adapter *i2c_adap,
-                   struct i2c_msg *msgs, int num)
-{
-       struct cx23885_i2c *bus = i2c_adap->algo_data;
-       struct cx23885_dev *dev = bus->dev;
-       int i, retval = 0;
-
-       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",
-                       __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 u32 cx23885_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm cx23885_i2c_algo_template = {
-       .master_xfer    = i2c_xfer,
-       .functionality  = cx23885_functionality,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_adapter cx23885_i2c_adap_template = {
-       .name              = "cx23885",
-       .owner             = THIS_MODULE,
-       .algo              = &cx23885_i2c_algo_template,
-};
-
-static struct i2c_client cx23885_i2c_client_template = {
-       .name   = "cx23885 internal",
-};
-
-static char *i2c_devs[128] = {
-       [0x10 >> 1] = "tda10048",
-       [0x12 >> 1] = "dib7000pc",
-       [0x1c >> 1] = "lgdt3303",
-       [0x86 >> 1] = "tda9887",
-       [0x32 >> 1] = "cx24227",
-       [0x88 >> 1] = "cx25837",
-       [0x84 >> 1] = "tda8295",
-       [0x98 >> 1] = "flatiron",
-       [0xa0 >> 1] = "eeprom",
-       [0xc0 >> 1] = "tuner/mt2131/tda8275",
-       [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
-       [0xc8 >> 1] = "tuner/xc3028L",
-};
-
-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 adapter */
-int cx23885_i2c_register(struct cx23885_i2c *bus)
-{
-       struct cx23885_dev *dev = bus->dev;
-
-       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
-
-       bus->i2c_adap = cx23885_i2c_adap_template;
-       bus->i2c_client = cx23885_i2c_client_template;
-       bus->i2c_adap.dev.parent = &dev->pci->dev;
-
-       strlcpy(bus->i2c_adap.name, bus->dev->name,
-               sizeof(bus->i2c_adap.name));
-
-       bus->i2c_adap.algo_data = bus;
-       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
-       i2c_add_adapter(&bus->i2c_adap);
-
-       bus->i2c_client.adapter = &bus->i2c_adap;
-
-       if (0 == bus->i2c_rc) {
-               dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
-               if (i2c_scan) {
-                       printk(KERN_INFO "%s: scan bus %d:\n",
-                                       dev->name, bus->nr);
-                       do_i2c_scan(dev->name, &bus->i2c_client);
-               }
-       } else
-               printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
-                       dev->name, bus->nr);
-
-       /* Instantiate the IR receiver device, if present */
-       if (0 == bus->i2c_rc) {
-               struct i2c_board_info info;
-               const unsigned short addr_list[] = {
-                       0x6b, I2C_CLIENT_END
-               };
-
-               memset(&info, 0, sizeof(struct i2c_board_info));
-               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-               /* Use quick read command for probe, some IR chips don't
-                * support writes */
-               i2c_new_probed_device(&bus->i2c_adap, &info, addr_list,
-                                     i2c_probe_func_quick_read);
-       }
-
-       return bus->i2c_rc;
-}
-
-int cx23885_i2c_unregister(struct cx23885_i2c *bus)
-{
-       i2c_del_adapter(&bus->i2c_adap);
-       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);
-}
-
-/* ----------------------------------------------------------------------- */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
deleted file mode 100644 (file)
index 5606672..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  Infrared remote control input device
- *
- *  Most of this file is
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
- *
- *  However, the cx23885_input_{init,fini} functions contained herein are
- *  derived from Linux kernel files linux/media/video/.../...-input.c marked as:
- *
- *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
- *  Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
- *                    Markus Rechberger <mrechberger@gmail.com>
- *                    Mauro Carvalho Chehab <mchehab@infradead.org>
- *                    Sascha Sommer <saschasommer@freenet.de>
- *  Copyright (C) 2004, 2005 Chris Pascoe
- *  Copyright (C) 2003, 2004 Gerd Knorr
- *  Copyright (C) 2003 Pavel Machek
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include <linux/slab.h>
-#include <media/rc-core.h>
-#include <media/v4l2-subdev.h>
-
-#include "cx23885.h"
-
-#define MODULE_NAME "cx23885"
-
-static void cx23885_input_process_measurements(struct cx23885_dev *dev,
-                                              bool overrun)
-{
-       struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
-
-       ssize_t num;
-       int count, i;
-       bool handle = false;
-       struct ir_raw_event ir_core_event[64];
-
-       do {
-               num = 0;
-               v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
-                                sizeof(ir_core_event), &num);
-
-               count = num / sizeof(struct ir_raw_event);
-
-               for (i = 0; i < count; i++) {
-                       ir_raw_event_store(kernel_ir->rc,
-                                          &ir_core_event[i]);
-                       handle = true;
-               }
-       } while (num != 0);
-
-       if (overrun)
-               ir_raw_event_reset(kernel_ir->rc);
-       else if (handle)
-               ir_raw_event_handle(kernel_ir->rc);
-}
-
-void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
-{
-       struct v4l2_subdev_ir_parameters params;
-       int overrun, data_available;
-
-       if (dev->sd_ir == NULL || events == 0)
-               return;
-
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-       case CX23885_BOARD_TEVII_S470:
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               /*
-                * The only boards we handle right now.  However other boards
-                * using the CX2388x integrated IR controller should be similar
-                */
-               break;
-       default:
-               return;
-       }
-
-       overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN |
-                           V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN);
-
-       data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED |
-                                  V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ);
-
-       if (overrun) {
-               /* If there was a FIFO overrun, stop the device */
-               v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
-               params.enable = false;
-               /* Mitigate race with cx23885_input_ir_stop() */
-               params.shutdown = atomic_read(&dev->ir_input_stopping);
-               v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
-       }
-
-       if (data_available)
-               cx23885_input_process_measurements(dev, overrun);
-
-       if (overrun) {
-               /* If there was a FIFO overrun, clear & restart the device */
-               params.enable = true;
-               /* Mitigate race with cx23885_input_ir_stop() */
-               params.shutdown = atomic_read(&dev->ir_input_stopping);
-               v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
-       }
-}
-
-static int cx23885_input_ir_start(struct cx23885_dev *dev)
-{
-       struct v4l2_subdev_ir_parameters params;
-
-       if (dev->sd_ir == NULL)
-               return -ENODEV;
-
-       atomic_set(&dev->ir_input_stopping, 0);
-
-       v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               /*
-                * The IR controller on this board only returns pulse widths.
-                * Any other mode setting will fail to set up the device.
-               */
-               params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
-               params.enable = true;
-               params.interrupt_enable = true;
-               params.shutdown = false;
-
-               /* Setup for baseband compatible with both RC-5 and RC-6A */
-               params.modulation = false;
-               /* RC-5:  2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/
-               /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/
-               params.max_pulse_width = 3333333; /* ns */
-               /* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
-               /* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
-               params.noise_filter_min_width = 333333; /* ns */
-               /*
-                * This board has inverted receive sense:
-                * mark is received as low logic level;
-                * falling edges are detected as rising edges; etc.
-                */
-               params.invert_level = true;
-               break;
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-       case CX23885_BOARD_TEVII_S470:
-               /*
-                * The IR controller on this board only returns pulse widths.
-                * Any other mode setting will fail to set up the device.
-                */
-               params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
-               params.enable = true;
-               params.interrupt_enable = true;
-               params.shutdown = false;
-
-               /* Setup for a standard NEC protocol */
-               params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
-               params.carrier_range_lower = 33000; /* Hz */
-               params.carrier_range_upper = 43000; /* Hz */
-               params.duty_cycle = 33; /* percent, 33 percent for NEC */
-
-               /*
-                * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
-                * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
-                */
-               params.max_pulse_width = 12378022; /* ns */
-
-               /*
-                * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
-                * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
-                */
-               params.noise_filter_min_width = 351648; /* ns */
-
-               params.modulation = false;
-               params.invert_level = true;
-               break;
-       }
-       v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
-       return 0;
-}
-
-static int cx23885_input_ir_open(struct rc_dev *rc)
-{
-       struct cx23885_kernel_ir *kernel_ir = rc->priv;
-
-       if (kernel_ir->cx == NULL)
-               return -ENODEV;
-
-       return cx23885_input_ir_start(kernel_ir->cx);
-}
-
-static void cx23885_input_ir_stop(struct cx23885_dev *dev)
-{
-       struct v4l2_subdev_ir_parameters params;
-
-       if (dev->sd_ir == NULL)
-               return;
-
-       /*
-        * Stop the sd_ir subdevice from generating notifications and
-        * scheduling work.
-        * It is shutdown this way in order to mitigate a race with
-        * cx23885_input_rx_work_handler() in the overrun case, which could
-        * re-enable the subdevice.
-        */
-       atomic_set(&dev->ir_input_stopping, 1);
-       v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
-       while (params.shutdown == false) {
-               params.enable = false;
-               params.interrupt_enable = false;
-               params.shutdown = true;
-               v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
-               v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
-       }
-       flush_work_sync(&dev->cx25840_work);
-       flush_work_sync(&dev->ir_rx_work);
-       flush_work_sync(&dev->ir_tx_work);
-}
-
-static void cx23885_input_ir_close(struct rc_dev *rc)
-{
-       struct cx23885_kernel_ir *kernel_ir = rc->priv;
-
-       if (kernel_ir->cx != NULL)
-               cx23885_input_ir_stop(kernel_ir->cx);
-}
-
-int cx23885_input_init(struct cx23885_dev *dev)
-{
-       struct cx23885_kernel_ir *kernel_ir;
-       struct rc_dev *rc;
-       char *rc_map;
-       enum rc_driver_type driver_type;
-       unsigned long allowed_protos;
-
-       int ret;
-
-       /*
-        * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't
-        * encapsulated in a v4l2_subdev, then I'm not going to deal with it.
-        */
-       if (dev->sd_ir == NULL)
-               return -ENODEV;
-
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1270:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-       case CX23885_BOARD_HAUPPAUGE_HVR1290:
-       case CX23885_BOARD_HAUPPAUGE_HVR1250:
-               /* Integrated CX2388[58] IR controller */
-               driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = RC_TYPE_ALL;
-               /* The grey Hauppauge RC-5 remote */
-               rc_map = RC_MAP_HAUPPAUGE;
-               break;
-       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
-               /* Integrated CX23885 IR controller */
-               driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = RC_TYPE_NEC;
-               /* The grey Terratec remote with orange buttons */
-               rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
-               break;
-       case CX23885_BOARD_TEVII_S470:
-               /* Integrated CX23885 IR controller */
-               driver_type = RC_DRIVER_IR_RAW;
-               allowed_protos = RC_TYPE_ALL;
-               /* A guess at the remote */
-               rc_map = RC_MAP_TEVII_NEC;
-               break;
-       default:
-               return -ENODEV;
-       }
-
-       /* cx23885 board instance kernel IR state */
-       kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
-       if (kernel_ir == NULL)
-               return -ENOMEM;
-
-       kernel_ir->cx = dev;
-       kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
-                                   cx23885_boards[dev->board].name);
-       kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
-                                   pci_name(dev->pci));
-
-       /* input device */
-       rc = rc_allocate_device();
-       if (!rc) {
-               ret = -ENOMEM;
-               goto err_out_free;
-       }
-
-       kernel_ir->rc = rc;
-       rc->input_name = kernel_ir->name;
-       rc->input_phys = kernel_ir->phys;
-       rc->input_id.bustype = BUS_PCI;
-       rc->input_id.version = 1;
-       if (dev->pci->subsystem_vendor) {
-               rc->input_id.vendor  = dev->pci->subsystem_vendor;
-               rc->input_id.product = dev->pci->subsystem_device;
-       } else {
-               rc->input_id.vendor  = dev->pci->vendor;
-               rc->input_id.product = dev->pci->device;
-       }
-       rc->dev.parent = &dev->pci->dev;
-       rc->driver_type = driver_type;
-       rc->allowed_protos = allowed_protos;
-       rc->priv = kernel_ir;
-       rc->open = cx23885_input_ir_open;
-       rc->close = cx23885_input_ir_close;
-       rc->map_name = rc_map;
-       rc->driver_name = MODULE_NAME;
-
-       /* Go */
-       dev->kernel_ir = kernel_ir;
-       ret = rc_register_device(rc);
-       if (ret)
-               goto err_out_stop;
-
-       return 0;
-
-err_out_stop:
-       cx23885_input_ir_stop(dev);
-       dev->kernel_ir = NULL;
-       rc_free_device(rc);
-err_out_free:
-       kfree(kernel_ir->phys);
-       kfree(kernel_ir->name);
-       kfree(kernel_ir);
-       return ret;
-}
-
-void cx23885_input_fini(struct cx23885_dev *dev)
-{
-       /* Always stop the IR hardware from generating interrupts */
-       cx23885_input_ir_stop(dev);
-
-       if (dev->kernel_ir == NULL)
-               return;
-       rc_unregister_device(dev->kernel_ir->rc);
-       kfree(dev->kernel_ir->phys);
-       kfree(dev->kernel_ir->name);
-       kfree(dev->kernel_ir);
-       dev->kernel_ir = NULL;
-}
diff --git a/drivers/media/video/cx23885/cx23885-input.h b/drivers/media/video/cx23885/cx23885-input.h
deleted file mode 100644 (file)
index 75ef15d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  Infrared remote control input device
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#ifndef _CX23885_INPUT_H_
-#define _CX23885_INPUT_H_
-int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
-
-int cx23885_input_init(struct cx23885_dev *dev);
-void cx23885_input_fini(struct cx23885_dev *dev);
-#endif
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.c b/drivers/media/video/cx23885/cx23885-ioctl.c
deleted file mode 100644 (file)
index 44812ca..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  Various common ioctl() support functions
- *
- *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.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 "cx23885.h"
-#include <media/v4l2-chip-ident.h>
-
-int cx23885_g_chip_ident(struct file *file, void *fh,
-                        struct v4l2_dbg_chip_ident *chip)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-       int err = 0;
-       u8 rev;
-
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-       switch (chip->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               switch (chip->match.addr) {
-               case 0:
-                       rev = cx_read(RDR_CFG2) & 0xff;
-                       switch (dev->pci->device) {
-                       case 0x8852:
-                               /* rev 0x04 could be '885 or '888. Pick '888. */
-                               if (rev == 0x04)
-                                       chip->ident = V4L2_IDENT_CX23888;
-                               else
-                                       chip->ident = V4L2_IDENT_CX23885;
-                               break;
-                       case 0x8880:
-                               if (rev == 0x0e || rev == 0x0f)
-                                       chip->ident = V4L2_IDENT_CX23887;
-                               else
-                                       chip->ident = V4L2_IDENT_CX23888;
-                               break;
-                       default:
-                               chip->ident = V4L2_IDENT_UNKNOWN;
-                               break;
-                       }
-                       chip->revision = (dev->pci->device << 16) | (rev << 8) |
-                                        (dev->hwrevision & 0xff);
-                       break;
-               case 1:
-                       if (dev->v4l_device != NULL) {
-                               chip->ident = V4L2_IDENT_CX23417;
-                               chip->revision = 0;
-                       }
-                       break;
-               case 2:
-                       /*
-                        * The integrated IR controller on the CX23888 is
-                        * host chip 2.  It may not be used/initialized or sd_ir
-                        * may be pointing at the cx25840 subdevice for the
-                        * IR controller on the CX23885.  Thus we find it
-                        * without using the dev->sd_ir pointer.
-                        */
-                       call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident,
-                               chip);
-                       break;
-               default:
-                       err = -EINVAL; /* per V4L2 spec */
-                       break;
-               }
-               break;
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               /* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
-               call_all(dev, core, g_chip_ident, chip);
-               break;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               /*
-                * We could return V4L2_IDENT_UNKNOWN, but we don't do the work
-                * to look if a chip is at the address with no driver.  That's a
-                * dangerous thing to do with EEPROMs anyway.
-                */
-               call_all(dev, core, g_chip_ident, chip);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-       return err;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx23885_g_host_register(struct cx23885_dev *dev,
-                                  struct v4l2_dbg_register *reg)
-{
-       if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
-               return -EINVAL;
-
-       reg->size = 4;
-       reg->val = cx_read(reg->reg);
-       return 0;
-}
-
-static int cx23417_g_register(struct cx23885_dev *dev,
-                             struct v4l2_dbg_register *reg)
-{
-       u32 value;
-
-       if (dev->v4l_device == NULL)
-               return -EINVAL;
-
-       if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
-               return -EINVAL;
-
-       if (mc417_register_read(dev, (u16) reg->reg, &value))
-               return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
-
-       reg->size = 4;
-       reg->val = value;
-       return 0;
-}
-
-int cx23885_g_register(struct file *file, void *fh,
-                      struct v4l2_dbg_register *reg)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
-               switch (reg->match.addr) {
-               case 0:
-                       return cx23885_g_host_register(dev, reg);
-               case 1:
-                       return cx23417_g_register(dev, reg);
-               default:
-                       break;
-               }
-       }
-
-       /* FIXME - any error returns should not be ignored */
-       call_all(dev, core, g_register, reg);
-       return 0;
-}
-
-static int cx23885_s_host_register(struct cx23885_dev *dev,
-                                  struct v4l2_dbg_register *reg)
-{
-       if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
-               return -EINVAL;
-
-       reg->size = 4;
-       cx_write(reg->reg, reg->val);
-       return 0;
-}
-
-static int cx23417_s_register(struct cx23885_dev *dev,
-                             struct v4l2_dbg_register *reg)
-{
-       if (dev->v4l_device == NULL)
-               return -EINVAL;
-
-       if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
-               return -EINVAL;
-
-       if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
-               return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
-
-       reg->size = 4;
-       return 0;
-}
-
-int cx23885_s_register(struct file *file, void *fh,
-                      struct v4l2_dbg_register *reg)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
-               switch (reg->match.addr) {
-               case 0:
-                       return cx23885_s_host_register(dev, reg);
-               case 1:
-                       return cx23417_s_register(dev, reg);
-               default:
-                       break;
-               }
-       }
-
-       /* FIXME - any error returns should not be ignored */
-       call_all(dev, core, s_register, reg);
-       return 0;
-}
-#endif
diff --git a/drivers/media/video/cx23885/cx23885-ioctl.h b/drivers/media/video/cx23885/cx23885-ioctl.h
deleted file mode 100644 (file)
index 315be0c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  Various common ioctl() support functions
- *
- *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.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.
- */
-
-#ifndef _CX23885_IOCTL_H_
-#define _CX23885_IOCTL_H_
-
-int cx23885_g_chip_ident(struct file *file, void *fh,
-                        struct v4l2_dbg_chip_ident *chip);
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-int cx23885_g_register(struct file *file, void *fh,
-                      struct v4l2_dbg_register *reg);
-
-
-int cx23885_s_register(struct file *file, void *fh,
-                      struct v4l2_dbg_register *reg);
-
-#endif
-#endif
diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c
deleted file mode 100644 (file)
index 7125247..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  Infrared device support routines - non-input, non-vl42_subdev routines
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include <media/v4l2-device.h>
-
-#include "cx23885.h"
-#include "cx23885-input.h"
-
-#define CX23885_IR_RX_FIFO_SERVICE_REQ         0
-#define CX23885_IR_RX_END_OF_RX_DETECTED       1
-#define CX23885_IR_RX_HW_FIFO_OVERRUN          2
-#define CX23885_IR_RX_SW_FIFO_OVERRUN          3
-
-#define CX23885_IR_TX_FIFO_SERVICE_REQ         0
-
-
-void cx23885_ir_rx_work_handler(struct work_struct *work)
-{
-       struct cx23885_dev *dev =
-                            container_of(work, struct cx23885_dev, ir_rx_work);
-       u32 events = 0;
-       unsigned long *notifications = &dev->ir_rx_notifications;
-
-       if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
-               events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
-       if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
-               events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
-       if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
-               events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
-       if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
-               events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
-
-       if (events == 0)
-               return;
-
-       if (dev->kernel_ir)
-               cx23885_input_rx_work_handler(dev, events);
-}
-
-void cx23885_ir_tx_work_handler(struct work_struct *work)
-{
-       struct cx23885_dev *dev =
-                            container_of(work, struct cx23885_dev, ir_tx_work);
-       u32 events = 0;
-       unsigned long *notifications = &dev->ir_tx_notifications;
-
-       if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
-               events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
-
-       if (events == 0)
-               return;
-
-}
-
-/* Possibly called in an IRQ context */
-void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
-{
-       struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
-       unsigned long *notifications = &dev->ir_rx_notifications;
-
-       if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
-               set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
-       if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
-               set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
-       if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
-               set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
-       if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
-               set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
-
-       /*
-        * For the integrated AV core, we are already in a workqueue context.
-        * For the CX23888 integrated IR, we are in an interrupt context.
-        */
-       if (sd == dev->sd_cx25840)
-               cx23885_ir_rx_work_handler(&dev->ir_rx_work);
-       else
-               schedule_work(&dev->ir_rx_work);
-}
-
-/* Possibly called in an IRQ context */
-void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
-{
-       struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
-       unsigned long *notifications = &dev->ir_tx_notifications;
-
-       if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
-               set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
-
-       /*
-        * For the integrated AV core, we are already in a workqueue context.
-        * For the CX23888 integrated IR, we are in an interrupt context.
-        */
-       if (sd == dev->sd_cx25840)
-               cx23885_ir_tx_work_handler(&dev->ir_tx_work);
-       else
-               schedule_work(&dev->ir_tx_work);
-}
diff --git a/drivers/media/video/cx23885/cx23885-ir.h b/drivers/media/video/cx23885/cx23885-ir.h
deleted file mode 100644 (file)
index 0c9d8bd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  Infrared device support routines - non-input, non-vl42_subdev routines
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#ifndef _CX23885_IR_H_
-#define _CX23885_IR_H_
-void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
-void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
-
-void cx23885_ir_rx_work_handler(struct work_struct *work);
-void cx23885_ir_tx_work_handler(struct work_struct *work);
-#endif
diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h
deleted file mode 100644 (file)
index a99936e..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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 _CX23885_REG_H_
-#define _CX23885_REG_H_
-
-/*
-Address Map
-0x00000000 -> 0x00009000   TX SRAM  (Fifos)
-0x00010000 -> 0x00013c00   RX SRAM  CMDS + CDT
-
-EACH CMDS struct is 0x80 bytes long
-
-DMAx_PTR1 = 0x03040 address of first cluster
-DMAx_PTR2 = 0x10600 address of the CDT
-DMAx_CNT1 = cluster size in (bytes >> 4) -1
-DMAx_CNT2 = total cdt size for all entries >> 3
-
-Cluster Descriptor entry = 4 DWORDS
- DWORD 0 -> ptr to cluster
- DWORD 1 Reserved
- DWORD 2 Reserved
- DWORD 3 Reserved
-
-Channel manager Data Structure entry = 20 DWORD
-  0  IntialProgramCounterLow
-  1  IntialProgramCounterHigh
-  2  ClusterDescriptorTableBase
-  3  ClusterDescriptorTableSize
-  4  InstructionQueueBase
-  5  InstructionQueueSize
-...  Reserved
- 19  Reserved
-*/
-
-/* Risc Instructions */
-#define RISC_CNT_INC            0x00010000
-#define RISC_CNT_RESET          0x00030000
-#define RISC_IRQ1               0x01000000
-#define RISC_IRQ2               0x02000000
-#define RISC_EOL                0x04000000
-#define RISC_SOL                0x08000000
-#define RISC_WRITE              0x10000000
-#define RISC_SKIP               0x20000000
-#define RISC_JUMP               0x70000000
-#define RISC_SYNC               0x80000000
-#define RISC_RESYNC             0x80008000
-#define RISC_READ               0x90000000
-#define RISC_WRITERM            0xB0000000
-#define RISC_WRITECM            0xC0000000
-#define RISC_WRITECR            0xD0000000
-#define RISC_WRITEC             0x50000000
-#define RISC_READC              0xA0000000
-
-
-/* Audio and Video Core */
-#define HOST_REG1              0x00000000
-#define HOST_REG2              0x00000001
-#define HOST_REG3              0x00000002
-
-/* Chip Configuration Registers */
-#define CHIP_CTRL              0x00000100
-#define AFE_CTRL               0x00000104
-#define VID_PLL_INT_POST       0x00000108
-#define VID_PLL_FRAC           0x0000010C
-#define AUX_PLL_INT_POST       0x00000110
-#define AUX_PLL_FRAC           0x00000114
-#define SYS_PLL_INT_POST       0x00000118
-#define SYS_PLL_FRAC           0x0000011C
-#define PIN_CTRL               0x00000120
-#define AUD_IO_CTRL            0x00000124
-#define AUD_LOCK1              0x00000128
-#define AUD_LOCK2              0x0000012C
-#define POWER_CTRL             0x00000130
-#define AFE_DIAG_CTRL1         0x00000134
-#define AFE_DIAG_CTRL3         0x0000013C
-#define PLL_DIAG_CTRL          0x00000140
-#define AFE_CLK_OUT_CTRL       0x00000144
-#define DLL1_DIAG_CTRL         0x0000015C
-
-/* GPIO[23:19] Output Enable */
-#define GPIO2_OUT_EN_REG       0x00000160
-/* GPIO[23:19] Data Registers */
-#define GPIO2                  0x00000164
-
-#define IFADC_CTRL             0x00000180
-
-/* Infrared Remote Registers */
-#define IR_CNTRL_REG   0x00000200
-#define IR_TXCLK_REG   0x00000204
-#define IR_RXCLK_REG   0x00000208
-#define IR_CDUTY_REG   0x0000020C
-#define IR_STAT_REG    0x00000210
-#define IR_IRQEN_REG   0x00000214
-#define IR_FILTR_REG   0x00000218
-#define IR_FIFO_REG    0x0000023C
-
-/* Video Decoder Registers */
-#define MODE_CTRL              0x00000400
-#define OUT_CTRL1              0x00000404
-#define OUT_CTRL2              0x00000408
-#define GEN_STAT               0x0000040C
-#define INT_STAT_MASK          0x00000410
-#define LUMA_CTRL              0x00000414
-#define HSCALE_CTRL            0x00000418
-#define VSCALE_CTRL            0x0000041C
-#define CHROMA_CTRL            0x00000420
-#define VBI_LINE_CTRL1         0x00000424
-#define VBI_LINE_CTRL2         0x00000428
-#define VBI_LINE_CTRL3         0x0000042C
-#define VBI_LINE_CTRL4         0x00000430
-#define VBI_LINE_CTRL5         0x00000434
-#define VBI_FC_CFG             0x00000438
-#define VBI_MISC_CFG1          0x0000043C
-#define VBI_MISC_CFG2          0x00000440
-#define VBI_PAY1               0x00000444
-#define VBI_PAY2               0x00000448
-#define VBI_CUST1_CFG1         0x0000044C
-#define VBI_CUST1_CFG2         0x00000450
-#define VBI_CUST1_CFG3         0x00000454
-#define VBI_CUST2_CFG1         0x00000458
-#define VBI_CUST2_CFG2         0x0000045C
-#define VBI_CUST2_CFG3         0x00000460
-#define VBI_CUST3_CFG1         0x00000464
-#define VBI_CUST3_CFG2         0x00000468
-#define VBI_CUST3_CFG3         0x0000046C
-#define HORIZ_TIM_CTRL         0x00000470
-#define VERT_TIM_CTRL          0x00000474
-#define SRC_COMB_CFG           0x00000478
-#define CHROMA_VBIOFF_CFG      0x0000047C
-#define FIELD_COUNT            0x00000480
-#define MISC_TIM_CTRL          0x00000484
-#define DFE_CTRL1              0x00000488
-#define DFE_CTRL2              0x0000048C
-#define DFE_CTRL3              0x00000490
-#define PLL_CTRL               0x00000494
-#define HTL_CTRL               0x00000498
-#define COMB_CTRL              0x0000049C
-#define CRUSH_CTRL             0x000004A0
-#define SOFT_RST_CTRL          0x000004A4
-#define CX885_VERSION          0x000004B4
-#define VBI_PASS_CTRL          0x000004BC
-
-/* Audio Decoder Registers */
-/* 8051 Configuration */
-#define DL_CTL         0x00000800
-#define STD_DET_STATUS 0x00000804
-#define STD_DET_CTL    0x00000808
-#define DW8051_INT     0x0000080C
-#define GENERAL_CTL    0x00000810
-#define AAGC_CTL       0x00000814
-#define DEMATRIX_CTL   0x000008CC
-#define PATH1_CTL1     0x000008D0
-#define PATH1_VOL_CTL  0x000008D4
-#define PATH1_EQ_CTL   0x000008D8
-#define PATH1_SC_CTL   0x000008DC
-#define PATH2_CTL1     0x000008E0
-#define PATH2_VOL_CTL  0x000008E4
-#define PATH2_EQ_CTL   0x000008E8
-#define PATH2_SC_CTL   0x000008EC
-
-/* Sample Rate Converter */
-#define SRC_CTL                0x000008F0
-#define SRC_LF_COEF    0x000008F4
-#define SRC1_CTL       0x000008F8
-#define SRC2_CTL       0x000008FC
-#define SRC3_CTL       0x00000900
-#define SRC4_CTL       0x00000904
-#define SRC5_CTL       0x00000908
-#define SRC6_CTL       0x0000090C
-#define BAND_OUT_SEL   0x00000910
-#define I2S_N_CTL      0x00000914
-#define I2S_OUT_CTL    0x00000918
-#define AUTOCONFIG_REG 0x000009C4
-
-/* Audio ADC Registers */
-#define DSM_CTRL1      0x00000000
-#define DSM_CTRL2      0x00000001
-#define CHP_EN_CTRL    0x00000002
-#define CHP_CLK_CTRL1  0x00000004
-#define CHP_CLK_CTRL2  0x00000005
-#define BG_REF_CTRL    0x00000006
-#define SD2_SW_CTRL1   0x00000008
-#define SD2_SW_CTRL2   0x00000009
-#define SD2_BIAS_CTRL  0x0000000A
-#define AMP_BIAS_CTRL  0x0000000C
-#define CH_PWR_CTRL1   0x0000000E
-#define FLD_CH_SEL      (1 << 3)
-#define CH_PWR_CTRL2   0x0000000F
-#define DSM_STATUS1    0x00000010
-#define DSM_STATUS2    0x00000011
-#define DIG_CTL1       0x00000012
-#define DIG_CTL2       0x00000013
-#define I2S_TX_CFG     0x0000001A
-
-#define DEV_CNTRL2     0x00040000
-
-#define PCI_MSK_IR        (1 << 28)
-#define PCI_MSK_AV_CORE   (1 << 27)
-#define PCI_MSK_GPIO1     (1 << 24)
-#define PCI_MSK_GPIO0     (1 << 23)
-#define PCI_MSK_APB_DMA   (1 << 12)
-#define PCI_MSK_AL_WR     (1 << 11)
-#define PCI_MSK_AL_RD     (1 << 10)
-#define PCI_MSK_RISC_WR   (1 <<  9)
-#define PCI_MSK_RISC_RD   (1 <<  8)
-#define PCI_MSK_AUD_EXT   (1 <<  4)
-#define PCI_MSK_AUD_INT   (1 <<  3)
-#define PCI_MSK_VID_C     (1 <<  2)
-#define PCI_MSK_VID_B     (1 <<  1)
-#define PCI_MSK_VID_A      1
-#define PCI_INT_MSK    0x00040010
-
-#define PCI_INT_STAT   0x00040014
-#define PCI_INT_MSTAT  0x00040018
-
-#define VID_A_INT_MSK  0x00040020
-#define VID_A_INT_STAT 0x00040024
-#define VID_A_INT_MSTAT        0x00040028
-#define VID_A_INT_SSTAT        0x0004002C
-
-#define VID_B_INT_MSK  0x00040030
-#define VID_B_MSK_BAD_PKT     (1 << 20)
-#define VID_B_MSK_VBI_OPC_ERR (1 << 17)
-#define VID_B_MSK_OPC_ERR     (1 << 16)
-#define VID_B_MSK_VBI_SYNC    (1 << 13)
-#define VID_B_MSK_SYNC        (1 << 12)
-#define VID_B_MSK_VBI_OF      (1 <<  9)
-#define VID_B_MSK_OF          (1 <<  8)
-#define VID_B_MSK_VBI_RISCI2  (1 <<  5)
-#define VID_B_MSK_RISCI2      (1 <<  4)
-#define VID_B_MSK_VBI_RISCI1  (1 <<  1)
-#define VID_B_MSK_RISCI1       1
-#define VID_B_INT_STAT 0x00040034
-#define VID_B_INT_MSTAT        0x00040038
-#define VID_B_INT_SSTAT        0x0004003C
-
-#define VID_B_MSK_BAD_PKT (1 << 20)
-#define VID_B_MSK_OPC_ERR (1 << 16)
-#define VID_B_MSK_SYNC    (1 << 12)
-#define VID_B_MSK_OF      (1 <<  8)
-#define VID_B_MSK_RISCI2  (1 <<  4)
-#define VID_B_MSK_RISCI1   1
-
-#define VID_C_MSK_BAD_PKT (1 << 20)
-#define VID_C_MSK_OPC_ERR (1 << 16)
-#define VID_C_MSK_SYNC    (1 << 12)
-#define VID_C_MSK_OF      (1 <<  8)
-#define VID_C_MSK_RISCI2  (1 <<  4)
-#define VID_C_MSK_RISCI1   1
-
-/* A superset for testing purposes */
-#define VID_BC_MSK_BAD_PKT (1 << 20)
-#define VID_BC_MSK_OPC_ERR (1 << 16)
-#define VID_BC_MSK_SYNC    (1 << 12)
-#define VID_BC_MSK_OF      (1 <<  8)
-#define VID_BC_MSK_VBI_RISCI2 (1 <<  5)
-#define VID_BC_MSK_RISCI2  (1 <<  4)
-#define VID_BC_MSK_VBI_RISCI1 (1 <<  1)
-#define VID_BC_MSK_RISCI1   1
-
-#define VID_C_INT_MSK  0x00040040
-#define VID_C_INT_STAT 0x00040044
-#define VID_C_INT_MSTAT        0x00040048
-#define VID_C_INT_SSTAT        0x0004004C
-
-#define AUDIO_INT_INT_MSK      0x00040050
-#define AUDIO_INT_INT_STAT     0x00040054
-#define AUDIO_INT_INT_MSTAT    0x00040058
-#define AUDIO_INT_INT_SSTAT    0x0004005C
-
-#define AUDIO_EXT_INT_MSK      0x00040060
-#define AUDIO_EXT_INT_STAT     0x00040064
-#define AUDIO_EXT_INT_MSTAT    0x00040068
-#define AUDIO_EXT_INT_SSTAT    0x0004006C
-
-#define RDR_CFG0       0x00050000
-#define RDR_CFG1       0x00050004
-#define RDR_CFG2       0x00050008
-#define RDR_RDRCTL1    0x0005030c
-#define RDR_TLCTL0     0x00050318
-
-/* APB DMAC Current Buffer Pointer */
-#define DMA1_PTR1      0x00100000
-#define DMA2_PTR1      0x00100004
-#define DMA3_PTR1      0x00100008
-#define DMA4_PTR1      0x0010000C
-#define DMA5_PTR1      0x00100010
-#define DMA6_PTR1      0x00100014
-#define DMA7_PTR1      0x00100018
-#define DMA8_PTR1      0x0010001C
-
-/* APB DMAC Current Table Pointer */
-#define DMA1_PTR2      0x00100040
-#define DMA2_PTR2      0x00100044
-#define DMA3_PTR2      0x00100048
-#define DMA4_PTR2      0x0010004C
-#define DMA5_PTR2      0x00100050
-#define DMA6_PTR2      0x00100054
-#define DMA7_PTR2      0x00100058
-#define DMA8_PTR2      0x0010005C
-
-/* APB DMAC Buffer Limit */
-#define DMA1_CNT1      0x00100080
-#define DMA2_CNT1      0x00100084
-#define DMA3_CNT1      0x00100088
-#define DMA4_CNT1      0x0010008C
-#define DMA5_CNT1      0x00100090
-#define DMA6_CNT1      0x00100094
-#define DMA7_CNT1      0x00100098
-#define DMA8_CNT1      0x0010009C
-
-/* APB DMAC Table Size */
-#define DMA1_CNT2      0x001000C0
-#define DMA2_CNT2      0x001000C4
-#define DMA3_CNT2      0x001000C8
-#define DMA4_CNT2      0x001000CC
-#define DMA5_CNT2      0x001000D0
-#define DMA6_CNT2      0x001000D4
-#define DMA7_CNT2      0x001000D8
-#define DMA8_CNT2      0x001000DC
-
-/* Timer Counters */
-#define TM_CNT_LDW     0x00110000
-#define TM_CNT_UW      0x00110004
-#define TM_LMT_LDW     0x00110008
-#define TM_LMT_UW      0x0011000C
-
-/* GPIO */
-#define GP0_IO         0x00110010
-#define GPIO_ISM       0x00110014
-#define SOFT_RESET     0x0011001C
-
-/* GPIO (417 Microsoftcontroller) RW Data */
-#define MC417_RWD      0x00110020
-
-/* GPIO (417 Microsoftcontroller) Output Enable, Low Active */
-#define MC417_OEN      0x00110024
-#define MC417_CTL      0x00110028
-#define ALT_PIN_OUT_SEL 0x0011002C
-#define CLK_DELAY      0x00110048
-#define PAD_CTRL       0x0011004C
-
-/* Video A Interface */
-#define VID_A_GPCNT            0x00130020
-#define VBI_A_GPCNT            0x00130024
-#define VID_A_GPCNT_CTL                0x00130030
-#define VBI_A_GPCNT_CTL                0x00130034
-#define VID_A_DMA_CTL          0x00130040
-#define VID_A_VIP_CTRL         0x00130080
-#define VID_A_PIXEL_FRMT       0x00130084
-#define VID_A_VBI_CTRL         0x00130088
-
-/* Video B Interface */
-#define VID_B_DMA              0x00130100
-#define VBI_B_DMA              0x00130108
-#define VID_B_GPCNT            0x00130120
-#define VBI_B_GPCNT            0x00130124
-#define VID_B_GPCNT_CTL                0x00130134
-#define VBI_B_GPCNT_CTL                0x00130138
-#define VID_B_DMA_CTL          0x00130140
-#define VID_B_SRC_SEL          0x00130144
-#define VID_B_LNGTH            0x00130150
-#define VID_B_HW_SOP_CTL       0x00130154
-#define VID_B_GEN_CTL          0x00130158
-#define VID_B_BD_PKT_STATUS    0x0013015C
-#define VID_B_SOP_STATUS       0x00130160
-#define VID_B_FIFO_OVFL_STAT   0x00130164
-#define VID_B_VLD_MISC         0x00130168
-#define VID_B_TS_CLK_EN                0x0013016C
-#define VID_B_VIP_CTRL         0x00130180
-#define VID_B_PIXEL_FRMT       0x00130184
-
-/* Video C Interface */
-#define VID_C_GPCNT            0x00130220
-#define VID_C_GPCNT_CTL                0x00130230
-#define VBI_C_GPCNT_CTL                0x00130234
-#define VID_C_DMA_CTL          0x00130240
-#define VID_C_LNGTH            0x00130250
-#define VID_C_HW_SOP_CTL       0x00130254
-#define VID_C_GEN_CTL          0x00130258
-#define VID_C_BD_PKT_STATUS    0x0013025C
-#define VID_C_SOP_STATUS       0x00130260
-#define VID_C_FIFO_OVFL_STAT   0x00130264
-#define VID_C_VLD_MISC         0x00130268
-#define VID_C_TS_CLK_EN                0x0013026C
-
-/* Internal Audio Interface */
-#define AUD_INT_A_GPCNT                0x00140020
-#define AUD_INT_B_GPCNT                0x00140024
-#define AUD_INT_A_GPCNT_CTL    0x00140030
-#define AUD_INT_B_GPCNT_CTL    0x00140034
-#define AUD_INT_DMA_CTL                0x00140040
-#define AUD_INT_A_LNGTH                0x00140050
-#define AUD_INT_B_LNGTH                0x00140054
-#define AUD_INT_A_MODE         0x00140058
-#define AUD_INT_B_MODE         0x0014005C
-
-/* External Audio Interface */
-#define AUD_EXT_DMA            0x00140100
-#define AUD_EXT_GPCNT          0x00140120
-#define AUD_EXT_GPCNT_CTL      0x00140130
-#define AUD_EXT_DMA_CTL                0x00140140
-#define AUD_EXT_LNGTH          0x00140150
-#define AUD_EXT_A_MODE         0x00140158
-
-/* I2C Bus 1 */
-#define I2C1_ADDR      0x00180000
-#define I2C1_WDATA     0x00180004
-#define I2C1_CTRL      0x00180008
-#define I2C1_RDATA     0x0018000C
-#define I2C1_STAT      0x00180010
-
-/* I2C Bus 2 */
-#define I2C2_ADDR      0x00190000
-#define I2C2_WDATA     0x00190004
-#define I2C2_CTRL      0x00190008
-#define I2C2_RDATA     0x0019000C
-#define I2C2_STAT      0x00190010
-
-/* I2C Bus 3 */
-#define I2C3_ADDR      0x001A0000
-#define I2C3_WDATA     0x001A0004
-#define I2C3_CTRL      0x001A0008
-#define I2C3_RDATA     0x001A000C
-#define I2C3_STAT      0x001A0010
-
-/* UART */
-#define UART_CTL       0x001B0000
-#define UART_BRD       0x001B0004
-#define UART_ISR       0x001B000C
-#define UART_CNT       0x001B0010
-
-#endif /* _CX23885_REG_H_ */
diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c
deleted file mode 100644 (file)
index a1154f0..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2007 Steven Toth <stoth@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>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-
-#include "cx23885.h"
-
-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;
-module_param(vbi_debug, int, 0644);
-MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
-
-#define dprintk(level, fmt, arg...)\
-       do { if (vbi_debug >= level)\
-               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
-       } while (0)
-
-/* ------------------------------------------------------------------ */
-
-#define VBI_LINE_LENGTH 1440
-#define NTSC_VBI_START_LINE 10        /* line 10 - 21 */
-#define NTSC_VBI_END_LINE   21
-#define NTSC_VBI_LINES      (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
-
-
-int cx23885_vbi_fmt(struct file *file, void *priv,
-       struct v4l2_format *f)
-{
-       struct cx23885_fh *fh = priv;
-       struct cx23885_dev *dev = fh->dev;
-
-       if (dev->tvnorm & V4L2_STD_525_60) {
-               /* ntsc */
-               f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
-               f->fmt.vbi.sampling_rate = 27000000;
-               f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-               f->fmt.vbi.offset = 0;
-               f->fmt.vbi.flags = 0;
-               f->fmt.vbi.start[0] = 10;
-               f->fmt.vbi.count[0] = 17;
-               f->fmt.vbi.start[1] = 263 + 10 + 1;
-               f->fmt.vbi.count[1] = 17;
-       } else if (dev->tvnorm & V4L2_STD_625_50) {
-               /* pal */
-               f->fmt.vbi.sampling_rate = 35468950;
-               f->fmt.vbi.start[0] = 7 - 1;
-               f->fmt.vbi.start[1] = 319 - 1;
-       }
-
-       return 0;
-}
-
-/* We're given the Video Interrupt status register.
- * The cx23885_video_irq() func has already validated
- * the potential error bits, we just need to
- * deal with vbi payload and return indication if
- * we actually processed any payload.
- */
-int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
-{
-       u32 count;
-       int handled = 0;
-
-       if (status & VID_BC_MSK_VBI_RISCI1) {
-               dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
-               spin_lock(&dev->slock);
-               count = cx_read(VID_A_GPCNT);
-               cx23885_video_wakeup(dev, &dev->vbiq, count);
-               spin_unlock(&dev->slock);
-               handled++;
-       }
-
-       if (status & VID_BC_MSK_VBI_RISCI2) {
-               dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
-               dprintk(2, "stopper vbi\n");
-               spin_lock(&dev->slock);
-               cx23885_restart_vbi_queue(dev, &dev->vbiq);
-               spin_unlock(&dev->slock);
-               handled++;
-       }
-
-       return handled;
-}
-
-static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
-                        struct cx23885_dmaqueue *q,
-                        struct cx23885_buffer   *buf)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       /* setup fifo + format */
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
-                               buf->vb.width, buf->risc.dma);
-
-       /* reset counter */
-       cx_write(VID_A_GPCNT_CTL, 3);
-       cx_write(VID_A_VBI_CTRL, 3);
-       cx_write(VBI_A_GPCNT_CTL, 3);
-       q->count = 1;
-
-       /* enable irq */
-       cx23885_irq_add_enable(dev, 0x01);
-       cx_set(VID_A_INT_MSK, 0x000022);
-
-       /* start dma */
-       cx_set(DEV_CNTRL2, (1<<5));
-       cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
-
-       return 0;
-}
-
-
-int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
-                            struct cx23885_dmaqueue *q)
-{
-       struct cx23885_buffer *buf;
-       struct list_head *item;
-
-       if (list_empty(&q->active))
-               return 0;
-
-       buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
-       dprintk(2, "restart_queue [%p/%d]: restart dma\n",
-               buf, buf->vb.i);
-       cx23885_start_vbi_dma(dev, q, buf);
-       list_for_each(item, &q->active) {
-               buf = list_entry(item, struct cx23885_buffer, vb.queue);
-               buf->count = q->count++;
-       }
-       mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
-       return 0;
-}
-
-void cx23885_vbi_timeout(unsigned long data)
-{
-       struct cx23885_dev *dev = (struct cx23885_dev *)data;
-       struct cx23885_dmaqueue *q = &dev->vbiq;
-       struct cx23885_buffer *buf;
-       unsigned long flags;
-
-       /* Stop the VBI engine */
-       cx_clear(VID_A_DMA_CTL, 0x22);
-
-       spin_lock_irqsave(&dev->slock, flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx23885_buffer,
-                       vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->name,
-                      buf, buf->vb.i, (unsigned long)buf->risc.dma);
-       }
-       cx23885_restart_vbi_queue(dev, q);
-       spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-/* ------------------------------------------------------------------ */
-#define VBI_LINE_LENGTH 1440
-#define VBI_LINE_COUNT 17
-
-static int
-vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
-       if (0 == *count)
-               *count = vbibufs;
-       if (*count < 2)
-               *count = 2;
-       if (*count > 32)
-               *count = 32;
-       return 0;
-}
-
-static int
-vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-           enum v4l2_field field)
-{
-       struct cx23885_fh *fh  = q->priv_data;
-       struct cx23885_dev *dev = fh->dev;
-       struct cx23885_buffer *buf = container_of(vb,
-               struct cx23885_buffer, vb);
-       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-       unsigned int size;
-       int rc;
-
-       size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               buf->vb.width  = VBI_LINE_LENGTH;
-               buf->vb.height = VBI_LINE_COUNT;
-               buf->vb.size   = size;
-               buf->vb.field  = V4L2_FIELD_SEQ_TB;
-
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (0 != rc)
-                       goto fail;
-               cx23885_risc_vbibuffer(dev->pci, &buf->risc,
-                                dma->sglist,
-                                0, buf->vb.width * buf->vb.height,
-                                buf->vb.width, 0,
-                                buf->vb.height);
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       cx23885_free_buffer(q, buf);
-       return rc;
-}
-
-static void
-vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx23885_buffer   *buf =
-               container_of(vb, struct cx23885_buffer, vb);
-       struct cx23885_buffer   *prev;
-       struct cx23885_fh       *fh   = vq->priv_data;
-       struct cx23885_dev      *dev  = fh->dev;
-       struct cx23885_dmaqueue *q    = &dev->vbiq;
-
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
-       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
-
-       if (list_empty(&q->active)) {
-               list_add_tail(&buf->vb.queue, &q->active);
-               cx23885_start_vbi_dma(dev, q, buf);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = q->count++;
-               mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
-               dprintk(2, "[%p/%d] vbi_queue - first active\n",
-                       buf, buf->vb.i);
-
-       } else {
-               prev = list_entry(q->active.prev, struct cx23885_buffer,
-                       vb.queue);
-               list_add_tail(&buf->vb.queue, &q->active);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = q->count++;
-               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-               prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63-32 */
-               dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-                       buf, buf->vb.i);
-       }
-}
-
-static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx23885_buffer *buf =
-               container_of(vb, struct cx23885_buffer, vb);
-
-       cx23885_free_buffer(q, buf);
-}
-
-struct videobuf_queue_ops cx23885_vbi_qops = {
-       .buf_setup    = vbi_setup,
-       .buf_prepare  = vbi_prepare,
-       .buf_queue    = vbi_queue,
-       .buf_release  = vbi_release,
-};
-
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c
deleted file mode 100644 (file)
index 22f8e7f..0000000
+++ /dev/null
@@ -1,1926 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2007 Steven Toth <stoth@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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <asm/div64.h>
-
-#include "cx23885.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include "cx23885-ioctl.h"
-#include "tuner-xc2028.h"
-
-#include <media/cx25840.h>
-
-MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
-MODULE_LICENSE("GPL");
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int video_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[]   = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(vbi_nr,   int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-
-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;
-module_param(video_debug, int, 0644);
-MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
-
-static unsigned int irq_debug;
-module_param(irq_debug, int, 0644);
-MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
-
-static unsigned int vid_limit = 16;
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
-
-#define dprintk(level, fmt, arg...)\
-       do { if (video_debug >= level)\
-               printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
-       } while (0)
-
-/* ------------------------------------------------------------------- */
-/* static data                                                         */
-
-#define FORMAT_FLAGS_PACKED       0x01
-#if 0
-static struct cx23885_fmt formats[] = {
-       {
-               .name     = "8 bpp, gray",
-               .fourcc   = V4L2_PIX_FMT_GREY,
-               .depth    = 8,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "15 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB555,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "15 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB555X,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "16 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB565,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "16 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB565X,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "24 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR24,
-               .depth    = 24,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "32 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR32,
-               .depth    = 32,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "32 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB32,
-               .depth    = 32,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "4:2:2, packed, YUYV",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-               .name     = "4:2:2, packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },
-};
-#else
-static struct cx23885_fmt formats[] = {
-       {
-#if 0
-               .name     = "4:2:2, packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }, {
-#endif
-               .name     = "4:2:2, packed, YUYV",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       }
-};
-#endif
-
-static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(formats); i++)
-               if (formats[i].fourcc == fourcc)
-                       return formats+i;
-
-       printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
-               (fourcc & 0xff),
-               ((fourcc >> 8) & 0xff),
-               ((fourcc >> 16) & 0xff),
-               ((fourcc >> 24) & 0xff)
-               );
-       return NULL;
-}
-
-/* ------------------------------------------------------------------- */
-
-static const struct v4l2_queryctrl no_ctl = {
-       .name  = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-static struct cx23885_ctrl cx23885_ctls[] = {
-       /* --- video --- */
-       {
-               .v = {
-                       .id            = V4L2_CID_BRIGHTNESS,
-                       .name          = "Brightness",
-                       .minimum       = 0x00,
-                       .maximum       = 0xff,
-                       .step          = 1,
-                       .default_value = 0x7f,
-                       .type          = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off                   = 128,
-               .reg                   = LUMA_CTRL,
-               .mask                  = 0x00ff,
-               .shift                 = 0,
-       }, {
-               .v = {
-                       .id            = V4L2_CID_CONTRAST,
-                       .name          = "Contrast",
-                       .minimum       = 0,
-                       .maximum       = 0x7f,
-                       .step          = 1,
-                       .default_value = 0x3f,
-                       .type          = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off                   = 0,
-               .reg                   = LUMA_CTRL,
-               .mask                  = 0xff00,
-               .shift                 = 8,
-       }, {
-               .v = {
-                       .id            = V4L2_CID_HUE,
-                       .name          = "Hue",
-                       .minimum       = -127,
-                       .maximum       = 128,
-                       .step          = 1,
-                       .default_value = 0x0,
-                       .type          = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off                   = 128,
-               .reg                   = CHROMA_CTRL,
-               .mask                  = 0xff0000,
-               .shift                 = 16,
-       }, {
-               /* strictly, this only describes only U saturation.
-                * V saturation is handled specially through code.
-                */
-               .v = {
-                       .id            = V4L2_CID_SATURATION,
-                       .name          = "Saturation",
-                       .minimum       = 0,
-                       .maximum       = 0x7f,
-                       .step          = 1,
-                       .default_value = 0x3f,
-                       .type          = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off                   = 0,
-               .reg                   = CHROMA_CTRL,
-               .mask                  = 0x00ff,
-               .shift                 = 0,
-       }, {
-       /* --- audio --- */
-               .v = {
-                       .id            = V4L2_CID_AUDIO_MUTE,
-                       .name          = "Mute",
-                       .minimum       = 0,
-                       .maximum       = 1,
-                       .default_value = 1,
-                       .type          = V4L2_CTRL_TYPE_BOOLEAN,
-               },
-               .reg                   = PATH1_CTL1,
-               .mask                  = (0x1f << 24),
-               .shift                 = 24,
-       }, {
-               .v = {
-                       .id            = V4L2_CID_AUDIO_VOLUME,
-                       .name          = "Volume",
-                       .minimum       = 0,
-                       .maximum       = 65535,
-                       .step          = 65535 / 100,
-                       .default_value = 65535,
-                       .type          = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .reg                   = PATH1_VOL_CTL,
-               .mask                  = 0xff,
-               .shift                 = 0,
-       }
-};
-static const int CX23885_CTLS = ARRAY_SIZE(cx23885_ctls);
-
-/* Must be sorted from low to high control ID! */
-static const u32 cx23885_user_ctrls[] = {
-       V4L2_CID_USER_CLASS,
-       V4L2_CID_BRIGHTNESS,
-       V4L2_CID_CONTRAST,
-       V4L2_CID_SATURATION,
-       V4L2_CID_HUE,
-       V4L2_CID_AUDIO_VOLUME,
-       V4L2_CID_AUDIO_MUTE,
-       0
-};
-
-static const u32 *ctrl_classes[] = {
-       cx23885_user_ctrls,
-       NULL
-};
-
-void cx23885_video_wakeup(struct cx23885_dev *dev,
-       struct cx23885_dmaqueue *q, u32 count)
-{
-       struct cx23885_buffer *buf;
-       int bc;
-
-       for (bc = 0;; bc++) {
-               if (list_empty(&q->active))
-                       break;
-               buf = list_entry(q->active.next,
-                                struct cx23885_buffer, vb.queue);
-
-               /* count comes from the hw and is is 16bit wide --
-                * this trick handles wrap-arounds correctly for
-                * up to 32767 buffers in flight... */
-               if ((s16) (count - buf->count) < 0)
-                       break;
-
-               do_gettimeofday(&buf->vb.ts);
-               dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
-                       count, buf->count);
-               buf->vb.state = VIDEOBUF_DONE;
-               list_del(&buf->vb.queue);
-               wake_up(&buf->vb.done);
-       }
-       if (list_empty(&q->active))
-               del_timer(&q->timeout);
-       else
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-       if (bc != 1)
-               printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
-                       __func__, bc);
-}
-
-int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
-{
-       dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
-               __func__,
-               (unsigned int)norm,
-               v4l2_norm_to_name(norm));
-
-       dev->tvnorm = norm;
-
-       call_all(dev, core, s_std, norm);
-
-       return 0;
-}
-
-static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
-                                   struct pci_dev *pci,
-                                   struct video_device *template,
-                                   char *type)
-{
-       struct video_device *vfd;
-       dprintk(1, "%s()\n", __func__);
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-       *vfd = *template;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->release = video_device_release;
-       snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
-                cx23885_boards[dev->board].name, type);
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
-{
-       int i;
-
-       if (qctrl->id < V4L2_CID_BASE ||
-           qctrl->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       for (i = 0; i < CX23885_CTLS; i++)
-               if (cx23885_ctls[i].v.id == qctrl->id)
-                       break;
-       if (i == CX23885_CTLS) {
-               *qctrl = no_ctl;
-               return 0;
-       }
-       *qctrl = cx23885_ctls[i].v;
-       return 0;
-}
-
-/* ------------------------------------------------------------------- */
-/* resource management                                                 */
-
-static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
-       unsigned int bit)
-{
-       dprintk(1, "%s()\n", __func__);
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       /* is it free? */
-       mutex_lock(&dev->lock);
-       if (dev->resources & bit) {
-               /* no, someone else uses it */
-               mutex_unlock(&dev->lock);
-               return 0;
-       }
-       /* it's free, grab it */
-       fh->resources  |= bit;
-       dev->resources |= bit;
-       dprintk(1, "res: get %d\n", bit);
-       mutex_unlock(&dev->lock);
-       return 1;
-}
-
-static int res_check(struct cx23885_fh *fh, unsigned int bit)
-{
-       return fh->resources & bit;
-}
-
-static int res_locked(struct cx23885_dev *dev, unsigned int bit)
-{
-       return dev->resources & bit;
-}
-
-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", __func__);
-
-       mutex_lock(&dev->lock);
-       fh->resources  &= ~bits;
-       dev->resources &= ~bits;
-       dprintk(1, "res: put %d\n", bits);
-       mutex_unlock(&dev->lock);
-}
-
-static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
-{
-       /* 8 bit registers, 8 bit values */
-       u8 buf[] = { reg, data };
-
-       struct i2c_msg msg = { .addr = 0x98 >> 1,
-               .flags = 0, .buf = buf, .len = 2 };
-
-       return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
-}
-
-static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
-{
-       /* 8 bit registers, 8 bit values */
-       int ret;
-       u8 b0[] = { reg };
-       u8 b1[] = { 0 };
-
-       struct i2c_msg msg[] = {
-               { .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
-               { .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
-       };
-
-       ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
-       if (ret != 2)
-               printk(KERN_ERR "%s() error\n", __func__);
-
-       return b1[0];
-}
-
-static void cx23885_flatiron_dump(struct cx23885_dev *dev)
-{
-       int i;
-       dprintk(1, "Flatiron dump\n");
-       for (i = 0; i < 0x24; i++) {
-               dprintk(1, "FI[%02x] = %02x\n", i,
-                       cx23885_flatiron_read(dev, i));
-       }
-}
-
-static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
-{
-       u8 val;
-       dprintk(1, "%s(input = %d)\n", __func__, input);
-
-       if (input == 1)
-               val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
-       else if (input == 2)
-               val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
-       else
-               return -EINVAL;
-
-       val |= 0x20; /* Enable clock to delta-sigma and dec filter */
-
-       cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
-
-       /* Wake up */
-       cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
-
-       if (video_debug)
-               cx23885_flatiron_dump(dev);
-
-       return 0;
-}
-
-static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
-{
-       dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
-               __func__,
-               input, INPUT(input)->vmux,
-               INPUT(input)->gpio0, INPUT(input)->gpio1,
-               INPUT(input)->gpio2, INPUT(input)->gpio3);
-       dev->input = input;
-
-       if (dev->board == CX23885_BOARD_MYGICA_X8506 ||
-               dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 ||
-               dev->board == CX23885_BOARD_MYGICA_X8507) {
-               /* Select Analog TV */
-               if (INPUT(input)->type == CX23885_VMUX_TELEVISION)
-                       cx23885_gpio_clear(dev, GPIO_0);
-       }
-
-       /* Tell the internal A/V decoder */
-       v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
-                       INPUT(input)->vmux, 0, 0);
-
-       if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
-               (dev->board == CX23885_BOARD_MPX885) ||
-               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
-               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
-               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
-               (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
-               /* Configure audio routing */
-               v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
-                       INPUT(input)->amux, 0, 0);
-
-               if (INPUT(input)->amux == CX25840_AUDIO7)
-                       cx23885_flatiron_mux(dev, 1);
-               else if (INPUT(input)->amux == CX25840_AUDIO6)
-                       cx23885_flatiron_mux(dev, 2);
-       }
-
-       return 0;
-}
-
-static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
-{
-       dprintk(1, "%s(input=%d)\n", __func__, input);
-
-       /* The baseband video core of the cx23885 has two audio inputs.
-        * LR1 and LR2. In almost every single case so far only HVR1xxx
-        * cards we've only ever supported LR1. Time to support LR2,
-        * which is available via the optional white breakout header on
-        * the board.
-        * We'll use a could of existing enums in the card struct to allow
-        * devs to specify which baseband input they need, or just default
-        * to what we've always used.
-        */
-       if (INPUT(input)->amux == CX25840_AUDIO7)
-               cx23885_flatiron_mux(dev, 1);
-       else if (INPUT(input)->amux == CX25840_AUDIO6)
-               cx23885_flatiron_mux(dev, 2);
-       else {
-               /* Not specifically defined, assume the default. */
-               cx23885_flatiron_mux(dev, 1);
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-static int cx23885_start_video_dma(struct cx23885_dev *dev,
-                          struct cx23885_dmaqueue *q,
-                          struct cx23885_buffer *buf)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       /* Stop the dma/fifo before we tamper with it's risc programs */
-       cx_clear(VID_A_DMA_CTL, 0x11);
-
-       /* setup fifo + format */
-       cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
-                               buf->bpl, buf->risc.dma);
-
-       /* reset counter */
-       cx_write(VID_A_GPCNT_CTL, 3);
-       q->count = 1;
-
-       /* enable irq */
-       cx23885_irq_add_enable(dev, 0x01);
-       cx_set(VID_A_INT_MSK, 0x000011);
-
-       /* start dma */
-       cx_set(DEV_CNTRL2, (1<<5));
-       cx_set(VID_A_DMA_CTL, 0x11); /* FIFO and RISC enable */
-
-       return 0;
-}
-
-
-static int cx23885_restart_video_queue(struct cx23885_dev *dev,
-                              struct cx23885_dmaqueue *q)
-{
-       struct cx23885_buffer *buf, *prev;
-       struct list_head *item;
-       dprintk(1, "%s()\n", __func__);
-
-       if (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx23885_buffer,
-                       vb.queue);
-               dprintk(2, "restart_queue [%p/%d]: restart dma\n",
-                       buf, buf->vb.i);
-               cx23885_start_video_dma(dev, q, buf);
-               list_for_each(item, &q->active) {
-                       buf = list_entry(item, struct cx23885_buffer,
-                               vb.queue);
-                       buf->count    = q->count++;
-               }
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-               return 0;
-       }
-
-       prev = NULL;
-       for (;;) {
-               if (list_empty(&q->queued))
-                       return 0;
-               buf = list_entry(q->queued.next, struct cx23885_buffer,
-                       vb.queue);
-               if (NULL == prev) {
-                       list_move_tail(&buf->vb.queue, &q->active);
-                       cx23885_start_video_dma(dev, q, buf);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count    = q->count++;
-                       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-                       dprintk(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_move_tail(&buf->vb.queue, &q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count    = q->count++;
-                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                       prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
-                       dprintk(2, "[%p/%d] restart_queue - move to active\n",
-                               buf, buf->vb.i);
-               } else {
-                       return 0;
-               }
-               prev = buf;
-       }
-}
-
-static int buffer_setup(struct videobuf_queue *q, unsigned int *count,
-       unsigned int *size)
-{
-       struct cx23885_fh *fh = q->priv_data;
-
-       *size = fh->fmt->depth*fh->width*fh->height >> 3;
-       if (0 == *count)
-               *count = 32;
-       if (*size * *count > vid_limit * 1024 * 1024)
-               *count = (vid_limit * 1024 * 1024) / *size;
-       return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-              enum v4l2_field field)
-{
-       struct cx23885_fh *fh  = q->priv_data;
-       struct cx23885_dev *dev = fh->dev;
-       struct cx23885_buffer *buf =
-               container_of(vb, struct cx23885_buffer, vb);
-       int rc, init_buffer = 0;
-       u32 line0_offset, line1_offset;
-       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-       int field_tff;
-
-       BUG_ON(NULL == fh->fmt);
-       if (fh->width  < 48 || fh->width  > norm_maxw(dev->tvnorm) ||
-           fh->height < 32 || fh->height > norm_maxh(dev->tvnorm))
-               return -EINVAL;
-       buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
-       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;
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               init_buffer = 1;
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (0 != rc)
-                       goto fail;
-       }
-
-       if (init_buffer) {
-               buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
-               switch (buf->vb.field) {
-               case V4L2_FIELD_TOP:
-                       cx23885_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist, 0, UNSET,
-                                        buf->bpl, 0, buf->vb.height);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       cx23885_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist, UNSET, 0,
-                                        buf->bpl, 0, buf->vb.height);
-                       break;
-               case V4L2_FIELD_INTERLACED:
-                       if (dev->tvnorm & V4L2_STD_NTSC)
-                               /* NTSC or  */
-                               field_tff = 1;
-                       else
-                               field_tff = 0;
-
-                       if (cx23885_boards[dev->board].force_bff)
-                               /* PAL / SECAM OR 888 in NTSC MODE */
-                               field_tff = 0;
-
-                       if (field_tff) {
-                               /* cx25840 transmits NTSC bottom field first */
-                               dprintk(1, "%s() Creating TFF/NTSC risc\n",
-                                       __func__);
-                               line0_offset = buf->bpl;
-                               line1_offset = 0;
-                       } else {
-                               /* All other formats are top field first */
-                               dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n",
-                                       __func__);
-                               line0_offset = 0;
-                               line1_offset = buf->bpl;
-                       }
-                       cx23885_risc_buffer(dev->pci, &buf->risc,
-                                       dma->sglist, line0_offset,
-                                       line1_offset,
-                                       buf->bpl, buf->bpl,
-                                       buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_TB:
-                       cx23885_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist,
-                                        0, buf->bpl * (buf->vb.height >> 1),
-                                        buf->bpl, 0,
-                                        buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_BT:
-                       cx23885_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist,
-                                        buf->bpl * (buf->vb.height >> 1), 0,
-                                        buf->bpl, 0,
-                                        buf->vb.height >> 1);
-                       break;
-               default:
-                       BUG();
-               }
-       }
-       dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-               buf, buf->vb.i,
-               fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
-               (unsigned long)buf->risc.dma);
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       cx23885_free_buffer(q, buf);
-       return rc;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx23885_buffer   *buf = container_of(vb,
-               struct cx23885_buffer, vb);
-       struct cx23885_buffer   *prev;
-       struct cx23885_fh       *fh   = vq->priv_data;
-       struct cx23885_dev      *dev  = fh->dev;
-       struct cx23885_dmaqueue *q    = &dev->vidq;
-
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
-       buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
-
-       if (!list_empty(&q->queued)) {
-               list_add_tail(&buf->vb.queue, &q->queued);
-               buf->vb.state = VIDEOBUF_QUEUED;
-               dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
-                       buf, buf->vb.i);
-
-       } else if (list_empty(&q->active)) {
-               list_add_tail(&buf->vb.queue, &q->active);
-               cx23885_start_video_dma(dev, q, buf);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = q->count++;
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(2, "[%p/%d] buffer_queue - first active\n",
-                       buf, buf->vb.i);
-
-       } else {
-               prev = list_entry(q->active.prev, struct cx23885_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, &q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count    = q->count++;
-                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                       /* 64 bit bits 63-32 */
-                       prev->risc.jmp[2] = cpu_to_le32(0);
-                       dprintk(2, "[%p/%d] buffer_queue - append to active\n",
-                               buf, buf->vb.i);
-
-               } else {
-                       list_add_tail(&buf->vb.queue, &q->queued);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-                       dprintk(2, "[%p/%d] buffer_queue - first queued\n",
-                               buf, buf->vb.i);
-               }
-       }
-}
-
-static void buffer_release(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
-{
-       struct cx23885_buffer *buf = container_of(vb,
-               struct cx23885_buffer, vb);
-
-       cx23885_free_buffer(q, buf);
-}
-
-static struct videobuf_queue_ops cx23885_video_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-static struct videobuf_queue *get_queue(struct cx23885_fh *fh)
-{
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               return &fh->vidq;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               return &fh->vbiq;
-       default:
-               BUG();
-               return NULL;
-       }
-}
-
-static int get_resource(struct cx23885_fh *fh)
-{
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               return RESOURCE_VIDEO;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               return RESOURCE_VBI;
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static int video_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx23885_dev *dev = video_drvdata(file);
-       struct cx23885_fh *fh;
-       enum v4l2_buf_type type = 0;
-       int radio = 0;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       dprintk(1, "open dev=%s radio=%d type=%s\n",
-               video_device_node_name(vdev), radio, v4l2_type_names[type]);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
-               return -ENOMEM;
-
-       file->private_data = fh;
-       fh->dev      = dev;
-       fh->radio    = radio;
-       fh->type     = type;
-       fh->width    = 320;
-       fh->height   = 240;
-       fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_YUYV);
-
-       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),
-                           fh, NULL);
-
-       videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
-               &dev->pci->dev, &dev->slock,
-               V4L2_BUF_TYPE_VBI_CAPTURE,
-               V4L2_FIELD_SEQ_TB,
-               sizeof(struct cx23885_buffer),
-               fh, NULL);
-
-
-       dprintk(1, "post videobuf_queue_init()\n");
-
-       return 0;
-}
-
-static ssize_t video_read(struct file *file, char __user *data,
-       size_t count, loff_t *ppos)
-{
-       struct cx23885_fh *fh = file->private_data;
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (res_locked(fh->dev, RESOURCE_VIDEO))
-                       return -EBUSY;
-               return videobuf_read_one(&fh->vidq, data, count, ppos,
-                                        file->f_flags & O_NONBLOCK);
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (!res_get(fh->dev, fh, RESOURCE_VBI))
-                       return -EBUSY;
-               return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
-                                           file->f_flags & O_NONBLOCK);
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static unsigned int video_poll(struct file *file,
-       struct poll_table_struct *wait)
-{
-       struct cx23885_fh *fh = file->private_data;
-       struct cx23885_buffer *buf;
-       unsigned int rc = POLLERR;
-
-       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
-               if (!res_get(fh->dev, fh, RESOURCE_VBI))
-                       return POLLERR;
-               return videobuf_poll_stream(file, &fh->vbiq, wait);
-       }
-
-       mutex_lock(&fh->vidq.vb_lock);
-       if (res_check(fh, RESOURCE_VIDEO)) {
-               /* streaming capture */
-               if (list_empty(&fh->vidq.stream))
-                       goto done;
-               buf = list_entry(fh->vidq.stream.next,
-                       struct cx23885_buffer, vb.stream);
-       } else {
-               /* read() capture */
-               buf = (struct cx23885_buffer *)fh->vidq.read_buf;
-               if (NULL == buf)
-                       goto done;
-       }
-       poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == VIDEOBUF_DONE ||
-           buf->vb.state == VIDEOBUF_ERROR)
-               rc =  POLLIN|POLLRDNORM;
-       else
-               rc = 0;
-done:
-       mutex_unlock(&fh->vidq.vb_lock);
-       return rc;
-}
-
-static int video_release(struct file *file)
-{
-       struct cx23885_fh *fh = file->private_data;
-       struct cx23885_dev *dev = fh->dev;
-
-       /* turn off overlay */
-       if (res_check(fh, RESOURCE_OVERLAY)) {
-               /* FIXME */
-               res_free(dev, fh, RESOURCE_OVERLAY);
-       }
-
-       /* stop video capture */
-       if (res_check(fh, RESOURCE_VIDEO)) {
-               videobuf_queue_cancel(&fh->vidq);
-               res_free(dev, fh, RESOURCE_VIDEO);
-       }
-       if (fh->vidq.read_buf) {
-               buffer_release(&fh->vidq, fh->vidq.read_buf);
-               kfree(fh->vidq.read_buf);
-       }
-
-       /* stop vbi capture */
-       if (res_check(fh, RESOURCE_VBI)) {
-               if (fh->vbiq.streaming)
-                       videobuf_streamoff(&fh->vbiq);
-               if (fh->vbiq.reading)
-                       videobuf_read_stop(&fh->vbiq);
-               res_free(dev, fh, RESOURCE_VBI);
-       }
-
-       videobuf_mmap_free(&fh->vidq);
-       videobuf_mmap_free(&fh->vbiq);
-
-       file->private_data = NULL;
-       kfree(fh);
-
-       /* We are not putting the tuner to sleep here on exit, because
-        * we want to use the mpeg encoder in another session to capture
-        * tuner video. Closing this will result in no video to the encoder.
-        */
-
-       return 0;
-}
-
-static int video_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct cx23885_fh *fh = file->private_data;
-
-       return videobuf_mmap_mapper(get_queue(fh), vma);
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO CTRL IOCTLS                                                  */
-
-int cx23885_get_control(struct cx23885_dev *dev,
-       struct v4l2_control *ctl)
-{
-       dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
-       call_all(dev, core, g_ctrl, ctl);
-       return 0;
-}
-
-int cx23885_set_control(struct cx23885_dev *dev,
-       struct v4l2_control *ctl)
-{
-       dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
-       call_all(dev, core, s_ctrl, ctl);
-
-       return 0;
-}
-
-static void init_controls(struct cx23885_dev *dev)
-{
-       struct v4l2_control ctrl;
-       int i;
-
-       for (i = 0; i < CX23885_CTLS; i++) {
-               ctrl.id = cx23885_ctls[i].v.id;
-               ctrl.value = cx23885_ctls[i].v.default_value;
-
-               cx23885_set_control(dev, &ctrl);
-       }
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO IOCTLS                                                       */
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-       struct v4l2_format *f)
-{
-       struct cx23885_fh *fh   = priv;
-
-       f->fmt.pix.width        = fh->width;
-       f->fmt.pix.height       = fh->height;
-       f->fmt.pix.field        = fh->vidq.field;
-       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fh->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-       struct v4l2_format *f)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       struct cx23885_fmt *fmt;
-       enum v4l2_field   field;
-       unsigned int      maxw, maxh;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-       maxw  = norm_maxw(dev->tvnorm);
-       maxh  = norm_maxh(dev->tvnorm);
-
-       if (V4L2_FIELD_ANY == field) {
-               field = (f->fmt.pix.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_BOTTOM;
-       }
-
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       f->fmt.pix.field = field;
-       v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
-                             &f->fmt.pix.height, 32, maxh, 0, 0);
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-       struct v4l2_format *f)
-{
-       struct cx23885_fh *fh = priv;
-       struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       int err;
-
-       dprintk(2, "%s()\n", __func__);
-       err = vidioc_try_fmt_vid_cap(file, priv, f);
-
-       if (0 != err)
-               return err;
-       fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
-       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", __func__,
-               fh->width, fh->height, fh->vidq.field);
-       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
-       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
-       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
-       return 0;
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-       struct v4l2_capability *cap)
-{
-       struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
-
-       strcpy(cap->driver, "cx23885");
-       strlcpy(cap->card, cx23885_boards[dev->board].name,
-               sizeof(cap->card));
-       sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
-       cap->capabilities =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_READWRITE     |
-               V4L2_CAP_STREAMING     |
-               V4L2_CAP_VBI_CAPTURE;
-       if (UNSET != dev->tuner_type)
-               cap->capabilities |= V4L2_CAP_TUNER;
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-       struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(formats)))
-               return -EINVAL;
-
-       strlcpy(f->description, formats[f->index].name,
-               sizeof(f->description));
-       f->pixelformat = formats[f->index].fourcc;
-
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-       struct v4l2_requestbuffers *p)
-{
-       struct cx23885_fh *fh = priv;
-       return videobuf_reqbufs(get_queue(fh), p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-       struct v4l2_buffer *p)
-{
-       struct cx23885_fh *fh = priv;
-       return videobuf_querybuf(get_queue(fh), p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv,
-       struct v4l2_buffer *p)
-{
-       struct cx23885_fh *fh = priv;
-       return videobuf_qbuf(get_queue(fh), p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv,
-       struct v4l2_buffer *p)
-{
-       struct cx23885_fh *fh = priv;
-       return videobuf_dqbuf(get_queue(fh), p,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
-       enum v4l2_buf_type i)
-{
-       struct cx23885_fh *fh = priv;
-       struct cx23885_dev *dev = fh->dev;
-       dprintk(1, "%s()\n", __func__);
-
-       if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-       if (unlikely(i != fh->type))
-               return -EINVAL;
-
-       if (unlikely(!res_get(dev, fh, get_resource(fh))))
-               return -EBUSY;
-
-       /* Don't start VBI streaming unless vida streaming
-        * has already started.
-        */
-       if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
-               ((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
-               return -EINVAL;
-
-       return videobuf_streamon(get_queue(fh));
-}
-
-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", __func__);
-
-       if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
-               (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-       if (i != fh->type)
-               return -EINVAL;
-
-       res = get_resource(fh);
-       err = videobuf_streamoff(get_queue(fh));
-       if (err < 0)
-               return err;
-       res_free(dev, fh, res);
-       return 0;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __func__);
-
-       call_all(dev, core, g_std, id);
-
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __func__);
-
-       mutex_lock(&dev->lock);
-       cx23885_set_tvnorm(dev, *tvnorms);
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
-{
-       static const char *iname[] = {
-               [CX23885_VMUX_COMPOSITE1] = "Composite1",
-               [CX23885_VMUX_COMPOSITE2] = "Composite2",
-               [CX23885_VMUX_COMPOSITE3] = "Composite3",
-               [CX23885_VMUX_COMPOSITE4] = "Composite4",
-               [CX23885_VMUX_SVIDEO]     = "S-Video",
-               [CX23885_VMUX_COMPONENT]  = "Component",
-               [CX23885_VMUX_TELEVISION] = "Television",
-               [CX23885_VMUX_CABLE]      = "Cable TV",
-               [CX23885_VMUX_DVB]        = "DVB",
-               [CX23885_VMUX_DEBUG]      = "for debug only",
-       };
-       unsigned int n;
-       dprintk(1, "%s()\n", __func__);
-
-       n = i->index;
-       if (n >= MAX_CX23885_INPUT)
-               return -EINVAL;
-
-       if (0 == INPUT(n)->type)
-               return -EINVAL;
-
-       i->index = n;
-       i->type  = V4L2_INPUT_TYPE_CAMERA;
-       strcpy(i->name, iname[INPUT(n)->type]);
-       if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) ||
-               (CX23885_VMUX_CABLE == INPUT(n)->type)) {
-               i->type = V4L2_INPUT_TYPE_TUNER;
-               i->std = CX23885_NORMS;
-       }
-
-       /* Two selectable audio inputs for non-tv inputs */
-       if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
-               i->audioset = 0x3;
-
-       if (dev->input == n) {
-               /* enum'd input matches our configured input.
-                * Ask the video decoder to process the call
-                * and give it an oppertunity to update the
-                * status field.
-                */
-               call_all(dev, video, g_input_status, &i->status);
-       }
-
-       return 0;
-}
-
-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", __func__);
-       return cx23885_enum_input(dev, i);
-}
-
-int cx23885_get_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", __func__, *i);
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       return cx23885_get_input(file, priv, i);
-}
-
-int cx23885_set_input(struct file *file, void *priv, unsigned int i)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       dprintk(1, "%s(%d)\n", __func__, i);
-
-       if (i >= MAX_CX23885_INPUT) {
-               dprintk(1, "%s() -EINVAL\n", __func__);
-               return -EINVAL;
-       }
-
-       if (INPUT(i)->type == 0)
-               return -EINVAL;
-
-       mutex_lock(&dev->lock);
-       cx23885_video_mux(dev, i);
-
-       /* By default establish the default audio input for the card also */
-       /* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
-       cx23885_audio_mux(dev, i);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       return cx23885_set_input(file, priv, i);
-}
-
-static int vidioc_log_status(struct file *file, void *priv)
-{
-       struct cx23885_fh  *fh  = priv;
-       struct cx23885_dev *dev = fh->dev;
-
-       printk(KERN_INFO
-               "%s/0: ============  START LOG STATUS  ============\n",
-               dev->name);
-       call_all(dev, core, log_status);
-       printk(KERN_INFO
-               "%s/0: =============  END LOG STATUS  =============\n",
-               dev->name);
-       return 0;
-}
-
-static int cx23885_query_audinput(struct file *file, void *priv,
-       struct v4l2_audio *i)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       static const char *iname[] = {
-               [0] = "Baseband L/R 1",
-               [1] = "Baseband L/R 2",
-       };
-       unsigned int n;
-       dprintk(1, "%s()\n", __func__);
-
-       n = i->index;
-       if (n >= 2)
-               return -EINVAL;
-
-       memset(i, 0, sizeof(*i));
-       i->index = n;
-       strcpy(i->name, iname[n]);
-       i->capability  = V4L2_AUDCAP_STEREO;
-       i->mode  = V4L2_AUDMODE_AVL;
-       return 0;
-
-}
-
-static int vidioc_enum_audinput(struct file *file, void *priv,
-                               struct v4l2_audio *i)
-{
-       return cx23885_query_audinput(file, priv, i);
-}
-
-static int vidioc_g_audinput(struct file *file, void *priv,
-       struct v4l2_audio *i)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       i->index = dev->audinput;
-       dprintk(1, "%s(input=%d)\n", __func__, i->index);
-
-       return cx23885_query_audinput(file, priv, i);
-}
-
-static int vidioc_s_audinput(struct file *file, void *priv,
-       struct v4l2_audio *i)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-       if (i->index >= 2)
-               return -EINVAL;
-
-       dprintk(1, "%s(%d)\n", __func__, i->index);
-
-       dev->audinput = i->index;
-
-       /* Skip the audio defaults from the cards struct, caller wants
-        * directly touch the audio mux hardware. */
-       cx23885_flatiron_mux(dev, dev->audinput + 1);
-       return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *qctrl)
-{
-       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
-       if (unlikely(qctrl->id == 0))
-               return -EINVAL;
-       return cx23885_ctrl_query(qctrl);
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctl)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       return cx23885_get_control(dev, ctl);
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctl)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       return cx23885_set_control(dev, ctl);
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Television");
-
-       call_all(dev, tuner, g_tuner, t);
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
-
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-       /* Update the A/V core */
-       call_all(dev, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct cx23885_fh *fh = priv;
-       struct cx23885_dev *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-
-       /* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
-       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->freq;
-
-       call_all(dev, tuner, g_frequency, f);
-
-       return 0;
-}
-
-static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
-{
-       struct v4l2_control ctrl;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-
-       mutex_lock(&dev->lock);
-       dev->freq = f->frequency;
-
-       /* I need to mute audio here */
-       ctrl.id = V4L2_CID_AUDIO_MUTE;
-       ctrl.value = 1;
-       cx23885_set_control(dev, &ctrl);
-
-       call_all(dev, tuner, s_frequency, f);
-
-       /* When changing channels it is required to reset TVAUDIO */
-       msleep(100);
-
-       /* I need to unmute audio here */
-       ctrl.value = 0;
-       cx23885_set_control(dev, &ctrl);
-
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
-       struct v4l2_frequency *f)
-{
-       struct v4l2_control ctrl;
-       struct videobuf_dvb_frontend *vfe;
-       struct dvb_frontend *fe;
-
-       struct analog_parameters params = {
-               .mode      = V4L2_TUNER_ANALOG_TV,
-               .audmode   = V4L2_TUNER_MODE_STEREO,
-               .std       = dev->tvnorm,
-               .frequency = f->frequency
-       };
-
-       mutex_lock(&dev->lock);
-       dev->freq = f->frequency;
-
-       /* I need to mute audio here */
-       ctrl.id = V4L2_CID_AUDIO_MUTE;
-       ctrl.value = 1;
-       cx23885_set_control(dev, &ctrl);
-
-       /* If HVR1850 */
-       dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__,
-               params.frequency, f->tuner, params.std);
-
-       vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
-       if (!vfe) {
-               mutex_unlock(&dev->lock);
-               return -EINVAL;
-       }
-
-       fe = vfe->dvb.frontend;
-
-       if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
-           (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
-           (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111))
-               fe = &dev->ts1.analog_fe;
-
-       if (fe && fe->ops.tuner_ops.set_analog_params) {
-               call_all(dev, core, s_std, dev->tvnorm);
-               fe->ops.tuner_ops.set_analog_params(fe, &params);
-       }
-       else
-               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
-
-       /* When changing channels it is required to reset TVAUDIO */
-       msleep(100);
-
-       /* I need to unmute audio here */
-       ctrl.value = 0;
-       cx23885_set_control(dev, &ctrl);
-
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-int cx23885_set_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       struct cx23885_fh *fh = priv;
-       struct cx23885_dev *dev = fh->dev;
-       int ret;
-
-       switch (dev->board) {
-       case CX23885_BOARD_HAUPPAUGE_HVR1255:
-       case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
-       case CX23885_BOARD_HAUPPAUGE_HVR1850:
-               ret = cx23885_set_freq_via_ops(dev, f);
-               break;
-       default:
-               ret = cx23885_set_freq(dev, f);
-       }
-
-       return ret;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       return cx23885_set_frequency(file, priv, f);
-}
-
-/* ----------------------------------------------------------- */
-
-static void cx23885_vid_timeout(unsigned long data)
-{
-       struct cx23885_dev *dev = (struct cx23885_dev *)data;
-       struct cx23885_dmaqueue *q = &dev->vidq;
-       struct cx23885_buffer *buf;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->slock, flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next,
-                       struct cx23885_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
-                       dev->name, buf, buf->vb.i,
-                       (unsigned long)buf->risc.dma);
-       }
-       cx23885_restart_video_queue(dev, q);
-       spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
-{
-       u32 mask, count;
-       int handled = 0;
-
-       mask   = cx_read(VID_A_INT_MSK);
-       if (0 == (status & mask))
-               return handled;
-
-       cx_write(VID_A_INT_STAT, status);
-
-       /* risc op code error, fifo overflow or line sync detection error */
-       if ((status & VID_BC_MSK_OPC_ERR) ||
-               (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);
-                       printk(KERN_WARNING "%s: video risc op code error\n",
-                               dev->name);
-                       cx23885_sram_channel_dump(dev,
-                               &dev->sram_channels[SRAM_CH01]);
-               }
-
-               if (status & VID_BC_MSK_SYNC)
-                       dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
-                               "video lines miss-match\n",
-                               VID_BC_MSK_SYNC);
-
-               if (status & VID_BC_MSK_OF)
-                       dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
-                               VID_BC_MSK_OF);
-
-       }
-
-       /* Video */
-       if (status & VID_BC_MSK_RISCI1) {
-               spin_lock(&dev->slock);
-               count = cx_read(VID_A_GPCNT);
-               cx23885_video_wakeup(dev, &dev->vidq, count);
-               spin_unlock(&dev->slock);
-               handled++;
-       }
-       if (status & VID_BC_MSK_RISCI2) {
-               dprintk(2, "stopper video\n");
-               spin_lock(&dev->slock);
-               cx23885_restart_video_queue(dev, &dev->vidq);
-               spin_unlock(&dev->slock);
-               handled++;
-       }
-
-       /* Allow the VBI framework to process it's payload */
-       handled += cx23885_vbi_irq(dev, status);
-
-       return handled;
-}
-
-/* ----------------------------------------------------------- */
-/* exported stuff                                              */
-
-static const struct v4l2_file_operations video_fops = {
-       .owner         = THIS_MODULE,
-       .open          = video_open,
-       .release       = video_release,
-       .read          = video_read,
-       .poll          = video_poll,
-       .mmap          = video_mmap,
-       .ioctl         = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vbi_cap     = cx23885_vbi_fmt,
-       .vidioc_try_fmt_vbi_cap   = cx23885_vbi_fmt,
-       .vidioc_s_fmt_vbi_cap     = cx23885_vbi_fmt,
-       .vidioc_reqbufs       = vidioc_reqbufs,
-       .vidioc_querybuf      = vidioc_querybuf,
-       .vidioc_qbuf          = vidioc_qbuf,
-       .vidioc_dqbuf         = vidioc_dqbuf,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_g_std         = vidioc_g_std,
-       .vidioc_querystd      = vidioc_g_std,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_log_status    = vidioc_log_status,
-       .vidioc_queryctrl     = vidioc_queryctrl,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
-       .vidioc_streamon      = vidioc_streamon,
-       .vidioc_streamoff     = vidioc_streamoff,
-       .vidioc_g_tuner       = vidioc_g_tuner,
-       .vidioc_s_tuner       = vidioc_s_tuner,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-       .vidioc_g_chip_ident  = cx23885_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = cx23885_g_register,
-       .vidioc_s_register    = cx23885_s_register,
-#endif
-       .vidioc_enumaudio     = vidioc_enum_audinput,
-       .vidioc_g_audio       = vidioc_g_audinput,
-       .vidioc_s_audio       = vidioc_s_audinput,
-};
-
-static struct video_device cx23885_vbi_template;
-static struct video_device cx23885_video_template = {
-       .name                 = "cx23885-video",
-       .fops                 = &video_fops,
-       .ioctl_ops            = &video_ioctl_ops,
-       .tvnorms              = CX23885_NORMS,
-       .current_norm         = V4L2_STD_NTSC_M,
-};
-
-static const struct v4l2_file_operations radio_fops = {
-       .owner         = THIS_MODULE,
-       .open          = video_open,
-       .release       = video_release,
-       .ioctl         = video_ioctl2,
-};
-
-
-void cx23885_video_unregister(struct cx23885_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-       cx23885_irq_remove(dev, 0x01);
-
-       if (dev->vbi_dev) {
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
-               btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
-       }
-       if (dev->video_dev) {
-               if (video_is_registered(dev->video_dev))
-                       video_unregister_device(dev->video_dev);
-               else
-                       video_device_release(dev->video_dev);
-               dev->video_dev = NULL;
-
-               btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
-       }
-
-       if (dev->audio_dev)
-               cx23885_audio_unregister(dev);
-}
-
-int cx23885_video_register(struct cx23885_dev *dev)
-{
-       int err;
-
-       dprintk(1, "%s()\n", __func__);
-       spin_lock_init(&dev->slock);
-
-       /* Initialize VBI template */
-       memcpy(&cx23885_vbi_template, &cx23885_video_template,
-               sizeof(cx23885_vbi_template));
-       strcpy(cx23885_vbi_template.name, "cx23885-vbi");
-
-       dev->tvnorm = cx23885_video_template.current_norm;
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&dev->vidq.active);
-       INIT_LIST_HEAD(&dev->vidq.queued);
-       dev->vidq.timeout.function = cx23885_vid_timeout;
-       dev->vidq.timeout.data = (unsigned long)dev;
-       init_timer(&dev->vidq.timeout);
-       cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
-               VID_A_DMA_CTL, 0x11, 0x00);
-
-       /* init vbi dma queues */
-       INIT_LIST_HEAD(&dev->vbiq.active);
-       INIT_LIST_HEAD(&dev->vbiq.queued);
-       dev->vbiq.timeout.function = cx23885_vbi_timeout;
-       dev->vbiq.timeout.data = (unsigned long)dev;
-       init_timer(&dev->vbiq.timeout);
-       cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
-               VID_A_DMA_CTL, 0x22, 0x00);
-
-       cx23885_irq_add_enable(dev, 0x01);
-
-       if ((TUNER_ABSENT != dev->tuner_type) &&
-                       ((dev->tuner_bus == 0) || (dev->tuner_bus == 1))) {
-               struct v4l2_subdev *sd = NULL;
-
-               if (dev->tuner_addr)
-                       sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_bus[dev->tuner_bus].i2c_adap,
-                               "tuner", dev->tuner_addr, NULL);
-               else
-                       sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_bus[dev->tuner_bus].i2c_adap,
-                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV));
-               if (sd) {
-                       struct tuner_setup tun_setup;
-
-                       memset(&tun_setup, 0, sizeof(tun_setup));
-                       tun_setup.mode_mask = T_ANALOG_TV;
-                       tun_setup.type = dev->tuner_type;
-                       tun_setup.addr = v4l2_i2c_subdev_addr(sd);
-                       tun_setup.tuner_callback = cx23885_tuner_callback;
-
-                       v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
-
-                       if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) {
-                               struct xc2028_ctrl ctrl = {
-                                       .fname = XC2028_DEFAULT_FIRMWARE,
-                                       .max_len = 64
-                               };
-                               struct v4l2_priv_tun_config cfg = {
-                                       .tuner = dev->tuner_type,
-                                       .priv = &ctrl
-                               };
-                               v4l2_subdev_call(sd, tuner, s_config, &cfg);
-                       }
-               }
-       }
-
-       /* register Video device */
-       dev->video_dev = cx23885_vdev_init(dev, dev->pci,
-               &cx23885_video_template, "video");
-       err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
-                                   video_nr[dev->nr]);
-       if (err < 0) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                       dev->name);
-               goto fail_unreg;
-       }
-       printk(KERN_INFO "%s: registered device %s [v4l2]\n",
-              dev->name, video_device_node_name(dev->video_dev));
-
-       /* register VBI device */
-       dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
-               &cx23885_vbi_template, "vbi");
-       err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
-                                   vbi_nr[dev->nr]);
-       if (err < 0) {
-               printk(KERN_INFO "%s: can't register vbi device\n",
-                       dev->name);
-               goto fail_unreg;
-       }
-       printk(KERN_INFO "%s: registered device %s\n",
-              dev->name, video_device_node_name(dev->vbi_dev));
-
-       /* Register ALSA audio device */
-       dev->audio_dev = cx23885_audio_register(dev);
-
-       /* initial device configuration */
-       mutex_lock(&dev->lock);
-       cx23885_set_tvnorm(dev, dev->tvnorm);
-       init_controls(dev);
-       cx23885_video_mux(dev, 0);
-       cx23885_audio_mux(dev, 0);
-       mutex_unlock(&dev->lock);
-
-       return 0;
-
-fail_unreg:
-       cx23885_video_unregister(dev);
-       return err;
-}
-
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h
deleted file mode 100644 (file)
index 5d560c7..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- *  Driver for the Conexant CX23885 PCIe bridge
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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/pci.h>
-#include <linux/i2c.h>
-#include <linux/kdev_t.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-device.h>
-#include <media/tuner.h>
-#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/videobuf-dvb.h>
-#include <media/rc-core.h>
-
-#include "btcx-risc.h"
-#include "cx23885-reg.h"
-#include "media/cx2341x.h"
-
-#include <linux/mutex.h>
-
-#define CX23885_VERSION "0.0.3"
-
-#define UNSET (-1U)
-
-#define CX23885_MAXBOARDS 8
-
-/* Max number of inputs by card */
-#define MAX_CX23885_INPUT 8
-#define INPUT(nr) (&cx23885_boards[dev->board].input[nr])
-#define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO         2
-#define RESOURCE_VBI           4
-
-#define BUFFER_TIMEOUT     (HZ)  /* 0.5 seconds */
-
-#define CX23885_BOARD_NOAUTO               UNSET
-#define CX23885_BOARD_UNKNOWN                  0
-#define CX23885_BOARD_HAUPPAUGE_HVR1800lp      1
-#define CX23885_BOARD_HAUPPAUGE_HVR1800        2
-#define CX23885_BOARD_HAUPPAUGE_HVR1250        3
-#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
-#define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 10
-#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP 11
-#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H 12
-#define CX23885_BOARD_COMPRO_VIDEOMATE_E650F   13
-#define CX23885_BOARD_TBS_6920                 14
-#define CX23885_BOARD_TEVII_S470               15
-#define CX23885_BOARD_DVBWORLD_2005            16
-#define CX23885_BOARD_NETUP_DUAL_DVBS2_CI      17
-#define CX23885_BOARD_HAUPPAUGE_HVR1270        18
-#define CX23885_BOARD_HAUPPAUGE_HVR1275        19
-#define CX23885_BOARD_HAUPPAUGE_HVR1255        20
-#define CX23885_BOARD_HAUPPAUGE_HVR1210        21
-#define CX23885_BOARD_MYGICA_X8506             22
-#define CX23885_BOARD_MAGICPRO_PROHDTVE2       23
-#define CX23885_BOARD_HAUPPAUGE_HVR1850        24
-#define CX23885_BOARD_COMPRO_VIDEOMATE_E800    25
-#define CX23885_BOARD_HAUPPAUGE_HVR1290        26
-#define CX23885_BOARD_MYGICA_X8558PRO          27
-#define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
-#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
-#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
-#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
-#define CX23885_BOARD_MPX885                   32
-#define CX23885_BOARD_MYGICA_X8507             33
-#define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
-#define CX23885_BOARD_TEVII_S471               35
-#define CX23885_BOARD_HAUPPAUGE_HVR1255_22111  36
-
-#define GPIO_0 0x00000001
-#define GPIO_1 0x00000002
-#define GPIO_2 0x00000004
-#define GPIO_3 0x00000008
-#define GPIO_4 0x00000010
-#define GPIO_5 0x00000020
-#define GPIO_6 0x00000040
-#define GPIO_7 0x00000080
-#define GPIO_8 0x00000100
-#define GPIO_9 0x00000200
-#define GPIO_10 0x00000400
-#define GPIO_11 0x00000800
-#define GPIO_12 0x00001000
-#define GPIO_13 0x00002000
-#define GPIO_14 0x00004000
-#define GPIO_15 0x00008000
-
-/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
-#define CX23885_NORMS (\
-       V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443 | \
-       V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
-       V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_Nc   | \
-       V4L2_STD_PAL_60 |  V4L2_STD_SECAM_L   |  V4L2_STD_SECAM_DK)
-
-struct cx23885_fmt {
-       char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-       int   flags;
-       u32   cxformat;
-};
-
-struct cx23885_ctrl {
-       struct v4l2_queryctrl v;
-       u32                   off;
-       u32                   reg;
-       u32                   mask;
-       u32                   shift;
-};
-
-struct cx23885_tvnorm {
-       char            *name;
-       v4l2_std_id     id;
-       u32             cxiformat;
-       u32             cxoformat;
-};
-
-struct cx23885_fh {
-       struct cx23885_dev         *dev;
-       enum v4l2_buf_type         type;
-       int                        radio;
-       u32                        resources;
-
-       /* video overlay */
-       struct v4l2_window         win;
-       struct v4l2_clip           *clips;
-       unsigned int               nclips;
-
-       /* video capture */
-       struct cx23885_fmt         *fmt;
-       unsigned int               width, height;
-
-       /* vbi capture */
-       struct videobuf_queue      vidq;
-       struct videobuf_queue      vbiq;
-
-       /* MPEG Encoder specifics ONLY */
-       struct videobuf_queue      mpegq;
-       atomic_t                   v4l_reading;
-};
-
-enum cx23885_itype {
-       CX23885_VMUX_COMPOSITE1 = 1,
-       CX23885_VMUX_COMPOSITE2,
-       CX23885_VMUX_COMPOSITE3,
-       CX23885_VMUX_COMPOSITE4,
-       CX23885_VMUX_SVIDEO,
-       CX23885_VMUX_COMPONENT,
-       CX23885_VMUX_TELEVISION,
-       CX23885_VMUX_CABLE,
-       CX23885_VMUX_DVB,
-       CX23885_VMUX_DEBUG,
-       CX23885_RADIO,
-};
-
-enum cx23885_src_sel_type {
-       CX23885_SRC_SEL_EXT_656_VIDEO = 0,
-       CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO
-};
-
-/* buffer for one video frame */
-struct cx23885_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       /* cx23885 specific */
-       unsigned int           bpl;
-       struct btcx_riscmem    risc;
-       struct cx23885_fmt     *fmt;
-       u32                    count;
-};
-
-struct cx23885_input {
-       enum cx23885_itype type;
-       unsigned int    vmux;
-       unsigned int    amux;
-       u32             gpio0, gpio1, gpio2, gpio3;
-};
-
-typedef enum {
-       CX23885_MPEG_UNDEFINED = 0,
-       CX23885_MPEG_DVB,
-       CX23885_ANALOG_VIDEO,
-       CX23885_MPEG_ENCODER,
-} port_t;
-
-struct cx23885_board {
-       char                    *name;
-       port_t                  porta, portb, portc;
-       int             num_fds_portb, num_fds_portc;
-       unsigned int            tuner_type;
-       unsigned int            radio_type;
-       unsigned char           tuner_addr;
-       unsigned char           radio_addr;
-       unsigned int            tuner_bus;
-
-       /* Vendors can and do run the PCIe bridge at different
-        * clock rates, driven physically by crystals on the PCBs.
-        * The core has to accommodate this. This allows the user
-        * to add new boards with new frequencys. The value is
-        * expressed in Hz.
-        *
-        * The core framework will default this value based on
-        * current designs, but it can vary.
-        */
-       u32                     clk_freq;
-       struct cx23885_input    input[MAX_CX23885_INPUT];
-       int                     ci_type; /* for NetUP */
-       /* Force bottom field first during DMA (888 workaround) */
-       u32                     force_bff;
-};
-
-struct cx23885_subid {
-       u16     subvendor;
-       u16     subdevice;
-       u32     card;
-};
-
-struct cx23885_i2c {
-       struct cx23885_dev *dev;
-
-       int                        nr;
-
-       /* i2c i/o */
-       struct i2c_adapter         i2c_adap;
-       struct i2c_client          i2c_client;
-       u32                        i2c_rc;
-
-       /* 885 registers used for raw addess */
-       u32                        i2c_period;
-       u32                        reg_ctrl;
-       u32                        reg_stat;
-       u32                        reg_addr;
-       u32                        reg_rdata;
-       u32                        reg_wdata;
-};
-
-struct cx23885_dmaqueue {
-       struct list_head       active;
-       struct list_head       queued;
-       struct timer_list      timeout;
-       struct btcx_riscmem    stopper;
-       u32                    count;
-};
-
-struct cx23885_tsport {
-       struct cx23885_dev *dev;
-
-       int                        nr;
-       int                        sram_chno;
-
-       struct videobuf_dvb_frontends frontends;
-
-       /* dma queues */
-       struct cx23885_dmaqueue    mpegq;
-       u32                        ts_packet_size;
-       u32                        ts_packet_count;
-
-       int                        width;
-       int                        height;
-
-       spinlock_t                 slock;
-
-       /* registers */
-       u32                        reg_gpcnt;
-       u32                        reg_gpcnt_ctl;
-       u32                        reg_dma_ctl;
-       u32                        reg_lngth;
-       u32                        reg_hw_sop_ctrl;
-       u32                        reg_gen_ctrl;
-       u32                        reg_bd_pkt_status;
-       u32                        reg_sop_status;
-       u32                        reg_fifo_ovfl_stat;
-       u32                        reg_vld_misc;
-       u32                        reg_ts_clk_en;
-       u32                        reg_ts_int_msk;
-       u32                        reg_ts_int_stat;
-       u32                        reg_src_sel;
-
-       /* Default register vals */
-       int                        pci_irqmask;
-       u32                        dma_ctl_val;
-       u32                        ts_int_msk_val;
-       u32                        gen_ctrl_val;
-       u32                        ts_clk_en_val;
-       u32                        src_sel_val;
-       u32                        vld_misc_val;
-       u32                        hw_sop_ctrl_val;
-
-       /* Allow a single tsport to have multiple frontends */
-       u32                        num_frontends;
-       void                (*gate_ctrl)(struct cx23885_tsport *port, int open);
-       void                       *port_priv;
-
-       /* Workaround for a temp dvb_frontend that the tuner can attached to */
-       struct dvb_frontend analog_fe;
-};
-
-struct cx23885_kernel_ir {
-       struct cx23885_dev      *cx;
-       char                    *name;
-       char                    *phys;
-
-       struct rc_dev           *rc;
-};
-
-struct cx23885_audio_buffer {
-       unsigned int            bpl;
-       struct btcx_riscmem     risc;
-       struct videobuf_dmabuf  dma;
-};
-
-struct cx23885_audio_dev {
-       struct cx23885_dev      *dev;
-
-       struct pci_dev          *pci;
-
-       struct snd_card         *card;
-
-       spinlock_t              lock;
-
-       atomic_t                count;
-
-       unsigned int            dma_size;
-       unsigned int            period_size;
-       unsigned int            num_periods;
-
-       struct videobuf_dmabuf  *dma_risc;
-
-       struct cx23885_audio_buffer   *buf;
-
-       struct snd_pcm_substream *substream;
-};
-
-struct cx23885_dev {
-       atomic_t                   refcount;
-       struct v4l2_device         v4l2_dev;
-
-       /* pci stuff */
-       struct pci_dev             *pci;
-       unsigned char              pci_rev, pci_lat;
-       int                        pci_bus, pci_slot;
-       u32                        __iomem *lmmio;
-       u8                         __iomem *bmmio;
-       int                        pci_irqmask;
-       spinlock_t                 pci_irqmask_lock; /* protects mask reg too */
-       int                        hwrevision;
-
-       /* This valud is board specific and is used to configure the
-        * AV core so we see nice clean and stable video and audio. */
-       u32                        clk_freq;
-
-       /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
-       struct cx23885_i2c         i2c_bus[3];
-
-       int                        nr;
-       struct mutex               lock;
-       struct mutex               gpio_lock;
-
-       /* board details */
-       unsigned int               board;
-       char                       name[32];
-
-       struct cx23885_tsport      ts1, ts2;
-
-       /* sram configuration */
-       struct sram_channel        *sram_channels;
-
-       enum {
-               CX23885_BRIDGE_UNDEFINED = 0,
-               CX23885_BRIDGE_885 = 885,
-               CX23885_BRIDGE_887 = 887,
-               CX23885_BRIDGE_888 = 888,
-       } bridge;
-
-       /* Analog video */
-       u32                        resources;
-       unsigned int               input;
-       unsigned int               audinput; /* Selectable audio input */
-       u32                        tvaudio;
-       v4l2_std_id                tvnorm;
-       unsigned int               tuner_type;
-       unsigned char              tuner_addr;
-       unsigned int               tuner_bus;
-       unsigned int               radio_type;
-       unsigned char              radio_addr;
-       unsigned int               has_radio;
-       struct v4l2_subdev         *sd_cx25840;
-       struct work_struct         cx25840_work;
-
-       /* Infrared */
-       struct v4l2_subdev         *sd_ir;
-       struct work_struct         ir_rx_work;
-       unsigned long              ir_rx_notifications;
-       struct work_struct         ir_tx_work;
-       unsigned long              ir_tx_notifications;
-
-       struct cx23885_kernel_ir   *kernel_ir;
-       atomic_t                   ir_input_stopping;
-
-       /* V4l */
-       u32                        freq;
-       struct video_device        *video_dev;
-       struct video_device        *vbi_dev;
-       struct video_device        *radio_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;
-
-       /* Analog raw audio */
-       struct cx23885_audio_dev   *audio_dev;
-
-};
-
-static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct cx23885_dev, v4l2_dev);
-}
-
-#define call_all(dev, o, f, args...) \
-       v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
-
-#define CX23885_HW_888_IR  (1 << 0)
-#define CX23885_HW_AV_CORE (1 << 1)
-
-#define call_hw(dev, grpid, o, f, args...) \
-       v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args)
-
-extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw);
-
-#define SRAM_CH01  0 /* Video A */
-#define SRAM_CH02  1 /* VBI A */
-#define SRAM_CH03  2 /* Video B */
-#define SRAM_CH04  3 /* Transport via B */
-#define SRAM_CH05  4 /* VBI B */
-#define SRAM_CH06  5 /* Video C */
-#define SRAM_CH07  6 /* Transport via C */
-#define SRAM_CH08  7 /* Audio Internal A */
-#define SRAM_CH09  8 /* Audio Internal B */
-#define SRAM_CH10  9 /* Audio External */
-#define SRAM_CH11 10 /* COMB_3D_N */
-#define SRAM_CH12 11 /* Comb 3D N1 */
-#define SRAM_CH13 12 /* Comb 3D N2 */
-#define SRAM_CH14 13 /* MOE Vid */
-#define SRAM_CH15 14 /* MOE RSLT */
-
-struct sram_channel {
-       char *name;
-       u32  cmds_start;
-       u32  ctrl_start;
-       u32  cdt;
-       u32  fifo_start;
-       u32  fifo_size;
-       u32  ptr1_reg;
-       u32  ptr2_reg;
-       u32  cnt1_reg;
-       u32  cnt2_reg;
-       u32  jumponly;
-};
-
-/* ----------------------------------------------------------- */
-
-#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
-#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
-
-#define cx_andor(reg, mask, value) \
-  writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
-  ((value) & (mask)), dev->lmmio+((reg)>>2))
-
-#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
-#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
-
-/* ----------------------------------------------------------- */
-/* cx23885-core.c                                              */
-
-extern int cx23885_sram_channel_setup(struct cx23885_dev *dev,
-       struct sram_channel *ch,
-       unsigned int bpl, u32 risc);
-
-extern void cx23885_sram_channel_dump(struct cx23885_dev *dev,
-       struct sram_channel *ch);
-
-extern int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-       u32 reg, u32 mask, u32 value);
-
-extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-       struct scatterlist *sglist,
-       unsigned int top_offset, unsigned int bottom_offset,
-       unsigned int bpl, unsigned int padding, unsigned int lines);
-
-extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
-       struct btcx_riscmem *risc, struct scatterlist *sglist,
-       unsigned int top_offset, unsigned int bottom_offset,
-       unsigned int bpl, unsigned int padding, unsigned int lines);
-
-void cx23885_cancel_buffers(struct cx23885_tsport *port);
-
-extern int cx23885_restart_queue(struct cx23885_tsport *port,
-                               struct cx23885_dmaqueue *q);
-
-extern void cx23885_wakeup(struct cx23885_tsport *port,
-                          struct cx23885_dmaqueue *q, u32 count);
-
-extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask);
-extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask);
-extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask);
-extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
-       int asoutput);
-
-extern void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask);
-extern void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask);
-extern void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask);
-extern void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask);
-
-/* ----------------------------------------------------------- */
-/* cx23885-cards.c                                             */
-extern struct cx23885_board cx23885_boards[];
-extern const unsigned int cx23885_bcount;
-
-extern struct cx23885_subid cx23885_subids[];
-extern const unsigned int cx23885_idcount;
-
-extern int cx23885_tuner_callback(void *priv, int component,
-       int command, int arg);
-extern void cx23885_card_list(struct cx23885_dev *dev);
-extern int  cx23885_ir_init(struct cx23885_dev *dev);
-extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev);
-extern void cx23885_ir_fini(struct cx23885_dev *dev);
-extern void cx23885_gpio_setup(struct cx23885_dev *dev);
-extern void cx23885_card_setup(struct cx23885_dev *dev);
-extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);
-
-extern int cx23885_dvb_register(struct cx23885_tsport *port);
-extern int cx23885_dvb_unregister(struct cx23885_tsport *port);
-
-extern int cx23885_buf_prepare(struct videobuf_queue *q,
-                              struct cx23885_tsport *port,
-                              struct cx23885_buffer *buf,
-                              enum v4l2_field field);
-extern void cx23885_buf_queue(struct cx23885_tsport *port,
-                             struct cx23885_buffer *buf);
-extern void cx23885_free_buffer(struct videobuf_queue *q,
-                               struct cx23885_buffer *buf);
-
-/* ----------------------------------------------------------- */
-/* cx23885-video.c                                             */
-/* Video */
-extern int cx23885_video_register(struct cx23885_dev *dev);
-extern void cx23885_video_unregister(struct cx23885_dev *dev);
-extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
-extern void cx23885_video_wakeup(struct cx23885_dev *dev,
-       struct cx23885_dmaqueue *q, u32 count);
-int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i);
-int cx23885_set_input(struct file *file, void *priv, unsigned int i);
-int cx23885_get_input(struct file *file, void *priv, unsigned int *i);
-int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
-int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
-int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
-int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm);
-
-/* ----------------------------------------------------------- */
-/* cx23885-vbi.c                                               */
-extern int cx23885_vbi_fmt(struct file *file, void *priv,
-       struct v4l2_format *f);
-extern void cx23885_vbi_timeout(unsigned long data);
-extern struct videobuf_queue_ops cx23885_vbi_qops;
-extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
-       struct cx23885_dmaqueue *q);
-extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
-
-/* cx23885-i2c.c                                                */
-extern int cx23885_i2c_register(struct cx23885_i2c *bus);
-extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
-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);
-extern int mc417_register_read(struct cx23885_dev *dev,
-                               u16 address, u32 *value);
-extern int mc417_register_write(struct cx23885_dev *dev,
-                               u16 address, u32 value);
-extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
-extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
-extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
-
-/* ----------------------------------------------------------- */
-/* cx23885-alsa.c                                             */
-extern struct cx23885_audio_dev *cx23885_audio_register(
-                                       struct cx23885_dev *dev);
-extern void cx23885_audio_unregister(struct cx23885_dev *dev);
-extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
-extern int cx23885_risc_databuffer(struct pci_dev *pci,
-                                  struct btcx_riscmem *risc,
-                                  struct scatterlist *sglist,
-                                  unsigned int bpl,
-                                  unsigned int lines,
-                                  unsigned int lpi);
-
-/* ----------------------------------------------------------- */
-/* tv norms                                                    */
-
-static inline unsigned int norm_maxw(v4l2_std_id norm)
-{
-       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
-}
-
-static inline unsigned int norm_maxh(v4l2_std_id norm)
-{
-       return (norm & V4L2_STD_625_50) ? 576 : 480;
-}
-
-static inline unsigned int norm_swidth(v4l2_std_id norm)
-{
-       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
-}
diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c
deleted file mode 100644 (file)
index c2bc39c..0000000
+++ /dev/null
@@ -1,1271 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  CX23888 Integrated Consumer Infrared Controller
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include <linux/kfifo.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/rc-core.h>
-
-#include "cx23885.h"
-
-static unsigned int ir_888_debug;
-module_param(ir_888_debug, int, 0644);
-MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
-
-#define CX23888_IR_REG_BASE    0x170000
-/*
- * These CX23888 register offsets have a straightforward one to one mapping
- * to the CX23885 register offsets of 0x200 through 0x218
- */
-#define CX23888_IR_CNTRL_REG   0x170000
-#define CNTRL_WIN_3_3  0x00000000
-#define CNTRL_WIN_4_3  0x00000001
-#define CNTRL_WIN_3_4  0x00000002
-#define CNTRL_WIN_4_4  0x00000003
-#define CNTRL_WIN      0x00000003
-#define CNTRL_EDG_NONE 0x00000000
-#define CNTRL_EDG_FALL 0x00000004
-#define CNTRL_EDG_RISE 0x00000008
-#define CNTRL_EDG_BOTH 0x0000000C
-#define CNTRL_EDG      0x0000000C
-#define CNTRL_DMD      0x00000010
-#define CNTRL_MOD      0x00000020
-#define CNTRL_RFE      0x00000040
-#define CNTRL_TFE      0x00000080
-#define CNTRL_RXE      0x00000100
-#define CNTRL_TXE      0x00000200
-#define CNTRL_RIC      0x00000400
-#define CNTRL_TIC      0x00000800
-#define CNTRL_CPL      0x00001000
-#define CNTRL_LBM      0x00002000
-#define CNTRL_R                0x00004000
-/* CX23888 specific control flag */
-#define CNTRL_IVO      0x00008000
-
-#define CX23888_IR_TXCLK_REG   0x170004
-#define TXCLK_TCD      0x0000FFFF
-
-#define CX23888_IR_RXCLK_REG   0x170008
-#define RXCLK_RCD      0x0000FFFF
-
-#define CX23888_IR_CDUTY_REG   0x17000C
-#define CDUTY_CDC      0x0000000F
-
-#define CX23888_IR_STATS_REG   0x170010
-#define STATS_RTO      0x00000001
-#define STATS_ROR      0x00000002
-#define STATS_RBY      0x00000004
-#define STATS_TBY      0x00000008
-#define STATS_RSR      0x00000010
-#define STATS_TSR      0x00000020
-
-#define CX23888_IR_IRQEN_REG   0x170014
-#define IRQEN_RTE      0x00000001
-#define IRQEN_ROE      0x00000002
-#define IRQEN_RSE      0x00000010
-#define IRQEN_TSE      0x00000020
-
-#define CX23888_IR_FILTR_REG   0x170018
-#define FILTR_LPF      0x0000FFFF
-
-/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
-#define CX23888_IR_FIFO_REG    0x170040
-#define FIFO_RXTX      0x0000FFFF
-#define FIFO_RXTX_LVL  0x00010000
-#define FIFO_RXTX_RTO  0x0001FFFF
-#define FIFO_RX_NDV    0x00020000
-#define FIFO_RX_DEPTH  8
-#define FIFO_TX_DEPTH  8
-
-/* CX23888 unique registers */
-#define CX23888_IR_SEEDP_REG   0x17001C
-#define CX23888_IR_TIMOL_REG   0x170020
-#define CX23888_IR_WAKE0_REG   0x170024
-#define CX23888_IR_WAKE1_REG   0x170028
-#define CX23888_IR_WAKE2_REG   0x17002C
-#define CX23888_IR_MASK0_REG   0x170030
-#define CX23888_IR_MASK1_REG   0x170034
-#define CX23888_IR_MAKS2_REG   0x170038
-#define CX23888_IR_DPIPG_REG   0x17003C
-#define CX23888_IR_LEARN_REG   0x170044
-
-#define CX23888_VIDCLK_FREQ    108000000 /* 108 MHz, BT.656 */
-#define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2)
-
-/*
- * We use this union internally for convenience, but callers to tx_write
- * and rx_read will be expecting records of type struct ir_raw_event.
- * Always ensure the size of this union is dictated by struct ir_raw_event.
- */
-union cx23888_ir_fifo_rec {
-       u32 hw_fifo_data;
-       struct ir_raw_event ir_core_data;
-};
-
-#define CX23888_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
-#define CX23888_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
-
-struct cx23888_ir_state {
-       struct v4l2_subdev sd;
-       struct cx23885_dev *dev;
-       u32 id;
-       u32 rev;
-
-       struct v4l2_subdev_ir_parameters rx_params;
-       struct mutex rx_params_lock;
-       atomic_t rxclk_divider;
-       atomic_t rx_invert;
-
-       struct kfifo rx_kfifo;
-       spinlock_t rx_kfifo_lock;
-
-       struct v4l2_subdev_ir_parameters tx_params;
-       struct mutex tx_params_lock;
-       atomic_t txclk_divider;
-};
-
-static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
-{
-       return v4l2_get_subdevdata(sd);
-}
-
-/*
- * IR register block read and write functions
- */
-static
-inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
-{
-       cx_write(addr, value);
-       return 0;
-}
-
-static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
-{
-       return cx_read(addr);
-}
-
-static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
-                                    u32 and_mask, u32 or_value)
-{
-       cx_andor(addr, ~and_mask, or_value);
-       return 0;
-}
-
-/*
- * Rx and Tx Clock Divider register computations
- *
- * Note the largest clock divider value of 0xffff corresponds to:
- *     (0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
- * which fits in 21 bits, so we'll use unsigned int for time arguments.
- */
-static inline u16 count_to_clock_divider(unsigned int d)
-{
-       if (d > RXCLK_RCD + 1)
-               d = RXCLK_RCD;
-       else if (d < 2)
-               d = 1;
-       else
-               d--;
-       return (u16) d;
-}
-
-static inline u16 ns_to_clock_divider(unsigned int ns)
-{
-       return count_to_clock_divider(
-               DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
-}
-
-static inline unsigned int clock_divider_to_ns(unsigned int divider)
-{
-       /* Period of the Rx or Tx clock in ns */
-       return DIV_ROUND_CLOSEST((divider + 1) * 1000,
-                                CX23888_IR_REFCLK_FREQ / 1000000);
-}
-
-static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
-{
-       return count_to_clock_divider(
-                         DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16));
-}
-
-static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
-{
-       return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16);
-}
-
-static inline u16 freq_to_clock_divider(unsigned int freq,
-                                       unsigned int rollovers)
-{
-       return count_to_clock_divider(
-                  DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers));
-}
-
-static inline unsigned int clock_divider_to_freq(unsigned int divider,
-                                                unsigned int rollovers)
-{
-       return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ,
-                                (divider + 1) * rollovers);
-}
-
-/*
- * Low Pass Filter register calculations
- *
- * Note the largest count value of 0xffff corresponds to:
- *     0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
- * which fits in 21 bits, so we'll use unsigned int for time arguments.
- */
-static inline u16 count_to_lpf_count(unsigned int d)
-{
-       if (d > FILTR_LPF)
-               d = FILTR_LPF;
-       else if (d < 4)
-               d = 0;
-       return (u16) d;
-}
-
-static inline u16 ns_to_lpf_count(unsigned int ns)
-{
-       return count_to_lpf_count(
-               DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
-}
-
-static inline unsigned int lpf_count_to_ns(unsigned int count)
-{
-       /* Duration of the Low Pass Filter rejection window in ns */
-       return DIV_ROUND_CLOSEST(count * 1000,
-                                CX23888_IR_REFCLK_FREQ / 1000000);
-}
-
-static inline unsigned int lpf_count_to_us(unsigned int count)
-{
-       /* Duration of the Low Pass Filter rejection window in us */
-       return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000);
-}
-
-/*
- * FIFO register pulse width count compuations
- */
-static u32 clock_divider_to_resolution(u16 divider)
-{
-       /*
-        * Resolution is the duration of 1 tick of the readable portion of
-        * of the pulse width counter as read from the FIFO.  The two lsb's are
-        * not readable, hence the << 2.  This function returns ns.
-        */
-       return DIV_ROUND_CLOSEST((1 << 2)  * ((u32) divider + 1) * 1000,
-                                CX23888_IR_REFCLK_FREQ / 1000000);
-}
-
-static u64 pulse_width_count_to_ns(u16 count, u16 divider)
-{
-       u64 n;
-       u32 rem;
-
-       /*
-        * The 2 lsb's of the pulse width timer count are not readable, hence
-        * the (count << 2) | 0x3
-        */
-       n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
-       rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000);     /* / MHz => ns */
-       if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
-               n++;
-       return n;
-}
-
-static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
-{
-       u64 n;
-       u32 rem;
-
-       /*
-        * The 2 lsb's of the pulse width timer count are not readable, hence
-        * the (count << 2) | 0x3
-        */
-       n = (((u64) count << 2) | 0x3) * (divider + 1);    /* cycles      */
-       rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
-       if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
-               n++;
-       return (unsigned int) n;
-}
-
-/*
- * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
- *
- * The total pulse clock count is an 18 bit pulse width timer count as the most
- * significant part and (up to) 16 bit clock divider count as a modulus.
- * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
- * width timer count's least significant bit.
- */
-static u64 ns_to_pulse_clocks(u32 ns)
-{
-       u64 clocks;
-       u32 rem;
-       clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles  */
-       rem = do_div(clocks, 1000);                         /* /1000 = cycles */
-       if (rem >= 1000 / 2)
-               clocks++;
-       return clocks;
-}
-
-static u16 pulse_clocks_to_clock_divider(u64 count)
-{
-       do_div(count, (FIFO_RXTX << 2) | 0x3);
-
-       /* net result needs to be rounded down and decremented by 1 */
-       if (count > RXCLK_RCD + 1)
-               count = RXCLK_RCD;
-       else if (count < 2)
-               count = 1;
-       else
-               count--;
-       return (u16) count;
-}
-
-/*
- * IR Control Register helpers
- */
-enum tx_fifo_watermark {
-       TX_FIFO_HALF_EMPTY = 0,
-       TX_FIFO_EMPTY      = CNTRL_TIC,
-};
-
-enum rx_fifo_watermark {
-       RX_FIFO_HALF_FULL = 0,
-       RX_FIFO_NOT_EMPTY = CNTRL_RIC,
-};
-
-static inline void control_tx_irq_watermark(struct cx23885_dev *dev,
-                                           enum tx_fifo_watermark level)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level);
-}
-
-static inline void control_rx_irq_watermark(struct cx23885_dev *dev,
-                                           enum rx_fifo_watermark level)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level);
-}
-
-static inline void control_tx_enable(struct cx23885_dev *dev, bool enable)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
-                          enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
-}
-
-static inline void control_rx_enable(struct cx23885_dev *dev, bool enable)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
-                          enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
-}
-
-static inline void control_tx_modulation_enable(struct cx23885_dev *dev,
-                                               bool enable)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD,
-                          enable ? CNTRL_MOD : 0);
-}
-
-static inline void control_rx_demodulation_enable(struct cx23885_dev *dev,
-                                                 bool enable)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD,
-                          enable ? CNTRL_DMD : 0);
-}
-
-static inline void control_rx_s_edge_detection(struct cx23885_dev *dev,
-                                              u32 edge_types)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
-                          edge_types & CNTRL_EDG_BOTH);
-}
-
-static void control_rx_s_carrier_window(struct cx23885_dev *dev,
-                                       unsigned int carrier,
-                                       unsigned int *carrier_range_low,
-                                       unsigned int *carrier_range_high)
-{
-       u32 v;
-       unsigned int c16 = carrier * 16;
-
-       if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
-               v = CNTRL_WIN_3_4;
-               *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
-       } else {
-               v = CNTRL_WIN_3_3;
-               *carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
-       }
-
-       if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
-               v |= CNTRL_WIN_4_3;
-               *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
-       } else {
-               v |= CNTRL_WIN_3_3;
-               *carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
-       }
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v);
-}
-
-static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
-                                             bool invert)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL,
-                          invert ? CNTRL_CPL : 0);
-}
-
-static inline void control_tx_level_invert(struct cx23885_dev *dev,
-                                         bool invert)
-{
-       cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO,
-                          invert ? CNTRL_IVO : 0);
-}
-
-/*
- * IR Rx & Tx Clock Register helpers
- */
-static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev,
-                                      unsigned int freq,
-                                      u16 *divider)
-{
-       *divider = carrier_freq_to_clock_divider(freq);
-       cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
-       return clock_divider_to_carrier_freq(*divider);
-}
-
-static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev,
-                                      unsigned int freq,
-                                      u16 *divider)
-{
-       *divider = carrier_freq_to_clock_divider(freq);
-       cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
-       return clock_divider_to_carrier_freq(*divider);
-}
-
-static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
-                                     u16 *divider)
-{
-       u64 pulse_clocks;
-
-       if (ns > IR_MAX_DURATION)
-               ns = IR_MAX_DURATION;
-       pulse_clocks = ns_to_pulse_clocks(ns);
-       *divider = pulse_clocks_to_clock_divider(pulse_clocks);
-       cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
-       return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
-}
-
-static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
-                                     u16 *divider)
-{
-       u64 pulse_clocks;
-
-       if (ns > IR_MAX_DURATION)
-               ns = IR_MAX_DURATION;
-       pulse_clocks = ns_to_pulse_clocks(ns);
-       *divider = pulse_clocks_to_clock_divider(pulse_clocks);
-       cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
-       return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
-}
-
-/*
- * IR Tx Carrier Duty Cycle register helpers
- */
-static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev,
-                                         unsigned int duty_cycle)
-{
-       u32 n;
-       n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
-       if (n != 0)
-               n--;
-       if (n > 15)
-               n = 15;
-       cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n);
-       return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
-}
-
-/*
- * IR Filter Register helpers
- */
-static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns)
-{
-       u32 count = ns_to_lpf_count(min_width_ns);
-       cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count);
-       return lpf_count_to_ns(count);
-}
-
-/*
- * IR IRQ Enable Register helpers
- */
-static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask)
-{
-       mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
-       cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG,
-                          ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
-}
-
-static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask)
-{
-       mask &= IRQEN_TSE;
-       cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask);
-}
-
-/*
- * V4L2 Subdevice IR Ops
- */
-static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
-                                 bool *handled)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-       unsigned long flags;
-
-       u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
-       u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
-       u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
-
-       union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
-       unsigned int i, j, k;
-       u32 events, v;
-       int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
-
-       tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
-       rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
-       rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
-       ror = stats & STATS_ROR; /* Rx FIFO Over Run */
-
-       tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
-       rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
-       rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
-       roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
-
-       *handled = false;
-       v4l2_dbg(2, ir_888_debug, sd, "IRQ Status:  %s %s %s %s %s %s\n",
-                tsr ? "tsr" : "   ", rsr ? "rsr" : "   ",
-                rto ? "rto" : "   ", ror ? "ror" : "   ",
-                stats & STATS_TBY ? "tby" : "   ",
-                stats & STATS_RBY ? "rby" : "   ");
-
-       v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
-                tse ? "tse" : "   ", rse ? "rse" : "   ",
-                rte ? "rte" : "   ", roe ? "roe" : "   ");
-
-       /*
-        * Transmitter interrupt service
-        */
-       if (tse && tsr) {
-               /*
-                * TODO:
-                * Check the watermark threshold setting
-                * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
-                * Push the data to the hardware FIFO.
-                * If there was nothing more to send in the tx_kfifo, disable
-                *      the TSR IRQ and notify the v4l2_device.
-                * If there was something in the tx_kfifo, check the tx_kfifo
-                *      level and notify the v4l2_device, if it is low.
-                */
-               /* For now, inhibit TSR interrupt until Tx is implemented */
-               irqenable_tx(dev, 0);
-               events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
-               v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
-               *handled = true;
-       }
-
-       /*
-        * Receiver interrupt service
-        */
-       kror = 0;
-       if ((rse && rsr) || (rte && rto)) {
-               /*
-                * Receive data on RSR to clear the STATS_RSR.
-                * Receive data on RTO, since we may not have yet hit the RSR
-                * watermark when we receive the RTO.
-                */
-               for (i = 0, v = FIFO_RX_NDV;
-                    (v & FIFO_RX_NDV) && !kror; i = 0) {
-                       for (j = 0;
-                            (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
-                               v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
-                               rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
-                               i++;
-                       }
-                       if (i == 0)
-                               break;
-                       j = i * sizeof(union cx23888_ir_fifo_rec);
-                       k = kfifo_in_locked(&state->rx_kfifo,
-                                     (unsigned char *) rx_data, j,
-                                     &state->rx_kfifo_lock);
-                       if (k != j)
-                               kror++; /* rx_kfifo over run */
-               }
-               *handled = true;
-       }
-
-       events = 0;
-       v = 0;
-       if (kror) {
-               events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
-               v4l2_err(sd, "IR receiver software FIFO overrun\n");
-       }
-       if (roe && ror) {
-               /*
-                * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
-                * the Rx FIFO Over Run status (STATS_ROR)
-                */
-               v |= CNTRL_RFE;
-               events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
-               v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
-       }
-       if (rte && rto) {
-               /*
-                * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
-                * the Rx Pulse Width Timer Time Out (STATS_RTO)
-                */
-               v |= CNTRL_RXE;
-               events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
-       }
-       if (v) {
-               /* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
-               cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
-               cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
-               *handled = true;
-       }
-
-       spin_lock_irqsave(&state->rx_kfifo_lock, flags);
-       if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
-               events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
-       spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
-
-       if (events)
-               v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
-       return 0;
-}
-
-/* Receiver */
-static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
-                             ssize_t *num)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       bool invert = (bool) atomic_read(&state->rx_invert);
-       u16 divider = (u16) atomic_read(&state->rxclk_divider);
-
-       unsigned int i, n;
-       union cx23888_ir_fifo_rec *p;
-       unsigned u, v, w;
-
-       n = count / sizeof(union cx23888_ir_fifo_rec)
-               * sizeof(union cx23888_ir_fifo_rec);
-       if (n == 0) {
-               *num = 0;
-               return 0;
-       }
-
-       n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
-
-       n /= sizeof(union cx23888_ir_fifo_rec);
-       *num = n * sizeof(union cx23888_ir_fifo_rec);
-
-       for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
-
-               if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
-                       /* Assume RTO was because of no IR light input */
-                       u = 0;
-                       w = 1;
-               } else {
-                       u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
-                       if (invert)
-                               u = u ? 0 : 1;
-                       w = 0;
-               }
-
-               v = (unsigned) pulse_width_count_to_ns(
-                                 (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
-               if (v > IR_MAX_DURATION)
-                       v = IR_MAX_DURATION;
-
-               init_ir_raw_event(&p->ir_core_data);
-               p->ir_core_data.pulse = u;
-               p->ir_core_data.duration = v;
-               p->ir_core_data.timeout = w;
-
-               v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s  %s\n",
-                        v, u ? "mark" : "space", w ? "(timed out)" : "");
-               if (w)
-                       v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
-       }
-       return 0;
-}
-
-static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd,
-                                     struct v4l2_subdev_ir_parameters *p)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       mutex_lock(&state->rx_params_lock);
-       memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters));
-       mutex_unlock(&state->rx_params_lock);
-       return 0;
-}
-
-static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-
-       mutex_lock(&state->rx_params_lock);
-
-       /* Disable or slow down all IR Rx circuits and counters */
-       irqenable_rx(dev, 0);
-       control_rx_enable(dev, false);
-       control_rx_demodulation_enable(dev, false);
-       control_rx_s_edge_detection(dev, CNTRL_EDG_NONE);
-       filter_rx_s_min_width(dev, 0);
-       cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD);
-
-       state->rx_params.shutdown = true;
-
-       mutex_unlock(&state->rx_params_lock);
-       return 0;
-}
-
-static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
-                                     struct v4l2_subdev_ir_parameters *p)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-       struct v4l2_subdev_ir_parameters *o = &state->rx_params;
-       u16 rxclk_divider;
-
-       if (p->shutdown)
-               return cx23888_ir_rx_shutdown(sd);
-
-       if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
-               return -ENOSYS;
-
-       mutex_lock(&state->rx_params_lock);
-
-       o->shutdown = p->shutdown;
-
-       o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
-
-       o->bytes_per_data_element = p->bytes_per_data_element
-                                 = sizeof(union cx23888_ir_fifo_rec);
-
-       /* Before we tweak the hardware, we have to disable the receiver */
-       irqenable_rx(dev, 0);
-       control_rx_enable(dev, false);
-
-       control_rx_demodulation_enable(dev, p->modulation);
-       o->modulation = p->modulation;
-
-       if (p->modulation) {
-               p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq,
-                                                    &rxclk_divider);
-
-               o->carrier_freq = p->carrier_freq;
-
-               o->duty_cycle = p->duty_cycle = 50;
-
-               control_rx_s_carrier_window(dev, p->carrier_freq,
-                                           &p->carrier_range_lower,
-                                           &p->carrier_range_upper);
-               o->carrier_range_lower = p->carrier_range_lower;
-               o->carrier_range_upper = p->carrier_range_upper;
-
-               p->max_pulse_width =
-                       (u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
-       } else {
-               p->max_pulse_width =
-                           rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
-                                                      &rxclk_divider);
-       }
-       o->max_pulse_width = p->max_pulse_width;
-       atomic_set(&state->rxclk_divider, rxclk_divider);
-
-       p->noise_filter_min_width =
-                         filter_rx_s_min_width(dev, p->noise_filter_min_width);
-       o->noise_filter_min_width = p->noise_filter_min_width;
-
-       p->resolution = clock_divider_to_resolution(rxclk_divider);
-       o->resolution = p->resolution;
-
-       /* FIXME - make this dependent on resolution for better performance */
-       control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL);
-
-       control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
-
-       o->invert_level = p->invert_level;
-       atomic_set(&state->rx_invert, p->invert_level);
-
-       o->interrupt_enable = p->interrupt_enable;
-       o->enable = p->enable;
-       if (p->enable) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&state->rx_kfifo_lock, flags);
-               kfifo_reset(&state->rx_kfifo);
-               /* reset tx_fifo too if there is one... */
-               spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
-               if (p->interrupt_enable)
-                       irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
-               control_rx_enable(dev, p->enable);
-       }
-
-       mutex_unlock(&state->rx_params_lock);
-       return 0;
-}
-
-/* Transmitter */
-static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
-                              ssize_t *num)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-       /* For now enable the Tx FIFO Service interrupt & pretend we did work */
-       irqenable_tx(dev, IRQEN_TSE);
-       *num = count;
-       return 0;
-}
-
-static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd,
-                                     struct v4l2_subdev_ir_parameters *p)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       mutex_lock(&state->tx_params_lock);
-       memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters));
-       mutex_unlock(&state->tx_params_lock);
-       return 0;
-}
-
-static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-
-       mutex_lock(&state->tx_params_lock);
-
-       /* Disable or slow down all IR Tx circuits and counters */
-       irqenable_tx(dev, 0);
-       control_tx_enable(dev, false);
-       control_tx_modulation_enable(dev, false);
-       cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD);
-
-       state->tx_params.shutdown = true;
-
-       mutex_unlock(&state->tx_params_lock);
-       return 0;
-}
-
-static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
-                                     struct v4l2_subdev_ir_parameters *p)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-       struct v4l2_subdev_ir_parameters *o = &state->tx_params;
-       u16 txclk_divider;
-
-       if (p->shutdown)
-               return cx23888_ir_tx_shutdown(sd);
-
-       if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
-               return -ENOSYS;
-
-       mutex_lock(&state->tx_params_lock);
-
-       o->shutdown = p->shutdown;
-
-       o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
-
-       o->bytes_per_data_element = p->bytes_per_data_element
-                                 = sizeof(union cx23888_ir_fifo_rec);
-
-       /* Before we tweak the hardware, we have to disable the transmitter */
-       irqenable_tx(dev, 0);
-       control_tx_enable(dev, false);
-
-       control_tx_modulation_enable(dev, p->modulation);
-       o->modulation = p->modulation;
-
-       if (p->modulation) {
-               p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq,
-                                                    &txclk_divider);
-               o->carrier_freq = p->carrier_freq;
-
-               p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
-               o->duty_cycle = p->duty_cycle;
-
-               p->max_pulse_width =
-                       (u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
-       } else {
-               p->max_pulse_width =
-                           txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
-                                                      &txclk_divider);
-       }
-       o->max_pulse_width = p->max_pulse_width;
-       atomic_set(&state->txclk_divider, txclk_divider);
-
-       p->resolution = clock_divider_to_resolution(txclk_divider);
-       o->resolution = p->resolution;
-
-       /* FIXME - make this dependent on resolution for better performance */
-       control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
-
-       control_tx_polarity_invert(dev, p->invert_carrier_sense);
-       o->invert_carrier_sense = p->invert_carrier_sense;
-
-       control_tx_level_invert(dev, p->invert_level);
-       o->invert_level = p->invert_level;
-
-       o->interrupt_enable = p->interrupt_enable;
-       o->enable = p->enable;
-       if (p->enable) {
-               if (p->interrupt_enable)
-                       irqenable_tx(dev, IRQEN_TSE);
-               control_tx_enable(dev, p->enable);
-       }
-
-       mutex_unlock(&state->tx_params_lock);
-       return 0;
-}
-
-
-/*
- * V4L2 Subdevice Core Ops
- */
-static int cx23888_ir_log_status(struct v4l2_subdev *sd)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       struct cx23885_dev *dev = state->dev;
-       char *s;
-       int i, j;
-
-       u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
-       u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD;
-       u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD;
-       u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC;
-       u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
-       u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
-       u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF;
-
-       v4l2_info(sd, "IR Receiver:\n");
-       v4l2_info(sd, "\tEnabled:                           %s\n",
-                 cntrl & CNTRL_RXE ? "yes" : "no");
-       v4l2_info(sd, "\tDemodulation from a carrier:       %s\n",
-                 cntrl & CNTRL_DMD ? "enabled" : "disabled");
-       v4l2_info(sd, "\tFIFO:                              %s\n",
-                 cntrl & CNTRL_RFE ? "enabled" : "disabled");
-       switch (cntrl & CNTRL_EDG) {
-       case CNTRL_EDG_NONE:
-               s = "disabled";
-               break;
-       case CNTRL_EDG_FALL:
-               s = "falling edge";
-               break;
-       case CNTRL_EDG_RISE:
-               s = "rising edge";
-               break;
-       case CNTRL_EDG_BOTH:
-               s = "rising & falling edges";
-               break;
-       default:
-               s = "??? edge";
-               break;
-       }
-       v4l2_info(sd, "\tPulse timers' start/stop trigger:  %s\n", s);
-       v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
-                 cntrl & CNTRL_R ? "not loaded" : "overflow marker");
-       v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
-                 cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
-       v4l2_info(sd, "\tLoopback mode:                     %s\n",
-                 cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
-       if (cntrl & CNTRL_DMD) {
-               v4l2_info(sd, "\tExpected carrier (16 clocks):      %u Hz\n",
-                         clock_divider_to_carrier_freq(rxclk));
-               switch (cntrl & CNTRL_WIN) {
-               case CNTRL_WIN_3_3:
-                       i = 3;
-                       j = 3;
-                       break;
-               case CNTRL_WIN_4_3:
-                       i = 4;
-                       j = 3;
-                       break;
-               case CNTRL_WIN_3_4:
-                       i = 3;
-                       j = 4;
-                       break;
-               case CNTRL_WIN_4_4:
-                       i = 4;
-                       j = 4;
-                       break;
-               default:
-                       i = 0;
-                       j = 0;
-                       break;
-               }
-               v4l2_info(sd, "\tNext carrier edge window:          16 clocks "
-                         "-%1d/+%1d, %u to %u Hz\n", i, j,
-                         clock_divider_to_freq(rxclk, 16 + j),
-                         clock_divider_to_freq(rxclk, 16 - i));
-       }
-       v4l2_info(sd, "\tMax measurable pulse width:        %u us, %llu ns\n",
-                 pulse_width_count_to_us(FIFO_RXTX, rxclk),
-                 pulse_width_count_to_ns(FIFO_RXTX, rxclk));
-       v4l2_info(sd, "\tLow pass filter:                   %s\n",
-                 filtr ? "enabled" : "disabled");
-       if (filtr)
-               v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, "
-                         "%u ns\n",
-                         lpf_count_to_us(filtr),
-                         lpf_count_to_ns(filtr));
-       v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
-                 stats & STATS_RTO ? "yes" : "no");
-       v4l2_info(sd, "\tPulse width timer time-out intr:   %s\n",
-                 irqen & IRQEN_RTE ? "enabled" : "disabled");
-       v4l2_info(sd, "\tFIFO overrun:                      %s\n",
-                 stats & STATS_ROR ? "yes" : "no");
-       v4l2_info(sd, "\tFIFO overrun interrupt:            %s\n",
-                 irqen & IRQEN_ROE ? "enabled" : "disabled");
-       v4l2_info(sd, "\tBusy:                              %s\n",
-                 stats & STATS_RBY ? "yes" : "no");
-       v4l2_info(sd, "\tFIFO service requested:            %s\n",
-                 stats & STATS_RSR ? "yes" : "no");
-       v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
-                 irqen & IRQEN_RSE ? "enabled" : "disabled");
-
-       v4l2_info(sd, "IR Transmitter:\n");
-       v4l2_info(sd, "\tEnabled:                           %s\n",
-                 cntrl & CNTRL_TXE ? "yes" : "no");
-       v4l2_info(sd, "\tModulation onto a carrier:         %s\n",
-                 cntrl & CNTRL_MOD ? "enabled" : "disabled");
-       v4l2_info(sd, "\tFIFO:                              %s\n",
-                 cntrl & CNTRL_TFE ? "enabled" : "disabled");
-       v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
-                 cntrl & CNTRL_TIC ? "not empty" : "half full or less");
-       v4l2_info(sd, "\tOutput pin level inversion         %s\n",
-                 cntrl & CNTRL_IVO ? "yes" : "no");
-       v4l2_info(sd, "\tCarrier polarity:                  %s\n",
-                 cntrl & CNTRL_CPL ? "space:burst mark:noburst"
-                                   : "space:noburst mark:burst");
-       if (cntrl & CNTRL_MOD) {
-               v4l2_info(sd, "\tCarrier (16 clocks):               %u Hz\n",
-                         clock_divider_to_carrier_freq(txclk));
-               v4l2_info(sd, "\tCarrier duty cycle:                %2u/16\n",
-                         cduty + 1);
-       }
-       v4l2_info(sd, "\tMax pulse width:                   %u us, %llu ns\n",
-                 pulse_width_count_to_us(FIFO_RXTX, txclk),
-                 pulse_width_count_to_ns(FIFO_RXTX, txclk));
-       v4l2_info(sd, "\tBusy:                              %s\n",
-                 stats & STATS_TBY ? "yes" : "no");
-       v4l2_info(sd, "\tFIFO service requested:            %s\n",
-                 stats & STATS_TSR ? "yes" : "no");
-       v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
-                 irqen & IRQEN_TSE ? "enabled" : "disabled");
-
-       return 0;
-}
-
-static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match)
-{
-       return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2;
-}
-
-static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd,
-                                  struct v4l2_dbg_chip_ident *chip)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-
-       if (cx23888_ir_dbg_match(&chip->match)) {
-               chip->ident = state->id;
-               chip->revision = state->rev;
-       }
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int cx23888_ir_g_register(struct v4l2_subdev *sd,
-                                struct v4l2_dbg_register *reg)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
-
-       if (!cx23888_ir_dbg_match(&reg->match))
-               return -EINVAL;
-       if ((addr & 0x3) != 0)
-               return -EINVAL;
-       if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
-               return -EINVAL;
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       reg->size = 4;
-       reg->val = cx23888_ir_read4(state->dev, addr);
-       return 0;
-}
-
-static int cx23888_ir_s_register(struct v4l2_subdev *sd,
-                                struct v4l2_dbg_register *reg)
-{
-       struct cx23888_ir_state *state = to_state(sd);
-       u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
-
-       if (!cx23888_ir_dbg_match(&reg->match))
-               return -EINVAL;
-       if ((addr & 0x3) != 0)
-               return -EINVAL;
-       if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
-               return -EINVAL;
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       cx23888_ir_write4(state->dev, addr, reg->val);
-       return 0;
-}
-#endif
-
-static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
-       .g_chip_ident = cx23888_ir_g_chip_ident,
-       .log_status = cx23888_ir_log_status,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .g_register = cx23888_ir_g_register,
-       .s_register = cx23888_ir_s_register,
-#endif
-       .interrupt_service_routine = cx23888_ir_irq_handler,
-};
-
-static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
-       .rx_read = cx23888_ir_rx_read,
-       .rx_g_parameters = cx23888_ir_rx_g_parameters,
-       .rx_s_parameters = cx23888_ir_rx_s_parameters,
-
-       .tx_write = cx23888_ir_tx_write,
-       .tx_g_parameters = cx23888_ir_tx_g_parameters,
-       .tx_s_parameters = cx23888_ir_tx_s_parameters,
-};
-
-static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
-       .core = &cx23888_ir_core_ops,
-       .ir = &cx23888_ir_ir_ops,
-};
-
-static const struct v4l2_subdev_ir_parameters default_rx_params = {
-       .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
-       .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
-
-       .enable = false,
-       .interrupt_enable = false,
-       .shutdown = true,
-
-       .modulation = true,
-       .carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */
-
-       /* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
-       /* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
-       .noise_filter_min_width = 333333, /* ns */
-       .carrier_range_lower = 35000,
-       .carrier_range_upper = 37000,
-       .invert_level = false,
-};
-
-static const struct v4l2_subdev_ir_parameters default_tx_params = {
-       .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
-       .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
-
-       .enable = false,
-       .interrupt_enable = false,
-       .shutdown = true,
-
-       .modulation = true,
-       .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
-       .duty_cycle = 25,      /* 25 %   - RC-5 carrier */
-       .invert_level = false,
-       .invert_carrier_sense = false,
-};
-
-int cx23888_ir_probe(struct cx23885_dev *dev)
-{
-       struct cx23888_ir_state *state;
-       struct v4l2_subdev *sd;
-       struct v4l2_subdev_ir_parameters default_params;
-       int ret;
-
-       state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
-       if (state == NULL)
-               return -ENOMEM;
-
-       spin_lock_init(&state->rx_kfifo_lock);
-       if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
-               return -ENOMEM;
-
-       state->dev = dev;
-       state->id = V4L2_IDENT_CX23888_IR;
-       state->rev = 0;
-       sd = &state->sd;
-
-       v4l2_subdev_init(sd, &cx23888_ir_controller_ops);
-       v4l2_set_subdevdata(sd, state);
-       /* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
-       snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
-       sd->grp_id = CX23885_HW_888_IR;
-
-       ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd);
-       if (ret == 0) {
-               /*
-                * Ensure no interrupts arrive from '888 specific conditions,
-                * since we ignore them in this driver to have commonality with
-                * similar IR controller cores.
-                */
-               cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0);
-
-               mutex_init(&state->rx_params_lock);
-               memcpy(&default_params, &default_rx_params,
-                      sizeof(struct v4l2_subdev_ir_parameters));
-               v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
-
-               mutex_init(&state->tx_params_lock);
-               memcpy(&default_params, &default_tx_params,
-                      sizeof(struct v4l2_subdev_ir_parameters));
-               v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
-       } else {
-               kfifo_free(&state->rx_kfifo);
-       }
-       return ret;
-}
-
-int cx23888_ir_remove(struct cx23885_dev *dev)
-{
-       struct v4l2_subdev *sd;
-       struct cx23888_ir_state *state;
-
-       sd = cx23885_find_hw(dev, CX23885_HW_888_IR);
-       if (sd == NULL)
-               return -ENODEV;
-
-       cx23888_ir_rx_shutdown(sd);
-       cx23888_ir_tx_shutdown(sd);
-
-       state = to_state(sd);
-       v4l2_device_unregister_subdev(sd);
-       kfifo_free(&state->rx_kfifo);
-       kfree(state);
-       /* Nothing more to free() as state held the actual v4l2_subdev object */
-       return 0;
-}
diff --git a/drivers/media/video/cx23885/cx23888-ir.h b/drivers/media/video/cx23885/cx23888-ir.h
deleted file mode 100644 (file)
index d2de41c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  Driver for the Conexant CX23885/7/8 PCIe bridge
- *
- *  CX23888 Integrated Consumer Infrared Controller
- *
- *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#ifndef _CX23888_IR_H_
-#define _CX23888_IR_H_
-int cx23888_ir_probe(struct cx23885_dev *dev);
-int cx23888_ir_remove(struct cx23885_dev *dev);
-#endif
diff --git a/drivers/media/video/cx23885/netup-eeprom.c b/drivers/media/video/cx23885/netup-eeprom.c
deleted file mode 100644 (file)
index 98a48f5..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-
-/*
- * netup-eeprom.c
- *
- * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card
- *
- * Copyright (C) 2009 NetUP Inc.
- * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
- *
- * 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 "cx23885.h"
-#include "netup-eeprom.h"
-
-#define EEPROM_I2C_ADDR 0x50
-
-int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr)
-{
-       int ret;
-       unsigned char buf[2];
-
-       /* Read from EEPROM */
-       struct i2c_msg msg[] = {
-               {
-                       .addr   = EEPROM_I2C_ADDR,
-                       .flags  = 0,
-                       .buf    = &buf[0],
-                       .len    = 1
-               }, {
-                       .addr   = EEPROM_I2C_ADDR,
-                       .flags  = I2C_M_RD,
-                       .buf    = &buf[1],
-                       .len    = 1
-               }
-
-       };
-
-       buf[0] = addr;
-       buf[1] = 0x0;
-
-       ret = i2c_transfer(i2c_adap, msg, 2);
-
-       if (ret != 2) {
-               printk(KERN_ERR "eeprom i2c read error, status=%d\n", ret);
-               return -1;
-       }
-
-       return buf[1];
-};
-
-int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data)
-{
-       int ret;
-       unsigned char bufw[2];
-
-       /* Write into EEPROM */
-       struct i2c_msg msg[] = {
-               {
-                       .addr   = EEPROM_I2C_ADDR,
-                       .flags  = 0,
-                       .buf    = &bufw[0],
-                       .len    = 2
-               }
-       };
-
-       bufw[0] = addr;
-       bufw[1] = data;
-
-       ret = i2c_transfer(i2c_adap, msg, 1);
-
-       if (ret != 1) {
-               printk(KERN_ERR "eeprom i2c write error, status=%d\n", ret);
-               return -1;
-       }
-
-       mdelay(10); /* prophylactic delay, datasheet write cycle time = 5 ms */
-       return 0;
-};
-
-void netup_get_card_info(struct i2c_adapter *i2c_adap,
-                               struct netup_card_info *cinfo)
-{
-       int i, j;
-
-       cinfo->rev =  netup_eeprom_read(i2c_adap, 63);
-
-       for (i = 64, j = 0; i < 70; i++, j++)
-               cinfo->port[0].mac[j] =  netup_eeprom_read(i2c_adap, i);
-
-       for (i = 70, j = 0; i < 76; i++, j++)
-               cinfo->port[1].mac[j] =  netup_eeprom_read(i2c_adap, i);
-};
diff --git a/drivers/media/video/cx23885/netup-eeprom.h b/drivers/media/video/cx23885/netup-eeprom.h
deleted file mode 100644 (file)
index 13926e1..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * netup-eeprom.h
- *
- * 24LC02 EEPROM driver in conjunction with NetUP Dual DVB-S2 CI card
- *
- * Copyright (C) 2009 NetUP Inc.
- * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
- *
- * 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 NETUP_EEPROM_H
-#define NETUP_EEPROM_H
-
-struct netup_port_info {
-       u8 mac[6];/* card MAC address */
-};
-
-struct netup_card_info {
-       struct netup_port_info port[2];/* ports - 1,2 */
-       u8 rev;/* card revision */
-};
-
-extern int netup_eeprom_read(struct i2c_adapter *i2c_adap, u8 addr);
-extern int netup_eeprom_write(struct i2c_adapter *i2c_adap, u8 addr, u8 data);
-extern void netup_get_card_info(struct i2c_adapter *i2c_adap,
-                               struct netup_card_info *cinfo);
-
-#endif
diff --git a/drivers/media/video/cx23885/netup-init.c b/drivers/media/video/cx23885/netup-init.c
deleted file mode 100644 (file)
index f4893e6..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * netup-init.c
- *
- * NetUP Dual DVB-S2 CI driver
- *
- * Copyright (C) 2009 NetUP Inc.
- * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
- * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
- *
- * 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 "cx23885.h"
-
-static void i2c_av_write(struct i2c_adapter *i2c, u16 reg, u8 val)
-{
-       int ret;
-       u8 buf[3];
-       struct i2c_msg msg = {
-               .addr   = 0x88 >> 1,
-               .flags  = 0,
-               .buf    = buf,
-               .len    = 3
-       };
-
-       buf[0] = reg >> 8;
-       buf[1] = reg & 0xff;
-       buf[2] = val;
-
-       ret = i2c_transfer(i2c, &msg, 1);
-
-       if (ret != 1)
-               printk(KERN_ERR "%s: i2c write error!\n", __func__);
-}
-
-static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val)
-{
-       int ret;
-       u8 buf[6];
-       struct i2c_msg msg = {
-               .addr   = 0x88 >> 1,
-               .flags  = 0,
-               .buf    = buf,
-               .len    = 6
-       };
-
-       buf[0] = reg >> 8;
-       buf[1] = reg & 0xff;
-       buf[2] = val & 0xff;
-       buf[3] = (val >> 8) & 0xff;
-       buf[4] = (val >> 16) & 0xff;
-       buf[5] = val >> 24;
-
-       ret = i2c_transfer(i2c, &msg, 1);
-
-       if (ret != 1)
-               printk(KERN_ERR "%s: i2c write error!\n", __func__);
-}
-
-static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg)
-{
-       int ret;
-       u8 buf[2];
-       struct i2c_msg msg = {
-               .addr   = 0x88 >> 1,
-               .flags  = 0,
-               .buf    = buf,
-               .len    = 2
-       };
-
-       buf[0] = reg >> 8;
-       buf[1] = reg & 0xff;
-
-       ret = i2c_transfer(i2c, &msg, 1);
-
-       if (ret != 1)
-               printk(KERN_ERR "%s: i2c write error!\n", __func__);
-
-       msg.flags = I2C_M_RD;
-       msg.len = 1;
-
-       ret = i2c_transfer(i2c, &msg, 1);
-
-       if (ret != 1)
-               printk(KERN_ERR "%s: i2c read error!\n", __func__);
-
-       return buf[0];
-}
-
-static void i2c_av_and_or(struct i2c_adapter *i2c, u16 reg, unsigned and_mask,
-                                                               u8 or_value)
-{
-       i2c_av_write(i2c, reg, (i2c_av_read(i2c, reg) & and_mask) | or_value);
-}
-/* set 27MHz on AUX_CLK */
-void netup_initialize(struct cx23885_dev *dev)
-{
-       struct cx23885_i2c *i2c_bus = &dev->i2c_bus[2];
-       struct i2c_adapter *i2c = &i2c_bus->i2c_adap;
-
-       /* Stop microcontroller */
-       i2c_av_and_or(i2c, 0x803, ~0x10, 0x00);
-
-       /* Aux PLL frac for 27 MHz */
-       i2c_av_write4(i2c, 0x114, 0xea0eb3);
-
-       /* Aux PLL int for 27 MHz */
-       i2c_av_write4(i2c, 0x110, 0x090319);
-
-       /* start microcontroller */
-       i2c_av_and_or(i2c, 0x803, ~0x10, 0x10);
-}
diff --git a/drivers/media/video/cx23885/netup-init.h b/drivers/media/video/cx23885/netup-init.h
deleted file mode 100644 (file)
index d26ae4b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * netup-init.h
- *
- * NetUP Dual DVB-S2 CI driver
- *
- * Copyright (C) 2009 NetUP Inc.
- * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
- * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
- *
- * 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.
- */
-extern void netup_initialize(struct cx23885_dev *dev);
diff --git a/drivers/media/video/cx25821/Kconfig b/drivers/media/video/cx25821/Kconfig
deleted file mode 100644 (file)
index 5f6b542..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-config VIDEO_CX25821
-       tristate "Conexant cx25821 support"
-       depends on DVB_CORE && VIDEO_DEV && PCI && I2C
-       select I2C_ALGOBIT
-       select VIDEO_BTCX
-       select VIDEO_TVEEPROM
-       depends on RC_CORE
-       select VIDEOBUF_DVB
-       select VIDEOBUF_DMA_SG
-       select VIDEO_CX25840
-       select VIDEO_CX2341X
-       ---help---
-         This is a video4linux driver for Conexant 25821 based
-         TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx25821
-
-config VIDEO_CX25821_ALSA
-       tristate "Conexant 25821 DMA audio support"
-       depends on VIDEO_CX25821 && SND && EXPERIMENTAL
-       select SND_PCM
-       ---help---
-         This is a video4linux driver for direct (DMA) audio on
-         Conexant 25821 based capture cards using ALSA.
-
-         It only works with boards with function 01 enabled.
-         To check if your board supports, use lspci -n.
-         If supported, you should see 14f1:8801 or 14f1:8811
-         PCI device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx25821-alsa.
-
diff --git a/drivers/media/video/cx25821/Makefile b/drivers/media/video/cx25821/Makefile
deleted file mode 100644 (file)
index 1434e80..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
-                      cx25821-gpio.o cx25821-medusa-video.o \
-                      cx25821-video.o cx25821-video-upstream.o \
-                      cx25821-video-upstream-ch2.o \
-                      cx25821-audio-upstream.o
-
-obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
-obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
-
-ccflags-y := -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c
deleted file mode 100644 (file)
index 1858a45..0000000
+++ /dev/null
@@ -1,784 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *     Based on SAA713x ALSA driver and CX88 driver
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, version 2
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/dma-mapping.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <linux/delay.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-
-#include "cx25821.h"
-#include "cx25821-reg.h"
-
-#define AUDIO_SRAM_CHANNEL     SRAM_CH08
-
-#define dprintk(level, fmt, arg...)                            \
-do {                                                           \
-       if (debug >= level)                                     \
-               pr_info("%s/1: " fmt, chip->dev->name, ##arg);  \
-} while (0)
-#define dprintk_core(level, fmt, arg...)                               \
-do {                                                                   \
-       if (debug >= level)                                             \
-               printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
-} while (0)
-
-/****************************************************************************
-       Data type declarations - Can be moded to a header file later
- ****************************************************************************/
-
-static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
-static int devno;
-
-struct cx25821_audio_buffer {
-       unsigned int bpl;
-       struct btcx_riscmem risc;
-       struct videobuf_dmabuf dma;
-};
-
-struct cx25821_audio_dev {
-       struct cx25821_dev *dev;
-       struct cx25821_dmaqueue q;
-
-       /* pci i/o */
-       struct pci_dev *pci;
-
-       /* audio controls */
-       int irq;
-
-       struct snd_card *card;
-
-       unsigned long iobase;
-       spinlock_t reg_lock;
-       atomic_t count;
-
-       unsigned int dma_size;
-       unsigned int period_size;
-       unsigned int num_periods;
-
-       struct videobuf_dmabuf *dma_risc;
-
-       struct cx25821_audio_buffer *buf;
-
-       struct snd_pcm_substream *substream;
-};
-
-
-/****************************************************************************
-                       Module global static vars
- ****************************************************************************/
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
-static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
-
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
-
-/****************************************************************************
-                               Module macros
- ****************************************************************************/
-
-MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
-MODULE_AUTHOR("Hiep Huynh");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");  /* "{{Conexant,23881}," */
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-/****************************************************************************
-                       Module specific funtions
- ****************************************************************************/
-/* Constants taken from cx88-reg.h */
-#define AUD_INT_DN_RISCI1       (1 <<  0)
-#define AUD_INT_UP_RISCI1       (1 <<  1)
-#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
-#define AUD_INT_DN_RISCI2       (1 <<  4)      /* yes, 3 is skipped */
-#define AUD_INT_UP_RISCI2       (1 <<  5)
-#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
-#define AUD_INT_DN_SYNC         (1 << 12)
-#define AUD_INT_UP_SYNC         (1 << 13)
-#define AUD_INT_RDS_DN_SYNC     (1 << 14)
-#define AUD_INT_OPC_ERR         (1 << 16)
-#define AUD_INT_BER_IRQ         (1 << 20)
-#define AUD_INT_MCHG_IRQ        (1 << 21)
-#define GP_COUNT_CONTROL_RESET 0x3
-
-#define PCI_MSK_AUD_EXT   (1 <<  4)
-#define PCI_MSK_AUD_INT   (1 <<  3)
-/*
- * BOARD Specific: Sets audio DMA
- */
-
-static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
-{
-       struct cx25821_audio_buffer *buf = chip->buf;
-       struct cx25821_dev *dev = chip->dev;
-       struct sram_channel *audio_ch =
-           &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
-       u32 tmp = 0;
-
-       /* enable output on the GPIO 0 for the MCLK ADC (Audio) */
-       cx25821_set_gpiopin_direction(chip->dev, 0, 0);
-
-       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
-       cx_clear(AUD_INT_DMA_CTL,
-                FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
-
-       /* setup fifo + format - out channel */
-       cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl,
-                                        buf->risc.dma);
-
-       /* sets bpl size */
-       cx_write(AUD_A_LNGTH, buf->bpl);
-
-       /* reset counter */
-       /* GP_COUNT_CONTROL_RESET = 0x3 */
-       cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
-       atomic_set(&chip->count, 0);
-
-       /* Set the input mode to 16-bit */
-       tmp = cx_read(AUD_A_CFG);
-       cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
-                FLD_AUD_CLK_ENABLE);
-
-       /*
-       pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n",
-               buf->bpl, audio_ch->cmds_start,
-               cx_read(audio_ch->cmds_start + 12)>>1,
-               chip->num_periods, buf->bpl * chip->num_periods);
-       */
-
-       /* Enables corresponding bits at AUD_INT_STAT */
-       cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF |
-                FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR);
-
-       /* Clean any pending interrupt bits already set */
-       cx_write(AUD_A_INT_STAT, ~0);
-
-       /* enable audio irqs */
-       cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
-
-       /* Turn on audio downstream fifo and risc enable 0x101 */
-       tmp = cx_read(AUD_INT_DMA_CTL);
-       cx_set(AUD_INT_DMA_CTL, tmp |
-              (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
-
-       mdelay(100);
-       return 0;
-}
-
-/*
- * BOARD Specific: Resets audio DMA
- */
-static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
-{
-       struct cx25821_dev *dev = chip->dev;
-
-       /* stop dma */
-       cx_clear(AUD_INT_DMA_CTL,
-                FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
-
-       /* disable irqs */
-       cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
-       cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
-                AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
-
-       return 0;
-}
-
-#define MAX_IRQ_LOOP 50
-
-/*
- * BOARD Specific: IRQ dma bits
- */
-static char *cx25821_aud_irqs[32] = {
-       "dn_risci1", "up_risci1", "rds_dn_risc1",       /* 0-2 */
-       NULL,                                           /* reserved */
-       "dn_risci2", "up_risci2", "rds_dn_risc2",       /* 4-6 */
-       NULL,                                           /* reserved */
-       "dnf_of", "upf_uf", "rds_dnf_uf",               /* 8-10 */
-       NULL,                                           /* reserved */
-       "dn_sync", "up_sync", "rds_dn_sync",            /* 12-14 */
-       NULL,                                           /* reserved */
-       "opc_err", "par_err", "rip_err",                /* 16-18 */
-       "pci_abort", "ber_irq", "mchg_irq"              /* 19-21 */
-};
-
-/*
- * BOARD Specific: Threats IRQ audio specific calls
- */
-static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
-                           u32 mask)
-{
-       struct cx25821_dev *dev = chip->dev;
-
-       if (0 == (status & mask))
-               return;
-
-       cx_write(AUD_A_INT_STAT, status);
-       if (debug > 1 || (status & mask & ~0xff))
-               cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs,
-                               ARRAY_SIZE(cx25821_aud_irqs), status, mask);
-
-       /* risc op code error */
-       if (status & AUD_INT_OPC_ERR) {
-               pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name);
-
-               cx_clear(AUD_INT_DMA_CTL,
-                        FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
-               cx25821_sram_channel_dump_audio(dev,
-                               &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]);
-       }
-       if (status & AUD_INT_DN_SYNC) {
-               pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
-               cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
-               return;
-       }
-
-       /* risc1 downstream */
-       if (status & AUD_INT_DN_RISCI1) {
-               atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
-               snd_pcm_period_elapsed(chip->substream);
-       }
-}
-
-/*
- * BOARD Specific: Handles IRQ calls
- */
-static irqreturn_t cx25821_irq(int irq, void *dev_id)
-{
-       struct cx25821_audio_dev *chip = dev_id;
-       struct cx25821_dev *dev = chip->dev;
-       u32 status, pci_status;
-       u32 audint_status, audint_mask;
-       int loop, handled = 0;
-
-       audint_status = cx_read(AUD_A_INT_STAT);
-       audint_mask = cx_read(AUD_A_INT_MSK);
-       status = cx_read(PCI_INT_STAT);
-
-       for (loop = 0; loop < 1; loop++) {
-               status = cx_read(PCI_INT_STAT);
-               if (0 == status) {
-                       status = cx_read(PCI_INT_STAT);
-                       audint_status = cx_read(AUD_A_INT_STAT);
-                       audint_mask = cx_read(AUD_A_INT_MSK);
-
-                       if (status) {
-                               handled = 1;
-                               cx_write(PCI_INT_STAT, status);
-
-                               cx25821_aud_irq(chip, audint_status,
-                                               audint_mask);
-                               break;
-                       } else {
-                               goto out;
-                       }
-               }
-
-               handled = 1;
-               cx_write(PCI_INT_STAT, status);
-
-               cx25821_aud_irq(chip, audint_status, audint_mask);
-       }
-
-       pci_status = cx_read(PCI_INT_STAT);
-
-       if (handled)
-               cx_write(PCI_INT_STAT, pci_status);
-
-out:
-       return IRQ_RETVAL(handled);
-}
-
-static int dsp_buffer_free(struct cx25821_audio_dev *chip)
-{
-       BUG_ON(!chip->dma_size);
-
-       dprintk(2, "Freeing buffer\n");
-       videobuf_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);
-
-       chip->dma_risc = NULL;
-       chip->dma_size = 0;
-
-       return 0;
-}
-
-/****************************************************************************
-                               ALSA PCM Interface
- ****************************************************************************/
-
-/*
- * Digital hardware definition
- */
-#define DEFAULT_FIFO_SIZE      384
-static struct snd_pcm_hardware snd_cx25821_digital_hw = {
-       .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates = SNDRV_PCM_RATE_48000,
-       .rate_min = 48000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       /* Analog audio output will be full of clicks and pops if there
-          are not exactly four lines in the SRAM FIFO buffer.  */
-       .period_bytes_min = DEFAULT_FIFO_SIZE / 3,
-       .period_bytes_max = DEFAULT_FIFO_SIZE / 3,
-       .periods_min = 1,
-       .periods_max = AUDIO_LINE_SIZE,
-       /* 128 * 128 = 16384 = 1024 * 16 */
-       .buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE),
-};
-
-/*
- * audio pcm capture open callback
- */
-static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int err;
-       unsigned int bpl = 0;
-
-       if (!chip) {
-               pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n");
-               return -ENODEV;
-       }
-
-       err = snd_pcm_hw_constraint_pow2(runtime, 0,
-                                        SNDRV_PCM_HW_PARAM_PERIODS);
-       if (err < 0)
-               goto _error;
-
-       chip->substream = substream;
-
-       runtime->hw = snd_cx25821_digital_hw;
-
-       if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
-           DEFAULT_FIFO_SIZE) {
-               /* since there are 3 audio Clusters */
-               bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;
-               bpl &= ~7;      /* must be multiple of 8 */
-
-               if (bpl > AUDIO_LINE_SIZE)
-                       bpl = AUDIO_LINE_SIZE;
-
-               runtime->hw.period_bytes_min = bpl;
-               runtime->hw.period_bytes_max = bpl;
-       }
-
-       return 0;
-_error:
-       dprintk(1, "Error opening PCM!\n");
-       return err;
-}
-
-/*
- * audio close callback
- */
-static int snd_cx25821_close(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
-/*
- * hw_params callback
- */
-static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
-       struct videobuf_dmabuf *dma;
-
-       struct cx25821_audio_buffer *buf;
-       int ret;
-
-       if (substream->runtime->dma_area) {
-               dsp_buffer_free(chip);
-               substream->runtime->dma_area = NULL;
-       }
-
-       chip->period_size = params_period_bytes(hw_params);
-       chip->num_periods = params_periods(hw_params);
-       chip->dma_size = chip->period_size * params_periods(hw_params);
-
-       BUG_ON(!chip->dma_size);
-       BUG_ON(chip->num_periods & (chip->num_periods - 1));
-
-       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
-       if (NULL == buf)
-               return -ENOMEM;
-
-       if (chip->period_size > AUDIO_LINE_SIZE)
-               chip->period_size = AUDIO_LINE_SIZE;
-
-       buf->bpl = chip->period_size;
-
-       dma = &buf->dma;
-       videobuf_dma_init(dma);
-       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
-                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
-       if (ret < 0)
-               goto error;
-
-       ret = videobuf_dma_map(&chip->pci->dev, dma);
-       if (ret < 0)
-               goto error;
-
-       ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
-                       chip->period_size, chip->num_periods, 1);
-       if (ret < 0) {
-               pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
-               goto error;
-       }
-
-       /* Loop back to start of program */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-       buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
-
-       chip->buf = buf;
-       chip->dma_risc = dma;
-
-       substream->runtime->dma_area = chip->dma_risc->vaddr;
-       substream->runtime->dma_bytes = chip->dma_size;
-       substream->runtime->dma_addr = 0;
-
-       return 0;
-
-error:
-       kfree(buf);
-       return ret;
-}
-
-/*
- * hw free callback
- */
-static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
-{
-       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
-
-       if (substream->runtime->dma_area) {
-               dsp_buffer_free(chip);
-               substream->runtime->dma_area = NULL;
-       }
-
-       return 0;
-}
-
-/*
- * prepare callback
- */
-static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
-/*
- * trigger callback
- */
-static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream,
-                                   int cmd)
-{
-       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
-       int err = 0;
-
-       /* Local interrupts are already disabled by ALSA */
-       spin_lock(&chip->reg_lock);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               err = _cx25821_start_audio_dma(chip);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               err = _cx25821_stop_audio_dma(chip);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-
-       spin_unlock(&chip->reg_lock);
-
-       return err;
-}
-
-/*
- * pointer callback
- */
-static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream
-                                            *substream)
-{
-       struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       u16 count;
-
-       count = atomic_read(&chip->count);
-
-       return runtime->period_size * (count & (runtime->periods - 1));
-}
-
-/*
- * page callback (needed for mmap)
- */
-static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
-                                    unsigned long offset)
-{
-       void *pageptr = substream->runtime->dma_area + offset;
-
-       return vmalloc_to_page(pageptr);
-}
-
-/*
- * operators
- */
-static struct snd_pcm_ops snd_cx25821_pcm_ops = {
-       .open = snd_cx25821_pcm_open,
-       .close = snd_cx25821_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_cx25821_hw_params,
-       .hw_free = snd_cx25821_hw_free,
-       .prepare = snd_cx25821_prepare,
-       .trigger = snd_cx25821_card_trigger,
-       .pointer = snd_cx25821_pointer,
-       .page = snd_cx25821_page,
-};
-
-/*
- * ALSA create a PCM device:  Called when initializing the board.
- * Sets up the name and hooks up the callbacks
- */
-static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
-                          char *name)
-{
-       struct snd_pcm *pcm;
-       int err;
-
-       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
-       if (err < 0) {
-               pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
-               return err;
-       }
-       pcm->private_data = chip;
-       pcm->info_flags = 0;
-       strcpy(pcm->name, name);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
-
-       return 0;
-}
-
-/****************************************************************************
-                       Basic Flow for Sound Devices
- ****************************************************************************/
-
-/*
- * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
- * Only boards with eeprom and byte 1 at eeprom=1 have it
- */
-
-static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = {
-       {0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {0,}
-};
-
-MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
-
-/*
- * Not used in the function snd_cx25821_dev_free so removing
- * from the file.
- */
-/*
-static int snd_cx25821_free(struct cx25821_audio_dev *chip)
-{
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       cx25821_dev_unregister(chip->dev);
-       pci_disable_device(chip->pci);
-
-       return 0;
-}
-*/
-
-/*
- * Component Destructor
- */
-static void snd_cx25821_dev_free(struct snd_card *card)
-{
-       struct cx25821_audio_dev *chip = card->private_data;
-
-       /* snd_cx25821_free(chip); */
-       snd_card_free(chip->card);
-}
-
-/*
- * Alsa Constructor - Component probe
- */
-static int cx25821_audio_initdev(struct cx25821_dev *dev)
-{
-       struct snd_card *card;
-       struct cx25821_audio_dev *chip;
-       int err;
-
-       if (devno >= SNDRV_CARDS) {
-               pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
-               return -ENODEV;
-       }
-
-       if (!enable[devno]) {
-               ++devno;
-               pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
-               return -ENOENT;
-       }
-
-       err = snd_card_create(index[devno], id[devno], THIS_MODULE,
-                       sizeof(struct cx25821_audio_dev), &card);
-       if (err < 0) {
-               pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
-                       __func__);
-               return err;
-       }
-
-       strcpy(card->driver, "cx25821");
-
-       /* Card "creation" */
-       card->private_free = snd_cx25821_dev_free;
-       chip = card->private_data;
-       spin_lock_init(&chip->reg_lock);
-
-       chip->dev = dev;
-       chip->card = card;
-       chip->pci = dev->pci;
-       chip->iobase = pci_resource_start(dev->pci, 0);
-
-       chip->irq = dev->pci->irq;
-
-       err = request_irq(dev->pci->irq, cx25821_irq,
-                         IRQF_SHARED, chip->dev->name, chip);
-
-       if (err < 0) {
-               pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
-                       dev->pci->irq);
-               goto error;
-       }
-
-       err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
-       if (err < 0) {
-               pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
-                       __func__);
-               goto error;
-       }
-
-       snd_card_set_dev(card, &chip->pci->dev);
-
-       strcpy(card->shortname, "cx25821");
-       sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
-               chip->iobase, chip->irq);
-       strcpy(card->mixername, "CX25821");
-
-       pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
-               devno);
-
-       err = snd_card_register(card);
-       if (err < 0) {
-               pr_info("DEBUG ERROR: cannot register sound card %s\n",
-                       __func__);
-               goto error;
-       }
-
-       snd_cx25821_cards[devno] = card;
-
-       devno++;
-       return 0;
-
-error:
-       snd_card_free(card);
-       return err;
-}
-
-/****************************************************************************
-                               LINUX MODULE INIT
- ****************************************************************************/
-static void cx25821_audio_fini(void)
-{
-       snd_card_free(snd_cx25821_cards[0]);
-}
-
-/*
- * Module initializer
- *
- * Loops through present saa7134 cards, and assigns an ALSA device
- * to each one
- *
- */
-static int cx25821_alsa_init(void)
-{
-       struct cx25821_dev *dev = NULL;
-       struct list_head *list;
-
-       mutex_lock(&cx25821_devlist_mutex);
-       list_for_each(list, &cx25821_devlist) {
-               dev = list_entry(list, struct cx25821_dev, devlist);
-               cx25821_audio_initdev(dev);
-       }
-       mutex_unlock(&cx25821_devlist_mutex);
-
-       if (dev == NULL)
-               pr_info("ERROR ALSA: no cx25821 cards found\n");
-
-       return 0;
-
-}
-
-late_initcall(cx25821_alsa_init);
-module_exit(cx25821_audio_fini);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c
deleted file mode 100644 (file)
index 8b2a999..0000000
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "cx25821-video.h"
-#include "cx25821-audio-upstream.h"
-
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/syscalls.h>
-#include <linux/file.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
-MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
-MODULE_LICENSE("GPL");
-
-static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
-                       FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
-
-int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
-                                             struct sram_channel *ch,
-                                             unsigned int bpl, u32 risc)
-{
-       unsigned int i, lines;
-       u32 cdt;
-
-       if (ch->cmds_start == 0) {
-               cx_write(ch->ptr1_reg, 0);
-               cx_write(ch->ptr2_reg, 0);
-               cx_write(ch->cnt2_reg, 0);
-               cx_write(ch->cnt1_reg, 0);
-               return 0;
-       }
-
-       bpl = (bpl + 7) & ~7;   /* alignment */
-       cdt = ch->cdt;
-       lines = ch->fifo_size / bpl;
-
-       if (lines > 3)
-               lines = 3;
-
-       BUG_ON(lines < 2);
-
-       /* write CDT */
-       for (i = 0; i < lines; i++) {
-               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
-               cx_write(cdt + 16 * i + 4, 0);
-               cx_write(cdt + 16 * i + 8, 0);
-               cx_write(cdt + 16 * i + 12, 0);
-       }
-
-       /* write CMDS */
-       cx_write(ch->cmds_start + 0, risc);
-
-       cx_write(ch->cmds_start + 4, 0);
-       cx_write(ch->cmds_start + 8, cdt);
-       cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);
-       cx_write(ch->cmds_start + 16, ch->ctrl_start);
-
-       /* IQ size */
-       cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);
-
-       for (i = 24; i < 80; i += 4)
-               cx_write(ch->cmds_start + i, 0);
-
-       /* fill registers */
-       cx_write(ch->ptr1_reg, ch->fifo_start);
-       cx_write(ch->ptr2_reg, cdt);
-       cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);
-       cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);
-
-       return 0;
-}
-
-static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
-                                                __le32 *rp,
-                                                dma_addr_t databuf_phys_addr,
-                                                unsigned int bpl,
-                                                int fifo_enable)
-{
-       unsigned int line;
-       struct sram_channel *sram_ch =
-               dev->channels[dev->_audio_upstream_channel].sram_channels;
-       int offset = 0;
-
-       /* scan lines */
-       for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) {
-               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
-               *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
-               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-
-               /* Check if we need to enable the FIFO
-                * after the first 3 lines.
-                * For the upstream audio channel,
-                * the risc engine will enable the FIFO */
-               if (fifo_enable && line == 2) {
-                       *(rp++) = RISC_WRITECR;
-                       *(rp++) = sram_ch->dma_ctl;
-                       *(rp++) = sram_ch->fld_aud_fifo_en;
-                       *(rp++) = 0x00000020;
-               }
-
-               offset += AUDIO_LINE_SIZE;
-       }
-
-       return rp;
-}
-
-int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
-                                      struct pci_dev *pci,
-                                      unsigned int bpl, unsigned int lines)
-{
-       __le32 *rp;
-       int fifo_enable = 0;
-       int frame = 0, i = 0;
-       int frame_size = AUDIO_DATA_BUF_SZ;
-       int databuf_offset = 0;
-       int risc_flag = RISC_CNT_INC;
-       dma_addr_t risc_phys_jump_addr;
-
-       /* Virtual address of Risc buffer program */
-       rp = dev->_risc_virt_addr;
-
-       /* sync instruction */
-       *(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);
-
-       for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) {
-               databuf_offset = frame_size * frame;
-
-               if (frame == 0) {
-                       fifo_enable = 1;
-                       risc_flag = RISC_CNT_RESET;
-               } else {
-                       fifo_enable = 0;
-                       risc_flag = RISC_CNT_INC;
-               }
-
-               /* Calculate physical jump address */
-               if ((frame + 1) == NUM_AUDIO_FRAMES) {
-                       risc_phys_jump_addr =
-                           dev->_risc_phys_start_addr +
-                           RISC_SYNC_INSTRUCTION_SIZE;
-               } else {
-                       risc_phys_jump_addr =
-                           dev->_risc_phys_start_addr +
-                           RISC_SYNC_INSTRUCTION_SIZE +
-                           AUDIO_RISC_DMA_BUF_SIZE * (frame + 1);
-               }
-
-               rp = cx25821_risc_field_upstream_audio(dev, rp,
-                               dev->_audiodata_buf_phys_addr + databuf_offset,
-                               bpl, fifo_enable);
-
-               if (USE_RISC_NOOP_AUDIO) {
-                       for (i = 0; i < NUM_NO_OPS; i++)
-                               *(rp++) = cpu_to_le32(RISC_NOOP);
-               }
-
-               /* Loop to (Nth)FrameRISC or to Start of Risc program &
-                * generate IRQ */
-               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
-               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
-               *(rp++) = cpu_to_le32(0);
-
-               /* Recalculate virtual address based on frame index */
-               rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
-                       (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
-       }
-
-       return 0;
-}
-
-void cx25821_free_memory_audio(struct cx25821_dev *dev)
-{
-       if (dev->_risc_virt_addr) {
-               pci_free_consistent(dev->pci, dev->_audiorisc_size,
-                                   dev->_risc_virt_addr, dev->_risc_phys_addr);
-               dev->_risc_virt_addr = NULL;
-       }
-
-       if (dev->_audiodata_buf_virt_addr) {
-               pci_free_consistent(dev->pci, dev->_audiodata_buf_size,
-                                   dev->_audiodata_buf_virt_addr,
-                                   dev->_audiodata_buf_phys_addr);
-               dev->_audiodata_buf_virt_addr = NULL;
-       }
-}
-
-void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
-{
-       struct sram_channel *sram_ch =
-               dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
-       u32 tmp = 0;
-
-       if (!dev->_audio_is_running) {
-               printk(KERN_DEBUG
-                      pr_fmt("No audio file is currently running so return!\n"));
-               return;
-       }
-       /* Disable RISC interrupts */
-       cx_write(sram_ch->int_msk, 0);
-
-       /* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */
-       tmp = cx_read(sram_ch->dma_ctl);
-       cx_write(sram_ch->dma_ctl,
-                tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en));
-
-       /* Clear data buffer memory */
-       if (dev->_audiodata_buf_virt_addr)
-               memset(dev->_audiodata_buf_virt_addr, 0,
-                      dev->_audiodata_buf_size);
-
-       dev->_audio_is_running = 0;
-       dev->_is_first_audio_frame = 0;
-       dev->_audioframe_count = 0;
-       dev->_audiofile_status = END_OF_FILE;
-
-       kfree(dev->_irq_audio_queues);
-       dev->_irq_audio_queues = NULL;
-
-       kfree(dev->_audiofilename);
-}
-
-void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
-{
-       if (dev->_audio_is_running)
-               cx25821_stop_upstream_audio(dev);
-
-       cx25821_free_memory_audio(dev);
-}
-
-int cx25821_get_audio_data(struct cx25821_dev *dev,
-                          struct sram_channel *sram_ch)
-{
-       struct file *myfile;
-       int frame_index_temp = dev->_audioframe_index;
-       int i = 0;
-       int line_size = AUDIO_LINE_SIZE;
-       int frame_size = AUDIO_DATA_BUF_SZ;
-       int frame_offset = frame_size * frame_index_temp;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t file_offset = dev->_audioframe_count * frame_size;
-       loff_t pos;
-       mm_segment_t old_fs;
-
-       if (dev->_audiofile_status == END_OF_FILE)
-               return 0;
-
-       myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
-
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_audiofilename, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-
-               for (i = 0; i < dev->_audio_lines_count; i++) {
-                       pos = file_offset;
-
-                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
-                                                                       &pos);
-
-                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
-                           && dev->_audiodata_buf_virt_addr != NULL) {
-                               memcpy((void *)(dev->_audiodata_buf_virt_addr +
-                                               frame_offset / 4), mybuf,
-                                       vfs_read_retval);
-                       }
-
-                       file_offset += vfs_read_retval;
-                       frame_offset += vfs_read_retval;
-
-                       if (vfs_read_retval < line_size) {
-                               pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
-                                       __func__);
-                               break;
-                       }
-               }
-
-               if (i > 0)
-                       dev->_audioframe_count++;
-
-               dev->_audiofile_status = (vfs_read_retval == line_size) ?
-                                               IN_PROGRESS : END_OF_FILE;
-
-               set_fs(old_fs);
-               filp_close(myfile, NULL);
-       }
-
-       return 0;
-}
-
-static void cx25821_audioups_handler(struct work_struct *work)
-{
-       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
-                       _audio_work_entry);
-
-       if (!dev) {
-               pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
-                       __func__);
-               return;
-       }
-
-       cx25821_get_audio_data(dev, dev->channels[dev->_audio_upstream_channel].
-                       sram_channels);
-}
-
-int cx25821_openfile_audio(struct cx25821_dev *dev,
-                          struct sram_channel *sram_ch)
-{
-       struct file *myfile;
-       int i = 0, j = 0;
-       int line_size = AUDIO_LINE_SIZE;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t pos;
-       loff_t offset = (unsigned long)0;
-       mm_segment_t old_fs;
-
-       myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
-
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                       __func__, dev->_audiofilename, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!\n",
-                               __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-
-               for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
-                       for (i = 0; i < dev->_audio_lines_count; i++) {
-                               pos = offset;
-
-                               vfs_read_retval = vfs_read(myfile, mybuf,
-                                               line_size, &pos);
-
-                               if (vfs_read_retval > 0 &&
-                                   vfs_read_retval == line_size &&
-                                   dev->_audiodata_buf_virt_addr != NULL) {
-                                       memcpy((void *)(dev->
-                                                       _audiodata_buf_virt_addr
-                                                       + offset / 4), mybuf,
-                                              vfs_read_retval);
-                               }
-
-                               offset += vfs_read_retval;
-
-                               if (vfs_read_retval < line_size) {
-                                       pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
-                                               __func__);
-                                       break;
-                               }
-                       }
-
-                       if (i > 0)
-                               dev->_audioframe_count++;
-
-                       if (vfs_read_retval < line_size)
-                               break;
-               }
-
-               dev->_audiofile_status = (vfs_read_retval == line_size) ?
-                                               IN_PROGRESS : END_OF_FILE;
-
-               set_fs(old_fs);
-               myfile->f_pos = 0;
-               filp_close(myfile, NULL);
-       }
-
-       return 0;
-}
-
-static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
-                                                struct sram_channel *sram_ch,
-                                                int bpl)
-{
-       int ret = 0;
-       dma_addr_t dma_addr;
-       dma_addr_t data_dma_addr;
-
-       cx25821_free_memory_audio(dev);
-
-       dev->_risc_virt_addr = pci_alloc_consistent(dev->pci,
-                       dev->audio_upstream_riscbuf_size, &dma_addr);
-       dev->_risc_virt_start_addr = dev->_risc_virt_addr;
-       dev->_risc_phys_start_addr = dma_addr;
-       dev->_risc_phys_addr = dma_addr;
-       dev->_audiorisc_size = dev->audio_upstream_riscbuf_size;
-
-       if (!dev->_risc_virt_addr) {
-               printk(KERN_DEBUG
-                       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
-               return -ENOMEM;
-       }
-       /* Clear out memory at address */
-       memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
-
-       /* For Audio Data buffer allocation */
-       dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci,
-                       dev->audio_upstream_databuf_size, &data_dma_addr);
-       dev->_audiodata_buf_phys_addr = data_dma_addr;
-       dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
-
-       if (!dev->_audiodata_buf_virt_addr) {
-               printk(KERN_DEBUG
-                       pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
-               return -ENOMEM;
-       }
-       /* Clear out memory at address */
-       memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size);
-
-       ret = cx25821_openfile_audio(dev, sram_ch);
-       if (ret < 0)
-               return ret;
-
-       /* Creating RISC programs */
-       ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
-                                               dev->_audio_lines_count);
-       if (ret < 0) {
-               printk(KERN_DEBUG
-                       pr_fmt("ERROR creating audio upstream RISC programs!\n"));
-               goto error;
-       }
-
-       return 0;
-
-error:
-       return ret;
-}
-
-int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
-                              u32 status)
-{
-       int i = 0;
-       u32 int_msk_tmp;
-       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
-       dma_addr_t risc_phys_jump_addr;
-       __le32 *rp;
-
-       if (status & FLD_AUD_SRC_RISCI1) {
-               /* Get interrupt_index of the program that interrupted */
-               u32 prog_cnt = cx_read(channel->gpcnt);
-
-               /* Since we've identified our IRQ, clear our bits from the
-                * interrupt mask and interrupt status registers */
-               cx_write(channel->int_msk, 0);
-               cx_write(channel->int_stat, cx_read(channel->int_stat));
-
-               spin_lock(&dev->slock);
-
-               while (prog_cnt != dev->_last_index_irq) {
-                       /* Update _last_index_irq */
-                       if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1))
-                               dev->_last_index_irq++;
-                       else
-                               dev->_last_index_irq = 0;
-
-                       dev->_audioframe_index = dev->_last_index_irq;
-
-                       queue_work(dev->_irq_audio_queues,
-                                  &dev->_audio_work_entry);
-               }
-
-               if (dev->_is_first_audio_frame) {
-                       dev->_is_first_audio_frame = 0;
-
-                       if (dev->_risc_virt_start_addr != NULL) {
-                               risc_phys_jump_addr =
-                                       dev->_risc_phys_start_addr +
-                                       RISC_SYNC_INSTRUCTION_SIZE +
-                                       AUDIO_RISC_DMA_BUF_SIZE;
-
-                               rp = cx25821_risc_field_upstream_audio(dev,
-                                               dev->_risc_virt_start_addr + 1,
-                                               dev->_audiodata_buf_phys_addr,
-                                               AUDIO_LINE_SIZE, FIFO_DISABLE);
-
-                               if (USE_RISC_NOOP_AUDIO) {
-                                       for (i = 0; i < NUM_NO_OPS; i++) {
-                                               *(rp++) =
-                                                   cpu_to_le32(RISC_NOOP);
-                                       }
-                               }
-                               /* Jump to 2nd Audio Frame */
-                               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 |
-                                               RISC_CNT_RESET);
-                               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
-                               *(rp++) = cpu_to_le32(0);
-                       }
-               }
-
-               spin_unlock(&dev->slock);
-       } else {
-               if (status & FLD_AUD_SRC_OF)
-                       pr_warn("%s(): Audio Received Overflow Error Interrupt!\n",
-                               __func__);
-
-               if (status & FLD_AUD_SRC_SYNC)
-                       pr_warn("%s(): Audio Received Sync Error Interrupt!\n",
-                               __func__);
-
-               if (status & FLD_AUD_SRC_OPC_ERR)
-                       pr_warn("%s(): Audio Received OpCode Error Interrupt!\n",
-                               __func__);
-
-               /* Read and write back the interrupt status register to clear
-                * our bits */
-               cx_write(channel->int_stat, cx_read(channel->int_stat));
-       }
-
-       if (dev->_audiofile_status == END_OF_FILE) {
-               pr_warn("EOF Channel Audio Framecount = %d\n",
-                       dev->_audioframe_count);
-               return -1;
-       }
-       /* ElSE, set the interrupt mask register, re-enable irq. */
-       int_msk_tmp = cx_read(channel->int_msk);
-       cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
-
-       return 0;
-}
-
-static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)
-{
-       struct cx25821_dev *dev = dev_id;
-       u32 audio_status;
-       int handled = 0;
-       struct sram_channel *sram_ch;
-
-       if (!dev)
-               return -1;
-
-       sram_ch = dev->channels[dev->_audio_upstream_channel].sram_channels;
-
-       audio_status = cx_read(sram_ch->int_stat);
-
-       /* Only deal with our interrupt */
-       if (audio_status) {
-               handled = cx25821_audio_upstream_irq(dev,
-                               dev->_audio_upstream_channel, audio_status);
-       }
-
-       if (handled < 0)
-               cx25821_stop_upstream_audio(dev);
-       else
-               handled += handled;
-
-       return IRQ_RETVAL(handled);
-}
-
-static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
-                                    struct sram_channel *sram_ch)
-{
-       int count = 0;
-       u32 tmp;
-
-       do {
-               /* Wait 10 microsecond before checking to see if the FIFO is
-                * turned ON. */
-               udelay(10);
-
-               tmp = cx_read(sram_ch->dma_ctl);
-
-               /* 10 millisecond timeout */
-               if (count++ > 1000) {
-                       pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
-                               __func__);
-                       return;
-               }
-
-       } while (!(tmp & sram_ch->fld_aud_fifo_en));
-
-}
-
-int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
-                                    struct sram_channel *sram_ch)
-{
-       u32 tmp = 0;
-       int err = 0;
-
-       /* Set the physical start address of the RISC program in the initial
-        * program counter(IPC) member of the CMDS. */
-       cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);
-       /* Risc IPC High 64 bits 63-32 */
-       cx_write(sram_ch->cmds_start + 4, 0);
-
-       /* reset counter */
-       cx_write(sram_ch->gpcnt_ctl, 3);
-
-       /* Set the line length       (It looks like we do not need to set the
-        * line length) */
-       cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH);
-
-       /* Set the input mode to 16-bit */
-       tmp = cx_read(sram_ch->aud_cfg);
-       tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
-               FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D |
-               FLD_AUD_SONY_MODE;
-       cx_write(sram_ch->aud_cfg, tmp);
-
-       /* Read and write back the interrupt status register to clear it */
-       tmp = cx_read(sram_ch->int_stat);
-       cx_write(sram_ch->int_stat, tmp);
-
-       /* Clear our bits from the interrupt status register. */
-       cx_write(sram_ch->int_stat, _intr_msk);
-
-       /* Set the interrupt mask register, enable irq. */
-       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
-       tmp = cx_read(sram_ch->int_msk);
-       cx_write(sram_ch->int_msk, tmp |= _intr_msk);
-
-       err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
-                       IRQF_SHARED, dev->name, dev);
-       if (err < 0) {
-               pr_err("%s: can't get upstream IRQ %d\n", dev->name,
-                               dev->pci->irq);
-               goto fail_irq;
-       }
-
-       /* Start the DMA  engine */
-       tmp = cx_read(sram_ch->dma_ctl);
-       cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en);
-
-       dev->_audio_is_running = 1;
-       dev->_is_first_audio_frame = 1;
-
-       /* The fifo_en bit turns on by the first Risc program */
-       cx25821_wait_fifo_enable(dev, sram_ch);
-
-       return 0;
-
-fail_irq:
-       cx25821_dev_unregister(dev);
-       return err;
-}
-
-int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
-{
-       struct sram_channel *sram_ch;
-       int retval = 0;
-       int err = 0;
-       int str_length = 0;
-
-       if (dev->_audio_is_running) {
-               pr_warn("Audio Channel is still running so return!\n");
-               return 0;
-       }
-
-       dev->_audio_upstream_channel = channel_select;
-       sram_ch = dev->channels[channel_select].sram_channels;
-
-       /* Work queue */
-       INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);
-       dev->_irq_audio_queues =
-           create_singlethread_workqueue("cx25821_audioworkqueue");
-
-       if (!dev->_irq_audio_queues) {
-               printk(KERN_DEBUG
-                       pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
-               return -ENOMEM;
-       }
-
-       dev->_last_index_irq = 0;
-       dev->_audio_is_running = 0;
-       dev->_audioframe_count = 0;
-       dev->_audiofile_status = RESET_STATUS;
-       dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
-       _line_size = AUDIO_LINE_SIZE;
-
-       if (dev->input_audiofilename) {
-               str_length = strlen(dev->input_audiofilename);
-               dev->_audiofilename = kmemdup(dev->input_audiofilename,
-                                             str_length + 1, GFP_KERNEL);
-
-               if (!dev->_audiofilename)
-                       goto error;
-
-               /* Default if filename is empty string */
-               if (strcmp(dev->input_audiofilename, "") == 0)
-                       dev->_audiofilename = "/root/audioGOOD.wav";
-       } else {
-               str_length = strlen(_defaultAudioName);
-               dev->_audiofilename = kmemdup(_defaultAudioName,
-                                             str_length + 1, GFP_KERNEL);
-
-               if (!dev->_audiofilename)
-                       goto error;
-       }
-
-       retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
-                                                       _line_size, 0);
-
-       dev->audio_upstream_riscbuf_size =
-               AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
-               RISC_SYNC_INSTRUCTION_SIZE;
-       dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
-
-       /* Allocating buffers and prepare RISC program */
-       retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
-                                                       _line_size);
-       if (retval < 0) {
-               pr_err("%s: Failed to set up Audio upstream buffers!\n",
-                       dev->name);
-               goto error;
-       }
-       /* Start RISC engine */
-       cx25821_start_audio_dma_upstream(dev, sram_ch);
-
-       return 0;
-
-error:
-       cx25821_dev_unregister(dev);
-
-       return err;
-}
diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.h b/drivers/media/video/cx25821/cx25821-audio-upstream.h
deleted file mode 100644 (file)
index af2ae7c..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
-#include <linux/workqueue.h>
-
-#define NUM_AUDIO_PROGS       8
-#define NUM_AUDIO_FRAMES      8
-#define END_OF_FILE           0
-#define IN_PROGRESS           1
-#define RESET_STATUS          -1
-#define FIFO_DISABLE          0
-#define FIFO_ENABLE           1
-#define NUM_NO_OPS            4
-
-#define RISC_READ_INSTRUCTION_SIZE      12
-#define RISC_JUMP_INSTRUCTION_SIZE      12
-#define RISC_WRITECR_INSTRUCTION_SIZE   16
-#define RISC_SYNC_INSTRUCTION_SIZE      4
-#define DWORD_SIZE                      4
-#define AUDIO_SYNC_LINE                 4
-
-#define LINES_PER_AUDIO_BUFFER      15
-#define AUDIO_LINE_SIZE             128
-#define AUDIO_DATA_BUF_SZ           (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)
-
-#define USE_RISC_NOOP_AUDIO   1
-
-#ifdef USE_RISC_NOOP_AUDIO
-#define AUDIO_RISC_DMA_BUF_SIZE                                                \
-       (LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +          \
-        RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS * DWORD_SIZE +      \
-        RISC_JUMP_INSTRUCTION_SIZE)
-#endif
-
-#ifndef USE_RISC_NOOP_AUDIO
-#define AUDIO_RISC_DMA_BUF_SIZE                                                \
-       (LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +          \
-        RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
-#endif
-
-static int _line_size;
-char *_defaultAudioName = "/root/audioGOOD.wav";
diff --git a/drivers/media/video/cx25821/cx25821-audio.h b/drivers/media/video/cx25821/cx25821-audio.h
deleted file mode 100644 (file)
index 1fc2d24..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __CX25821_AUDIO_H__
-#define __CX25821_AUDIO_H__
-
-#define USE_RISC_NOOP          1
-#define LINES_PER_BUFFER       15
-#define AUDIO_LINE_SIZE                128
-
-/* Number of buffer programs to use at once. */
-#define NUMBER_OF_PROGRAMS     8
-
-/*
- * Max size of the RISC program for a buffer. - worst case is 2 writes per line
- * Space is also added for the 4 no-op instructions added on the end.
- */
-#ifndef USE_RISC_NOOP
-#define MAX_BUFFER_PROGRAM_SIZE                                                \
-       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +           \
-        RISC_WRITECR_INSTRUCTION_SIZE * 4)
-#endif
-
-/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
-#ifdef USE_RISC_NOOP
-#define MAX_BUFFER_PROGRAM_SIZE                                                \
-       (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +           \
-        RISC_NOOP_INSTRUCTION_SIZE * 4)
-#endif
-
-/* Sizes of various instructions in bytes.  Used when adding instructions. */
-#define RISC_WRITE_INSTRUCTION_SIZE    12
-#define RISC_JUMP_INSTRUCTION_SIZE     12
-#define RISC_SKIP_INSTRUCTION_SIZE     4
-#define RISC_SYNC_INSTRUCTION_SIZE     4
-#define RISC_WRITECR_INSTRUCTION_SIZE  16
-#define RISC_NOOP_INSTRUCTION_SIZE     4
-
-#define MAX_AUDIO_DMA_BUFFER_SIZE                                      \
-       (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS +                 \
-        RISC_SYNC_INSTRUCTION_SIZE)
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-biffuncs.h b/drivers/media/video/cx25821/cx25821-biffuncs.h
deleted file mode 100644 (file)
index 9326a7c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _BITFUNCS_H
-#define _BITFUNCS_H
-
-#define SetBit(Bit)  (1 << Bit)
-
-inline u8 getBit(u32 sample, u8 index)
-{
-       return (u8) ((sample >> index) & 1);
-}
-
-inline u32 clearBitAtPos(u32 value, u8 bit)
-{
-       return value & ~(1 << bit);
-}
-
-inline u32 setBitAtPos(u32 sample, u8 bit)
-{
-       sample |= (1 << bit);
-       return sample;
-
-}
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-cards.c b/drivers/media/video/cx25821/cx25821-cards.c
deleted file mode 100644 (file)
index 99988c9..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *     Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
- *
- *  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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <media/cx25840.h>
-
-#include "cx25821.h"
-#include "tuner-xc2028.h"
-
-/* board config info */
-
-struct cx25821_board cx25821_boards[] = {
-       [UNKNOWN_BOARD] = {
-               .name = "UNKNOWN/GENERIC",
-               /* Ensure safe default for unknown boards */
-               .clk_freq = 0,
-       },
-
-       [CX25821_BOARD] = {
-               .name = "CX25821",
-               .portb = CX25821_RAW,
-               .portc = CX25821_264,
-               .input[0].type = CX25821_VMUX_COMPOSITE,
-       },
-
-};
-
-const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
-
-struct cx25821_subid cx25821_subids[] = {
-       {
-               .subvendor = 0x14f1,
-               .subdevice = 0x0920,
-               .card = CX25821_BOARD,
-       },
-};
-
-void cx25821_card_setup(struct cx25821_dev *dev)
-{
-       static u8 eeprom[256];
-
-       if (dev->i2c_bus[0].i2c_rc == 0) {
-               dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
-               tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
-                               sizeof(eeprom));
-       }
-}
diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c
deleted file mode 100644 (file)
index f11f6f0..0000000
+++ /dev/null
@@ -1,1502 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
- *
- *  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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include "cx25821.h"
-#include "cx25821-sram.h"
-#include "cx25821-video.h"
-
-MODULE_DESCRIPTION("Driver for Athena cards");
-MODULE_AUTHOR("Shu Lin - Hiep Huynh");
-MODULE_LICENSE("GPL");
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
-module_param_array(card, int, NULL, 0444);
-MODULE_PARM_DESC(card, "card type");
-
-static unsigned int cx25821_devcount;
-
-DEFINE_MUTEX(cx25821_devlist_mutex);
-EXPORT_SYMBOL(cx25821_devlist_mutex);
-LIST_HEAD(cx25821_devlist);
-EXPORT_SYMBOL(cx25821_devlist);
-
-struct sram_channel cx25821_sram_channels[] = {
-       [SRAM_CH00] = {
-               .i = SRAM_CH00,
-               .name = "VID A",
-               .cmds_start = VID_A_DOWN_CMDS,
-               .ctrl_start = VID_A_IQ,
-               .cdt = VID_A_CDT,
-               .fifo_start = VID_A_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA1_PTR1,
-               .ptr2_reg = DMA1_PTR2,
-               .cnt1_reg = DMA1_CNT1,
-               .cnt2_reg = DMA1_CNT2,
-               .int_msk = VID_A_INT_MSK,
-               .int_stat = VID_A_INT_STAT,
-               .int_mstat = VID_A_INT_MSTAT,
-               .dma_ctl = VID_DST_A_DMA_CTL,
-               .gpcnt_ctl = VID_DST_A_GPCNT_CTL,
-               .gpcnt = VID_DST_A_GPCNT,
-               .vip_ctl = VID_DST_A_VIP_CTL,
-               .pix_frmt = VID_DST_A_PIX_FRMT,
-       },
-
-       [SRAM_CH01] = {
-               .i = SRAM_CH01,
-               .name = "VID B",
-               .cmds_start = VID_B_DOWN_CMDS,
-               .ctrl_start = VID_B_IQ,
-               .cdt = VID_B_CDT,
-               .fifo_start = VID_B_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA2_PTR1,
-               .ptr2_reg = DMA2_PTR2,
-               .cnt1_reg = DMA2_CNT1,
-               .cnt2_reg = DMA2_CNT2,
-               .int_msk = VID_B_INT_MSK,
-               .int_stat = VID_B_INT_STAT,
-               .int_mstat = VID_B_INT_MSTAT,
-               .dma_ctl = VID_DST_B_DMA_CTL,
-               .gpcnt_ctl = VID_DST_B_GPCNT_CTL,
-               .gpcnt = VID_DST_B_GPCNT,
-               .vip_ctl = VID_DST_B_VIP_CTL,
-               .pix_frmt = VID_DST_B_PIX_FRMT,
-       },
-
-       [SRAM_CH02] = {
-               .i = SRAM_CH02,
-               .name = "VID C",
-               .cmds_start = VID_C_DOWN_CMDS,
-               .ctrl_start = VID_C_IQ,
-               .cdt = VID_C_CDT,
-               .fifo_start = VID_C_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA3_PTR1,
-               .ptr2_reg = DMA3_PTR2,
-               .cnt1_reg = DMA3_CNT1,
-               .cnt2_reg = DMA3_CNT2,
-               .int_msk = VID_C_INT_MSK,
-               .int_stat = VID_C_INT_STAT,
-               .int_mstat = VID_C_INT_MSTAT,
-               .dma_ctl = VID_DST_C_DMA_CTL,
-               .gpcnt_ctl = VID_DST_C_GPCNT_CTL,
-               .gpcnt = VID_DST_C_GPCNT,
-               .vip_ctl = VID_DST_C_VIP_CTL,
-               .pix_frmt = VID_DST_C_PIX_FRMT,
-       },
-
-       [SRAM_CH03] = {
-               .i = SRAM_CH03,
-               .name = "VID D",
-               .cmds_start = VID_D_DOWN_CMDS,
-               .ctrl_start = VID_D_IQ,
-               .cdt = VID_D_CDT,
-               .fifo_start = VID_D_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA4_PTR1,
-               .ptr2_reg = DMA4_PTR2,
-               .cnt1_reg = DMA4_CNT1,
-               .cnt2_reg = DMA4_CNT2,
-               .int_msk = VID_D_INT_MSK,
-               .int_stat = VID_D_INT_STAT,
-               .int_mstat = VID_D_INT_MSTAT,
-               .dma_ctl = VID_DST_D_DMA_CTL,
-               .gpcnt_ctl = VID_DST_D_GPCNT_CTL,
-               .gpcnt = VID_DST_D_GPCNT,
-               .vip_ctl = VID_DST_D_VIP_CTL,
-               .pix_frmt = VID_DST_D_PIX_FRMT,
-       },
-
-       [SRAM_CH04] = {
-               .i = SRAM_CH04,
-               .name = "VID E",
-               .cmds_start = VID_E_DOWN_CMDS,
-               .ctrl_start = VID_E_IQ,
-               .cdt = VID_E_CDT,
-               .fifo_start = VID_E_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA5_PTR1,
-               .ptr2_reg = DMA5_PTR2,
-               .cnt1_reg = DMA5_CNT1,
-               .cnt2_reg = DMA5_CNT2,
-               .int_msk = VID_E_INT_MSK,
-               .int_stat = VID_E_INT_STAT,
-               .int_mstat = VID_E_INT_MSTAT,
-               .dma_ctl = VID_DST_E_DMA_CTL,
-               .gpcnt_ctl = VID_DST_E_GPCNT_CTL,
-               .gpcnt = VID_DST_E_GPCNT,
-               .vip_ctl = VID_DST_E_VIP_CTL,
-               .pix_frmt = VID_DST_E_PIX_FRMT,
-       },
-
-       [SRAM_CH05] = {
-               .i = SRAM_CH05,
-               .name = "VID F",
-               .cmds_start = VID_F_DOWN_CMDS,
-               .ctrl_start = VID_F_IQ,
-               .cdt = VID_F_CDT,
-               .fifo_start = VID_F_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA6_PTR1,
-               .ptr2_reg = DMA6_PTR2,
-               .cnt1_reg = DMA6_CNT1,
-               .cnt2_reg = DMA6_CNT2,
-               .int_msk = VID_F_INT_MSK,
-               .int_stat = VID_F_INT_STAT,
-               .int_mstat = VID_F_INT_MSTAT,
-               .dma_ctl = VID_DST_F_DMA_CTL,
-               .gpcnt_ctl = VID_DST_F_GPCNT_CTL,
-               .gpcnt = VID_DST_F_GPCNT,
-               .vip_ctl = VID_DST_F_VIP_CTL,
-               .pix_frmt = VID_DST_F_PIX_FRMT,
-       },
-
-       [SRAM_CH06] = {
-               .i = SRAM_CH06,
-               .name = "VID G",
-               .cmds_start = VID_G_DOWN_CMDS,
-               .ctrl_start = VID_G_IQ,
-               .cdt = VID_G_CDT,
-               .fifo_start = VID_G_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA7_PTR1,
-               .ptr2_reg = DMA7_PTR2,
-               .cnt1_reg = DMA7_CNT1,
-               .cnt2_reg = DMA7_CNT2,
-               .int_msk = VID_G_INT_MSK,
-               .int_stat = VID_G_INT_STAT,
-               .int_mstat = VID_G_INT_MSTAT,
-               .dma_ctl = VID_DST_G_DMA_CTL,
-               .gpcnt_ctl = VID_DST_G_GPCNT_CTL,
-               .gpcnt = VID_DST_G_GPCNT,
-               .vip_ctl = VID_DST_G_VIP_CTL,
-               .pix_frmt = VID_DST_G_PIX_FRMT,
-       },
-
-       [SRAM_CH07] = {
-               .i = SRAM_CH07,
-               .name = "VID H",
-               .cmds_start = VID_H_DOWN_CMDS,
-               .ctrl_start = VID_H_IQ,
-               .cdt = VID_H_CDT,
-               .fifo_start = VID_H_DOWN_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA8_PTR1,
-               .ptr2_reg = DMA8_PTR2,
-               .cnt1_reg = DMA8_CNT1,
-               .cnt2_reg = DMA8_CNT2,
-               .int_msk = VID_H_INT_MSK,
-               .int_stat = VID_H_INT_STAT,
-               .int_mstat = VID_H_INT_MSTAT,
-               .dma_ctl = VID_DST_H_DMA_CTL,
-               .gpcnt_ctl = VID_DST_H_GPCNT_CTL,
-               .gpcnt = VID_DST_H_GPCNT,
-               .vip_ctl = VID_DST_H_VIP_CTL,
-               .pix_frmt = VID_DST_H_PIX_FRMT,
-       },
-
-       [SRAM_CH08] = {
-               .name = "audio from",
-               .cmds_start = AUD_A_DOWN_CMDS,
-               .ctrl_start = AUD_A_IQ,
-               .cdt = AUD_A_CDT,
-               .fifo_start = AUD_A_DOWN_CLUSTER_1,
-               .fifo_size = AUDIO_CLUSTER_SIZE * 3,
-               .ptr1_reg = DMA17_PTR1,
-               .ptr2_reg = DMA17_PTR2,
-               .cnt1_reg = DMA17_CNT1,
-               .cnt2_reg = DMA17_CNT2,
-       },
-
-       [SRAM_CH09] = {
-               .i = SRAM_CH09,
-               .name = "VID Upstream I",
-               .cmds_start = VID_I_UP_CMDS,
-               .ctrl_start = VID_I_IQ,
-               .cdt = VID_I_CDT,
-               .fifo_start = VID_I_UP_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA15_PTR1,
-               .ptr2_reg = DMA15_PTR2,
-               .cnt1_reg = DMA15_CNT1,
-               .cnt2_reg = DMA15_CNT2,
-               .int_msk = VID_I_INT_MSK,
-               .int_stat = VID_I_INT_STAT,
-               .int_mstat = VID_I_INT_MSTAT,
-               .dma_ctl = VID_SRC_I_DMA_CTL,
-               .gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
-               .gpcnt = VID_SRC_I_GPCNT,
-
-               .vid_fmt_ctl = VID_SRC_I_FMT_CTL,
-               .vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
-               .vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
-               .vid_cdt_size = VID_SRC_I_CDT_SZ,
-               .irq_bit = 8,
-       },
-
-       [SRAM_CH10] = {
-               .i = SRAM_CH10,
-               .name = "VID Upstream J",
-               .cmds_start = VID_J_UP_CMDS,
-               .ctrl_start = VID_J_IQ,
-               .cdt = VID_J_CDT,
-               .fifo_start = VID_J_UP_CLUSTER_1,
-               .fifo_size = (VID_CLUSTER_SIZE << 2),
-               .ptr1_reg = DMA16_PTR1,
-               .ptr2_reg = DMA16_PTR2,
-               .cnt1_reg = DMA16_CNT1,
-               .cnt2_reg = DMA16_CNT2,
-               .int_msk = VID_J_INT_MSK,
-               .int_stat = VID_J_INT_STAT,
-               .int_mstat = VID_J_INT_MSTAT,
-               .dma_ctl = VID_SRC_J_DMA_CTL,
-               .gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
-               .gpcnt = VID_SRC_J_GPCNT,
-
-               .vid_fmt_ctl = VID_SRC_J_FMT_CTL,
-               .vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
-               .vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
-               .vid_cdt_size = VID_SRC_J_CDT_SZ,
-               .irq_bit = 9,
-       },
-
-       [SRAM_CH11] = {
-               .i = SRAM_CH11,
-               .name = "Audio Upstream Channel B",
-               .cmds_start = AUD_B_UP_CMDS,
-               .ctrl_start = AUD_B_IQ,
-               .cdt = AUD_B_CDT,
-               .fifo_start = AUD_B_UP_CLUSTER_1,
-               .fifo_size = (AUDIO_CLUSTER_SIZE * 3),
-               .ptr1_reg = DMA22_PTR1,
-               .ptr2_reg = DMA22_PTR2,
-               .cnt1_reg = DMA22_CNT1,
-               .cnt2_reg = DMA22_CNT2,
-               .int_msk = AUD_B_INT_MSK,
-               .int_stat = AUD_B_INT_STAT,
-               .int_mstat = AUD_B_INT_MSTAT,
-               .dma_ctl = AUD_INT_DMA_CTL,
-               .gpcnt_ctl = AUD_B_GPCNT_CTL,
-               .gpcnt = AUD_B_GPCNT,
-               .aud_length = AUD_B_LNGTH,
-               .aud_cfg = AUD_B_CFG,
-               .fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
-               .fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
-               .irq_bit = 11,
-       },
-};
-EXPORT_SYMBOL(cx25821_sram_channels);
-
-struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
-struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
-struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
-struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
-struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
-struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
-struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
-struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
-struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
-struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
-struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
-
-struct cx25821_dmaqueue mpegq;
-
-static int cx25821_risc_decode(u32 risc)
-{
-       static const char * const 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",
-       };
-       static const 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,
-       };
-       static const char * const bits[] = {
-               "12", "13", "14", "resync",
-               "cnt0", "cnt1", "18", "19",
-               "20", "21", "22", "23",
-               "irq1", "irq2", "eol", "sol",
-       };
-       int i;
-
-       pr_cont("0x%08x [ %s",
-               risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
-       for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
-               if (risc & (1 << (i + 12)))
-                       pr_cont(" %s", bits[i]);
-       }
-       pr_cont(" count=%d ]\n", risc & 0xfff);
-       return incr[risc >> 28] ? incr[risc >> 28] : 1;
-}
-
-static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
-{
-       struct cx25821_i2c *bus = i2c_adap->algo_data;
-       struct cx25821_dev *dev = bus->dev;
-       return cx_read(bus->reg_stat) & 0x01;
-}
-
-static void cx25821_registers_init(struct cx25821_dev *dev)
-{
-       u32 tmp;
-
-       /* enable RUN_RISC in Pecos */
-       cx_write(DEV_CNTRL2, 0x20);
-
-       /* Set the master PCI interrupt masks to enable video, audio, MBIF,
-        * and GPIO interrupts
-        * I2C interrupt masking is handled by the I2C objects themselves. */
-       cx_write(PCI_INT_MSK, 0x2001FFFF);
-
-       tmp = cx_read(RDR_TLCTL0);
-       tmp &= ~FLD_CFG_RCB_CK_EN;      /* Clear the RCB_CK_EN bit */
-       cx_write(RDR_TLCTL0, tmp);
-
-       /* PLL-A setting for the Audio Master Clock */
-       cx_write(PLL_A_INT_FRAC, 0x9807A58B);
-
-       /* PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 */
-       cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
-
-       /* clear reset bit [31] */
-       tmp = cx_read(PLL_A_INT_FRAC);
-       cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
-
-       /* PLL-B setting for Mobilygen Host Bus Interface */
-       cx_write(PLL_B_INT_FRAC, 0x9883A86F);
-
-       /* PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 */
-       cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
-
-       /* clear reset bit [31] */
-       tmp = cx_read(PLL_B_INT_FRAC);
-       cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
-
-       /* PLL-C setting for video upstream channel */
-       cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
-
-       /* PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 */
-       cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
-
-       /* clear reset bit [31] */
-       tmp = cx_read(PLL_C_INT_FRAC);
-       cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
-
-       /* PLL-D setting for audio upstream channel */
-       cx_write(PLL_D_INT_FRAC, 0x98757F5B);
-
-       /* PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 */
-       cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
-
-       /* clear reset bit [31] */
-       tmp = cx_read(PLL_D_INT_FRAC);
-       cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
-
-       /* This selects the PLL C clock source for the video upstream channel
-        * I and J */
-       tmp = cx_read(VID_CH_CLK_SEL);
-       cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
-
-       /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
-        * channel A-C
-        * select 656/VIP DST for downstream Channel A - C */
-       tmp = cx_read(VID_CH_MODE_SEL);
-       /* cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); */
-       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
-
-       /* enables 656 port I and J as output */
-       tmp = cx_read(CLK_RST);
-       /* use external ALT_PLL_REF pin as its reference clock instead */
-       tmp |= FLD_USE_ALT_PLL_REF;
-       cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
-
-       mdelay(100);
-}
-
-int cx25821_sram_channel_setup(struct cx25821_dev *dev,
-                              struct sram_channel *ch,
-                              unsigned int bpl, u32 risc)
-{
-       unsigned int i, lines;
-       u32 cdt;
-
-       if (ch->cmds_start == 0) {
-               cx_write(ch->ptr1_reg, 0);
-               cx_write(ch->ptr2_reg, 0);
-               cx_write(ch->cnt2_reg, 0);
-               cx_write(ch->cnt1_reg, 0);
-               return 0;
-       }
-
-       bpl = (bpl + 7) & ~7;   /* alignment */
-       cdt = ch->cdt;
-       lines = ch->fifo_size / bpl;
-
-       if (lines > 4)
-               lines = 4;
-
-       BUG_ON(lines < 2);
-
-       cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       cx_write(8 + 4, 8);
-       cx_write(8 + 8, 0);
-
-       /* write CDT */
-       for (i = 0; i < lines; i++) {
-               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
-               cx_write(cdt + 16 * i + 4, 0);
-               cx_write(cdt + 16 * i + 8, 0);
-               cx_write(cdt + 16 * i + 12, 0);
-       }
-
-       /* init the first cdt buffer */
-       for (i = 0; i < 128; i++)
-               cx_write(ch->fifo_start + 4 * i, i);
-
-       /* write CMDS */
-       if (ch->jumponly)
-               cx_write(ch->cmds_start + 0, 8);
-       else
-               cx_write(ch->cmds_start + 0, risc);
-
-       cx_write(ch->cmds_start + 4, 0);        /* 64 bits 63-32 */
-       cx_write(ch->cmds_start + 8, cdt);
-       cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
-       cx_write(ch->cmds_start + 16, ch->ctrl_start);
-
-       if (ch->jumponly)
-               cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
-       else
-               cx_write(ch->cmds_start + 20, 64 >> 2);
-
-       for (i = 24; i < 80; i += 4)
-               cx_write(ch->cmds_start + i, 0);
-
-       /* fill registers */
-       cx_write(ch->ptr1_reg, ch->fifo_start);
-       cx_write(ch->ptr2_reg, cdt);
-       cx_write(ch->cnt2_reg, (lines * 16) >> 3);
-       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
-
-       return 0;
-}
-EXPORT_SYMBOL(cx25821_sram_channel_setup);
-
-int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
-                                    struct sram_channel *ch,
-                                    unsigned int bpl, u32 risc)
-{
-       unsigned int i, lines;
-       u32 cdt;
-
-       if (ch->cmds_start == 0) {
-               cx_write(ch->ptr1_reg, 0);
-               cx_write(ch->ptr2_reg, 0);
-               cx_write(ch->cnt2_reg, 0);
-               cx_write(ch->cnt1_reg, 0);
-               return 0;
-       }
-
-       bpl = (bpl + 7) & ~7;   /* alignment */
-       cdt = ch->cdt;
-       lines = ch->fifo_size / bpl;
-
-       if (lines > 3)
-               lines = 3;      /* for AUDIO */
-
-       BUG_ON(lines < 2);
-
-       cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       cx_write(8 + 4, 8);
-       cx_write(8 + 8, 0);
-
-       /* write CDT */
-       for (i = 0; i < lines; i++) {
-               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
-               cx_write(cdt + 16 * i + 4, 0);
-               cx_write(cdt + 16 * i + 8, 0);
-               cx_write(cdt + 16 * i + 12, 0);
-       }
-
-       /* write CMDS */
-       if (ch->jumponly)
-               cx_write(ch->cmds_start + 0, 8);
-       else
-               cx_write(ch->cmds_start + 0, risc);
-
-       cx_write(ch->cmds_start + 4, 0);        /* 64 bits 63-32 */
-       cx_write(ch->cmds_start + 8, cdt);
-       cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
-       cx_write(ch->cmds_start + 16, ch->ctrl_start);
-
-       /* IQ size */
-       if (ch->jumponly)
-               cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
-       else
-               cx_write(ch->cmds_start + 20, 64 >> 2);
-
-       /* zero out */
-       for (i = 24; i < 80; i += 4)
-               cx_write(ch->cmds_start + i, 0);
-
-       /* fill registers */
-       cx_write(ch->ptr1_reg, ch->fifo_start);
-       cx_write(ch->ptr2_reg, cdt);
-       cx_write(ch->cnt2_reg, (lines * 16) >> 3);
-       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
-
-       return 0;
-}
-EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
-
-void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
-{
-       static char *name[] = {
-               "init risc lo",
-               "init risc hi",
-               "cdt base",
-               "cdt size",
-               "iq base",
-               "iq size",
-               "risc pc lo",
-               "risc pc hi",
-               "iq wr ptr",
-               "iq rd ptr",
-               "cdt current",
-               "pci target lo",
-               "pci target hi",
-               "line / byte",
-       };
-       u32 risc;
-       unsigned int i, j, n;
-
-       pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
-       for (i = 0; i < ARRAY_SIZE(name); i++)
-               pr_warn("cmds + 0x%2x:   %-15s: 0x%08x\n",
-                       i * 4, name[i], cx_read(ch->cmds_start + 4 * i));
-
-       j = i * 4;
-       for (i = 0; i < 4;) {
-               risc = cx_read(ch->cmds_start + 4 * (i + 14));
-               pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
-               i += cx25821_risc_decode(risc);
-       }
-
-       for (i = 0; i < (64 >> 2); i += n) {
-               risc = cx_read(ch->ctrl_start + 4 * i);
-               /* No consideration for bits 63-32 */
-
-               pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
-                       i * 4, ch->ctrl_start + 4 * i, i);
-               n = cx25821_risc_decode(risc);
-               for (j = 1; j < n; j++) {
-                       risc = cx_read(ch->ctrl_start + 4 * (i + j));
-                       pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
-                               4 * (i + j), i + j, risc, j);
-               }
-       }
-
-       pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
-               ch->fifo_start, ch->fifo_start + ch->fifo_size);
-       pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
-               ch->ctrl_start, ch->ctrl_start + 6 * 16);
-       pr_warn("        :   ptr1_reg: 0x%08x\n",
-               cx_read(ch->ptr1_reg));
-       pr_warn("        :   ptr2_reg: 0x%08x\n",
-               cx_read(ch->ptr2_reg));
-       pr_warn("        :   cnt1_reg: 0x%08x\n",
-               cx_read(ch->cnt1_reg));
-       pr_warn("        :   cnt2_reg: 0x%08x\n",
-               cx_read(ch->cnt2_reg));
-}
-EXPORT_SYMBOL(cx25821_sram_channel_dump);
-
-void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
-                                    struct sram_channel *ch)
-{
-       static const char * const name[] = {
-               "init risc lo",
-               "init risc hi",
-               "cdt base",
-               "cdt size",
-               "iq base",
-               "iq size",
-               "risc pc lo",
-               "risc pc hi",
-               "iq wr ptr",
-               "iq rd ptr",
-               "cdt current",
-               "pci target lo",
-               "pci target hi",
-               "line / byte",
-       };
-
-       u32 risc, value, tmp;
-       unsigned int i, j, n;
-
-       pr_info("\n%s: %s - dma Audio channel status dump\n",
-               dev->name, ch->name);
-
-       for (i = 0; i < ARRAY_SIZE(name); i++)
-               pr_info("%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
-                       dev->name, i * 4, name[i],
-                       cx_read(ch->cmds_start + 4 * i));
-
-       j = i * 4;
-       for (i = 0; i < 4;) {
-               risc = cx_read(ch->cmds_start + 4 * (i + 14));
-               pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
-               i += cx25821_risc_decode(risc);
-       }
-
-       for (i = 0; i < (64 >> 2); i += n) {
-               risc = cx_read(ch->ctrl_start + 4 * i);
-               /* No consideration for bits 63-32 */
-
-               pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
-                       i * 4, ch->ctrl_start + 4 * i, i);
-               n = cx25821_risc_decode(risc);
-
-               for (j = 1; j < n; j++) {
-                       risc = cx_read(ch->ctrl_start + 4 * (i + j));
-                       pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
-                               4 * (i + j), i + j, risc, j);
-               }
-       }
-
-       pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
-               ch->fifo_start, ch->fifo_start + ch->fifo_size);
-       pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
-               ch->ctrl_start, ch->ctrl_start + 6 * 16);
-       pr_warn("        :   ptr1_reg: 0x%08x\n",
-               cx_read(ch->ptr1_reg));
-       pr_warn("        :   ptr2_reg: 0x%08x\n",
-               cx_read(ch->ptr2_reg));
-       pr_warn("        :   cnt1_reg: 0x%08x\n",
-               cx_read(ch->cnt1_reg));
-       pr_warn("        :   cnt2_reg: 0x%08x\n",
-               cx_read(ch->cnt2_reg));
-
-       for (i = 0; i < 4; i++) {
-               risc = cx_read(ch->cmds_start + 56 + (i * 4));
-               pr_warn("instruction %d = 0x%x\n", i, risc);
-       }
-
-       /* read data from the first cdt buffer */
-       risc = cx_read(AUD_A_CDT);
-       pr_warn("\nread cdt loc=0x%x\n", risc);
-       for (i = 0; i < 8; i++) {
-               n = cx_read(risc + i * 4);
-               pr_cont("0x%x ", n);
-       }
-       pr_cont("\n\n");
-
-       value = cx_read(CLK_RST);
-       CX25821_INFO(" CLK_RST = 0x%x\n\n", value);
-
-       value = cx_read(PLL_A_POST_STAT_BIST);
-       CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x\n\n", value);
-       value = cx_read(PLL_A_INT_FRAC);
-       CX25821_INFO(" PLL_A_INT_FRAC = 0x%x\n\n", value);
-
-       value = cx_read(PLL_B_POST_STAT_BIST);
-       CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x\n\n", value);
-       value = cx_read(PLL_B_INT_FRAC);
-       CX25821_INFO(" PLL_B_INT_FRAC = 0x%x\n\n", value);
-
-       value = cx_read(PLL_C_POST_STAT_BIST);
-       CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x\n\n", value);
-       value = cx_read(PLL_C_INT_FRAC);
-       CX25821_INFO(" PLL_C_INT_FRAC = 0x%x\n\n", value);
-
-       value = cx_read(PLL_D_POST_STAT_BIST);
-       CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x\n\n", value);
-       value = cx_read(PLL_D_INT_FRAC);
-       CX25821_INFO(" PLL_D_INT_FRAC = 0x%x\n\n", value);
-
-       value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
-       CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x\n\n", value);
-}
-EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
-
-static void cx25821_shutdown(struct cx25821_dev *dev)
-{
-       int i;
-
-       /* disable RISC controller */
-       cx_write(DEV_CNTRL2, 0);
-
-       /* Disable Video A/B activity */
-       for (i = 0; i < VID_CHANNEL_NUM; i++) {
-               cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
-               cx_write(dev->channels[i].sram_channels->int_msk, 0);
-       }
-
-       for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
-               i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
-               cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
-               cx_write(dev->channels[i].sram_channels->int_msk, 0);
-       }
-
-       /* Disable Audio activity */
-       cx_write(AUD_INT_DMA_CTL, 0);
-
-       /* Disable Serial port */
-       cx_write(UART_CTL, 0);
-
-       /* Disable Interrupts */
-       cx_write(PCI_INT_MSK, 0);
-       cx_write(AUD_A_INT_MSK, 0);
-}
-
-void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
-                             u32 format)
-{
-       if (channel_select <= 7 && channel_select >= 0) {
-               cx_write(dev->channels[channel_select].sram_channels->pix_frmt,
-                               format);
-               dev->channels[channel_select].pixel_formats = format;
-       }
-}
-
-static void cx25821_set_vip_mode(struct cx25821_dev *dev,
-                                struct sram_channel *ch)
-{
-       cx_write(ch->pix_frmt, PIXEL_FRMT_422);
-       cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
-}
-
-static void cx25821_initialize(struct cx25821_dev *dev)
-{
-       int i;
-
-       dprintk(1, "%s()\n", __func__);
-
-       cx25821_shutdown(dev);
-       cx_write(PCI_INT_STAT, 0xffffffff);
-
-       for (i = 0; i < VID_CHANNEL_NUM; i++)
-               cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
-
-       cx_write(AUD_A_INT_STAT, 0xffffffff);
-       cx_write(AUD_B_INT_STAT, 0xffffffff);
-       cx_write(AUD_C_INT_STAT, 0xffffffff);
-       cx_write(AUD_D_INT_STAT, 0xffffffff);
-       cx_write(AUD_E_INT_STAT, 0xffffffff);
-
-       cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
-       cx_write(PAD_CTRL, 0x12);       /* for I2C */
-       cx25821_registers_init(dev);    /* init Pecos registers */
-       mdelay(100);
-
-       for (i = 0; i < VID_CHANNEL_NUM; i++) {
-               cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
-               cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels,
-                                               1440, 0);
-               dev->channels[i].pixel_formats = PIXEL_FRMT_422;
-               dev->channels[i].use_cif_resolution = FALSE;
-       }
-
-       /* Probably only affect Downstream */
-       for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
-               i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
-               cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
-       }
-
-       cx25821_sram_channel_setup_audio(dev,
-                       dev->channels[SRAM_CH08].sram_channels, 128, 0);
-
-       cx25821_gpio_init(dev);
-}
-
-static int cx25821_get_resources(struct cx25821_dev *dev)
-{
-       if (request_mem_region(pci_resource_start(dev->pci, 0),
-                               pci_resource_len(dev->pci, 0), dev->name))
-               return 0;
-
-       pr_err("%s: can't get MMIO memory @ 0x%llx\n",
-               dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
-
-       return -EBUSY;
-}
-
-static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
-{
-       dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
-
-       pr_info("%s(): Hardware revision = 0x%02x\n",
-               __func__, dev->hwrevision);
-}
-
-static void cx25821_iounmap(struct cx25821_dev *dev)
-{
-       if (dev == NULL)
-               return;
-
-       /* Releasing IO memory */
-       if (dev->lmmio != NULL) {
-               CX25821_INFO("Releasing lmmio.\n");
-               iounmap(dev->lmmio);
-               dev->lmmio = NULL;
-       }
-}
-
-static int cx25821_dev_setup(struct cx25821_dev *dev)
-{
-       int i;
-
-       pr_info("\n***********************************\n");
-       pr_info("cx25821 set up\n");
-       pr_info("***********************************\n\n");
-
-       mutex_init(&dev->lock);
-
-       atomic_inc(&dev->refcount);
-
-       dev->nr = ++cx25821_devcount;
-       sprintf(dev->name, "cx25821[%d]", dev->nr);
-
-       mutex_lock(&cx25821_devlist_mutex);
-       list_add_tail(&dev->devlist, &cx25821_devlist);
-       mutex_unlock(&cx25821_devlist_mutex);
-
-       if (dev->pci->device != 0x8210) {
-               pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
-                       __func__, dev->pci->device);
-               return -1;
-       } else {
-               pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
-       }
-
-       /* Apply a sensible clock frequency for the PCIe bridge */
-       dev->clk_freq = 28000000;
-       for (i = 0; i < MAX_VID_CHANNEL_NUM; i++)
-               dev->channels[i].sram_channels = &cx25821_sram_channels[i];
-
-       if (dev->nr > 1)
-               CX25821_INFO("dev->nr > 1!");
-
-       /* board config */
-       dev->board = 1;         /* card[dev->nr]; */
-       dev->_max_num_decoders = MAX_DECODERS;
-
-       dev->pci_bus = dev->pci->bus->number;
-       dev->pci_slot = PCI_SLOT(dev->pci->devfn);
-       dev->pci_irqmask = 0x001f00;
-
-       /* External Master 1 Bus */
-       dev->i2c_bus[0].nr = 0;
-       dev->i2c_bus[0].dev = dev;
-       dev->i2c_bus[0].reg_stat = I2C1_STAT;
-       dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
-       dev->i2c_bus[0].reg_addr = I2C1_ADDR;
-       dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
-       dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
-       dev->i2c_bus[0].i2c_period = (0x07 << 24);      /* 1.95MHz */
-
-       if (cx25821_get_resources(dev) < 0) {
-               pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
-                      dev->name, dev->pci->subsystem_vendor,
-                      dev->pci->subsystem_device);
-
-               cx25821_devcount--;
-               return -EBUSY;
-       }
-
-       /* PCIe stuff */
-       dev->base_io_addr = pci_resource_start(dev->pci, 0);
-
-       if (!dev->base_io_addr) {
-               CX25821_ERR("No PCI Memory resources, exiting!\n");
-               return -ENODEV;
-       }
-
-       dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
-
-       if (!dev->lmmio) {
-               CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
-               cx25821_iounmap(dev);
-               return -ENOMEM;
-       }
-
-       dev->bmmio = (u8 __iomem *) dev->lmmio;
-
-       pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-               dev->name, dev->pci->subsystem_vendor,
-               dev->pci->subsystem_device, cx25821_boards[dev->board].name,
-               dev->board, card[dev->nr] == dev->board ?
-               "insmod option" : "autodetected");
-
-       /* init hardware */
-       cx25821_initialize(dev);
-
-       cx25821_i2c_register(&dev->i2c_bus[0]);
-/*  cx25821_i2c_register(&dev->i2c_bus[1]);
- *  cx25821_i2c_register(&dev->i2c_bus[2]); */
-
-       CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
-                       dev->i2c_bus[0].i2c_rc);
-
-       cx25821_card_setup(dev);
-
-       if (medusa_video_init(dev) < 0)
-               CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
-
-       cx25821_video_register(dev);
-
-       /* register IOCTL device */
-       dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci,
-                       &cx25821_videoioctl_template, "video");
-
-       if (video_register_device
-           (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
-               cx25821_videoioctl_unregister(dev);
-               pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n",
-                      __func__);
-       }
-
-       cx25821_dev_checkrevision(dev);
-       CX25821_INFO("setup done!\n");
-
-       return 0;
-}
-
-void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
-                                     struct upstream_user_struct *up_data)
-{
-       dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
-
-       dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
-       medusa_set_videostandard(dev);
-
-       cx25821_vidupstream_init_ch1(dev, dev->channel_select,
-                                    dev->pixel_format);
-}
-
-void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
-                                     struct upstream_user_struct *up_data)
-{
-       dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
-
-       dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
-       medusa_set_videostandard(dev);
-
-       cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
-                                    dev->pixel_format_ch2);
-}
-
-void cx25821_start_upstream_audio(struct cx25821_dev *dev,
-                                 struct upstream_user_struct *up_data)
-{
-       cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
-}
-
-void cx25821_dev_unregister(struct cx25821_dev *dev)
-{
-       int i;
-
-       if (!dev->base_io_addr)
-               return;
-
-       cx25821_free_mem_upstream_ch1(dev);
-       cx25821_free_mem_upstream_ch2(dev);
-       cx25821_free_mem_upstream_audio(dev);
-
-       release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
-
-       if (!atomic_dec_and_test(&dev->refcount))
-               return;
-
-       for (i = 0; i < VID_CHANNEL_NUM; i++)
-               cx25821_video_unregister(dev, i);
-
-       for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
-            i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
-               cx25821_video_unregister(dev, i);
-       }
-
-       cx25821_videoioctl_unregister(dev);
-
-       cx25821_i2c_unregister(&dev->i2c_bus[0]);
-       cx25821_iounmap(dev);
-}
-EXPORT_SYMBOL(cx25821_dev_unregister);
-
-static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
-                                 unsigned int offset, u32 sync_line,
-                                 unsigned int bpl, unsigned int padding,
-                                 unsigned int lines)
-{
-       struct scatterlist *sg;
-       unsigned int line, todo;
-
-       /* sync instruction */
-       if (sync_line != NO_SYNC_LINE)
-               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       /* scan lines */
-       sg = sglist;
-       for (line = 0; line < lines; line++) {
-               while (offset && offset >= sg_dma_len(sg)) {
-                       offset -= sg_dma_len(sg);
-                       sg++;
-               }
-               if (bpl <= sg_dma_len(sg) - offset) {
-                       /* fits into current chunk */
-                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL |
-                                       bpl);
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
-                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                       offset += bpl;
-               } else {
-                       /* scanline needs to be split */
-                       todo = bpl;
-                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL |
-                                       (sg_dma_len(sg) - offset));
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
-                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                       todo -= (sg_dma_len(sg) - offset);
-                       offset = 0;
-                       sg++;
-                       while (todo > sg_dma_len(sg)) {
-                               *(rp++) = cpu_to_le32(RISC_WRITE |
-                                               sg_dma_len(sg));
-                               *(rp++) = cpu_to_le32(sg_dma_address(sg));
-                               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                               todo -= sg_dma_len(sg);
-                               sg++;
-                       }
-                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg));
-                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                       offset += todo;
-               }
-
-               offset += padding;
-       }
-
-       return rp;
-}
-
-int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                       struct scatterlist *sglist, unsigned int top_offset,
-                       unsigned int bottom_offset, unsigned int bpl,
-                       unsigned int padding, unsigned int lines)
-{
-       u32 instructions;
-       u32 fields;
-       __le32 *rp;
-       int rc;
-
-       fields = 0;
-       if (UNSET != top_offset)
-               fields++;
-       if (UNSET != bottom_offset)
-               fields++;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Padding
-          can cause next bpl to start close to a page border.  First DMA
-          region may be smaller than PAGE_SIZE */
-       /* write and jump need and extra dword */
-       instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE +
-                       lines);
-       instructions += 2;
-       rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
-
-       if (rc < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-
-       if (UNSET != top_offset) {
-               rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
-                                       lines);
-       }
-
-       if (UNSET != bottom_offset) {
-               rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
-                                       padding, lines);
-       }
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-
-       return 0;
-}
-
-static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
-                                       unsigned int offset, u32 sync_line,
-                                       unsigned int bpl, unsigned int padding,
-                                       unsigned int lines, unsigned int lpi)
-{
-       struct scatterlist *sg;
-       unsigned int line, todo, sol;
-
-       /* sync instruction */
-       if (sync_line != NO_SYNC_LINE)
-               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       /* scan lines */
-       sg = sglist;
-       for (line = 0; line < lines; line++) {
-               while (offset && offset >= sg_dma_len(sg)) {
-                       offset -= sg_dma_len(sg);
-                       sg++;
-               }
-
-               if (lpi && line > 0 && !(line % lpi))
-                       sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
-               else
-                       sol = RISC_SOL;
-
-               if (bpl <= sg_dma_len(sg) - offset) {
-                       /* fits into current chunk */
-                       *(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL |
-                                       bpl);
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
-                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                       offset += bpl;
-               } else {
-                       /* scanline needs to be split */
-                       todo = bpl;
-                       *(rp++) = cpu_to_le32(RISC_WRITE | sol |
-                                       (sg_dma_len(sg) - offset));
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
-                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                       todo -= (sg_dma_len(sg) - offset);
-                       offset = 0;
-                       sg++;
-                       while (todo > sg_dma_len(sg)) {
-                               *(rp++) = cpu_to_le32(RISC_WRITE |
-                                               sg_dma_len(sg));
-                               *(rp++) = cpu_to_le32(sg_dma_address(sg));
-                               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                               todo -= sg_dma_len(sg);
-                               sg++;
-                       }
-                       *(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
-                       *(rp++) = cpu_to_le32(sg_dma_address(sg));
-                       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-                       offset += todo;
-               }
-               offset += padding;
-       }
-
-       return rp;
-}
-
-int cx25821_risc_databuffer_audio(struct pci_dev *pci,
-                                 struct btcx_riscmem *risc,
-                                 struct scatterlist *sglist,
-                                 unsigned int bpl,
-                                 unsigned int lines, unsigned int lpi)
-{
-       u32 instructions;
-       __le32 *rp;
-       int rc;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Here
-          there is no padding and no sync.  First DMA region may be smaller
-          than PAGE_SIZE */
-       /* Jump and write need an extra dword */
-       instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
-       instructions += 1;
-
-       rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
-       if (rc < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
-                                     lines, lpi);
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
-       return 0;
-}
-EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
-
-int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-                        u32 reg, u32 mask, u32 value)
-{
-       __le32 *rp;
-       int rc;
-
-       rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
-
-       if (rc < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-
-       *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
-       *(rp++) = cpu_to_le32(reg);
-       *(rp++) = cpu_to_le32(value);
-       *(rp++) = cpu_to_le32(mask);
-       *(rp++) = cpu_to_le32(RISC_JUMP);
-       *(rp++) = cpu_to_le32(risc->dma);
-       *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-       return 0;
-}
-
-void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
-{
-       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-
-       BUG_ON(in_interrupt());
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_dma_unmap(q->dev, dma);
-       videobuf_dma_free(dma);
-       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static irqreturn_t cx25821_irq(int irq, void *dev_id)
-{
-       struct cx25821_dev *dev = dev_id;
-       u32 pci_status;
-       u32 vid_status;
-       int i, handled = 0;
-       u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
-
-       pci_status = cx_read(PCI_INT_STAT);
-
-       if (pci_status == 0)
-               goto out;
-
-       for (i = 0; i < VID_CHANNEL_NUM; i++) {
-               if (pci_status & mask[i]) {
-                       vid_status = cx_read(dev->channels[i].
-                               sram_channels->int_stat);
-
-                       if (vid_status)
-                               handled += cx25821_video_irq(dev, i,
-                                               vid_status);
-
-                       cx_write(PCI_INT_STAT, mask[i]);
-               }
-       }
-
-out:
-       return IRQ_RETVAL(handled);
-}
-
-void cx25821_print_irqbits(char *name, char *tag, char **strings,
-                          int len, u32 bits, u32 mask)
-{
-       unsigned int i;
-
-       printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits);
-
-       for (i = 0; i < len; i++) {
-               if (!(bits & (1 << i)))
-                       continue;
-               if (strings[i])
-                       pr_cont(" %s", strings[i]);
-               else
-                       pr_cont(" %d", i);
-               if (!(mask & (1 << i)))
-                       continue;
-               pr_cont("*");
-       }
-       pr_cont("\n");
-}
-EXPORT_SYMBOL(cx25821_print_irqbits);
-
-struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
-{
-       struct cx25821_dev *dev = pci_get_drvdata(pci);
-       return dev;
-}
-EXPORT_SYMBOL(cx25821_dev_get);
-
-static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
-{
-       struct cx25821_dev *dev;
-       int err = 0;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (NULL == dev)
-               return -ENOMEM;
-
-       err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
-       if (err < 0)
-               goto fail_free;
-
-       /* pci init */
-       dev->pci = pci_dev;
-       if (pci_enable_device(pci_dev)) {
-               err = -EIO;
-
-               pr_info("pci enable failed!\n");
-
-               goto fail_unregister_device;
-       }
-
-       pr_info("Athena pci enable !\n");
-
-       err = cx25821_dev_setup(dev);
-       if (err) {
-               if (err == -EBUSY)
-                       goto fail_unregister_device;
-               else
-                       goto fail_unregister_pci;
-       }
-
-       /* print pci info */
-       pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
-       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
-       pr_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)dev->base_io_addr);
-
-       pci_set_master(pci_dev);
-       if (!pci_dma_supported(pci_dev, 0xffffffff)) {
-               pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
-               goto fail_irq;
-       }
-
-       err = request_irq(pci_dev->irq, cx25821_irq,
-                       IRQF_SHARED, dev->name, dev);
-
-       if (err < 0) {
-               pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
-               goto fail_irq;
-       }
-
-       return 0;
-
-fail_irq:
-       pr_info("cx25821_initdev() can't get IRQ !\n");
-       cx25821_dev_unregister(dev);
-
-fail_unregister_pci:
-       pci_disable_device(pci_dev);
-fail_unregister_device:
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-fail_free:
-       kfree(dev);
-       return err;
-}
-
-static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct cx25821_dev *dev = get_cx25821(v4l2_dev);
-
-       cx25821_shutdown(dev);
-       pci_disable_device(pci_dev);
-
-       /* unregister stuff */
-       if (pci_dev->irq)
-               free_irq(pci_dev->irq, dev);
-
-       mutex_lock(&cx25821_devlist_mutex);
-       list_del(&dev->devlist);
-       mutex_unlock(&cx25821_devlist_mutex);
-
-       cx25821_dev_unregister(dev);
-       v4l2_device_unregister(v4l2_dev);
-       kfree(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = {
-       {
-               /* CX25821 Athena */
-               .vendor = 0x14f1,
-               .device = 0x8210,
-               .subvendor = 0x14f1,
-               .subdevice = 0x0920,
-       }, {
-               /* CX25821 No Brand */
-               .vendor = 0x14f1,
-               .device = 0x8210,
-               .subvendor = 0x0000,
-               .subdevice = 0x0000,
-       }, {
-               /* --- end of list --- */
-       }
-};
-
-MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
-
-static struct pci_driver cx25821_pci_driver = {
-       .name = "cx25821",
-       .id_table = cx25821_pci_tbl,
-       .probe = cx25821_initdev,
-       .remove = __devexit_p(cx25821_finidev),
-       /* TODO */
-       .suspend = NULL,
-       .resume = NULL,
-};
-
-static int __init cx25821_init(void)
-{
-       pr_info("driver version %d.%d.%d loaded\n",
-               (CX25821_VERSION_CODE >> 16) & 0xff,
-               (CX25821_VERSION_CODE >> 8) & 0xff,
-               CX25821_VERSION_CODE & 0xff);
-       return pci_register_driver(&cx25821_pci_driver);
-}
-
-static void __exit cx25821_fini(void)
-{
-       pci_unregister_driver(&cx25821_pci_driver);
-}
-
-module_init(cx25821_init);
-module_exit(cx25821_fini);
diff --git a/drivers/media/video/cx25821/cx25821-gpio.c b/drivers/media/video/cx25821/cx25821-gpio.c
deleted file mode 100644 (file)
index 29e43b0..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 "cx25821.h"
-
-/********************* GPIO stuffs *********************/
-void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
-                                  int pin_number, int pin_logic_value)
-{
-       int bit = pin_number;
-       u32 gpio_oe_reg = GPIO_LO_OE;
-       u32 gpio_register = 0;
-       u32 value = 0;
-
-       /* Check for valid pinNumber */
-       if (pin_number >= 47)
-               return;
-
-       if (pin_number > 31) {
-               bit = pin_number - 31;
-               gpio_oe_reg = GPIO_HI_OE;
-       }
-       /* Here we will make sure that the GPIOs 0 and 1 are output. keep the
-        * rest as is */
-       gpio_register = cx_read(gpio_oe_reg);
-
-       if (pin_logic_value == 1)
-               value = gpio_register | Set_GPIO_Bit(bit);
-       else
-               value = gpio_register & Clear_GPIO_Bit(bit);
-
-       cx_write(gpio_oe_reg, value);
-}
-EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
-
-static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
-                                          int pin_number, int pin_logic_value)
-{
-       int bit = pin_number;
-       u32 gpio_reg = GPIO_LO;
-       u32 value = 0;
-
-       /* Check for valid pinNumber */
-       if (pin_number >= 47)
-               return;
-
-       /* change to output direction */
-       cx25821_set_gpiopin_direction(dev, pin_number, 0);
-
-       if (pin_number > 31) {
-               bit = pin_number - 31;
-               gpio_reg = GPIO_HI;
-       }
-
-       value = cx_read(gpio_reg);
-
-       if (pin_logic_value == 0)
-               value &= Clear_GPIO_Bit(bit);
-       else
-               value |= Set_GPIO_Bit(bit);
-
-       cx_write(gpio_reg, value);
-}
-
-void cx25821_gpio_init(struct cx25821_dev *dev)
-{
-       if (dev == NULL)
-               return;
-
-       switch (dev->board) {
-       case CX25821_BOARD_CONEXANT_ATHENA10:
-       default:
-               /* set GPIO 5 to select the path for Medusa/Athena */
-               cx25821_set_gpiopin_logicvalue(dev, 5, 1);
-               mdelay(20);
-               break;
-       }
-
-}
diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c
deleted file mode 100644 (file)
index 9844549..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *     Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
- *
- *  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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "cx25821.h"
-#include <linux/i2c.h>
-
-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;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-
-#define dprintk(level, fmt, arg...)                                    \
-do {                                                                   \
-       if (i2c_debug >= level)                                         \
-               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);      \
-} while (0)
-
-#define I2C_WAIT_DELAY 32
-#define I2C_WAIT_RETRY 64
-
-#define I2C_EXTEND  (1 << 3)
-#define I2C_NOSTOP  (1 << 4)
-
-static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
-{
-       struct cx25821_i2c *bus = i2c_adap->algo_data;
-       struct cx25821_dev *dev = bus->dev;
-       return cx_read(bus->reg_stat) & 0x01;
-}
-
-static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
-{
-       struct cx25821_i2c *bus = i2c_adap->algo_data;
-       struct cx25821_dev *dev = bus->dev;
-       return cx_read(bus->reg_stat) & 0x02 ? 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;
-}
-
-static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
-                        const struct i2c_msg *msg, int joined_rlen)
-{
-       struct cx25821_i2c *bus = i2c_adap->algo_data;
-       struct cx25821_dev *dev = bus->dev;
-       u32 wdata, addr, ctrl;
-       int retval, cnt;
-
-       if (joined_rlen)
-               dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
-                       msg->len, joined_rlen);
-       else
-               dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
-
-       /* Deal with i2c probe functions with zero payload */
-       if (msg->len == 0) {
-               cx_write(bus->reg_addr, msg->addr << 25);
-               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
-
-               if (!i2c_wait_done(i2c_adap))
-                       return -EIO;
-
-               if (!i2c_slave_did_ack(i2c_adap))
-                       return -EIO;
-
-               dprintk(1, "%s(): returns 0\n", __func__);
-               return 0;
-       }
-
-       /* dev, reg + first byte */
-       addr = (msg->addr << 25) | msg->buf[0];
-       wdata = msg->buf[0];
-
-       ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
-
-       if (msg->len > 1)
-               ctrl |= I2C_NOSTOP | I2C_EXTEND;
-       else if (joined_rlen)
-               ctrl |= I2C_NOSTOP;
-
-       cx_write(bus->reg_addr, addr);
-       cx_write(bus->reg_wdata, wdata);
-       cx_write(bus->reg_ctrl, ctrl);
-
-       retval = i2c_wait_done(i2c_adap);
-       if (retval < 0)
-               goto err;
-
-       if (retval == 0)
-               goto eio;
-
-       if (i2c_debug) {
-               if (!(ctrl & I2C_NOSTOP))
-                       printk(" >\n");
-       }
-
-       for (cnt = 1; cnt < msg->len; cnt++) {
-               /* following bytes */
-               wdata = msg->buf[cnt];
-               ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
-
-               if (cnt < msg->len - 1)
-                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
-               else if (joined_rlen)
-                       ctrl |= I2C_NOSTOP;
-
-               cx_write(bus->reg_addr, addr);
-               cx_write(bus->reg_wdata, wdata);
-               cx_write(bus->reg_ctrl, ctrl);
-
-               retval = i2c_wait_done(i2c_adap);
-               if (retval < 0)
-                       goto err;
-
-               if (retval == 0)
-                       goto eio;
-
-               if (i2c_debug) {
-                       dprintk(1, " %02x", msg->buf[cnt]);
-                       if (!(ctrl & I2C_NOSTOP))
-                               dprintk(1, " >\n");
-               }
-       }
-
-       return msg->len;
-
-eio:
-       retval = -EIO;
-err:
-       if (i2c_debug)
-               pr_err(" ERR: %d\n", retval);
-       return retval;
-}
-
-static int i2c_readbytes(struct i2c_adapter *i2c_adap,
-                        const struct i2c_msg *msg, int joined)
-{
-       struct cx25821_i2c *bus = i2c_adap->algo_data;
-       struct cx25821_dev *dev = bus->dev;
-       u32 ctrl, cnt;
-       int retval;
-
-       if (i2c_debug && !joined)
-               dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
-
-       /* Deal with i2c probe functions with zero payload */
-       if (msg->len == 0) {
-               cx_write(bus->reg_addr, msg->addr << 25);
-               cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
-               if (!i2c_wait_done(i2c_adap))
-                       return -EIO;
-               if (!i2c_slave_did_ack(i2c_adap))
-                       return -EIO;
-
-               dprintk(1, "%s(): returns 0\n", __func__);
-               return 0;
-       }
-
-       if (i2c_debug) {
-               if (joined)
-                       dprintk(1, " R");
-               else
-                       dprintk(1, " <R %02x", (msg->addr << 1) + 1);
-       }
-
-       for (cnt = 0; cnt < msg->len; cnt++) {
-
-               ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
-
-               if (cnt < msg->len - 1)
-                       ctrl |= I2C_NOSTOP | I2C_EXTEND;
-
-               cx_write(bus->reg_addr, msg->addr << 25);
-               cx_write(bus->reg_ctrl, ctrl);
-
-               retval = i2c_wait_done(i2c_adap);
-               if (retval < 0)
-                       goto err;
-               if (retval == 0)
-                       goto eio;
-               msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
-
-               if (i2c_debug) {
-                       dprintk(1, " %02x", msg->buf[cnt]);
-                       if (!(ctrl & I2C_NOSTOP))
-                               dprintk(1, " >\n");
-               }
-       }
-
-       return msg->len;
-eio:
-       retval = -EIO;
-err:
-       if (i2c_debug)
-               pr_err(" ERR: %d\n", retval);
-       return retval;
-}
-
-static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
-       struct cx25821_i2c *bus = i2c_adap->algo_data;
-       struct cx25821_dev *dev = bus->dev;
-       int i, retval = 0;
-
-       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",
-                       __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 u32 cx25821_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA |
-               I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
-}
-
-static struct i2c_algorithm cx25821_i2c_algo_template = {
-       .master_xfer = i2c_xfer,
-       .functionality = cx25821_functionality,
-#ifdef NEED_ALGO_CONTROL
-       .algo_control = dummy_algo_control,
-#endif
-};
-
-static struct i2c_adapter cx25821_i2c_adap_template = {
-       .name = "cx25821",
-       .owner = THIS_MODULE,
-       .algo = &cx25821_i2c_algo_template,
-};
-
-static struct i2c_client cx25821_i2c_client_template = {
-       .name = "cx25821 internal",
-};
-
-/* init + register i2c adapter */
-int cx25821_i2c_register(struct cx25821_i2c *bus)
-{
-       struct cx25821_dev *dev = bus->dev;
-
-       dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
-
-       bus->i2c_adap = cx25821_i2c_adap_template;
-       bus->i2c_client = cx25821_i2c_client_template;
-       bus->i2c_adap.dev.parent = &dev->pci->dev;
-
-       strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
-
-       bus->i2c_adap.algo_data = bus;
-       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
-       i2c_add_adapter(&bus->i2c_adap);
-
-       bus->i2c_client.adapter = &bus->i2c_adap;
-
-       /* set up the I2c */
-       bus->i2c_client.addr = (0x88 >> 1);
-
-       return bus->i2c_rc;
-}
-
-int cx25821_i2c_unregister(struct cx25821_i2c *bus)
-{
-       i2c_del_adapter(&bus->i2c_adap);
-       return 0;
-}
-
-void cx25821_av_clk(struct cx25821_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[0].i2c_adap, &msg, 1);
-}
-
-int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
-{
-       struct i2c_client *client = &bus->i2c_client;
-       int v = 0;
-       u8 addr[2] = { 0, 0 };
-       u8 buf[4] = { 0, 0, 0, 0 };
-
-       struct i2c_msg msgs[2] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = 2,
-                       .buf = addr,
-               }, {
-                       .addr = client->addr,
-                       .flags = I2C_M_RD,
-                       .len = 4,
-                       .buf = buf,
-               }
-       };
-
-       addr[0] = (reg_addr >> 8);
-       addr[1] = (reg_addr & 0xff);
-       msgs[0].addr = 0x44;
-       msgs[1].addr = 0x44;
-
-       i2c_xfer(client->adapter, msgs, 2);
-
-       v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
-       *value = v;
-
-       return v;
-}
-
-int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
-{
-       struct i2c_client *client = &bus->i2c_client;
-       int retval = 0;
-       u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
-
-       struct i2c_msg msgs[1] = {
-               {
-                       .addr = client->addr,
-                       .flags = 0,
-                       .len = 6,
-                       .buf = buf,
-               }
-       };
-
-       buf[0] = reg_addr >> 8;
-       buf[1] = reg_addr & 0xff;
-       buf[5] = (value >> 24) & 0xff;
-       buf[4] = (value >> 16) & 0xff;
-       buf[3] = (value >> 8) & 0xff;
-       buf[2] = value & 0xff;
-       client->flags = 0;
-       msgs[0].addr = 0x44;
-
-       retval = i2c_xfer(client->adapter, msgs, 1);
-
-       return retval;
-}
diff --git a/drivers/media/video/cx25821/cx25821-medusa-defines.h b/drivers/media/video/cx25821/cx25821-medusa-defines.h
deleted file mode 100644 (file)
index 7a9e647..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _MEDUSA_DEF_H_
-#define _MEDUSA_DEF_H_
-
-/* Video decoder that we supported */
-#define VDEC_A         0
-#define VDEC_B         1
-#define VDEC_C         2
-#define VDEC_D         3
-#define VDEC_E         4
-#define VDEC_F         5
-#define VDEC_G         6
-#define VDEC_H         7
-
-/* end of display sequence */
-#define END_OF_SEQ     0xF;
-
-/* registry string size */
-#define MAX_REGISTRY_SZ        40;
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-medusa-reg.h b/drivers/media/video/cx25821/cx25821-medusa-reg.h
deleted file mode 100644 (file)
index c98ac94..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __MEDUSA_REGISTERS__
-#define __MEDUSA_REGISTERS__
-
-/* Serial Slave Registers */
-#define        HOST_REGISTER1                          0x0000
-#define        HOST_REGISTER2                          0x0001
-
-/* Chip Configuration Registers */
-#define        CHIP_CTRL                               0x0100
-#define        AFE_AB_CTRL                             0x0104
-#define        AFE_CD_CTRL                             0x0108
-#define        AFE_EF_CTRL                             0x010C
-#define        AFE_GH_CTRL                             0x0110
-#define        DENC_AB_CTRL                            0x0114
-#define        BYP_AB_CTRL                             0x0118
-#define        MON_A_CTRL                              0x011C
-#define        DISP_SEQ_A                              0x0120
-#define        DISP_SEQ_B                              0x0124
-#define        DISP_AB_CNT                             0x0128
-#define        DISP_CD_CNT                             0x012C
-#define        DISP_EF_CNT                             0x0130
-#define        DISP_GH_CNT                             0x0134
-#define        DISP_IJ_CNT                             0x0138
-#define        PIN_OE_CTRL                             0x013C
-#define        PIN_SPD_CTRL                            0x0140
-#define        PIN_SPD_CTRL2                           0x0144
-#define        IRQ_STAT_CTRL                           0x0148
-#define        POWER_CTRL_AB                           0x014C
-#define        POWER_CTRL_CD                           0x0150
-#define        POWER_CTRL_EF                           0x0154
-#define        POWER_CTRL_GH                           0x0158
-#define        TUNE_CTRL                               0x015C
-#define        BIAS_CTRL                               0x0160
-#define        AFE_AB_DIAG_CTRL                        0x0164
-#define        AFE_CD_DIAG_CTRL                        0x0168
-#define        AFE_EF_DIAG_CTRL                        0x016C
-#define        AFE_GH_DIAG_CTRL                        0x0170
-#define        PLL_AB_DIAG_CTRL                        0x0174
-#define        PLL_CD_DIAG_CTRL                        0x0178
-#define        PLL_EF_DIAG_CTRL                        0x017C
-#define        PLL_GH_DIAG_CTRL                        0x0180
-#define        TEST_CTRL                               0x0184
-#define        BIST_STAT                               0x0188
-#define        BIST_STAT2                              0x018C
-#define        BIST_VID_PLL_AB_STAT                    0x0190
-#define        BIST_VID_PLL_CD_STAT                    0x0194
-#define        BIST_VID_PLL_EF_STAT                    0x0198
-#define        BIST_VID_PLL_GH_STAT                    0x019C
-#define        DLL_DIAG_CTRL                           0x01A0
-#define        DEV_CH_ID_CTRL                          0x01A4
-#define        ABIST_CTRL_STATUS                       0x01A8
-#define        ABIST_FREQ                              0x01AC
-#define        ABIST_GOERT_SHIFT                       0x01B0
-#define        ABIST_COEF12                            0x01B4
-#define        ABIST_COEF34                            0x01B8
-#define        ABIST_COEF56                            0x01BC
-#define        ABIST_COEF7_SNR                         0x01C0
-#define        ABIST_ADC_CAL                           0x01C4
-#define        ABIST_BIN1_VGA0                         0x01C8
-#define        ABIST_BIN2_VGA1                         0x01CC
-#define        ABIST_BIN3_VGA2                         0x01D0
-#define        ABIST_BIN4_VGA3                         0x01D4
-#define        ABIST_BIN5_VGA4                         0x01D8
-#define        ABIST_BIN6_VGA5                         0x01DC
-#define        ABIST_BIN7_VGA6                         0x0x1E0
-#define        ABIST_CLAMP_A                           0x0x1E4
-#define        ABIST_CLAMP_B                           0x0x1E8
-#define        ABIST_CLAMP_C                           0x01EC
-#define        ABIST_CLAMP_D                           0x01F0
-#define        ABIST_CLAMP_E                           0x01F4
-#define        ABIST_CLAMP_F                           0x01F8
-
-/* Digital Video Encoder A Registers */
-#define        DENC_A_REG_1                            0x0200
-#define        DENC_A_REG_2                            0x0204
-#define        DENC_A_REG_3                            0x0208
-#define        DENC_A_REG_4                            0x020C
-#define        DENC_A_REG_5                            0x0210
-#define        DENC_A_REG_6                            0x0214
-#define        DENC_A_REG_7                            0x0218
-#define        DENC_A_REG_8                            0x021C
-
-/* Digital Video Encoder B Registers */
-#define        DENC_B_REG_1                            0x0300
-#define        DENC_B_REG_2                            0x0304
-#define        DENC_B_REG_3                            0x0308
-#define        DENC_B_REG_4                            0x030C
-#define        DENC_B_REG_5                            0x0310
-#define        DENC_B_REG_6                            0x0314
-#define        DENC_B_REG_7                            0x0318
-#define        DENC_B_REG_8                            0x031C
-
-/* Video Decoder A Registers */
-#define        MODE_CTRL                               0x1000
-#define        OUT_CTRL1                               0x1004
-#define        OUT_CTRL_NS                             0x1008
-#define        GEN_STAT                                0x100C
-#define        INT_STAT_MASK                           0x1010
-#define        LUMA_CTRL                               0x1014
-#define        CHROMA_CTRL                             0x1018
-#define        CRUSH_CTRL                              0x101C
-#define        HORIZ_TIM_CTRL                          0x1020
-#define        VERT_TIM_CTRL                           0x1024
-#define        MISC_TIM_CTRL                           0x1028
-#define        FIELD_COUNT                             0x102C
-#define        HSCALE_CTRL                             0x1030
-#define        VSCALE_CTRL                             0x1034
-#define        MAN_VGA_CTRL                            0x1038
-#define        MAN_AGC_CTRL                            0x103C
-#define        DFE_CTRL1                               0x1040
-#define        DFE_CTRL2                               0x1044
-#define        DFE_CTRL3                               0x1048
-#define        PLL_CTRL                                0x104C
-#define        PLL_CTRL_FAST                           0x1050
-#define        HTL_CTRL                                0x1054
-#define        SRC_CFG                                 0x1058
-#define        SC_STEP_SIZE                            0x105C
-#define        SC_CONVERGE_CTRL                        0x1060
-#define        SC_LOOP_CTRL                            0x1064
-#define        COMB_2D_HFS_CFG                         0x1068
-#define        COMB_2D_HFD_CFG                         0x106C
-#define        COMB_2D_LF_CFG                          0x1070
-#define        COMB_2D_BLEND                           0x1074
-#define        COMB_MISC_CTRL                          0x1078
-#define        COMB_FLAT_THRESH_CTRL                   0x107C
-#define        COMB_TEST                               0x1080
-#define        BP_MISC_CTRL                            0x1084
-#define        VCR_DET_CTRL                            0x1088
-#define        NOISE_DET_CTRL                          0x108C
-#define        COMB_FLAT_NOISE_CTRL                    0x1090
-#define        VERSION                                 0x11F8
-#define        SOFT_RST_CTRL                           0x11FC
-
-/* Video Decoder B Registers */
-#define        VDEC_B_MODE_CTRL                        0x1200
-#define        VDEC_B_OUT_CTRL1                        0x1204
-#define        VDEC_B_OUT_CTRL_NS                      0x1208
-#define        VDEC_B_GEN_STAT                         0x120C
-#define        VDEC_B_INT_STAT_MASK                    0x1210
-#define        VDEC_B_LUMA_CTRL                        0x1214
-#define        VDEC_B_CHROMA_CTRL                      0x1218
-#define        VDEC_B_CRUSH_CTRL                       0x121C
-#define        VDEC_B_HORIZ_TIM_CTRL                   0x1220
-#define        VDEC_B_VERT_TIM_CTRL                    0x1224
-#define        VDEC_B_MISC_TIM_CTRL                    0x1228
-#define        VDEC_B_FIELD_COUNT                      0x122C
-#define        VDEC_B_HSCALE_CTRL                      0x1230
-#define        VDEC_B_VSCALE_CTRL                      0x1234
-#define        VDEC_B_MAN_VGA_CTRL                     0x1238
-#define        VDEC_B_MAN_AGC_CTRL                     0x123C
-#define        VDEC_B_DFE_CTRL1                        0x1240
-#define        VDEC_B_DFE_CTRL2                        0x1244
-#define        VDEC_B_DFE_CTRL3                        0x1248
-#define        VDEC_B_PLL_CTRL                         0x124C
-#define        VDEC_B_PLL_CTRL_FAST                    0x1250
-#define        VDEC_B_HTL_CTRL                         0x1254
-#define        VDEC_B_SRC_CFG                          0x1258
-#define        VDEC_B_SC_STEP_SIZE                     0x125C
-#define        VDEC_B_SC_CONVERGE_CTRL                 0x1260
-#define        VDEC_B_SC_LOOP_CTRL                     0x1264
-#define        VDEC_B_COMB_2D_HFS_CFG                  0x1268
-#define        VDEC_B_COMB_2D_HFD_CFG                  0x126C
-#define        VDEC_B_COMB_2D_LF_CFG                   0x1270
-#define        VDEC_B_COMB_2D_BLEND                    0x1274
-#define        VDEC_B_COMB_MISC_CTRL                   0x1278
-#define        VDEC_B_COMB_FLAT_THRESH_CTRL            0x127C
-#define        VDEC_B_COMB_TEST                        0x1280
-#define        VDEC_B_BP_MISC_CTRL                     0x1284
-#define        VDEC_B_VCR_DET_CTRL                     0x1288
-#define        VDEC_B_NOISE_DET_CTRL                   0x128C
-#define        VDEC_B_COMB_FLAT_NOISE_CTRL             0x1290
-#define        VDEC_B_VERSION                          0x13F8
-#define        VDEC_B_SOFT_RST_CTRL                    0x13FC
-
-/* Video Decoder C Registers */
-#define        VDEC_C_MODE_CTRL                        0x1400
-#define        VDEC_C_OUT_CTRL1                        0x1404
-#define        VDEC_C_OUT_CTRL_NS                      0x1408
-#define        VDEC_C_GEN_STAT                         0x140C
-#define        VDEC_C_INT_STAT_MASK                    0x1410
-#define VDEC_C_LUMA_CTRL                       0x1414
-#define VDEC_C_CHROMA_CTRL                     0x1418
-#define        VDEC_C_CRUSH_CTRL                       0x141C
-#define        VDEC_C_HORIZ_TIM_CTRL                   0x1420
-#define        VDEC_C_VERT_TIM_CTRL                    0x1424
-#define        VDEC_C_MISC_TIM_CTRL                    0x1428
-#define        VDEC_C_FIELD_COUNT                      0x142C
-#define        VDEC_C_HSCALE_CTRL                      0x1430
-#define        VDEC_C_VSCALE_CTRL                      0x1434
-#define        VDEC_C_MAN_VGA_CTRL                     0x1438
-#define        VDEC_C_MAN_AGC_CTRL                     0x143C
-#define        VDEC_C_DFE_CTRL1                        0x1440
-#define        VDEC_C_DFE_CTRL2                        0x1444
-#define        VDEC_C_DFE_CTRL3                        0x1448
-#define        VDEC_C_PLL_CTRL                         0x144C
-#define        VDEC_C_PLL_CTRL_FAST                    0x1450
-#define        VDEC_C_HTL_CTRL                         0x1454
-#define        VDEC_C_SRC_CFG                          0x1458
-#define        VDEC_C_SC_STEP_SIZE                     0x145C
-#define        VDEC_C_SC_CONVERGE_CTRL                 0x1460
-#define        VDEC_C_SC_LOOP_CTRL                     0x1464
-#define        VDEC_C_COMB_2D_HFS_CFG                  0x1468
-#define        VDEC_C_COMB_2D_HFD_CFG                  0x146C
-#define        VDEC_C_COMB_2D_LF_CFG                   0x1470
-#define        VDEC_C_COMB_2D_BLEND                    0x1474
-#define        VDEC_C_COMB_MISC_CTRL                   0x1478
-#define        VDEC_C_COMB_FLAT_THRESH_CTRL            0x147C
-#define        VDEC_C_COMB_TEST                        0x1480
-#define        VDEC_C_BP_MISC_CTRL                     0x1484
-#define        VDEC_C_VCR_DET_CTRL                     0x1488
-#define        VDEC_C_NOISE_DET_CTRL                   0x148C
-#define        VDEC_C_COMB_FLAT_NOISE_CTRL             0x1490
-#define        VDEC_C_VERSION                          0x15F8
-#define        VDEC_C_SOFT_RST_CTRL                    0x15FC
-
-/* Video Decoder D Registers */
-#define VDEC_D_MODE_CTRL                       0x1600
-#define VDEC_D_OUT_CTRL1                       0x1604
-#define VDEC_D_OUT_CTRL_NS                     0x1608
-#define VDEC_D_GEN_STAT                                0x160C
-#define VDEC_D_INT_STAT_MASK                   0x1610
-#define VDEC_D_LUMA_CTRL                       0x1614
-#define VDEC_D_CHROMA_CTRL                     0x1618
-#define VDEC_D_CRUSH_CTRL                      0x161C
-#define VDEC_D_HORIZ_TIM_CTRL                  0x1620
-#define VDEC_D_VERT_TIM_CTRL                   0x1624
-#define VDEC_D_MISC_TIM_CTRL                   0x1628
-#define VDEC_D_FIELD_COUNT                     0x162C
-#define VDEC_D_HSCALE_CTRL                     0x1630
-#define VDEC_D_VSCALE_CTRL                     0x1634
-#define VDEC_D_MAN_VGA_CTRL                    0x1638
-#define VDEC_D_MAN_AGC_CTRL                    0x163C
-#define VDEC_D_DFE_CTRL1                       0x1640
-#define VDEC_D_DFE_CTRL2                       0x1644
-#define VDEC_D_DFE_CTRL3                       0x1648
-#define VDEC_D_PLL_CTRL                                0x164C
-#define VDEC_D_PLL_CTRL_FAST                   0x1650
-#define VDEC_D_HTL_CTRL                                0x1654
-#define VDEC_D_SRC_CFG                         0x1658
-#define VDEC_D_SC_STEP_SIZE                    0x165C
-#define VDEC_D_SC_CONVERGE_CTRL                        0x1660
-#define VDEC_D_SC_LOOP_CTRL                    0x1664
-#define VDEC_D_COMB_2D_HFS_CFG                 0x1668
-#define VDEC_D_COMB_2D_HFD_CFG                 0x166C
-#define VDEC_D_COMB_2D_LF_CFG                  0x1670
-#define VDEC_D_COMB_2D_BLEND                   0x1674
-#define VDEC_D_COMB_MISC_CTRL                  0x1678
-#define VDEC_D_COMB_FLAT_THRESH_CTRL           0x167C
-#define VDEC_D_COMB_TEST                       0x1680
-#define VDEC_D_BP_MISC_CTRL                    0x1684
-#define VDEC_D_VCR_DET_CTRL                    0x1688
-#define VDEC_D_NOISE_DET_CTRL                  0x168C
-#define VDEC_D_COMB_FLAT_NOISE_CTRL            0x1690
-#define VDEC_D_VERSION                         0x17F8
-#define VDEC_D_SOFT_RST_CTRL                   0x17FC
-
-/* Video Decoder E Registers */
-#define        VDEC_E_MODE_CTRL                        0x1800
-#define        VDEC_E_OUT_CTRL1                        0x1804
-#define        VDEC_E_OUT_CTRL_NS                      0x1808
-#define        VDEC_E_GEN_STAT                         0x180C
-#define        VDEC_E_INT_STAT_MASK                    0x1810
-#define        VDEC_E_LUMA_CTRL                        0x1814
-#define        VDEC_E_CHROMA_CTRL                      0x1818
-#define        VDEC_E_CRUSH_CTRL                       0x181C
-#define        VDEC_E_HORIZ_TIM_CTRL                   0x1820
-#define        VDEC_E_VERT_TIM_CTRL                    0x1824
-#define        VDEC_E_MISC_TIM_CTRL                    0x1828
-#define        VDEC_E_FIELD_COUNT                      0x182C
-#define        VDEC_E_HSCALE_CTRL                      0x1830
-#define        VDEC_E_VSCALE_CTRL                      0x1834
-#define        VDEC_E_MAN_VGA_CTRL                     0x1838
-#define        VDEC_E_MAN_AGC_CTRL                     0x183C
-#define        VDEC_E_DFE_CTRL1                        0x1840
-#define        VDEC_E_DFE_CTRL2                        0x1844
-#define        VDEC_E_DFE_CTRL3                        0x1848
-#define        VDEC_E_PLL_CTRL                         0x184C
-#define        VDEC_E_PLL_CTRL_FAST                    0x1850
-#define        VDEC_E_HTL_CTRL                         0x1854
-#define        VDEC_E_SRC_CFG                          0x1858
-#define        VDEC_E_SC_STEP_SIZE                     0x185C
-#define        VDEC_E_SC_CONVERGE_CTRL                 0x1860
-#define        VDEC_E_SC_LOOP_CTRL                     0x1864
-#define        VDEC_E_COMB_2D_HFS_CFG                  0x1868
-#define        VDEC_E_COMB_2D_HFD_CFG                  0x186C
-#define        VDEC_E_COMB_2D_LF_CFG                   0x1870
-#define        VDEC_E_COMB_2D_BLEND                    0x1874
-#define        VDEC_E_COMB_MISC_CTRL                   0x1878
-#define        VDEC_E_COMB_FLAT_THRESH_CTRL            0x187C
-#define        VDEC_E_COMB_TEST                        0x1880
-#define        VDEC_E_BP_MISC_CTRL                     0x1884
-#define        VDEC_E_VCR_DET_CTRL                     0x1888
-#define        VDEC_E_NOISE_DET_CTRL                   0x188C
-#define        VDEC_E_COMB_FLAT_NOISE_CTRL             0x1890
-#define        VDEC_E_VERSION                          0x19F8
-#define        VDEC_E_SOFT_RST_CTRL                    0x19FC
-
-/* Video Decoder F Registers */
-#define        VDEC_F_MODE_CTRL                        0x1A00
-#define        VDEC_F_OUT_CTRL1                        0x1A04
-#define        VDEC_F_OUT_CTRL_NS                      0x1A08
-#define        VDEC_F_GEN_STAT                         0x1A0C
-#define        VDEC_F_INT_STAT_MASK                    0x1A10
-#define        VDEC_F_LUMA_CTRL                        0x1A14
-#define        VDEC_F_CHROMA_CTRL                      0x1A18
-#define        VDEC_F_CRUSH_CTRL                       0x1A1C
-#define        VDEC_F_HORIZ_TIM_CTRL                   0x1A20
-#define        VDEC_F_VERT_TIM_CTRL                    0x1A24
-#define        VDEC_F_MISC_TIM_CTRL                    0x1A28
-#define        VDEC_F_FIELD_COUNT                      0x1A2C
-#define        VDEC_F_HSCALE_CTRL                      0x1A30
-#define        VDEC_F_VSCALE_CTRL                      0x1A34
-#define        VDEC_F_MAN_VGA_CTRL                     0x1A38
-#define        VDEC_F_MAN_AGC_CTRL                     0x1A3C
-#define        VDEC_F_DFE_CTRL1                        0x1A40
-#define        VDEC_F_DFE_CTRL2                        0x1A44
-#define        VDEC_F_DFE_CTRL3                        0x1A48
-#define        VDEC_F_PLL_CTRL                         0x1A4C
-#define        VDEC_F_PLL_CTRL_FAST                    0x1A50
-#define        VDEC_F_HTL_CTRL                         0x1A54
-#define        VDEC_F_SRC_CFG                          0x1A58
-#define        VDEC_F_SC_STEP_SIZE                     0x1A5C
-#define        VDEC_F_SC_CONVERGE_CTRL                 0x1A60
-#define        VDEC_F_SC_LOOP_CTRL                     0x1A64
-#define        VDEC_F_COMB_2D_HFS_CFG                  0x1A68
-#define        VDEC_F_COMB_2D_HFD_CFG                  0x1A6C
-#define        VDEC_F_COMB_2D_LF_CFG                   0x1A70
-#define        VDEC_F_COMB_2D_BLEND                    0x1A74
-#define        VDEC_F_COMB_MISC_CTRL                   0x1A78
-#define        VDEC_F_COMB_FLAT_THRESH_CTRL            0x1A7C
-#define        VDEC_F_COMB_TEST                        0x1A80
-#define        VDEC_F_BP_MISC_CTRL                     0x1A84
-#define        VDEC_F_VCR_DET_CTRL                     0x1A88
-#define        VDEC_F_NOISE_DET_CTRL                   0x1A8C
-#define        VDEC_F_COMB_FLAT_NOISE_CTRL             0x1A90
-#define        VDEC_F_VERSION                          0x1BF8
-#define        VDEC_F_SOFT_RST_CTRL                    0x1BFC
-
-/* Video Decoder G Registers */
-#define        VDEC_G_MODE_CTRL                        0x1C00
-#define        VDEC_G_OUT_CTRL1                        0x1C04
-#define        VDEC_G_OUT_CTRL_NS                      0x1C08
-#define        VDEC_G_GEN_STAT                         0x1C0C
-#define        VDEC_G_INT_STAT_MASK                    0x1C10
-#define        VDEC_G_LUMA_CTRL                        0x1C14
-#define        VDEC_G_CHROMA_CTRL                      0x1C18
-#define        VDEC_G_CRUSH_CTRL                       0x1C1C
-#define        VDEC_G_HORIZ_TIM_CTRL                   0x1C20
-#define        VDEC_G_VERT_TIM_CTRL                    0x1C24
-#define        VDEC_G_MISC_TIM_CTRL                    0x1C28
-#define        VDEC_G_FIELD_COUNT                      0x1C2C
-#define        VDEC_G_HSCALE_CTRL                      0x1C30
-#define        VDEC_G_VSCALE_CTRL                      0x1C34
-#define        VDEC_G_MAN_VGA_CTRL                     0x1C38
-#define        VDEC_G_MAN_AGC_CTRL                     0x1C3C
-#define        VDEC_G_DFE_CTRL1                        0x1C40
-#define        VDEC_G_DFE_CTRL2                        0x1C44
-#define        VDEC_G_DFE_CTRL3                        0x1C48
-#define        VDEC_G_PLL_CTRL                         0x1C4C
-#define        VDEC_G_PLL_CTRL_FAST                    0x1C50
-#define        VDEC_G_HTL_CTRL                         0x1C54
-#define        VDEC_G_SRC_CFG                          0x1C58
-#define        VDEC_G_SC_STEP_SIZE                     0x1C5C
-#define        VDEC_G_SC_CONVERGE_CTRL                 0x1C60
-#define        VDEC_G_SC_LOOP_CTRL                     0x1C64
-#define        VDEC_G_COMB_2D_HFS_CFG                  0x1C68
-#define        VDEC_G_COMB_2D_HFD_CFG                  0x1C6C
-#define        VDEC_G_COMB_2D_LF_CFG                   0x1C70
-#define        VDEC_G_COMB_2D_BLEND                    0x1C74
-#define        VDEC_G_COMB_MISC_CTRL                   0x1C78
-#define        VDEC_G_COMB_FLAT_THRESH_CTRL            0x1C7C
-#define        VDEC_G_COMB_TEST                        0x1C80
-#define        VDEC_G_BP_MISC_CTRL                     0x1C84
-#define        VDEC_G_VCR_DET_CTRL                     0x1C88
-#define        VDEC_G_NOISE_DET_CTRL                   0x1C8C
-#define        VDEC_G_COMB_FLAT_NOISE_CTRL             0x1C90
-#define        VDEC_G_VERSION                          0x1DF8
-#define        VDEC_G_SOFT_RST_CTRL                    0x1DFC
-
-/* Video Decoder H Registers  */
-#define        VDEC_H_MODE_CTRL                        0x1E00
-#define        VDEC_H_OUT_CTRL1                        0x1E04
-#define        VDEC_H_OUT_CTRL_NS                      0x1E08
-#define        VDEC_H_GEN_STAT                         0x1E0C
-#define        VDEC_H_INT_STAT_MASK                    0x1E1E
-#define        VDEC_H_LUMA_CTRL                        0x1E14
-#define        VDEC_H_CHROMA_CTRL                      0x1E18
-#define        VDEC_H_CRUSH_CTRL                       0x1E1C
-#define        VDEC_H_HORIZ_TIM_CTRL                   0x1E20
-#define        VDEC_H_VERT_TIM_CTRL                    0x1E24
-#define        VDEC_H_MISC_TIM_CTRL                    0x1E28
-#define        VDEC_H_FIELD_COUNT                      0x1E2C
-#define        VDEC_H_HSCALE_CTRL                      0x1E30
-#define        VDEC_H_VSCALE_CTRL                      0x1E34
-#define        VDEC_H_MAN_VGA_CTRL                     0x1E38
-#define        VDEC_H_MAN_AGC_CTRL                     0x1E3C
-#define        VDEC_H_DFE_CTRL1                        0x1E40
-#define        VDEC_H_DFE_CTRL2                        0x1E44
-#define        VDEC_H_DFE_CTRL3                        0x1E48
-#define        VDEC_H_PLL_CTRL                         0x1E4C
-#define        VDEC_H_PLL_CTRL_FAST                    0x1E50
-#define        VDEC_H_HTL_CTRL                         0x1E54
-#define        VDEC_H_SRC_CFG                          0x1E58
-#define        VDEC_H_SC_STEP_SIZE                     0x1E5C
-#define        VDEC_H_SC_CONVERGE_CTRL                 0x1E60
-#define        VDEC_H_SC_LOOP_CTRL                     0x1E64
-#define        VDEC_H_COMB_2D_HFS_CFG                  0x1E68
-#define        VDEC_H_COMB_2D_HFD_CFG                  0x1E6C
-#define        VDEC_H_COMB_2D_LF_CFG                   0x1E70
-#define        VDEC_H_COMB_2D_BLEND                    0x1E74
-#define        VDEC_H_COMB_MISC_CTRL                   0x1E78
-#define        VDEC_H_COMB_FLAT_THRESH_CTRL            0x1E7C
-#define        VDEC_H_COMB_TEST                        0x1E80
-#define        VDEC_H_BP_MISC_CTRL                     0x1E84
-#define        VDEC_H_VCR_DET_CTRL                     0x1E88
-#define        VDEC_H_NOISE_DET_CTRL                   0x1E8C
-#define        VDEC_H_COMB_FLAT_NOISE_CTRL             0x1E90
-#define        VDEC_H_VERSION                          0x1FF8
-#define        VDEC_H_SOFT_RST_CTRL                    0x1FFC
-
-/*****************************************************************************/
-/* LUMA_CTRL register fields */
-#define VDEC_A_BRITE_CTRL                      0x1014
-#define VDEC_A_CNTRST_CTRL                     0x1015
-#define VDEC_A_PEAK_SEL                                0x1016
-
-/*****************************************************************************/
-/* CHROMA_CTRL register fields */
-#define VDEC_A_USAT_CTRL                       0x1018
-#define VDEC_A_VSAT_CTRL                       0x1019
-#define VDEC_A_HUE_CTRL                                0x101A
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c
deleted file mode 100644 (file)
index 6a92e5c..0000000
+++ /dev/null
@@ -1,787 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "cx25821.h"
-#include "cx25821-medusa-video.h"
-#include "cx25821-biffuncs.h"
-
-/*
- * medusa_enable_bluefield_output()
- *
- * Enable the generation of blue filed output if no video
- *
- */
-static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
-                                          int enable)
-{
-       u32 value = 0;
-       u32 tmp = 0;
-       int out_ctrl = OUT_CTRL1;
-       int out_ctrl_ns = OUT_CTRL_NS;
-
-       switch (channel) {
-       default:
-       case VDEC_A:
-               break;
-       case VDEC_B:
-               out_ctrl = VDEC_B_OUT_CTRL1;
-               out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
-               break;
-       case VDEC_C:
-               out_ctrl = VDEC_C_OUT_CTRL1;
-               out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
-               break;
-       case VDEC_D:
-               out_ctrl = VDEC_D_OUT_CTRL1;
-               out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
-               break;
-       case VDEC_E:
-               out_ctrl = VDEC_E_OUT_CTRL1;
-               out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
-               return;
-       case VDEC_F:
-               out_ctrl = VDEC_F_OUT_CTRL1;
-               out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
-               return;
-       case VDEC_G:
-               out_ctrl = VDEC_G_OUT_CTRL1;
-               out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
-               return;
-       case VDEC_H:
-               out_ctrl = VDEC_H_OUT_CTRL1;
-               out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
-               return;
-       }
-
-       value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
-       value &= 0xFFFFFF7F;    /* clear BLUE_FIELD_EN */
-       if (enable)
-               value |= 0x00000080;    /* set BLUE_FIELD_EN */
-       cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
-
-       value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
-       value &= 0xFFFFFF7F;
-       if (enable)
-               value |= 0x00000080;    /* set BLUE_FIELD_EN */
-       cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
-}
-
-static int medusa_initialize_ntsc(struct cx25821_dev *dev)
-{
-       int ret_val = 0;
-       int i = 0;
-       u32 value = 0;
-       u32 tmp = 0;
-
-       mutex_lock(&dev->lock);
-
-       for (i = 0; i < MAX_DECODERS; i++) {
-               /* set video format NTSC-M */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               MODE_CTRL + (0x200 * i), &tmp);
-               value &= 0xFFFFFFF0;
-               /* enable the fast locking mode bit[16] */
-               value |= 0x10001;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               MODE_CTRL + (0x200 * i), value);
-
-               /* resolution NTSC 720x480 */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               HORIZ_TIM_CTRL + (0x200 * i), &tmp);
-               value &= 0x00C00C00;
-               value |= 0x612D0074;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               HORIZ_TIM_CTRL + (0x200 * i), value);
-
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               VERT_TIM_CTRL + (0x200 * i), &tmp);
-               value &= 0x00C00C00;
-               value |= 0x1C1E001A;    /* vblank_cnt + 2 to get camera ID */
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               VERT_TIM_CTRL + (0x200 * i), value);
-
-               /* chroma subcarrier step size */
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               SC_STEP_SIZE + (0x200 * i), 0x43E00000);
-
-               /* enable VIP optional active */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               OUT_CTRL_NS + (0x200 * i), &tmp);
-               value &= 0xFFFBFFFF;
-               value |= 0x00040000;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               OUT_CTRL_NS + (0x200 * i), value);
-
-               /* enable VIP optional active (VIP_OPT_AL) for direct output. */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               OUT_CTRL1 + (0x200 * i), &tmp);
-               value &= 0xFFFBFFFF;
-               value |= 0x00040000;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               OUT_CTRL1 + (0x200 * i), value);
-
-               /*
-                * clear VPRES_VERT_EN bit, fixes the chroma run away problem
-                * when the input switching rate < 16 fields
-               */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               MISC_TIM_CTRL + (0x200 * i), &tmp);
-               /* disable special play detection */
-               value = setBitAtPos(value, 14);
-               value = clearBitAtPos(value, 15);
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               MISC_TIM_CTRL + (0x200 * i), value);
-
-               /* set vbi_gate_en to 0 */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DFE_CTRL1 + (0x200 * i), &tmp);
-               value = clearBitAtPos(value, 29);
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DFE_CTRL1 + (0x200 * i), value);
-
-               /* Enable the generation of blue field output if no video */
-               medusa_enable_bluefield_output(dev, i, 1);
-       }
-
-       for (i = 0; i < MAX_ENCODERS; i++) {
-               /* NTSC hclock */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_1 + (0x100 * i), &tmp);
-               value &= 0xF000FC00;
-               value |= 0x06B402D0;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_1 + (0x100 * i), value);
-
-               /* burst begin and burst end */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_2 + (0x100 * i), &tmp);
-               value &= 0xFF000000;
-               value |= 0x007E9054;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_2 + (0x100 * i), value);
-
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_3 + (0x100 * i), &tmp);
-               value &= 0xFC00FE00;
-               value |= 0x00EC00F0;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_3 + (0x100 * i), value);
-
-               /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_4 + (0x100 * i), &tmp);
-               value &= 0x00FCFFFF;
-               value |= 0x13020000;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_4 + (0x100 * i), value);
-
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_5 + (0x100 * i), &tmp);
-               value &= 0xFFFF0000;
-               value |= 0x0000E575;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_5 + (0x100 * i), value);
-
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
-
-               /* Subcarrier Increment */
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
-       }
-
-       /* set picture resolutions */
-       /* 0 - 720 */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
-       /* 0 - 480 */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
-
-       /* set Bypass input format to NTSC 525 lines */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
-       value |= 0x00080200;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
-
-       mutex_unlock(&dev->lock);
-
-       return ret_val;
-}
-
-static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
-{
-       int ret_val = -1;
-       u32 value = 0, tmp = 0;
-
-       /* Setup for 2D threshold */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                       COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861);
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                       COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861);
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                       COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023);
-
-       /* Setup flat chroma and luma thresholds */
-       value = cx25821_i2c_read(&dev->i2c_bus[0],
-                       COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
-       value &= 0x06230000;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                       COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
-
-       /* set comb 2D blend */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                       COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F);
-
-       /* COMB MISC CONTROL */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                       COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F);
-
-       return ret_val;
-}
-
-static int medusa_initialize_pal(struct cx25821_dev *dev)
-{
-       int ret_val = 0;
-       int i = 0;
-       u32 value = 0;
-       u32 tmp = 0;
-
-       mutex_lock(&dev->lock);
-
-       for (i = 0; i < MAX_DECODERS; i++) {
-               /* set video format PAL-BDGHI */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               MODE_CTRL + (0x200 * i), &tmp);
-               value &= 0xFFFFFFF0;
-               /* enable the fast locking mode bit[16] */
-               value |= 0x10004;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               MODE_CTRL + (0x200 * i), value);
-
-               /* resolution PAL 720x576 */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               HORIZ_TIM_CTRL + (0x200 * i), &tmp);
-               value &= 0x00C00C00;
-               value |= 0x632D007D;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               HORIZ_TIM_CTRL + (0x200 * i), value);
-
-               /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               VERT_TIM_CTRL + (0x200 * i), &tmp);
-               value &= 0x00C00C00;
-               value |= 0x28240026;    /* vblank_cnt + 2 to get camera ID */
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               VERT_TIM_CTRL + (0x200 * i), value);
-
-               /* chroma subcarrier step size */
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
-
-               /* enable VIP optional active */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               OUT_CTRL_NS + (0x200 * i), &tmp);
-               value &= 0xFFFBFFFF;
-               value |= 0x00040000;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               OUT_CTRL_NS + (0x200 * i), value);
-
-               /* enable VIP optional active (VIP_OPT_AL) for direct output. */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               OUT_CTRL1 + (0x200 * i), &tmp);
-               value &= 0xFFFBFFFF;
-               value |= 0x00040000;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               OUT_CTRL1 + (0x200 * i), value);
-
-               /*
-                * clear VPRES_VERT_EN bit, fixes the chroma run away problem
-                * when the input switching rate < 16 fields
-                */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               MISC_TIM_CTRL + (0x200 * i), &tmp);
-               /* disable special play detection */
-               value = setBitAtPos(value, 14);
-               value = clearBitAtPos(value, 15);
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               MISC_TIM_CTRL + (0x200 * i), value);
-
-               /* set vbi_gate_en to 0 */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DFE_CTRL1 + (0x200 * i), &tmp);
-               value = clearBitAtPos(value, 29);
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DFE_CTRL1 + (0x200 * i), value);
-
-               medusa_PALCombInit(dev, i);
-
-               /* Enable the generation of blue field output if no video */
-               medusa_enable_bluefield_output(dev, i, 1);
-       }
-
-       for (i = 0; i < MAX_ENCODERS; i++) {
-               /* PAL hclock */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_1 + (0x100 * i), &tmp);
-               value &= 0xF000FC00;
-               value |= 0x06C002D0;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_1 + (0x100 * i), value);
-
-               /* burst begin and burst end */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_2 + (0x100 * i), &tmp);
-               value &= 0xFF000000;
-               value |= 0x007E9754;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_2 + (0x100 * i), value);
-
-               /* hblank and vactive */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_3 + (0x100 * i), &tmp);
-               value &= 0xFC00FE00;
-               value |= 0x00FC0120;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_3 + (0x100 * i), value);
-
-               /* set PAL vblank, phase alternation, 0 IRE pedestal */
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_4 + (0x100 * i), &tmp);
-               value &= 0x00FCFFFF;
-               value |= 0x14010000;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_4 + (0x100 * i), value);
-
-               value = cx25821_i2c_read(&dev->i2c_bus[0],
-                               DENC_A_REG_5 + (0x100 * i), &tmp);
-               value &= 0xFFFF0000;
-               value |= 0x0000F078;
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_5 + (0x100 * i), value);
-
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
-
-               /* Subcarrier Increment */
-               ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
-                               DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
-       }
-
-       /* set picture resolutions */
-       /* 0 - 720 */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
-       /* 0 - 576 */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
-
-       /* set Bypass input format to PAL 625 lines */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
-       value &= 0xFFF7FDFF;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
-
-       mutex_unlock(&dev->lock);
-
-       return ret_val;
-}
-
-int medusa_set_videostandard(struct cx25821_dev *dev)
-{
-       int status = STATUS_SUCCESS;
-       u32 value = 0, tmp = 0;
-
-       if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
-               status = medusa_initialize_pal(dev);
-       else
-               status = medusa_initialize_ntsc(dev);
-
-       /* Enable DENC_A output */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
-       value = setBitAtPos(value, 4);
-       status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
-
-       /* Enable DENC_B output */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
-       value = setBitAtPos(value, 4);
-       status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
-
-       return status;
-}
-
-void medusa_set_resolution(struct cx25821_dev *dev, int width,
-                          int decoder_select)
-{
-       int decoder = 0;
-       int decoder_count = 0;
-       u32 hscale = 0x0;
-       u32 vscale = 0x0;
-       const int MAX_WIDTH = 720;
-
-       mutex_lock(&dev->lock);
-
-       /* validate the width */
-       if (width > MAX_WIDTH) {
-               pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
-                       __func__, width, MAX_WIDTH);
-               width = MAX_WIDTH;
-       }
-
-       if (decoder_select <= 7 && decoder_select >= 0) {
-               decoder = decoder_select;
-               decoder_count = decoder_select + 1;
-       } else {
-               decoder = 0;
-               decoder_count = _num_decoders;
-       }
-
-       switch (width) {
-       case 320:
-               hscale = 0x13E34B;
-               vscale = 0x0;
-               break;
-
-       case 352:
-               hscale = 0x10A273;
-               vscale = 0x0;
-               break;
-
-       case 176:
-               hscale = 0x3115B2;
-               vscale = 0x1E00;
-               break;
-
-       case 160:
-               hscale = 0x378D84;
-               vscale = 0x1E00;
-               break;
-
-       default:                /* 720 */
-               hscale = 0x0;
-               vscale = 0x0;
-               break;
-       }
-
-       for (; decoder < decoder_count; decoder++) {
-               /* write scaling values for each decoder */
-               cx25821_i2c_write(&dev->i2c_bus[0],
-                               HSCALE_CTRL + (0x200 * decoder), hscale);
-               cx25821_i2c_write(&dev->i2c_bus[0],
-                               VSCALE_CTRL + (0x200 * decoder), vscale);
-       }
-
-       mutex_unlock(&dev->lock);
-}
-
-static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
-                                      int duration)
-{
-       u32 fld_cnt = 0;
-       u32 tmp = 0;
-       u32 disp_cnt_reg = DISP_AB_CNT;
-
-       mutex_lock(&dev->lock);
-
-       /* no support */
-       if (decoder < VDEC_A || decoder > VDEC_H) {
-               mutex_unlock(&dev->lock);
-               return;
-       }
-
-       switch (decoder) {
-       default:
-               break;
-       case VDEC_C:
-       case VDEC_D:
-               disp_cnt_reg = DISP_CD_CNT;
-               break;
-       case VDEC_E:
-       case VDEC_F:
-               disp_cnt_reg = DISP_EF_CNT;
-               break;
-       case VDEC_G:
-       case VDEC_H:
-               disp_cnt_reg = DISP_GH_CNT;
-               break;
-       }
-
-       _display_field_cnt[decoder] = duration;
-
-       /* update hardware */
-       fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
-
-       if (!(decoder % 2)) {   /* EVEN decoder */
-               fld_cnt &= 0xFFFF0000;
-               fld_cnt |= duration;
-       } else {
-               fld_cnt &= 0x0000FFFF;
-               fld_cnt |= ((u32) duration) << 16;
-       }
-
-       cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
-
-       mutex_unlock(&dev->lock);
-}
-
-/* Map to Medusa register setting */
-static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax,
-               int *dstVal)
-{
-       int numerator;
-       int denominator;
-       int quotient;
-
-       if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
-               return -1;
-       /*
-        * This is the overall expression used:
-        * *dstVal =
-        *   (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
-        * but we need to account for rounding so below we use the modulus
-        * operator to find the remainder and increment if necessary.
-        */
-       numerator = (srcVal - srcMin) * (dstMax - dstMin);
-       denominator = srcMax - srcMin;
-       quotient = numerator / denominator;
-
-       if (2 * (numerator % denominator) >= denominator)
-               quotient++;
-
-       *dstVal = quotient + dstMin;
-
-       return 0;
-}
-
-static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
-{
-       unsigned char temp;
-
-       if (numeric >= 0)
-               return numeric;
-       else {
-               temp = ~(abs(numeric) & 0xFF);
-               temp += 1;
-               return temp;
-       }
-}
-
-int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
-{
-       int ret_val = 0;
-       int value = 0;
-       u32 val = 0, tmp = 0;
-
-       mutex_lock(&dev->lock);
-       if ((brightness > VIDEO_PROCAMP_MAX) ||
-           (brightness < VIDEO_PROCAMP_MIN)) {
-               mutex_unlock(&dev->lock);
-               return -1;
-       }
-       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
-                       SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
-       value = convert_to_twos(value, 8);
-       val = cx25821_i2c_read(&dev->i2c_bus[0],
-                       VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
-       val &= 0xFFFFFF00;
-       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
-                       VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value);
-       mutex_unlock(&dev->lock);
-       return ret_val;
-}
-
-int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
-{
-       int ret_val = 0;
-       int value = 0;
-       u32 val = 0, tmp = 0;
-
-       mutex_lock(&dev->lock);
-
-       if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
-               mutex_unlock(&dev->lock);
-               return -1;
-       }
-
-       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
-                       UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
-       val = cx25821_i2c_read(&dev->i2c_bus[0],
-                       VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
-       val &= 0xFFFFFF00;
-       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
-                       VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value);
-
-       mutex_unlock(&dev->lock);
-       return ret_val;
-}
-
-int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
-{
-       int ret_val = 0;
-       int value = 0;
-       u32 val = 0, tmp = 0;
-
-       mutex_lock(&dev->lock);
-
-       if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
-               mutex_unlock(&dev->lock);
-               return -1;
-       }
-
-       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue,
-                       SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
-
-       value = convert_to_twos(value, 8);
-       val = cx25821_i2c_read(&dev->i2c_bus[0],
-                       VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
-       val &= 0xFFFFFF00;
-
-       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
-                       VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
-
-       mutex_unlock(&dev->lock);
-       return ret_val;
-}
-
-int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
-{
-       int ret_val = 0;
-       int value = 0;
-       u32 val = 0, tmp = 0;
-
-       mutex_lock(&dev->lock);
-
-       if ((saturation > VIDEO_PROCAMP_MAX) ||
-           (saturation < VIDEO_PROCAMP_MIN)) {
-               mutex_unlock(&dev->lock);
-               return -1;
-       }
-
-       ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
-                       UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
-
-       val = cx25821_i2c_read(&dev->i2c_bus[0],
-                       VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
-       val &= 0xFFFFFF00;
-       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
-                       VDEC_A_USAT_CTRL + (0x200 * decoder), val | value);
-
-       val = cx25821_i2c_read(&dev->i2c_bus[0],
-                       VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
-       val &= 0xFFFFFF00;
-       ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
-                       VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value);
-
-       mutex_unlock(&dev->lock);
-       return ret_val;
-}
-
-/* Program the display sequence and monitor output. */
-
-int medusa_video_init(struct cx25821_dev *dev)
-{
-       u32 value = 0, tmp = 0;
-       int ret_val = 0;
-       int i = 0;
-
-       mutex_lock(&dev->lock);
-
-       _num_decoders = dev->_max_num_decoders;
-
-       /* disable Auto source selection on all video decoders */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
-       value &= 0xFFFFF0FF;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
-
-       if (ret_val < 0)
-               goto error;
-
-       /* Turn off Master source switch enable */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
-       value &= 0xFFFFFFDF;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
-
-       if (ret_val < 0)
-               goto error;
-
-       mutex_unlock(&dev->lock);
-
-       for (i = 0; i < _num_decoders; i++)
-               medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
-
-       mutex_lock(&dev->lock);
-
-       /* Select monitor as DENC A input, power up the DAC */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
-       value &= 0xFF70FF70;
-       value |= 0x00090008;    /* set en_active */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
-
-       if (ret_val < 0)
-               goto error;
-
-       /* enable input is VIP/656 */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
-       value |= 0x00040100;    /* enable VIP */
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
-
-       if (ret_val < 0)
-               goto error;
-
-       /* select AFE clock to output mode */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
-       value &= 0x83FFFFFF;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
-                       value | 0x10000000);
-
-       if (ret_val < 0)
-               goto error;
-
-       /* Turn on all of the data out and control output pins. */
-       value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
-       value &= 0xFEF0FE00;
-       if (_num_decoders == MAX_DECODERS) {
-               /*
-                * Note: The octal board does not support control pins(bit16-19)
-                * These bits are ignored in the octal board.
-                *
-                * disable VDEC A-C port, default to Mobilygen Interface
-                */
-               value |= 0x010001F8;
-       } else {
-               /* disable VDEC A-C port, default to Mobilygen Interface */
-               value |= 0x010F0108;
-       }
-
-       value |= 7;
-       ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
-
-       if (ret_val < 0)
-               goto error;
-
-
-       mutex_unlock(&dev->lock);
-
-       ret_val = medusa_set_videostandard(dev);
-
-       return ret_val;
-
-error:
-       mutex_unlock(&dev->lock);
-       return ret_val;
-}
diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.h b/drivers/media/video/cx25821/cx25821-medusa-video.h
deleted file mode 100644 (file)
index 6175e09..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 _MEDUSA_VIDEO_H
-#define _MEDUSA_VIDEO_H
-
-#include "cx25821-medusa-defines.h"
-
-/* Color control constants */
-#define VIDEO_PROCAMP_MIN                 0
-#define VIDEO_PROCAMP_MAX                 10000
-#define UNSIGNED_BYTE_MIN                 0
-#define UNSIGNED_BYTE_MAX                 0xFF
-#define SIGNED_BYTE_MIN                   -128
-#define SIGNED_BYTE_MAX                   127
-
-/* Default video color settings */
-#define SHARPNESS_DEFAULT                 50
-#define SATURATION_DEFAULT              5000
-#define BRIGHTNESS_DEFAULT              6200
-#define CONTRAST_DEFAULT                5000
-#define HUE_DEFAULT                     5000
-
-unsigned short _num_decoders;
-unsigned short _num_cameras;
-
-unsigned int _video_standard;
-int _display_field_cnt[MAX_DECODERS];
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-reg.h b/drivers/media/video/cx25821/cx25821-reg.h
deleted file mode 100644 (file)
index a3fc25a..0000000
+++ /dev/null
@@ -1,1592 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __CX25821_REGISTERS__
-#define __CX25821_REGISTERS__
-
-/* Risc Instructions */
-#define RISC_CNT_INC    0x00010000
-#define RISC_CNT_RESET  0x00030000
-#define RISC_IRQ1               0x01000000
-#define RISC_IRQ2               0x02000000
-#define RISC_EOL                0x04000000
-#define RISC_SOL                0x08000000
-#define RISC_WRITE              0x10000000
-#define RISC_SKIP               0x20000000
-#define RISC_JUMP               0x70000000
-#define RISC_SYNC               0x80000000
-#define RISC_RESYNC             0x80008000
-#define RISC_READ               0x90000000
-#define RISC_WRITERM    0xB0000000
-#define RISC_WRITECM    0xC0000000
-#define RISC_WRITECR    0xD0000000
-#define RISC_WRITEC             0x50000000
-#define RISC_READC              0xA0000000
-
-#define RISC_SYNC_ODD           0x00000000
-#define RISC_SYNC_EVEN          0x00000200
-#define RISC_SYNC_ODD_VBI       0x00000006
-#define RISC_SYNC_EVEN_VBI      0x00000207
-#define RISC_NOOP                       0xF0000000
-
-/*****************************************************************************
-* ASB SRAM
- *****************************************************************************/
-#define  TX_SRAM                   0x000000    /* Transmit SRAM */
-
-/*****************************************************************************/
-#define  RX_RAM                    0x010000    /* Receive SRAM */
-
-/*****************************************************************************
-* Application Layer (AL)
- *****************************************************************************/
-#define  DEV_CNTRL2                0x040000    /* Device control */
-#define  FLD_RUN_RISC              0x00000020
-
-/* ***************************************************************************** */
-#define  PCI_INT_MSK               0x040010    /* PCI interrupt mask */
-#define  PCI_INT_STAT              0x040014    /* PCI interrupt status */
-#define  PCI_INT_MSTAT             0x040018    /* PCI interrupt masked status */
-#define  FLD_HAMMERHEAD_INT        (1 << 27)
-#define  FLD_UART_INT              (1 << 26)
-#define  FLD_IRQN_INT              (1 << 25)
-#define  FLD_TM_INT                (1 << 28)
-#define  FLD_I2C_3_RACK            (1 << 27)
-#define  FLD_I2C_3_INT             (1 << 26)
-#define  FLD_I2C_2_RACK            (1 << 25)
-#define  FLD_I2C_2_INT             (1 << 24)
-#define  FLD_I2C_1_RACK            (1 << 23)
-#define  FLD_I2C_1_INT             (1 << 22)
-
-#define  FLD_APB_DMA_BERR_INT      (1 << 21)
-#define  FLD_AL_WR_BERR_INT        (1 << 20)
-#define  FLD_AL_RD_BERR_INT        (1 << 19)
-#define  FLD_RISC_WR_BERR_INT      (1 << 18)
-#define  FLD_RISC_RD_BERR_INT      (1 << 17)
-
-#define  FLD_VID_I_INT             (1 << 8)
-#define  FLD_VID_H_INT             (1 << 7)
-#define  FLD_VID_G_INT             (1 << 6)
-#define  FLD_VID_F_INT             (1 << 5)
-#define  FLD_VID_E_INT             (1 << 4)
-#define  FLD_VID_D_INT             (1 << 3)
-#define  FLD_VID_C_INT             (1 << 2)
-#define  FLD_VID_B_INT             (1 << 1)
-#define  FLD_VID_A_INT             (1 << 0)
-
-/* ***************************************************************************** */
-#define  VID_A_INT_MSK             0x040020    /* Video A interrupt mask */
-#define  VID_A_INT_STAT            0x040024    /* Video A interrupt status */
-#define  VID_A_INT_MSTAT           0x040028    /* Video A interrupt masked status */
-#define  VID_A_INT_SSTAT           0x04002C    /* Video A interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_B_INT_MSK             0x040030    /* Video B interrupt mask */
-#define  VID_B_INT_STAT            0x040034    /* Video B interrupt status */
-#define  VID_B_INT_MSTAT           0x040038    /* Video B interrupt masked status */
-#define  VID_B_INT_SSTAT           0x04003C    /* Video B interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_C_INT_MSK             0x040040    /* Video C interrupt mask */
-#define  VID_C_INT_STAT            0x040044    /* Video C interrupt status */
-#define  VID_C_INT_MSTAT           0x040048    /* Video C interrupt masked status */
-#define  VID_C_INT_SSTAT           0x04004C    /* Video C interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_D_INT_MSK             0x040050    /* Video D interrupt mask */
-#define  VID_D_INT_STAT            0x040054    /* Video D interrupt status */
-#define  VID_D_INT_MSTAT           0x040058    /* Video D interrupt masked status */
-#define  VID_D_INT_SSTAT           0x04005C    /* Video D interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_E_INT_MSK             0x040060    /* Video E interrupt mask */
-#define  VID_E_INT_STAT            0x040064    /* Video E interrupt status */
-#define  VID_E_INT_MSTAT           0x040068    /* Video E interrupt masked status */
-#define  VID_E_INT_SSTAT           0x04006C    /* Video E interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_F_INT_MSK             0x040070    /* Video F interrupt mask */
-#define  VID_F_INT_STAT            0x040074    /* Video F interrupt status */
-#define  VID_F_INT_MSTAT           0x040078    /* Video F interrupt masked status */
-#define  VID_F_INT_SSTAT           0x04007C    /* Video F interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_G_INT_MSK             0x040080    /* Video G interrupt mask */
-#define  VID_G_INT_STAT            0x040084    /* Video G interrupt status */
-#define  VID_G_INT_MSTAT           0x040088    /* Video G interrupt masked status */
-#define  VID_G_INT_SSTAT           0x04008C    /* Video G interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_H_INT_MSK             0x040090    /* Video H interrupt mask */
-#define  VID_H_INT_STAT            0x040094    /* Video H interrupt status */
-#define  VID_H_INT_MSTAT           0x040098    /* Video H interrupt masked status */
-#define  VID_H_INT_SSTAT           0x04009C    /* Video H interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_I_INT_MSK             0x0400A0    /* Video I interrupt mask */
-#define  VID_I_INT_STAT            0x0400A4    /* Video I interrupt status */
-#define  VID_I_INT_MSTAT           0x0400A8    /* Video I interrupt masked status */
-#define  VID_I_INT_SSTAT           0x0400AC    /* Video I interrupt set status */
-
-/* ***************************************************************************** */
-#define  VID_J_INT_MSK             0x0400B0    /* Video J interrupt mask */
-#define  VID_J_INT_STAT            0x0400B4    /* Video J interrupt status */
-#define  VID_J_INT_MSTAT           0x0400B8    /* Video J interrupt masked status */
-#define  VID_J_INT_SSTAT           0x0400BC    /* Video J interrupt set status */
-
-#define  FLD_VID_SRC_OPC_ERR       0x00020000
-#define  FLD_VID_DST_OPC_ERR       0x00010000
-#define  FLD_VID_SRC_SYNC          0x00002000
-#define  FLD_VID_DST_SYNC          0x00001000
-#define  FLD_VID_SRC_UF            0x00000200
-#define  FLD_VID_DST_OF            0x00000100
-#define  FLD_VID_SRC_RISC2         0x00000020
-#define  FLD_VID_DST_RISC2         0x00000010
-#define  FLD_VID_SRC_RISC1         0x00000002
-#define  FLD_VID_DST_RISC1         0x00000001
-#define  FLD_VID_SRC_ERRORS            (FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF)
-#define  FLD_VID_DST_ERRORS            (FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF)
-
-/* ***************************************************************************** */
-#define  AUD_A_INT_MSK             0x0400C0    /* Audio Int interrupt mask */
-#define  AUD_A_INT_STAT            0x0400C4    /* Audio Int interrupt status */
-#define  AUD_A_INT_MSTAT           0x0400C8    /* Audio Int interrupt masked status */
-#define  AUD_A_INT_SSTAT           0x0400CC    /* Audio Int interrupt set status */
-
-/* ***************************************************************************** */
-#define  AUD_B_INT_MSK             0x0400D0    /* Audio Int interrupt mask */
-#define  AUD_B_INT_STAT            0x0400D4    /* Audio Int interrupt status */
-#define  AUD_B_INT_MSTAT           0x0400D8    /* Audio Int interrupt masked status */
-#define  AUD_B_INT_SSTAT           0x0400DC    /* Audio Int interrupt set status */
-
-/* ***************************************************************************** */
-#define  AUD_C_INT_MSK             0x0400E0    /* Audio Int interrupt mask */
-#define  AUD_C_INT_STAT            0x0400E4    /* Audio Int interrupt status */
-#define  AUD_C_INT_MSTAT           0x0400E8    /* Audio Int interrupt masked status */
-#define  AUD_C_INT_SSTAT           0x0400EC    /* Audio Int interrupt set status */
-
-/* ***************************************************************************** */
-#define  AUD_D_INT_MSK             0x0400F0    /* Audio Int interrupt mask */
-#define  AUD_D_INT_STAT            0x0400F4    /* Audio Int interrupt status */
-#define  AUD_D_INT_MSTAT           0x0400F8    /* Audio Int interrupt masked status */
-#define  AUD_D_INT_SSTAT           0x0400FC    /* Audio Int interrupt set status */
-
-/* ***************************************************************************** */
-#define  AUD_E_INT_MSK             0x040100    /* Audio Int interrupt mask */
-#define  AUD_E_INT_STAT            0x040104    /* Audio Int interrupt status */
-#define  AUD_E_INT_MSTAT           0x040108    /* Audio Int interrupt masked status */
-#define  AUD_E_INT_SSTAT           0x04010C    /* Audio Int interrupt set status */
-
-#define  FLD_AUD_SRC_OPC_ERR       0x00020000
-#define  FLD_AUD_DST_OPC_ERR       0x00010000
-#define  FLD_AUD_SRC_SYNC          0x00002000
-#define  FLD_AUD_DST_SYNC          0x00001000
-#define  FLD_AUD_SRC_OF            0x00000200
-#define  FLD_AUD_DST_OF            0x00000100
-#define  FLD_AUD_SRC_RISCI2        0x00000020
-#define  FLD_AUD_DST_RISCI2        0x00000010
-#define  FLD_AUD_SRC_RISCI1        0x00000002
-#define  FLD_AUD_DST_RISCI1        0x00000001
-
-/* ***************************************************************************** */
-#define  MBIF_A_INT_MSK             0x040110   /* MBIF Int interrupt mask */
-#define  MBIF_A_INT_STAT            0x040114   /* MBIF Int interrupt status */
-#define  MBIF_A_INT_MSTAT           0x040118   /* MBIF Int interrupt masked status */
-#define  MBIF_A_INT_SSTAT           0x04011C   /* MBIF Int interrupt set status */
-
-/* ***************************************************************************** */
-#define  MBIF_B_INT_MSK             0x040120   /* MBIF Int interrupt mask */
-#define  MBIF_B_INT_STAT            0x040124   /* MBIF Int interrupt status */
-#define  MBIF_B_INT_MSTAT           0x040128   /* MBIF Int interrupt masked status */
-#define  MBIF_B_INT_SSTAT           0x04012C   /* MBIF Int interrupt set status */
-
-#define  FLD_MBIF_DST_OPC_ERR       0x00010000
-#define  FLD_MBIF_DST_SYNC          0x00001000
-#define  FLD_MBIF_DST_OF            0x00000100
-#define  FLD_MBIF_DST_RISCI2        0x00000010
-#define  FLD_MBIF_DST_RISCI1        0x00000001
-
-/* ***************************************************************************** */
-#define  AUD_EXT_INT_MSK           0x040060    /* Audio Ext interrupt mask */
-#define  AUD_EXT_INT_STAT          0x040064    /* Audio Ext interrupt status */
-#define  AUD_EXT_INT_MSTAT         0x040068    /* Audio Ext interrupt masked status */
-#define  AUD_EXT_INT_SSTAT         0x04006C    /* Audio Ext interrupt set status */
-#define  FLD_AUD_EXT_OPC_ERR       0x00010000
-#define  FLD_AUD_EXT_SYNC          0x00001000
-#define  FLD_AUD_EXT_OF            0x00000100
-#define  FLD_AUD_EXT_RISCI2        0x00000010
-#define  FLD_AUD_EXT_RISCI1        0x00000001
-
-/* ***************************************************************************** */
-#define  GPIO_LO                   0x110010    /* Lower  of GPIO pins [31:0] */
-#define  GPIO_HI                   0x110014    /* Upper WORD  of GPIO pins [47:31] */
-
-#define  GPIO_LO_OE                0x110018    /* Lower  of GPIO output enable [31:0] */
-#define  GPIO_HI_OE                0x11001C    /* Upper word  of GPIO output enable [47:32] */
-
-#define  GPIO_LO_INT_MSK           0x11003C    /* GPIO interrupt mask */
-#define  GPIO_LO_INT_STAT          0x110044    /* GPIO interrupt status */
-#define  GPIO_LO_INT_MSTAT         0x11004C    /* GPIO interrupt masked status */
-#define  GPIO_LO_ISM_SNS           0x110054    /* GPIO interrupt sensitivity */
-#define  GPIO_LO_ISM_POL           0x11005C    /* GPIO interrupt polarity */
-
-#define  GPIO_HI_INT_MSK           0x110040    /* GPIO interrupt mask */
-#define  GPIO_HI_INT_STAT          0x110048    /* GPIO interrupt status */
-#define  GPIO_HI_INT_MSTAT         0x110050    /* GPIO interrupt masked status */
-#define  GPIO_HI_ISM_SNS           0x110058    /* GPIO interrupt sensitivity */
-#define  GPIO_HI_ISM_POL           0x110060    /* GPIO interrupt polarity */
-
-#define  FLD_GPIO43_INT            (1 << 11)
-#define  FLD_GPIO42_INT            (1 << 10)
-#define  FLD_GPIO41_INT            (1 << 9)
-#define  FLD_GPIO40_INT            (1 << 8)
-
-#define  FLD_GPIO9_INT             (1 << 9)
-#define  FLD_GPIO8_INT             (1 << 8)
-#define  FLD_GPIO7_INT             (1 << 7)
-#define  FLD_GPIO6_INT             (1 << 6)
-#define  FLD_GPIO5_INT             (1 << 5)
-#define  FLD_GPIO4_INT             (1 << 4)
-#define  FLD_GPIO3_INT             (1 << 3)
-#define  FLD_GPIO2_INT             (1 << 2)
-#define  FLD_GPIO1_INT             (1 << 1)
-#define  FLD_GPIO0_INT             (1 << 0)
-
-/* ***************************************************************************** */
-#define  TC_REQ                    0x040090    /* Rider PCI Express traFFic class request */
-
-/* ***************************************************************************** */
-#define  TC_REQ_SET                0x040094    /* Rider PCI Express traFFic class request set */
-
-/* ***************************************************************************** */
-/* Rider */
-/* ***************************************************************************** */
-
-/* PCI Compatible Header */
-/* ***************************************************************************** */
-#define  RDR_CFG0                  0x050000
-#define  RDR_VENDOR_DEVICE_ID_CFG  0x050000
-
-/* ***************************************************************************** */
-#define  RDR_CFG1                  0x050004
-
-/* ***************************************************************************** */
-#define  RDR_CFG2                  0x050008
-
-/* ***************************************************************************** */
-#define  RDR_CFG3                  0x05000C
-
-/* ***************************************************************************** */
-#define  RDR_CFG4                  0x050010
-
-/* ***************************************************************************** */
-#define  RDR_CFG5                  0x050014
-
-/* ***************************************************************************** */
-#define  RDR_CFG6                  0x050018
-
-/* ***************************************************************************** */
-#define  RDR_CFG7                  0x05001C
-
-/* ***************************************************************************** */
-#define  RDR_CFG8                  0x050020
-
-/* ***************************************************************************** */
-#define  RDR_CFG9                  0x050024
-
-/* ***************************************************************************** */
-#define  RDR_CFGA                  0x050028
-
-/* ***************************************************************************** */
-#define  RDR_CFGB                  0x05002C
-#define  RDR_SUSSYSTEM_ID_CFG      0x05002C
-
-/* ***************************************************************************** */
-#define  RDR_CFGC                  0x050030
-
-/* ***************************************************************************** */
-#define  RDR_CFGD                  0x050034
-
-/* ***************************************************************************** */
-#define  RDR_CFGE                  0x050038
-
-/* ***************************************************************************** */
-#define  RDR_CFGF                  0x05003C
-
-/* ***************************************************************************** */
-/* PCI-Express Capabilities */
-/* ***************************************************************************** */
-#define  RDR_PECAP                 0x050040
-
-/* ***************************************************************************** */
-#define  RDR_PEDEVCAP              0x050044
-
-/* ***************************************************************************** */
-#define  RDR_PEDEVSC               0x050048
-
-/* ***************************************************************************** */
-#define  RDR_PELINKCAP             0x05004C
-
-/* ***************************************************************************** */
-#define  RDR_PELINKSC              0x050050
-
-/* ***************************************************************************** */
-#define  RDR_PMICAP                0x050080
-
-/* ***************************************************************************** */
-#define  RDR_PMCSR                 0x050084
-
-/* ***************************************************************************** */
-#define  RDR_VPDCAP                0x050090
-
-/* ***************************************************************************** */
-#define  RDR_VPDDATA               0x050094
-
-/* ***************************************************************************** */
-#define  RDR_MSICAP                0x0500A0
-
-/* ***************************************************************************** */
-#define  RDR_MSIARL                0x0500A4
-
-/* ***************************************************************************** */
-#define  RDR_MSIARU                0x0500A8
-
-/* ***************************************************************************** */
-#define  RDR_MSIDATA               0x0500AC
-
-/* ***************************************************************************** */
-/* PCI Express Extended Capabilities */
-/* ***************************************************************************** */
-#define  RDR_AERXCAP               0x050100
-
-/* ***************************************************************************** */
-#define  RDR_AERUESTA              0x050104
-
-/* ***************************************************************************** */
-#define  RDR_AERUEMSK              0x050108
-
-/* ***************************************************************************** */
-#define  RDR_AERUESEV              0x05010C
-
-/* ***************************************************************************** */
-#define  RDR_AERCESTA              0x050110
-
-/* ***************************************************************************** */
-#define  RDR_AERCEMSK              0x050114
-
-/* ***************************************************************************** */
-#define  RDR_AERCC                 0x050118
-
-/* ***************************************************************************** */
-#define  RDR_AERHL0                0x05011C
-
-/* ***************************************************************************** */
-#define  RDR_AERHL1                0x050120
-
-/* ***************************************************************************** */
-#define  RDR_AERHL2                0x050124
-
-/* ***************************************************************************** */
-#define  RDR_AERHL3                0x050128
-
-/* ***************************************************************************** */
-#define  RDR_VCXCAP                0x050200
-
-/* ***************************************************************************** */
-#define  RDR_VCCAP1                0x050204
-
-/* ***************************************************************************** */
-#define  RDR_VCCAP2                0x050208
-
-/* ***************************************************************************** */
-#define  RDR_VCSC                  0x05020C
-
-/* ***************************************************************************** */
-#define  RDR_VCR0_CAP              0x050210
-
-/* ***************************************************************************** */
-#define  RDR_VCR0_CTRL             0x050214
-
-/* ***************************************************************************** */
-#define  RDR_VCR0_STAT             0x050218
-
-/* ***************************************************************************** */
-#define  RDR_VCR1_CAP              0x05021C
-
-/* ***************************************************************************** */
-#define  RDR_VCR1_CTRL             0x050220
-
-/* ***************************************************************************** */
-#define  RDR_VCR1_STAT             0x050224
-
-/* ***************************************************************************** */
-#define  RDR_VCR2_CAP              0x050228
-
-/* ***************************************************************************** */
-#define  RDR_VCR2_CTRL             0x05022C
-
-/* ***************************************************************************** */
-#define  RDR_VCR2_STAT             0x050230
-
-/* ***************************************************************************** */
-#define  RDR_VCR3_CAP              0x050234
-
-/* ***************************************************************************** */
-#define  RDR_VCR3_CTRL             0x050238
-
-/* ***************************************************************************** */
-#define  RDR_VCR3_STAT             0x05023C
-
-/* ***************************************************************************** */
-#define  RDR_VCARB0                0x050240
-
-/* ***************************************************************************** */
-#define  RDR_VCARB1                0x050244
-
-/* ***************************************************************************** */
-#define  RDR_VCARB2                0x050248
-
-/* ***************************************************************************** */
-#define  RDR_VCARB3                0x05024C
-
-/* ***************************************************************************** */
-#define  RDR_VCARB4                0x050250
-
-/* ***************************************************************************** */
-#define  RDR_VCARB5                0x050254
-
-/* ***************************************************************************** */
-#define  RDR_VCARB6                0x050258
-
-/* ***************************************************************************** */
-#define  RDR_VCARB7                0x05025C
-
-/* ***************************************************************************** */
-#define  RDR_RDRSTAT0              0x050300
-
-/* ***************************************************************************** */
-#define  RDR_RDRSTAT1              0x050304
-
-/* ***************************************************************************** */
-#define  RDR_RDRCTL0               0x050308
-
-/* ***************************************************************************** */
-#define  RDR_RDRCTL1               0x05030C
-
-/* ***************************************************************************** */
-/* Transaction Layer Registers */
-/* ***************************************************************************** */
-#define  RDR_TLSTAT0               0x050310
-
-/* ***************************************************************************** */
-#define  RDR_TLSTAT1               0x050314
-
-/* ***************************************************************************** */
-#define  RDR_TLCTL0                0x050318
-#define  FLD_CFG_UR_CPL_MODE       0x00000040
-#define  FLD_CFG_CORR_ERR_QUITE    0x00000020
-#define  FLD_CFG_RCB_CK_EN         0x00000010
-#define  FLD_CFG_BNDRY_CK_EN       0x00000008
-#define  FLD_CFG_BYTE_EN_CK_EN     0x00000004
-#define  FLD_CFG_RELAX_ORDER_MSK   0x00000002
-#define  FLD_CFG_TAG_ORDER_EN      0x00000001
-
-/* ***************************************************************************** */
-#define  RDR_TLCTL1                0x05031C
-
-/* ***************************************************************************** */
-#define  RDR_REQRCAL               0x050320
-
-/* ***************************************************************************** */
-#define  RDR_REQRCAU               0x050324
-
-/* ***************************************************************************** */
-#define  RDR_REQEPA                0x050328
-
-/* ***************************************************************************** */
-#define  RDR_REQCTRL               0x05032C
-
-/* ***************************************************************************** */
-#define  RDR_REQSTAT               0x050330
-
-/* ***************************************************************************** */
-#define  RDR_TL_TEST               0x050334
-
-/* ***************************************************************************** */
-#define  RDR_VCR01_CTL             0x050348
-
-/* ***************************************************************************** */
-#define  RDR_VCR23_CTL             0x05034C
-
-/* ***************************************************************************** */
-#define  RDR_RX_VCR0_FC            0x050350
-
-/* ***************************************************************************** */
-#define  RDR_RX_VCR1_FC            0x050354
-
-/* ***************************************************************************** */
-#define  RDR_RX_VCR2_FC            0x050358
-
-/* ***************************************************************************** */
-#define  RDR_RX_VCR3_FC            0x05035C
-
-/* ***************************************************************************** */
-/* Data Link Layer Registers */
-/* ***************************************************************************** */
-#define  RDR_DLLSTAT               0x050360
-
-/* ***************************************************************************** */
-#define  RDR_DLLCTRL               0x050364
-
-/* ***************************************************************************** */
-#define  RDR_REPLAYTO              0x050368
-
-/* ***************************************************************************** */
-#define  RDR_ACKLATTO              0x05036C
-
-/* ***************************************************************************** */
-/* MAC Layer Registers */
-/* ***************************************************************************** */
-#define  RDR_MACSTAT0              0x050380
-
-/* ***************************************************************************** */
-#define  RDR_MACSTAT1              0x050384
-
-/* ***************************************************************************** */
-#define  RDR_MACCTRL0              0x050388
-
-/* ***************************************************************************** */
-#define  RDR_MACCTRL1              0x05038C
-
-/* ***************************************************************************** */
-#define  RDR_MACCTRL2              0x050390
-
-/* ***************************************************************************** */
-#define  RDR_MAC_LB_DATA           0x050394
-
-/* ***************************************************************************** */
-#define  RDR_L0S_EXIT_LAT          0x050398
-
-/* ***************************************************************************** */
-/* DMAC */
-/* ***************************************************************************** */
-#define  DMA1_PTR1                 0x100000    /* DMA Current Ptr : Ch#1 */
-
-/* ***************************************************************************** */
-#define  DMA2_PTR1                 0x100004    /* DMA Current Ptr : Ch#2 */
-
-/* ***************************************************************************** */
-#define  DMA3_PTR1                 0x100008    /* DMA Current Ptr : Ch#3 */
-
-/* ***************************************************************************** */
-#define  DMA4_PTR1                 0x10000C    /* DMA Current Ptr : Ch#4 */
-
-/* ***************************************************************************** */
-#define  DMA5_PTR1                 0x100010    /* DMA Current Ptr : Ch#5 */
-
-/* ***************************************************************************** */
-#define  DMA6_PTR1                 0x100014    /* DMA Current Ptr : Ch#6 */
-
-/* ***************************************************************************** */
-#define  DMA7_PTR1                 0x100018    /* DMA Current Ptr : Ch#7 */
-
-/* ***************************************************************************** */
-#define  DMA8_PTR1                 0x10001C    /* DMA Current Ptr : Ch#8 */
-
-/* ***************************************************************************** */
-#define  DMA9_PTR1                 0x100020    /* DMA Current Ptr : Ch#9 */
-
-/* ***************************************************************************** */
-#define  DMA10_PTR1                0x100024    /* DMA Current Ptr : Ch#10 */
-
-/* ***************************************************************************** */
-#define  DMA11_PTR1                0x100028    /* DMA Current Ptr : Ch#11 */
-
-/* ***************************************************************************** */
-#define  DMA12_PTR1                0x10002C    /* DMA Current Ptr : Ch#12 */
-
-/* ***************************************************************************** */
-#define  DMA13_PTR1                0x100030    /* DMA Current Ptr : Ch#13 */
-
-/* ***************************************************************************** */
-#define  DMA14_PTR1                0x100034    /* DMA Current Ptr : Ch#14 */
-
-/* ***************************************************************************** */
-#define  DMA15_PTR1                0x100038    /* DMA Current Ptr : Ch#15 */
-
-/* ***************************************************************************** */
-#define  DMA16_PTR1                0x10003C    /* DMA Current Ptr : Ch#16 */
-
-/* ***************************************************************************** */
-#define  DMA17_PTR1                0x100040    /* DMA Current Ptr : Ch#17 */
-
-/* ***************************************************************************** */
-#define  DMA18_PTR1                0x100044    /* DMA Current Ptr : Ch#18 */
-
-/* ***************************************************************************** */
-#define  DMA19_PTR1                0x100048    /* DMA Current Ptr : Ch#19 */
-
-/* ***************************************************************************** */
-#define  DMA20_PTR1                0x10004C    /* DMA Current Ptr : Ch#20 */
-
-/* ***************************************************************************** */
-#define  DMA21_PTR1                0x100050    /* DMA Current Ptr : Ch#21 */
-
-/* ***************************************************************************** */
-#define  DMA22_PTR1                0x100054    /* DMA Current Ptr : Ch#22 */
-
-/* ***************************************************************************** */
-#define  DMA23_PTR1                0x100058    /* DMA Current Ptr : Ch#23 */
-
-/* ***************************************************************************** */
-#define  DMA24_PTR1                0x10005C    /* DMA Current Ptr : Ch#24 */
-
-/* ***************************************************************************** */
-#define  DMA25_PTR1                0x100060    /* DMA Current Ptr : Ch#25 */
-
-/* ***************************************************************************** */
-#define  DMA26_PTR1                0x100064    /* DMA Current Ptr : Ch#26 */
-
-/* ***************************************************************************** */
-#define  DMA1_PTR2                 0x100080    /* DMA Tab Ptr : Ch#1 */
-
-/* ***************************************************************************** */
-#define  DMA2_PTR2                 0x100084    /* DMA Tab Ptr : Ch#2 */
-
-/* ***************************************************************************** */
-#define  DMA3_PTR2                 0x100088    /* DMA Tab Ptr : Ch#3 */
-
-/* ***************************************************************************** */
-#define  DMA4_PTR2                 0x10008C    /* DMA Tab Ptr : Ch#4 */
-
-/* ***************************************************************************** */
-#define  DMA5_PTR2                 0x100090    /* DMA Tab Ptr : Ch#5 */
-
-/* ***************************************************************************** */
-#define  DMA6_PTR2                 0x100094    /* DMA Tab Ptr : Ch#6 */
-
-/* ***************************************************************************** */
-#define  DMA7_PTR2                 0x100098    /* DMA Tab Ptr : Ch#7 */
-
-/* ***************************************************************************** */
-#define  DMA8_PTR2                 0x10009C    /* DMA Tab Ptr : Ch#8 */
-
-/* ***************************************************************************** */
-#define  DMA9_PTR2                 0x1000A0    /* DMA Tab Ptr : Ch#9 */
-
-/* ***************************************************************************** */
-#define  DMA10_PTR2                0x1000A4    /* DMA Tab Ptr : Ch#10 */
-
-/* ***************************************************************************** */
-#define  DMA11_PTR2                0x1000A8    /* DMA Tab Ptr : Ch#11 */
-
-/* ***************************************************************************** */
-#define  DMA12_PTR2                0x1000AC    /* DMA Tab Ptr : Ch#12 */
-
-/* ***************************************************************************** */
-#define  DMA13_PTR2                0x1000B0    /* DMA Tab Ptr : Ch#13 */
-
-/* ***************************************************************************** */
-#define  DMA14_PTR2                0x1000B4    /* DMA Tab Ptr : Ch#14 */
-
-/* ***************************************************************************** */
-#define  DMA15_PTR2                0x1000B8    /* DMA Tab Ptr : Ch#15 */
-
-/* ***************************************************************************** */
-#define  DMA16_PTR2                0x1000BC    /* DMA Tab Ptr : Ch#16 */
-
-/* ***************************************************************************** */
-#define  DMA17_PTR2                0x1000C0    /* DMA Tab Ptr : Ch#17 */
-
-/* ***************************************************************************** */
-#define  DMA18_PTR2                0x1000C4    /* DMA Tab Ptr : Ch#18 */
-
-/* ***************************************************************************** */
-#define  DMA19_PTR2                0x1000C8    /* DMA Tab Ptr : Ch#19 */
-
-/* ***************************************************************************** */
-#define  DMA20_PTR2                0x1000CC    /* DMA Tab Ptr : Ch#20 */
-
-/* ***************************************************************************** */
-#define  DMA21_PTR2                0x1000D0    /* DMA Tab Ptr : Ch#21 */
-
-/* ***************************************************************************** */
-#define  DMA22_PTR2                0x1000D4    /* DMA Tab Ptr : Ch#22 */
-
-/* ***************************************************************************** */
-#define  DMA23_PTR2                0x1000D8    /* DMA Tab Ptr : Ch#23 */
-
-/* ***************************************************************************** */
-#define  DMA24_PTR2                0x1000DC    /* DMA Tab Ptr : Ch#24 */
-
-/* ***************************************************************************** */
-#define  DMA25_PTR2                0x1000E0    /* DMA Tab Ptr : Ch#25 */
-
-/* ***************************************************************************** */
-#define  DMA26_PTR2                0x1000E4    /* DMA Tab Ptr : Ch#26 */
-
-/* ***************************************************************************** */
-#define  DMA1_CNT1                 0x100100    /* DMA BuFFer Size : Ch#1 */
-
-/* ***************************************************************************** */
-#define  DMA2_CNT1                 0x100104    /* DMA BuFFer Size : Ch#2 */
-
-/* ***************************************************************************** */
-#define  DMA3_CNT1                 0x100108    /* DMA BuFFer Size : Ch#3 */
-
-/* ***************************************************************************** */
-#define  DMA4_CNT1                 0x10010C    /* DMA BuFFer Size : Ch#4 */
-
-/* ***************************************************************************** */
-#define  DMA5_CNT1                 0x100110    /* DMA BuFFer Size : Ch#5 */
-
-/* ***************************************************************************** */
-#define  DMA6_CNT1                 0x100114    /* DMA BuFFer Size : Ch#6 */
-
-/* ***************************************************************************** */
-#define  DMA7_CNT1                 0x100118    /* DMA BuFFer Size : Ch#7 */
-
-/* ***************************************************************************** */
-#define  DMA8_CNT1                 0x10011C    /* DMA BuFFer Size : Ch#8 */
-
-/* ***************************************************************************** */
-#define  DMA9_CNT1                 0x100120    /* DMA BuFFer Size : Ch#9 */
-
-/* ***************************************************************************** */
-#define  DMA10_CNT1                0x100124    /* DMA BuFFer Size : Ch#10 */
-
-/* ***************************************************************************** */
-#define  DMA11_CNT1                0x100128    /* DMA BuFFer Size : Ch#11 */
-
-/* ***************************************************************************** */
-#define  DMA12_CNT1                0x10012C    /* DMA BuFFer Size : Ch#12 */
-
-/* ***************************************************************************** */
-#define  DMA13_CNT1                0x100130    /* DMA BuFFer Size : Ch#13 */
-
-/* ***************************************************************************** */
-#define  DMA14_CNT1                0x100134    /* DMA BuFFer Size : Ch#14 */
-
-/* ***************************************************************************** */
-#define  DMA15_CNT1                0x100138    /* DMA BuFFer Size : Ch#15 */
-
-/* ***************************************************************************** */
-#define  DMA16_CNT1                0x10013C    /* DMA BuFFer Size : Ch#16 */
-
-/* ***************************************************************************** */
-#define  DMA17_CNT1                0x100140    /* DMA BuFFer Size : Ch#17 */
-
-/* ***************************************************************************** */
-#define  DMA18_CNT1                0x100144    /* DMA BuFFer Size : Ch#18 */
-
-/* ***************************************************************************** */
-#define  DMA19_CNT1                0x100148    /* DMA BuFFer Size : Ch#19 */
-
-/* ***************************************************************************** */
-#define  DMA20_CNT1                0x10014C    /* DMA BuFFer Size : Ch#20 */
-
-/* ***************************************************************************** */
-#define  DMA21_CNT1                0x100150    /* DMA BuFFer Size : Ch#21 */
-
-/* ***************************************************************************** */
-#define  DMA22_CNT1                0x100154    /* DMA BuFFer Size : Ch#22 */
-
-/* ***************************************************************************** */
-#define  DMA23_CNT1                0x100158    /* DMA BuFFer Size : Ch#23 */
-
-/* ***************************************************************************** */
-#define  DMA24_CNT1                0x10015C    /* DMA BuFFer Size : Ch#24 */
-
-/* ***************************************************************************** */
-#define  DMA25_CNT1                0x100160    /* DMA BuFFer Size : Ch#25 */
-
-/* ***************************************************************************** */
-#define  DMA26_CNT1                0x100164    /* DMA BuFFer Size : Ch#26 */
-
-/* ***************************************************************************** */
-#define  DMA1_CNT2                 0x100180    /* DMA Table Size : Ch#1 */
-
-/* ***************************************************************************** */
-#define  DMA2_CNT2                 0x100184    /* DMA Table Size : Ch#2 */
-
-/* ***************************************************************************** */
-#define  DMA3_CNT2                 0x100188    /* DMA Table Size : Ch#3 */
-
-/* ***************************************************************************** */
-#define  DMA4_CNT2                 0x10018C    /* DMA Table Size : Ch#4 */
-
-/* ***************************************************************************** */
-#define  DMA5_CNT2                 0x100190    /* DMA Table Size : Ch#5 */
-
-/* ***************************************************************************** */
-#define  DMA6_CNT2                 0x100194    /* DMA Table Size : Ch#6 */
-
-/* ***************************************************************************** */
-#define  DMA7_CNT2                 0x100198    /* DMA Table Size : Ch#7 */
-
-/* ***************************************************************************** */
-#define  DMA8_CNT2                 0x10019C    /* DMA Table Size : Ch#8 */
-
-/* ***************************************************************************** */
-#define  DMA9_CNT2                 0x1001A0    /* DMA Table Size : Ch#9 */
-
-/* ***************************************************************************** */
-#define  DMA10_CNT2                0x1001A4    /* DMA Table Size : Ch#10 */
-
-/* ***************************************************************************** */
-#define  DMA11_CNT2                0x1001A8    /* DMA Table Size : Ch#11 */
-
-/* ***************************************************************************** */
-#define  DMA12_CNT2                0x1001AC    /* DMA Table Size : Ch#12 */
-
-/* ***************************************************************************** */
-#define  DMA13_CNT2                0x1001B0    /* DMA Table Size : Ch#13 */
-
-/* ***************************************************************************** */
-#define  DMA14_CNT2                0x1001B4    /* DMA Table Size : Ch#14 */
-
-/* ***************************************************************************** */
-#define  DMA15_CNT2                0x1001B8    /* DMA Table Size : Ch#15 */
-
-/* ***************************************************************************** */
-#define  DMA16_CNT2                0x1001BC    /* DMA Table Size : Ch#16 */
-
-/* ***************************************************************************** */
-#define  DMA17_CNT2                0x1001C0    /* DMA Table Size : Ch#17 */
-
-/* ***************************************************************************** */
-#define  DMA18_CNT2                0x1001C4    /* DMA Table Size : Ch#18 */
-
-/* ***************************************************************************** */
-#define  DMA19_CNT2                0x1001C8    /* DMA Table Size : Ch#19 */
-
-/* ***************************************************************************** */
-#define  DMA20_CNT2                0x1001CC    /* DMA Table Size : Ch#20 */
-
-/* ***************************************************************************** */
-#define  DMA21_CNT2                0x1001D0    /* DMA Table Size : Ch#21 */
-
-/* ***************************************************************************** */
-#define  DMA22_CNT2                0x1001D4    /* DMA Table Size : Ch#22 */
-
-/* ***************************************************************************** */
-#define  DMA23_CNT2                0x1001D8    /* DMA Table Size : Ch#23 */
-
-/* ***************************************************************************** */
-#define  DMA24_CNT2                0x1001DC    /* DMA Table Size : Ch#24 */
-
-/* ***************************************************************************** */
-#define  DMA25_CNT2                0x1001E0    /* DMA Table Size : Ch#25 */
-
-/* ***************************************************************************** */
-#define  DMA26_CNT2                0x1001E4    /* DMA Table Size : Ch#26 */
-
-/* ***************************************************************************** */
- /* ITG */
-/* ***************************************************************************** */
-#define  TM_CNT_LDW                0x110000    /* Timer : Counter low */
-
-/* ***************************************************************************** */
-#define  TM_CNT_UW                 0x110004    /* Timer : Counter high word */
-
-/* ***************************************************************************** */
-#define  TM_LMT_LDW                0x110008    /* Timer : Limit low */
-
-/* ***************************************************************************** */
-#define  TM_LMT_UW                 0x11000C    /* Timer : Limit high word */
-
-/* ***************************************************************************** */
-#define  GP0_IO                    0x110010    /* GPIO output enables data I/O */
-#define  FLD_GP_OE                 0x00FF0000  /* GPIO: GP_OE output enable */
-#define  FLD_GP_IN                 0x0000FF00  /* GPIO: GP_IN status */
-#define  FLD_GP_OUT                0x000000FF  /* GPIO: GP_OUT control */
-
-/* ***************************************************************************** */
-#define  GPIO_ISM                  0x110014    /* GPIO interrupt sensitivity mode */
-#define  FLD_GP_ISM_SNS            0x00000070
-#define  FLD_GP_ISM_POL            0x00000007
-
-/* ***************************************************************************** */
-#define  SOFT_RESET                0x11001C    /* Output system reset reg */
-#define  FLD_PECOS_SOFT_RESET      0x00000001
-
-/* ***************************************************************************** */
-#define  MC416_RWD                 0x110020    /* MC416 GPIO[18:3] pin */
-#define  MC416_OEN                 0x110024    /* Output enable of GPIO[18:3] */
-#define  MC416_CTL                 0x110028
-
-/* ***************************************************************************** */
-#define  ALT_PIN_OUT_SEL           0x11002C    /* Alternate GPIO output select */
-
-#define  FLD_ALT_GPIO_OUT_SEL      0xF0000000
-/* 0          Disabled <-- default */
-/* 1          GPIO[0] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-/* 8          ATT_IF */
-
-#define  FLD_AUX_PLL_CLK_ALT_SEL   0x0F000000
-/* 0          AUX_PLL_CLK<-- default */
-/* 1          GPIO[2] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  FLD_IR_TX_ALT_SEL         0x00F00000
-/* 0          IR_TX <-- default */
-/* 1          GPIO[1] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  FLD_IR_RX_ALT_SEL         0x000F0000
-/* 0          IR_RX <-- default */
-/* 1          GPIO[0] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  FLD_GPIO10_ALT_SEL        0x0000F000
-/* 0          GPIO[10] <-- default */
-/* 1          GPIO[0] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  FLD_GPIO2_ALT_SEL         0x00000F00
-/* 0          GPIO[2] <-- default */
-/* 1          GPIO[1] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  FLD_GPIO1_ALT_SEL         0x000000F0
-/* 0          GPIO[1] <-- default */
-/* 1          GPIO[0] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  FLD_GPIO0_ALT_SEL         0x0000000F
-/* 0          GPIO[0] <-- default */
-/* 1          GPIO[1] */
-/* 2          GPIO[10] */
-/* 3          VIP_656_DATA_VAL */
-/* 4          VIP_656_DATA[0] */
-/* 5          VIP_656_CLK */
-/* 6          VIP_656_DATA_EXT[1] */
-/* 7          VIP_656_DATA_EXT[0] */
-
-#define  ALT_PIN_IN_SEL            0x110030    /* Alternate GPIO input select */
-
-#define  FLD_GPIO10_ALT_IN_SEL     0x0000F000
-/* 0          GPIO[10] <-- default */
-/* 1          IR_RX */
-/* 2          IR_TX */
-/* 3          AUX_PLL_CLK */
-/* 4          IF_ATT_SEL */
-/* 5          GPIO[0] */
-/* 6          GPIO[1] */
-/* 7          GPIO[2] */
-
-#define  FLD_GPIO2_ALT_IN_SEL      0x00000F00
-/* 0          GPIO[2] <-- default */
-/* 1          IR_RX */
-/* 2          IR_TX */
-/* 3          AUX_PLL_CLK */
-/* 4          IF_ATT_SEL */
-
-#define  FLD_GPIO1_ALT_IN_SEL      0x000000F0
-/* 0          GPIO[1] <-- default */
-/* 1          IR_RX */
-/* 2          IR_TX */
-/* 3          AUX_PLL_CLK */
-/* 4          IF_ATT_SEL */
-
-#define  FLD_GPIO0_ALT_IN_SEL      0x0000000F
-/* 0          GPIO[0] <-- default */
-/* 1          IR_RX */
-/* 2          IR_TX */
-/* 3          AUX_PLL_CLK */
-/* 4          IF_ATT_SEL */
-
-/* ***************************************************************************** */
-#define  TEST_BUS_CTL1             0x110040    /* Test bus control register #1 */
-
-/* ***************************************************************************** */
-#define  TEST_BUS_CTL2             0x110044    /* Test bus control register #2 */
-
-/* ***************************************************************************** */
-#define  CLK_DELAY                 0x110048    /* Clock delay */
-#define  FLD_MOE_CLK_DIS           0x80000000  /* Disable MoE clock */
-
-/* ***************************************************************************** */
-#define  PAD_CTRL                  0x110068    /* Pad drive strength control */
-
-/* ***************************************************************************** */
-#define  MBIST_CTRL                0x110050    /* SRAM memory built-in self test control */
-
-/* ***************************************************************************** */
-#define  MBIST_STAT                0x110054    /* SRAM memory built-in self test status */
-
-/* ***************************************************************************** */
-/* PLL registers */
-/* ***************************************************************************** */
-#define  PLL_A_INT_FRAC            0x110088
-#define  PLL_A_POST_STAT_BIST      0x11008C
-#define  PLL_B_INT_FRAC            0x110090
-#define  PLL_B_POST_STAT_BIST      0x110094
-#define  PLL_C_INT_FRAC            0x110098
-#define  PLL_C_POST_STAT_BIST      0x11009C
-#define  PLL_D_INT_FRAC            0x1100A0
-#define  PLL_D_POST_STAT_BIST      0x1100A4
-
-#define  CLK_RST                   0x11002C
-#define  FLD_VID_I_CLK_NOE         0x00001000
-#define  FLD_VID_J_CLK_NOE         0x00002000
-#define  FLD_USE_ALT_PLL_REF       0x00004000
-
-#define  VID_CH_MODE_SEL           0x110078
-#define  VID_CH_CLK_SEL            0x11007C
-
-/* ***************************************************************************** */
-#define  VBI_A_DMA                 0x130008    /* VBI A DMA data port */
-
-/* ***************************************************************************** */
-#define  VID_A_VIP_CTL             0x130080    /* Video A VIP format control */
-#define  FLD_VIP_MODE              0x00000001
-
-/* ***************************************************************************** */
-#define  VID_A_PIXEL_FRMT          0x130084    /* Video A pixel format */
-#define  FLD_VID_A_GAMMA_DIS       0x00000008
-#define  FLD_VID_A_FORMAT          0x00000007
-#define  FLD_VID_A_GAMMA_FACTOR    0x00000010
-
-/* ***************************************************************************** */
-#define  VID_A_VBI_CTL             0x130088    /* Video A VBI miscellaneous control */
-#define  FLD_VID_A_VIP_EXT         0x00000003
-
-/* ***************************************************************************** */
-#define  VID_B_DMA                 0x130100    /* Video B DMA data port */
-
-/* ***************************************************************************** */
-#define  VBI_B_DMA                 0x130108    /* VBI B DMA data port */
-
-/* ***************************************************************************** */
-#define  VID_B_SRC_SEL             0x130144    /* Video B source select */
-#define  FLD_VID_B_SRC_SEL         0x00000000
-
-/* ***************************************************************************** */
-#define  VID_B_LNGTH               0x130150    /* Video B line length */
-#define  FLD_VID_B_LN_LNGTH        0x00000FFF
-
-/* ***************************************************************************** */
-#define  VID_B_VIP_CTL             0x130180    /* Video B VIP format control */
-
-/* ***************************************************************************** */
-#define  VID_B_PIXEL_FRMT          0x130184    /* Video B pixel format */
-#define  FLD_VID_B_GAMMA_DIS       0x00000008
-#define  FLD_VID_B_FORMAT          0x00000007
-#define  FLD_VID_B_GAMMA_FACTOR    0x00000010
-
-/* ***************************************************************************** */
-#define  VID_C_DMA                 0x130200    /* Video C DMA data port */
-
-/* ***************************************************************************** */
-#define  VID_C_LNGTH               0x130250    /* Video C line length */
-#define  FLD_VID_C_LN_LNGTH        0x00000FFF
-
-/* ***************************************************************************** */
-/* Video Destination Channels */
-/* ***************************************************************************** */
-
-#define  VID_DST_A_GPCNT           0x130020    /* Video A general purpose counter */
-#define  VID_DST_B_GPCNT           0x130120    /* Video B general purpose counter */
-#define  VID_DST_C_GPCNT           0x130220    /* Video C general purpose counter */
-#define  VID_DST_D_GPCNT           0x130320    /* Video D general purpose counter */
-#define  VID_DST_E_GPCNT           0x130420    /* Video E general purpose counter */
-#define  VID_DST_F_GPCNT           0x130520    /* Video F general purpose counter */
-#define  VID_DST_G_GPCNT           0x130620    /* Video G general purpose counter */
-#define  VID_DST_H_GPCNT           0x130720    /* Video H general purpose counter */
-
-/* ***************************************************************************** */
-
-#define  VID_DST_A_GPCNT_CTL       0x130030    /* Video A general purpose control */
-#define  VID_DST_B_GPCNT_CTL       0x130130    /* Video B general purpose control */
-#define  VID_DST_C_GPCNT_CTL       0x130230    /* Video C general purpose control */
-#define  VID_DST_D_GPCNT_CTL       0x130330    /* Video D general purpose control */
-#define  VID_DST_E_GPCNT_CTL       0x130430    /* Video E general purpose control */
-#define  VID_DST_F_GPCNT_CTL       0x130530    /* Video F general purpose control */
-#define  VID_DST_G_GPCNT_CTL       0x130630    /* Video G general purpose control */
-#define  VID_DST_H_GPCNT_CTL       0x130730    /* Video H general purpose control */
-
-/* ***************************************************************************** */
-
-#define  VID_DST_A_DMA_CTL         0x130040    /* Video A DMA control */
-#define  VID_DST_B_DMA_CTL         0x130140    /* Video B DMA control */
-#define  VID_DST_C_DMA_CTL         0x130240    /* Video C DMA control */
-#define  VID_DST_D_DMA_CTL         0x130340    /* Video D DMA control */
-#define  VID_DST_E_DMA_CTL         0x130440    /* Video E DMA control */
-#define  VID_DST_F_DMA_CTL         0x130540    /* Video F DMA control */
-#define  VID_DST_G_DMA_CTL         0x130640    /* Video G DMA control */
-#define  VID_DST_H_DMA_CTL         0x130740    /* Video H DMA control */
-
-#define  FLD_VID_RISC_EN           0x00000010
-#define  FLD_VID_FIFO_EN           0x00000001
-
-/* ***************************************************************************** */
-
-#define  VID_DST_A_VIP_CTL         0x130080    /* Video A VIP control */
-#define  VID_DST_B_VIP_CTL         0x130180    /* Video B VIP control */
-#define  VID_DST_C_VIP_CTL         0x130280    /* Video C VIP control */
-#define  VID_DST_D_VIP_CTL         0x130380    /* Video D VIP control */
-#define  VID_DST_E_VIP_CTL         0x130480    /* Video E VIP control */
-#define  VID_DST_F_VIP_CTL         0x130580    /* Video F VIP control */
-#define  VID_DST_G_VIP_CTL         0x130680    /* Video G VIP control */
-#define  VID_DST_H_VIP_CTL         0x130780    /* Video H VIP control */
-
-/* ***************************************************************************** */
-
-#define  VID_DST_A_PIX_FRMT        0x130084    /* Video A Pixel format */
-#define  VID_DST_B_PIX_FRMT        0x130184    /* Video B Pixel format */
-#define  VID_DST_C_PIX_FRMT        0x130284    /* Video C Pixel format */
-#define  VID_DST_D_PIX_FRMT        0x130384    /* Video D Pixel format */
-#define  VID_DST_E_PIX_FRMT        0x130484    /* Video E Pixel format */
-#define  VID_DST_F_PIX_FRMT        0x130584    /* Video F Pixel format */
-#define  VID_DST_G_PIX_FRMT        0x130684    /* Video G Pixel format */
-#define  VID_DST_H_PIX_FRMT        0x130784    /* Video H Pixel format */
-
-/* ***************************************************************************** */
-/* Video Source Channels */
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_GPCNT_CTL       0x130804    /* Video A general purpose control */
-#define  VID_SRC_B_GPCNT_CTL       0x130904    /* Video B general purpose control */
-#define  VID_SRC_C_GPCNT_CTL       0x130A04    /* Video C general purpose control */
-#define  VID_SRC_D_GPCNT_CTL       0x130B04    /* Video D general purpose control */
-#define  VID_SRC_E_GPCNT_CTL       0x130C04    /* Video E general purpose control */
-#define  VID_SRC_F_GPCNT_CTL       0x130D04    /* Video F general purpose control */
-#define  VID_SRC_I_GPCNT_CTL       0x130E04    /* Video I general purpose control */
-#define  VID_SRC_J_GPCNT_CTL       0x130F04    /* Video J general purpose control */
-
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_GPCNT           0x130808    /* Video A general purpose counter */
-#define  VID_SRC_B_GPCNT           0x130908    /* Video B general purpose counter */
-#define  VID_SRC_C_GPCNT           0x130A08    /* Video C general purpose counter */
-#define  VID_SRC_D_GPCNT           0x130B08    /* Video D general purpose counter */
-#define  VID_SRC_E_GPCNT           0x130C08    /* Video E general purpose counter */
-#define  VID_SRC_F_GPCNT           0x130D08    /* Video F general purpose counter */
-#define  VID_SRC_I_GPCNT           0x130E08    /* Video I general purpose counter */
-#define  VID_SRC_J_GPCNT           0x130F08    /* Video J general purpose counter */
-
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_DMA_CTL         0x13080C    /* Video A DMA control */
-#define  VID_SRC_B_DMA_CTL         0x13090C    /* Video B DMA control */
-#define  VID_SRC_C_DMA_CTL         0x130A0C    /* Video C DMA control */
-#define  VID_SRC_D_DMA_CTL         0x130B0C    /* Video D DMA control */
-#define  VID_SRC_E_DMA_CTL         0x130C0C    /* Video E DMA control */
-#define  VID_SRC_F_DMA_CTL         0x130D0C    /* Video F DMA control */
-#define  VID_SRC_I_DMA_CTL         0x130E0C    /* Video I DMA control */
-#define  VID_SRC_J_DMA_CTL         0x130F0C    /* Video J DMA control */
-
-#define  FLD_APB_RISC_EN           0x00000010
-#define  FLD_APB_FIFO_EN           0x00000001
-
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_FMT_CTL         0x130810    /* Video A format control */
-#define  VID_SRC_B_FMT_CTL         0x130910    /* Video B format control */
-#define  VID_SRC_C_FMT_CTL         0x130A10    /* Video C format control */
-#define  VID_SRC_D_FMT_CTL         0x130B10    /* Video D format control */
-#define  VID_SRC_E_FMT_CTL         0x130C10    /* Video E format control */
-#define  VID_SRC_F_FMT_CTL         0x130D10    /* Video F format control */
-#define  VID_SRC_I_FMT_CTL         0x130E10    /* Video I format control */
-#define  VID_SRC_J_FMT_CTL         0x130F10    /* Video J format control */
-
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_ACTIVE_CTL1     0x130814    /* Video A active control      1 */
-#define  VID_SRC_B_ACTIVE_CTL1     0x130914    /* Video B active control      1 */
-#define  VID_SRC_C_ACTIVE_CTL1     0x130A14    /* Video C active control      1 */
-#define  VID_SRC_D_ACTIVE_CTL1     0x130B14    /* Video D active control      1 */
-#define  VID_SRC_E_ACTIVE_CTL1     0x130C14    /* Video E active control      1 */
-#define  VID_SRC_F_ACTIVE_CTL1     0x130D14    /* Video F active control      1 */
-#define  VID_SRC_I_ACTIVE_CTL1     0x130E14    /* Video I active control      1 */
-#define  VID_SRC_J_ACTIVE_CTL1     0x130F14    /* Video J active control      1 */
-
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_ACTIVE_CTL2     0x130818    /* Video A active control      2 */
-#define  VID_SRC_B_ACTIVE_CTL2     0x130918    /* Video B active control      2 */
-#define  VID_SRC_C_ACTIVE_CTL2     0x130A18    /* Video C active control      2 */
-#define  VID_SRC_D_ACTIVE_CTL2     0x130B18    /* Video D active control      2 */
-#define  VID_SRC_E_ACTIVE_CTL2     0x130C18    /* Video E active control      2 */
-#define  VID_SRC_F_ACTIVE_CTL2     0x130D18    /* Video F active control      2 */
-#define  VID_SRC_I_ACTIVE_CTL2     0x130E18    /* Video I active control      2 */
-#define  VID_SRC_J_ACTIVE_CTL2     0x130F18    /* Video J active control      2 */
-
-/* ***************************************************************************** */
-
-#define  VID_SRC_A_CDT_SZ          0x13081C    /* Video A CDT size */
-#define  VID_SRC_B_CDT_SZ          0x13091C    /* Video B CDT size */
-#define  VID_SRC_C_CDT_SZ          0x130A1C    /* Video C CDT size */
-#define  VID_SRC_D_CDT_SZ          0x130B1C    /* Video D CDT size */
-#define  VID_SRC_E_CDT_SZ          0x130C1C    /* Video E CDT size */
-#define  VID_SRC_F_CDT_SZ          0x130D1C    /* Video F CDT size */
-#define  VID_SRC_I_CDT_SZ          0x130E1C    /* Video I CDT size */
-#define  VID_SRC_J_CDT_SZ          0x130F1C    /* Video J CDT size */
-
-/* ***************************************************************************** */
-/* Audio I/F */
-/* ***************************************************************************** */
-#define  AUD_DST_A_DMA             0x140000    /* Audio Int A DMA data port */
-#define  AUD_SRC_A_DMA             0x140008    /* Audio Int A DMA data port */
-
-#define  AUD_A_GPCNT               0x140010    /* Audio Int A gp counter */
-#define  FLD_AUD_A_GP_CNT          0x0000FFFF
-
-#define  AUD_A_GPCNT_CTL           0x140014    /* Audio Int A gp control */
-
-#define  AUD_A_LNGTH               0x140018    /* Audio Int A line length */
-
-#define  AUD_A_CFG                 0x14001C    /* Audio Int A configuration */
-
-/* ***************************************************************************** */
-#define  AUD_DST_B_DMA             0x140100    /* Audio Int B DMA data port */
-#define  AUD_SRC_B_DMA             0x140108    /* Audio Int B DMA data port */
-
-#define  AUD_B_GPCNT               0x140110    /* Audio Int B gp counter */
-#define  FLD_AUD_B_GP_CNT          0x0000FFFF
-
-#define  AUD_B_GPCNT_CTL           0x140114    /* Audio Int B gp control */
-
-#define  AUD_B_LNGTH               0x140118    /* Audio Int B line length */
-
-#define  AUD_B_CFG                 0x14011C    /* Audio Int B configuration */
-
-/* ***************************************************************************** */
-#define  AUD_DST_C_DMA             0x140200    /* Audio Int C DMA data port */
-#define  AUD_SRC_C_DMA             0x140208    /* Audio Int C DMA data port */
-
-#define  AUD_C_GPCNT               0x140210    /* Audio Int C gp counter */
-#define  FLD_AUD_C_GP_CNT          0x0000FFFF
-
-#define  AUD_C_GPCNT_CTL           0x140214    /* Audio Int C gp control */
-
-#define  AUD_C_LNGTH               0x140218    /* Audio Int C line length */
-
-#define  AUD_C_CFG                 0x14021C    /* Audio Int C configuration */
-
-/* ***************************************************************************** */
-#define  AUD_DST_D_DMA             0x140300    /* Audio Int D DMA data port */
-#define  AUD_SRC_D_DMA             0x140308    /* Audio Int D DMA data port */
-
-#define  AUD_D_GPCNT               0x140310    /* Audio Int D gp counter */
-#define  FLD_AUD_D_GP_CNT          0x0000FFFF
-
-#define  AUD_D_GPCNT_CTL           0x140314    /* Audio Int D gp control */
-
-#define  AUD_D_LNGTH               0x140318    /* Audio Int D line length */
-
-#define  AUD_D_CFG                 0x14031C    /* Audio Int D configuration */
-
-/* ***************************************************************************** */
-#define  AUD_SRC_E_DMA             0x140400    /* Audio Int E DMA data port */
-
-#define  AUD_E_GPCNT               0x140410    /* Audio Int E gp counter */
-#define  FLD_AUD_E_GP_CNT          0x0000FFFF
-
-#define  AUD_E_GPCNT_CTL           0x140414    /* Audio Int E gp control */
-
-#define  AUD_E_CFG                 0x14041C    /* Audio Int E configuration */
-
-/* ***************************************************************************** */
-
-#define  FLD_AUD_DST_LN_LNGTH      0x00000FFF
-
-#define  FLD_AUD_DST_PK_MODE       0x00004000
-
-#define  FLD_AUD_CLK_ENABLE        0x00000200
-
-#define  FLD_AUD_MASTER_MODE       0x00000002
-
-#define  FLD_AUD_SONY_MODE         0x00000001
-
-#define  FLD_AUD_CLK_SELECT_PLL_D  0x00001800
-
-#define  FLD_AUD_DST_ENABLE        0x00020000
-
-#define  FLD_AUD_SRC_ENABLE        0x00010000
-
-/* ***************************************************************************** */
-#define  AUD_INT_DMA_CTL           0x140500    /* Audio Int DMA control */
-
-#define  FLD_AUD_SRC_E_RISC_EN     0x00008000
-#define  FLD_AUD_SRC_C_RISC_EN     0x00004000
-#define  FLD_AUD_SRC_B_RISC_EN     0x00002000
-#define  FLD_AUD_SRC_A_RISC_EN     0x00001000
-
-#define  FLD_AUD_DST_D_RISC_EN     0x00000800
-#define  FLD_AUD_DST_C_RISC_EN     0x00000400
-#define  FLD_AUD_DST_B_RISC_EN     0x00000200
-#define  FLD_AUD_DST_A_RISC_EN     0x00000100
-
-#define  FLD_AUD_SRC_E_FIFO_EN     0x00000080
-#define  FLD_AUD_SRC_C_FIFO_EN     0x00000040
-#define  FLD_AUD_SRC_B_FIFO_EN     0x00000020
-#define  FLD_AUD_SRC_A_FIFO_EN     0x00000010
-
-#define  FLD_AUD_DST_D_FIFO_EN     0x00000008
-#define  FLD_AUD_DST_C_FIFO_EN     0x00000004
-#define  FLD_AUD_DST_B_FIFO_EN     0x00000002
-#define  FLD_AUD_DST_A_FIFO_EN     0x00000001
-
-/* ***************************************************************************** */
-/*  */
-/* Mobilygen Interface Registers */
-/*  */
-/* ***************************************************************************** */
-/* Mobilygen Interface A */
-/* ***************************************************************************** */
-#define  MB_IF_A_DMA               0x150000    /* MBIF A DMA data port */
-#define  MB_IF_A_GPCN              0x150008    /* MBIF A GP counter */
-#define  MB_IF_A_GPCN_CTRL         0x15000C
-#define  MB_IF_A_DMA_CTRL          0x150010
-#define  MB_IF_A_LENGTH            0x150014
-#define  MB_IF_A_HDMA_XFER_SZ      0x150018
-#define  MB_IF_A_HCMD              0x15001C
-#define  MB_IF_A_HCONFIG           0x150020
-#define  MB_IF_A_DATA_STRUCT_0     0x150024
-#define  MB_IF_A_DATA_STRUCT_1     0x150028
-#define  MB_IF_A_DATA_STRUCT_2     0x15002C
-#define  MB_IF_A_DATA_STRUCT_3     0x150030
-#define  MB_IF_A_DATA_STRUCT_4     0x150034
-#define  MB_IF_A_DATA_STRUCT_5     0x150038
-#define  MB_IF_A_DATA_STRUCT_6     0x15003C
-#define  MB_IF_A_DATA_STRUCT_7     0x150040
-#define  MB_IF_A_DATA_STRUCT_8     0x150044
-#define  MB_IF_A_DATA_STRUCT_9     0x150048
-#define  MB_IF_A_DATA_STRUCT_A     0x15004C
-#define  MB_IF_A_DATA_STRUCT_B     0x150050
-#define  MB_IF_A_DATA_STRUCT_C     0x150054
-#define  MB_IF_A_DATA_STRUCT_D     0x150058
-#define  MB_IF_A_DATA_STRUCT_E     0x15005C
-#define  MB_IF_A_DATA_STRUCT_F     0x150060
-/* ***************************************************************************** */
-/* Mobilygen Interface B */
-/* ***************************************************************************** */
-#define  MB_IF_B_DMA               0x160000    /* MBIF A DMA data port */
-#define  MB_IF_B_GPCN              0x160008    /* MBIF A GP counter */
-#define  MB_IF_B_GPCN_CTRL         0x16000C
-#define  MB_IF_B_DMA_CTRL          0x160010
-#define  MB_IF_B_LENGTH            0x160014
-#define  MB_IF_B_HDMA_XFER_SZ      0x160018
-#define  MB_IF_B_HCMD              0x16001C
-#define  MB_IF_B_HCONFIG           0x160020
-#define  MB_IF_B_DATA_STRUCT_0     0x160024
-#define  MB_IF_B_DATA_STRUCT_1     0x160028
-#define  MB_IF_B_DATA_STRUCT_2     0x16002C
-#define  MB_IF_B_DATA_STRUCT_3     0x160030
-#define  MB_IF_B_DATA_STRUCT_4     0x160034
-#define  MB_IF_B_DATA_STRUCT_5     0x160038
-#define  MB_IF_B_DATA_STRUCT_6     0x16003C
-#define  MB_IF_B_DATA_STRUCT_7     0x160040
-#define  MB_IF_B_DATA_STRUCT_8     0x160044
-#define  MB_IF_B_DATA_STRUCT_9     0x160048
-#define  MB_IF_B_DATA_STRUCT_A     0x16004C
-#define  MB_IF_B_DATA_STRUCT_B     0x160050
-#define  MB_IF_B_DATA_STRUCT_C     0x160054
-#define  MB_IF_B_DATA_STRUCT_D     0x160058
-#define  MB_IF_B_DATA_STRUCT_E     0x16005C
-#define  MB_IF_B_DATA_STRUCT_F     0x160060
-
-/* MB_DMA_CTRL */
-#define  FLD_MB_IF_RISC_EN         0x00000010
-#define  FLD_MB_IF_FIFO_EN         0x00000001
-
-/* MB_LENGTH */
-#define  FLD_MB_IF_LN_LNGTH        0x00000FFF
-
-/* MB_HCMD register */
-#define  FLD_MB_HCMD_H_GO          0x80000000
-#define  FLD_MB_HCMD_H_BUSY        0x40000000
-#define  FLD_MB_HCMD_H_DMA_HOLD    0x10000000
-#define  FLD_MB_HCMD_H_DMA_BUSY    0x08000000
-#define  FLD_MB_HCMD_H_DMA_TYPE    0x04000000
-#define  FLD_MB_HCMD_H_DMA_XACT    0x02000000
-#define  FLD_MB_HCMD_H_RW_N        0x01000000
-#define  FLD_MB_HCMD_H_ADDR        0x00FF0000
-#define  FLD_MB_HCMD_H_DATA        0x0000FFFF
-
-/* ***************************************************************************** */
-/* I2C #1 */
-/* ***************************************************************************** */
-#define  I2C1_ADDR                 0x180000    /* I2C #1 address */
-#define  FLD_I2C_DADDR             0xfe000000  /* RW [31:25] I2C Device Address */
-                                                /* RO [24] reserved */
-/* ***************************************************************************** */
-#define  FLD_I2C_SADDR             0x00FFFFFF  /* RW [23:0]  I2C Sub-address */
-
-/* ***************************************************************************** */
-#define  I2C1_WDATA                0x180004    /* I2C #1 write data */
-#define  FLD_I2C_WDATA             0xFFFFFFFF  /* RW [31:0] */
-
-/* ***************************************************************************** */
-#define  I2C1_CTRL                 0x180008    /* I2C #1 control */
-#define  FLD_I2C_PERIOD            0xFF000000  /* RW [31:24] */
-#define  FLD_I2C_SCL_IN            0x00200000  /* RW [21] */
-#define  FLD_I2C_SDA_IN            0x00100000  /* RW [20] */
-                                                /* RO [19:18] reserved */
-#define  FLD_I2C_SCL_OUT           0x00020000  /* RW [17] */
-#define  FLD_I2C_SDA_OUT           0x00010000  /* RW [16] */
-                                                /* RO [15] reserved */
-#define  FLD_I2C_DATA_LEN          0x00007000  /* RW [14:12] */
-#define  FLD_I2C_SADDR_INC         0x00000800  /* RW [11] */
-                                                /* RO [10:9] reserved */
-#define  FLD_I2C_SADDR_LEN         0x00000300  /* RW [9:8] */
-                                                /* RO [7:6] reserved */
-#define  FLD_I2C_SOFT              0x00000020  /* RW [5] */
-#define  FLD_I2C_NOSTOP            0x00000010  /* RW [4] */
-#define  FLD_I2C_EXTEND            0x00000008  /* RW [3] */
-#define  FLD_I2C_SYNC              0x00000004  /* RW [2] */
-#define  FLD_I2C_READ_SA           0x00000002  /* RW [1] */
-#define  FLD_I2C_READ_WRN          0x00000001  /* RW [0] */
-
-/* ***************************************************************************** */
-#define  I2C1_RDATA                0x18000C    /* I2C #1 read data */
-#define  FLD_I2C_RDATA             0xFFFFFFFF  /* RO [31:0] */
-
-/* ***************************************************************************** */
-#define  I2C1_STAT                 0x180010    /* I2C #1 status */
-#define  FLD_I2C_XFER_IN_PROG      0x00000002  /* RO [1] */
-#define  FLD_I2C_RACK              0x00000001  /* RO [0] */
-
-/* ***************************************************************************** */
-/* I2C #2 */
-/* ***************************************************************************** */
-#define  I2C2_ADDR                 0x190000    /* I2C #2 address */
-
-/* ***************************************************************************** */
-#define  I2C2_WDATA                0x190004    /* I2C #2 write data */
-
-/* ***************************************************************************** */
-#define  I2C2_CTRL                 0x190008    /* I2C #2 control */
-
-/* ***************************************************************************** */
-#define  I2C2_RDATA                0x19000C    /* I2C #2 read data */
-
-/* ***************************************************************************** */
-#define  I2C2_STAT                 0x190010    /* I2C #2 status */
-
-/* ***************************************************************************** */
-/* I2C #3 */
-/* ***************************************************************************** */
-#define  I2C3_ADDR                 0x1A0000    /* I2C #3 address */
-
-/* ***************************************************************************** */
-#define  I2C3_WDATA                0x1A0004    /* I2C #3 write data */
-
-/* ***************************************************************************** */
-#define  I2C3_CTRL                 0x1A0008    /* I2C #3 control */
-
-/* ***************************************************************************** */
-#define  I2C3_RDATA                0x1A000C    /* I2C #3 read data */
-
-/* ***************************************************************************** */
-#define  I2C3_STAT                 0x1A0010    /* I2C #3 status */
-
-/* ***************************************************************************** */
-/* UART */
-/* ***************************************************************************** */
-#define  UART_CTL                  0x1B0000    /* UART Control Register */
-#define  FLD_LOOP_BACK_EN          (1 << 7)    /* RW field - default 0 */
-#define  FLD_RX_TRG_SZ             (3 << 2)    /* RW field - default 0 */
-#define  FLD_RX_EN                 (1 << 1)    /* RW field - default 0 */
-#define  FLD_TX_EN                 (1 << 0)    /* RW field - default 0 */
-
-/* ***************************************************************************** */
-#define  UART_BRD                  0x1B0004    /* UART Baud Rate Divisor */
-#define  FLD_BRD                   0x0000FFFF  /* RW field - default 0x197 */
-
-/* ***************************************************************************** */
-#define  UART_DBUF                 0x1B0008    /* UART Tx/Rx Data BuFFer */
-#define  FLD_DB                    0xFFFFFFFF  /* RW field - default 0 */
-
-/* ***************************************************************************** */
-#define  UART_ISR                  0x1B000C    /* UART Interrupt Status */
-#define  FLD_RXD_TIMEOUT_EN        (1 << 7)    /* RW field - default 0 */
-#define  FLD_FRM_ERR_EN            (1 << 6)    /* RW field - default 0 */
-#define  FLD_RXD_RDY_EN            (1 << 5)    /* RW field - default 0 */
-#define  FLD_TXD_EMPTY_EN          (1 << 4)    /* RW field - default 0 */
-#define  FLD_RXD_OVERFLOW          (1 << 3)    /* RW field - default 0 */
-#define  FLD_FRM_ERR               (1 << 2)    /* RW field - default 0 */
-#define  FLD_RXD_RDY               (1 << 1)    /* RW field - default 0 */
-#define  FLD_TXD_EMPTY             (1 << 0)    /* RW field - default 0 */
-
-/* ***************************************************************************** */
-#define  UART_CNT                  0x1B0010    /* UART Tx/Rx FIFO Byte Count */
-#define  FLD_TXD_CNT               (0x1F << 8) /* RW field - default 0 */
-#define  FLD_RXD_CNT               (0x1F << 0) /* RW field - default 0 */
-
-/* ***************************************************************************** */
-/* Motion Detection */
-#define  MD_CH0_GRID_BLOCK_YCNT    0x170014
-#define  MD_CH1_GRID_BLOCK_YCNT    0x170094
-#define  MD_CH2_GRID_BLOCK_YCNT    0x170114
-#define  MD_CH3_GRID_BLOCK_YCNT    0x170194
-#define  MD_CH4_GRID_BLOCK_YCNT    0x170214
-#define  MD_CH5_GRID_BLOCK_YCNT    0x170294
-#define  MD_CH6_GRID_BLOCK_YCNT    0x170314
-#define  MD_CH7_GRID_BLOCK_YCNT    0x170394
-
-#define PIXEL_FRMT_422    4
-#define PIXEL_FRMT_411    5
-#define PIXEL_FRMT_Y8     6
-
-#define PIXEL_ENGINE_VIP1 0
-#define PIXEL_ENGINE_VIP2 1
-
-#endif /* Athena_REGISTERS */
diff --git a/drivers/media/video/cx25821/cx25821-sram.h b/drivers/media/video/cx25821/cx25821-sram.h
deleted file mode 100644 (file)
index 5f05d15..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.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 __ATHENA_SRAM_H__
-#define __ATHENA_SRAM_H__
-
-/* #define RX_SRAM_START_SIZE        = 0;  //  Start of reserved SRAM */
-#define VID_CMDS_SIZE             80   /* Video CMDS size in bytes */
-#define AUDIO_CMDS_SIZE           80   /* AUDIO CMDS size in bytes */
-#define MBIF_CMDS_SIZE            80   /* MBIF  CMDS size in bytes */
-
-/* #define RX_SRAM_POOL_START_SIZE   = 0;  //  Start of useable RX SRAM for buffers */
-#define VID_IQ_SIZE               64   /* VID instruction queue size in bytes */
-#define MBIF_IQ_SIZE              64
-#define AUDIO_IQ_SIZE             64   /* AUD instruction queue size in bytes */
-
-#define VID_CDT_SIZE              64   /* VID cluster descriptor table size in bytes */
-#define MBIF_CDT_SIZE             64   /* MBIF/HBI cluster descriptor table size in bytes */
-#define AUDIO_CDT_SIZE            48   /* AUD cluster descriptor table size in bytes */
-
-/* #define RX_SRAM_POOL_FREE_SIZE    = 16; //  Start of available RX SRAM */
-/* #define RX_SRAM_END_SIZE          = 0;  //  End of RX SRAM */
-
-/* #define TX_SRAM_POOL_START_SIZE   = 0;  //  Start of transmit pool SRAM */
-/* #define MSI_DATA_SIZE             = 64; //  Reserved (MSI Data, RISC working stora */
-
-#define VID_CLUSTER_SIZE          1440 /* VID cluster data line */
-#define AUDIO_CLUSTER_SIZE        128  /* AUDIO cluster data line */
-#define MBIF_CLUSTER_SIZE         1440 /* MBIF/HBI cluster data line */
-
-/* #define TX_SRAM_POOL_FREE_SIZE    = 704;    //  Start of available TX SRAM */
-/* #define TX_SRAM_END_SIZE          = 0;      //  End of TX SRAM */
-
-/* Receive SRAM */
-#define RX_SRAM_START             0x10000
-#define VID_A_DOWN_CMDS           0x10000
-#define VID_B_DOWN_CMDS           0x10050
-#define VID_C_DOWN_CMDS           0x100A0
-#define VID_D_DOWN_CMDS           0x100F0
-#define VID_E_DOWN_CMDS           0x10140
-#define VID_F_DOWN_CMDS           0x10190
-#define VID_G_DOWN_CMDS           0x101E0
-#define VID_H_DOWN_CMDS           0x10230
-#define VID_A_UP_CMDS             0x10280
-#define VID_B_UP_CMDS             0x102D0
-#define VID_C_UP_CMDS             0x10320
-#define VID_D_UP_CMDS             0x10370
-#define VID_E_UP_CMDS             0x103C0
-#define VID_F_UP_CMDS             0x10410
-#define VID_I_UP_CMDS             0x10460
-#define VID_J_UP_CMDS             0x104B0
-#define AUD_A_DOWN_CMDS           0x10500
-#define AUD_B_DOWN_CMDS           0x10550
-#define AUD_C_DOWN_CMDS           0x105A0
-#define AUD_D_DOWN_CMDS           0x105F0
-#define AUD_A_UP_CMDS             0x10640
-#define AUD_B_UP_CMDS             0x10690
-#define AUD_C_UP_CMDS             0x106E0
-#define AUD_E_UP_CMDS             0x10730
-#define MBIF_A_DOWN_CMDS          0x10780
-#define MBIF_B_DOWN_CMDS          0x107D0
-#define DMA_SCRATCH_PAD           0x10820      /* Scratch pad area from 0x10820 to 0x10B40 */
-
-/* #define RX_SRAM_POOL_START        = 0x105B0; */
-
-#define VID_A_IQ                  0x11000
-#define VID_B_IQ                  0x11040
-#define VID_C_IQ                  0x11080
-#define VID_D_IQ                  0x110C0
-#define VID_E_IQ                  0x11100
-#define VID_F_IQ                  0x11140
-#define VID_G_IQ                  0x11180
-#define VID_H_IQ                  0x111C0
-#define VID_I_IQ                  0x11200
-#define VID_J_IQ                  0x11240
-#define AUD_A_IQ                  0x11280
-#define AUD_B_IQ                  0x112C0
-#define AUD_C_IQ                  0x11300
-#define AUD_D_IQ                  0x11340
-#define AUD_E_IQ                  0x11380
-#define MBIF_A_IQ                 0x11000
-#define MBIF_B_IQ                 0x110C0
-
-#define VID_A_CDT                 0x10C00
-#define VID_B_CDT                 0x10C40
-#define VID_C_CDT                 0x10C80
-#define VID_D_CDT                 0x10CC0
-#define VID_E_CDT                 0x10D00
-#define VID_F_CDT                 0x10D40
-#define VID_G_CDT                 0x10D80
-#define VID_H_CDT                 0x10DC0
-#define VID_I_CDT                 0x10E00
-#define VID_J_CDT                 0x10E40
-#define AUD_A_CDT                 0x10E80
-#define AUD_B_CDT                 0x10EB0
-#define AUD_C_CDT                 0x10EE0
-#define AUD_D_CDT                 0x10F10
-#define AUD_E_CDT                 0x10F40
-#define MBIF_A_CDT                0x10C00
-#define MBIF_B_CDT                0x10CC0
-
-/* Cluster Buffer for RX */
-#define VID_A_UP_CLUSTER_1        0x11400
-#define VID_A_UP_CLUSTER_2        0x119A0
-#define VID_A_UP_CLUSTER_3        0x11F40
-#define VID_A_UP_CLUSTER_4        0x124E0
-
-#define VID_B_UP_CLUSTER_1        0x12A80
-#define VID_B_UP_CLUSTER_2        0x13020
-#define VID_B_UP_CLUSTER_3        0x135C0
-#define VID_B_UP_CLUSTER_4        0x13B60
-
-#define VID_C_UP_CLUSTER_1        0x14100
-#define VID_C_UP_CLUSTER_2        0x146A0
-#define VID_C_UP_CLUSTER_3        0x14C40
-#define VID_C_UP_CLUSTER_4        0x151E0
-
-#define VID_D_UP_CLUSTER_1        0x15780
-#define VID_D_UP_CLUSTER_2        0x15D20
-#define VID_D_UP_CLUSTER_3        0x162C0
-#define VID_D_UP_CLUSTER_4        0x16860
-
-#define VID_E_UP_CLUSTER_1        0x16E00
-#define VID_E_UP_CLUSTER_2        0x173A0
-#define VID_E_UP_CLUSTER_3        0x17940
-#define VID_E_UP_CLUSTER_4        0x17EE0
-
-#define VID_F_UP_CLUSTER_1        0x18480
-#define VID_F_UP_CLUSTER_2        0x18A20
-#define VID_F_UP_CLUSTER_3        0x18FC0
-#define VID_F_UP_CLUSTER_4        0x19560
-
-#define VID_I_UP_CLUSTER_1        0x19B00
-#define VID_I_UP_CLUSTER_2        0x1A0A0
-#define VID_I_UP_CLUSTER_3        0x1A640
-#define VID_I_UP_CLUSTER_4        0x1ABE0
-
-#define VID_J_UP_CLUSTER_1        0x1B180
-#define VID_J_UP_CLUSTER_2        0x1B720
-#define VID_J_UP_CLUSTER_3        0x1BCC0
-#define VID_J_UP_CLUSTER_4        0x1C260
-
-#define AUD_A_UP_CLUSTER_1        0x1C800
-#define AUD_A_UP_CLUSTER_2        0x1C880
-#define AUD_A_UP_CLUSTER_3        0x1C900
-
-#define AUD_B_UP_CLUSTER_1        0x1C980
-#define AUD_B_UP_CLUSTER_2        0x1CA00
-#define AUD_B_UP_CLUSTER_3        0x1CA80
-
-#define AUD_C_UP_CLUSTER_1        0x1CB00
-#define AUD_C_UP_CLUSTER_2        0x1CB80
-#define AUD_C_UP_CLUSTER_3        0x1CC00
-
-#define AUD_E_UP_CLUSTER_1        0x1CC80
-#define AUD_E_UP_CLUSTER_2        0x1CD00
-#define AUD_E_UP_CLUSTER_3        0x1CD80
-
-#define RX_SRAM_POOL_FREE         0x1CE00
-#define RX_SRAM_END               0x1D000
-
-/* Free Receive SRAM    144 Bytes */
-
-/* Transmit SRAM */
-#define TX_SRAM_POOL_START        0x00000
-
-#define VID_A_DOWN_CLUSTER_1      0x00040
-#define VID_A_DOWN_CLUSTER_2      0x005E0
-#define VID_A_DOWN_CLUSTER_3      0x00B80
-#define VID_A_DOWN_CLUSTER_4      0x01120
-
-#define VID_B_DOWN_CLUSTER_1      0x016C0
-#define VID_B_DOWN_CLUSTER_2      0x01C60
-#define VID_B_DOWN_CLUSTER_3      0x02200
-#define VID_B_DOWN_CLUSTER_4      0x027A0
-
-#define VID_C_DOWN_CLUSTER_1      0x02D40
-#define VID_C_DOWN_CLUSTER_2      0x032E0
-#define VID_C_DOWN_CLUSTER_3      0x03880
-#define VID_C_DOWN_CLUSTER_4      0x03E20
-
-#define VID_D_DOWN_CLUSTER_1      0x043C0
-#define VID_D_DOWN_CLUSTER_2      0x04960
-#define VID_D_DOWN_CLUSTER_3      0x04F00
-#define VID_D_DOWN_CLUSTER_4      0x054A0
-
-#define VID_E_DOWN_CLUSTER_1      0x05a40
-#define VID_E_DOWN_CLUSTER_2      0x05FE0
-#define VID_E_DOWN_CLUSTER_3      0x06580
-#define VID_E_DOWN_CLUSTER_4      0x06B20
-
-#define VID_F_DOWN_CLUSTER_1      0x070C0
-#define VID_F_DOWN_CLUSTER_2      0x07660
-#define VID_F_DOWN_CLUSTER_3      0x07C00
-#define VID_F_DOWN_CLUSTER_4      0x081A0
-
-#define VID_G_DOWN_CLUSTER_1      0x08740
-#define VID_G_DOWN_CLUSTER_2      0x08CE0
-#define VID_G_DOWN_CLUSTER_3      0x09280
-#define VID_G_DOWN_CLUSTER_4      0x09820
-
-#define VID_H_DOWN_CLUSTER_1      0x09DC0
-#define VID_H_DOWN_CLUSTER_2      0x0A360
-#define VID_H_DOWN_CLUSTER_3      0x0A900
-#define VID_H_DOWN_CLUSTER_4      0x0AEA0
-
-#define AUD_A_DOWN_CLUSTER_1      0x0B500
-#define AUD_A_DOWN_CLUSTER_2      0x0B580
-#define AUD_A_DOWN_CLUSTER_3      0x0B600
-
-#define AUD_B_DOWN_CLUSTER_1      0x0B680
-#define AUD_B_DOWN_CLUSTER_2      0x0B700
-#define AUD_B_DOWN_CLUSTER_3      0x0B780
-
-#define AUD_C_DOWN_CLUSTER_1      0x0B800
-#define AUD_C_DOWN_CLUSTER_2      0x0B880
-#define AUD_C_DOWN_CLUSTER_3      0x0B900
-
-#define AUD_D_DOWN_CLUSTER_1      0x0B980
-#define AUD_D_DOWN_CLUSTER_2      0x0BA00
-#define AUD_D_DOWN_CLUSTER_3      0x0BA80
-
-#define TX_SRAM_POOL_FREE         0x0BB00
-#define TX_SRAM_END               0x0C000
-
-#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
-#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
-#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
-
-#define VID_IQ_SIZE_DW             BYTES_TO_DWORDS(VID_IQ_SIZE)
-#define VID_CDT_SIZE_QW            BYTES_TO_QWORDS(VID_CDT_SIZE)
-#define VID_CLUSTER_SIZE_OW        BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
-
-#define AUDIO_IQ_SIZE_DW           BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
-#define AUDIO_CDT_SIZE_QW          BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
-#define AUDIO_CLUSTER_SIZE_QW      BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
-
-#define MBIF_IQ_SIZE_DW            BYTES_TO_DWORDS(MBIF_IQ_SIZE)
-#define MBIF_CDT_SIZE_QW           BYTES_TO_QWORDS(MBIF_CDT_SIZE)
-#define MBIF_CLUSTER_SIZE_OW       BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c
deleted file mode 100644 (file)
index c8c94fb..0000000
+++ /dev/null
@@ -1,802 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "cx25821-video.h"
-#include "cx25821-video-upstream-ch2.h"
-
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/syscalls.h>
-#include <linux/file.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
-MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
-MODULE_LICENSE("GPL");
-
-static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
-                       FLD_VID_SRC_OPC_ERR;
-
-static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
-                                             __le32 *rp, unsigned int offset,
-                                             unsigned int bpl, u32 sync_line,
-                                             unsigned int lines,
-                                             int fifo_enable, int field_type)
-{
-       unsigned int line, i;
-       int dist_betwn_starts = bpl * 2;
-
-       *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       if (USE_RISC_NOOP_VIDEO) {
-               for (i = 0; i < NUM_NO_OPS; i++)
-                       *(rp++) = cpu_to_le32(RISC_NOOP);
-       }
-
-       /* scan lines */
-       for (line = 0; line < lines; line++) {
-               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
-               *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
-               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-
-               if ((lines <= NTSC_FIELD_HEIGHT) ||
-                   (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
-                       offset += dist_betwn_starts;
-               }
-       }
-
-       return rp;
-}
-
-static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
-                                              __le32 *rp,
-                                              dma_addr_t databuf_phys_addr,
-                                              unsigned int offset,
-                                              u32 sync_line, unsigned int bpl,
-                                              unsigned int lines,
-                                              int fifo_enable, int field_type)
-{
-       unsigned int line, i;
-       struct sram_channel *sram_ch =
-               dev->channels[dev->_channel2_upstream_select].sram_channels;
-       int dist_betwn_starts = bpl * 2;
-
-       /* sync instruction */
-       if (sync_line != NO_SYNC_LINE)
-               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       if (USE_RISC_NOOP_VIDEO) {
-               for (i = 0; i < NUM_NO_OPS; i++)
-                       *(rp++) = cpu_to_le32(RISC_NOOP);
-       }
-
-       /* scan lines */
-       for (line = 0; line < lines; line++) {
-               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
-               *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
-               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-
-               if ((lines <= NTSC_FIELD_HEIGHT) ||
-                   (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
-                       offset += dist_betwn_starts;
-               }
-
-              /*
-                check if we need to enable the FIFO after the first 4 lines
-                 For the upstream video channel, the risc engine will enable
-                 the FIFO.
-              */
-               if (fifo_enable && line == 3) {
-                       *(rp++) = RISC_WRITECR;
-                       *(rp++) = sram_ch->dma_ctl;
-                       *(rp++) = FLD_VID_FIFO_EN;
-                       *(rp++) = 0x00000001;
-               }
-       }
-
-       return rp;
-}
-
-int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
-                                    struct pci_dev *pci,
-                                    unsigned int top_offset, unsigned int bpl,
-                                    unsigned int lines)
-{
-       __le32 *rp;
-       int fifo_enable = 0;
-       int singlefield_lines = lines >> 1; /*get line count for single field */
-       int odd_num_lines = singlefield_lines;
-       int frame = 0;
-       int frame_size = 0;
-       int databuf_offset = 0;
-       int risc_program_size = 0;
-       int risc_flag = RISC_CNT_RESET;
-       unsigned int bottom_offset = bpl;
-       dma_addr_t risc_phys_jump_addr;
-
-       if (dev->_isNTSC_ch2) {
-               odd_num_lines = singlefield_lines + 1;
-               risc_program_size = FRAME1_VID_PROG_SIZE;
-               if (bpl == Y411_LINE_SZ)
-                       frame_size = FRAME_SIZE_NTSC_Y411;
-               else
-                       frame_size = FRAME_SIZE_NTSC_Y422;
-       } else {
-               risc_program_size = PAL_VID_PROG_SIZE;
-               if (bpl == Y411_LINE_SZ)
-                       frame_size = FRAME_SIZE_PAL_Y411;
-               else
-                       frame_size = FRAME_SIZE_PAL_Y422;
-       }
-
-       /* Virtual address of Risc buffer program */
-       rp = dev->_dma_virt_addr_ch2;
-
-       for (frame = 0; frame < NUM_FRAMES; frame++) {
-               databuf_offset = frame_size * frame;
-
-               if (UNSET != top_offset) {
-                       fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
-                       rp = cx25821_risc_field_upstream_ch2(dev, rp,
-                               dev->_data_buf_phys_addr_ch2 + databuf_offset,
-                               top_offset, 0, bpl, odd_num_lines, fifo_enable,
-                               ODD_FIELD);
-               }
-
-               fifo_enable = FIFO_DISABLE;
-
-               /* Even field */
-               rp = cx25821_risc_field_upstream_ch2(dev, rp,
-                               dev->_data_buf_phys_addr_ch2 + databuf_offset,
-                               bottom_offset, 0x200, bpl, singlefield_lines,
-                               fifo_enable, EVEN_FIELD);
-
-               if (frame == 0) {
-                       risc_flag = RISC_CNT_RESET;
-                       risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 +
-                                       risc_program_size;
-               } else {
-                       risc_flag = RISC_CNT_INC;
-                       risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;
-               }
-
-              /*
-               * Loop to 2ndFrameRISC or to Start of
-               * Risc program & generate IRQ
-               */
-               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
-               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
-               *(rp++) = cpu_to_le32(0);
-       }
-
-       return 0;
-}
-
-void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
-{
-       struct sram_channel *sram_ch =
-               dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
-       u32 tmp = 0;
-
-       if (!dev->_is_running_ch2) {
-               pr_info("No video file is currently running so return!\n");
-               return;
-       }
-       /* Disable RISC interrupts */
-       tmp = cx_read(sram_ch->int_msk);
-       cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
-
-       /* Turn OFF risc and fifo */
-       tmp = cx_read(sram_ch->dma_ctl);
-       cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
-
-       /* Clear data buffer memory */
-       if (dev->_data_buf_virt_addr_ch2)
-               memset(dev->_data_buf_virt_addr_ch2, 0,
-                      dev->_data_buf_size_ch2);
-
-       dev->_is_running_ch2 = 0;
-       dev->_is_first_frame_ch2 = 0;
-       dev->_frame_count_ch2 = 0;
-       dev->_file_status_ch2 = END_OF_FILE;
-
-       kfree(dev->_irq_queues_ch2);
-       dev->_irq_queues_ch2 = NULL;
-
-       kfree(dev->_filename_ch2);
-
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
-}
-
-void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
-{
-       if (dev->_is_running_ch2)
-               cx25821_stop_upstream_video_ch2(dev);
-
-       if (dev->_dma_virt_addr_ch2) {
-               pci_free_consistent(dev->pci, dev->_risc_size_ch2,
-                                   dev->_dma_virt_addr_ch2,
-                                   dev->_dma_phys_addr_ch2);
-               dev->_dma_virt_addr_ch2 = NULL;
-       }
-
-       if (dev->_data_buf_virt_addr_ch2) {
-               pci_free_consistent(dev->pci, dev->_data_buf_size_ch2,
-                                   dev->_data_buf_virt_addr_ch2,
-                                   dev->_data_buf_phys_addr_ch2);
-               dev->_data_buf_virt_addr_ch2 = NULL;
-       }
-}
-
-int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
-{
-       struct file *myfile;
-       int frame_index_temp = dev->_frame_index_ch2;
-       int i = 0;
-       int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
-               Y411_LINE_SZ : Y422_LINE_SZ;
-       int frame_size = 0;
-       int frame_offset = 0;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t file_offset;
-       loff_t pos;
-       mm_segment_t old_fs;
-
-       if (dev->_file_status_ch2 == END_OF_FILE)
-               return 0;
-
-       if (dev->_isNTSC_ch2) {
-               frame_size = (line_size == Y411_LINE_SZ) ?
-                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
-       } else {
-               frame_size = (line_size == Y411_LINE_SZ) ?
-                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
-       }
-
-       frame_offset = (frame_index_temp > 0) ? frame_size : 0;
-       file_offset = dev->_frame_count_ch2 * frame_size;
-
-       myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_filename_ch2, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-
-               for (i = 0; i < dev->_lines_count_ch2; i++) {
-                       pos = file_offset;
-
-                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
-                                       &pos);
-
-                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
-                           && dev->_data_buf_virt_addr_ch2 != NULL) {
-                               memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
-                                               frame_offset / 4), mybuf,
-                                               vfs_read_retval);
-                       }
-
-                       file_offset += vfs_read_retval;
-                       frame_offset += vfs_read_retval;
-
-                       if (vfs_read_retval < line_size) {
-                               pr_info("Done: exit %s() since no more bytes to read from Video file\n",
-                                       __func__);
-                               break;
-                       }
-               }
-
-               if (i > 0)
-                       dev->_frame_count_ch2++;
-
-               dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
-                       IN_PROGRESS : END_OF_FILE;
-
-               set_fs(old_fs);
-               filp_close(myfile, NULL);
-       }
-
-       return 0;
-}
-
-static void cx25821_vidups_handler_ch2(struct work_struct *work)
-{
-       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
-                       _irq_work_entry_ch2);
-
-       if (!dev) {
-               pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
-                      __func__);
-               return;
-       }
-
-       cx25821_get_frame_ch2(dev, dev->channels[dev->
-                       _channel2_upstream_select].sram_channels);
-}
-
-int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
-{
-       struct file *myfile;
-       int i = 0, j = 0;
-       int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
-               Y411_LINE_SZ : Y422_LINE_SZ;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t pos;
-       loff_t offset = (unsigned long)0;
-       mm_segment_t old_fs;
-
-       myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
-
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_filename_ch2, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!  Returning\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-
-               for (j = 0; j < NUM_FRAMES; j++) {
-                       for (i = 0; i < dev->_lines_count_ch2; i++) {
-                               pos = offset;
-
-                               vfs_read_retval = vfs_read(myfile, mybuf,
-                                               line_size, &pos);
-
-                               if (vfs_read_retval > 0 &&
-                                   vfs_read_retval == line_size &&
-                                   dev->_data_buf_virt_addr_ch2 != NULL) {
-                                       memcpy((void *)(dev->
-                                                       _data_buf_virt_addr_ch2
-                                                       + offset / 4), mybuf,
-                                                       vfs_read_retval);
-                               }
-
-                               offset += vfs_read_retval;
-
-                               if (vfs_read_retval < line_size) {
-                                       pr_info("Done: exit %s() since no more bytes to read from Video file\n",
-                                               __func__);
-                                       break;
-                               }
-                       }
-
-                       if (i > 0)
-                               dev->_frame_count_ch2++;
-
-                       if (vfs_read_retval < line_size)
-                               break;
-               }
-
-               dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
-                       IN_PROGRESS : END_OF_FILE;
-
-               set_fs(old_fs);
-               myfile->f_pos = 0;
-               filp_close(myfile, NULL);
-       }
-
-       return 0;
-}
-
-static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
-                                              struct sram_channel *sram_ch,
-                                              int bpl)
-{
-       int ret = 0;
-       dma_addr_t dma_addr;
-       dma_addr_t data_dma_addr;
-
-       if (dev->_dma_virt_addr_ch2 != NULL) {
-               pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
-                                   dev->_dma_virt_addr_ch2,
-                                   dev->_dma_phys_addr_ch2);
-       }
-
-       dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
-                       dev->upstream_riscbuf_size_ch2, &dma_addr);
-       dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
-       dev->_dma_phys_start_addr_ch2 = dma_addr;
-       dev->_dma_phys_addr_ch2 = dma_addr;
-       dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
-
-       if (!dev->_dma_virt_addr_ch2) {
-               pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
-               return -ENOMEM;
-       }
-
-       /* Iniitize at this address until n bytes to 0 */
-       memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2);
-
-       if (dev->_data_buf_virt_addr_ch2 != NULL) {
-               pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2,
-                                   dev->_data_buf_virt_addr_ch2,
-                                   dev->_data_buf_phys_addr_ch2);
-       }
-       /* For Video Data buffer allocation */
-       dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
-                       dev->upstream_databuf_size_ch2, &data_dma_addr);
-       dev->_data_buf_phys_addr_ch2 = data_dma_addr;
-       dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
-
-       if (!dev->_data_buf_virt_addr_ch2) {
-               pr_err("FAILED to allocate memory for data buffer! Returning\n");
-               return -ENOMEM;
-       }
-
-       /* Initialize at this address until n bytes to 0 */
-       memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2);
-
-       ret = cx25821_openfile_ch2(dev, sram_ch);
-       if (ret < 0)
-               return ret;
-
-       /* Creating RISC programs */
-       ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
-                                               dev->_lines_count_ch2);
-       if (ret < 0) {
-               pr_info("Failed creating Video Upstream Risc programs!\n");
-               goto error;
-       }
-
-       return 0;
-
-error:
-       return ret;
-}
-
-int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
-                                  u32 status)
-{
-       u32 int_msk_tmp;
-       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
-       int singlefield_lines = NTSC_FIELD_HEIGHT;
-       int line_size_in_bytes = Y422_LINE_SZ;
-       int odd_risc_prog_size = 0;
-       dma_addr_t risc_phys_jump_addr;
-       __le32 *rp;
-
-       if (status & FLD_VID_SRC_RISC1) {
-               /* We should only process one program per call */
-               u32 prog_cnt = cx_read(channel->gpcnt);
-
-               /*
-                *  Since we've identified our IRQ, clear our bits from the
-                *  interrupt mask and interrupt status registers
-                */
-               int_msk_tmp = cx_read(channel->int_msk);
-               cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
-               cx_write(channel->int_stat, _intr_msk);
-
-               spin_lock(&dev->slock);
-
-               dev->_frame_index_ch2 = prog_cnt;
-
-               queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);
-
-               if (dev->_is_first_frame_ch2) {
-                       dev->_is_first_frame_ch2 = 0;
-
-                       if (dev->_isNTSC_ch2) {
-                               singlefield_lines += 1;
-                               odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
-                       } else {
-                               singlefield_lines = PAL_FIELD_HEIGHT;
-                               odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
-                       }
-
-                       if (dev->_dma_virt_start_addr_ch2 != NULL) {
-                               if (dev->_pixel_format_ch2 == PIXEL_FRMT_411)
-                                       line_size_in_bytes = Y411_LINE_SZ;
-                               else
-                                       line_size_in_bytes = Y422_LINE_SZ;
-                               risc_phys_jump_addr =
-                                       dev->_dma_phys_start_addr_ch2 +
-                                       odd_risc_prog_size;
-
-                               rp = cx25821_update_riscprogram_ch2(dev,
-                                               dev->_dma_virt_start_addr_ch2,
-                                               TOP_OFFSET, line_size_in_bytes,
-                                               0x0, singlefield_lines,
-                                               FIFO_DISABLE, ODD_FIELD);
-
-                              /* Jump to Even Risc program of 1st Frame */
-                               *(rp++) = cpu_to_le32(RISC_JUMP);
-                               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
-                               *(rp++) = cpu_to_le32(0);
-                       }
-               }
-
-               spin_unlock(&dev->slock);
-       }
-
-       if (dev->_file_status_ch2 == END_OF_FILE) {
-               pr_info("EOF Channel 2 Framecount = %d\n",
-                       dev->_frame_count_ch2);
-               return -1;
-       }
-       /* ElSE, set the interrupt mask register, re-enable irq. */
-       int_msk_tmp = cx_read(channel->int_msk);
-       cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
-
-       return 0;
-}
-
-static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
-{
-       struct cx25821_dev *dev = dev_id;
-       u32 vid_status;
-       int handled = 0;
-       int channel_num = 0;
-       struct sram_channel *sram_ch;
-
-       if (!dev)
-               return -1;
-
-       channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;
-       sram_ch = dev->channels[channel_num].sram_channels;
-
-       vid_status = cx_read(sram_ch->int_stat);
-
-       /* Only deal with our interrupt */
-       if (vid_status)
-               handled = cx25821_video_upstream_irq_ch2(dev, channel_num,
-                               vid_status);
-
-       if (handled < 0)
-               cx25821_stop_upstream_video_ch2(dev);
-       else
-               handled += handled;
-
-       return IRQ_RETVAL(handled);
-}
-
-static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
-                                       struct sram_channel *ch, int pix_format)
-{
-       int width = WIDTH_D1;
-       int height = dev->_lines_count_ch2;
-       int num_lines, odd_num_lines;
-       u32 value;
-       int vip_mode = PIXEL_ENGINE_VIP1;
-
-       value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
-       value &= 0xFFFFFFEF;
-       value |= dev->_isNTSC_ch2 ? 0 : 0x10;
-       cx_write(ch->vid_fmt_ctl, value);
-
-       /*
-        *  set number of active pixels in each line. Default is 720
-        * pixels in both NTSC and PAL format
-        */
-       cx_write(ch->vid_active_ctl1, width);
-
-       num_lines = (height / 2) & 0x3FF;
-       odd_num_lines = num_lines;
-
-       if (dev->_isNTSC_ch2)
-               odd_num_lines += 1;
-
-       value = (num_lines << 16) | odd_num_lines;
-
-       /* set number of active lines in field 0 (top) and field 1 (bottom) */
-       cx_write(ch->vid_active_ctl2, value);
-
-       cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
-}
-
-int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
-                                        struct sram_channel *sram_ch)
-{
-       u32 tmp = 0;
-       int err = 0;
-
-       /*
-        *  656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface
-        * for channel A-C
-        */
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
-
-       /*
-        *  Set the physical start address of the RISC program in the initial
-        *  program counter(IPC) member of the cmds.
-        */
-       cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);
-       cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
-
-       /* reset counter */
-       cx_write(sram_ch->gpcnt_ctl, 3);
-
-       /* Clear our bits from the interrupt status register. */
-       cx_write(sram_ch->int_stat, _intr_msk);
-
-       /* Set the interrupt mask register, enable irq. */
-       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
-       tmp = cx_read(sram_ch->int_msk);
-       cx_write(sram_ch->int_msk, tmp |= _intr_msk);
-
-       err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
-                       IRQF_SHARED, dev->name, dev);
-       if (err < 0) {
-               pr_err("%s: can't get upstream IRQ %d\n",
-                      dev->name, dev->pci->irq);
-               goto fail_irq;
-       }
-       /* Start the DMA  engine */
-       tmp = cx_read(sram_ch->dma_ctl);
-       cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
-
-       dev->_is_running_ch2 = 1;
-       dev->_is_first_frame_ch2 = 1;
-
-       return 0;
-
-fail_irq:
-       cx25821_dev_unregister(dev);
-       return err;
-}
-
-int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
-                                int pixel_format)
-{
-       struct sram_channel *sram_ch;
-       u32 tmp;
-       int retval = 0;
-       int err = 0;
-       int data_frame_size = 0;
-       int risc_buffer_size = 0;
-       int str_length = 0;
-
-       if (dev->_is_running_ch2) {
-               pr_info("Video Channel is still running so return!\n");
-               return 0;
-       }
-
-       dev->_channel2_upstream_select = channel_select;
-       sram_ch = dev->channels[channel_select].sram_channels;
-
-       INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);
-       dev->_irq_queues_ch2 =
-           create_singlethread_workqueue("cx25821_workqueue2");
-
-       if (!dev->_irq_queues_ch2) {
-               pr_err("create_singlethread_workqueue() for Video FAILED!\n");
-               return -ENOMEM;
-       }
-       /*
-        * 656/VIP SRC Upstream Channel I & J and 7 -
-        * Host Bus Interface for channel A-C
-        */
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
-
-       dev->_is_running_ch2 = 0;
-       dev->_frame_count_ch2 = 0;
-       dev->_file_status_ch2 = RESET_STATUS;
-       dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
-       dev->_pixel_format_ch2 = pixel_format;
-       dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ?
-               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
-       data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
-       risc_buffer_size = dev->_isNTSC_ch2 ?
-               NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
-
-       if (dev->input_filename_ch2) {
-               str_length = strlen(dev->input_filename_ch2);
-               dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
-                                            str_length + 1, GFP_KERNEL);
-
-               if (!dev->_filename_ch2)
-                       goto error;
-       } else {
-               str_length = strlen(dev->_defaultname_ch2);
-               dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
-                                            str_length + 1, GFP_KERNEL);
-
-               if (!dev->_filename_ch2)
-                       goto error;
-       }
-
-       /* Default if filename is empty string */
-       if (strcmp(dev->input_filename_ch2, "") == 0) {
-               if (dev->_isNTSC_ch2) {
-                       dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
-                               PIXEL_FRMT_411) ? "/root/vid411.yuv" :
-                               "/root/vidtest.yuv";
-               } else {
-                       dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
-                               PIXEL_FRMT_411) ? "/root/pal411.yuv" :
-                               "/root/pal422.yuv";
-               }
-       }
-
-       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
-                                               dev->_line_size_ch2, 0);
-
-       /* setup fifo + format */
-       cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);
-
-       dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;
-       dev->upstream_databuf_size_ch2 = data_frame_size * 2;
-
-       /* Allocating buffers and prepare RISC program */
-       retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
-                                               dev->_line_size_ch2);
-       if (retval < 0) {
-               pr_err("%s: Failed to set up Video upstream buffers!\n",
-                      dev->name);
-               goto error;
-       }
-
-       cx25821_start_video_dma_upstream_ch2(dev, sram_ch);
-
-       return 0;
-
-error:
-       cx25821_dev_unregister(dev);
-
-       return err;
-}
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.h
deleted file mode 100644 (file)
index d42dab5..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
-#include <linux/workqueue.h>
-
-#define OPEN_FILE_1           0
-#define NUM_PROGS             8
-#define NUM_FRAMES            2
-#define ODD_FIELD             0
-#define EVEN_FIELD            1
-#define TOP_OFFSET            0
-#define FIFO_DISABLE          0
-#define FIFO_ENABLE           1
-#define TEST_FRAMES           5
-#define END_OF_FILE           0
-#define IN_PROGRESS           1
-#define RESET_STATUS          -1
-#define NUM_NO_OPS            5
-
-/* PAL and NTSC line sizes and number of lines. */
-#define WIDTH_D1              720
-#define NTSC_LINES_PER_FRAME  480
-#define PAL_LINES_PER_FRAME   576
-#define PAL_LINE_SZ           1440
-#define Y422_LINE_SZ          1440
-#define Y411_LINE_SZ          1080
-#define NTSC_FIELD_HEIGHT     240
-#define NTSC_ODD_FLD_LINES    241
-#define PAL_FIELD_HEIGHT      288
-
-#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
-#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
-#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
-#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
-
-#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
-#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
-
-#define RISC_WRITECR_INSTRUCTION_SIZE   16
-#define RISC_SYNC_INSTRUCTION_SIZE      4
-#define JUMP_INSTRUCTION_SIZE           12
-#define MAXSIZE_NO_OPS                  36
-#define DWORD_SIZE                      4
-
-#define USE_RISC_NOOP_VIDEO   1
-
-#ifdef USE_RISC_NOOP_VIDEO
-#define PAL_US_VID_PROG_SIZE                                           \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +   \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define PAL_RISC_BUF_SIZE         (2 * PAL_US_VID_PROG_SIZE)
-
-#define PAL_VID_PROG_SIZE                                              \
-       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
-        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
-        JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
-
-#define ODD_FLD_PAL_PROG_SIZE                                          \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define NTSC_US_VID_PROG_SIZE                                          \
-       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
-        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +        \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define NTSC_RISC_BUF_SIZE                                             \
-       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
-
-#define FRAME1_VID_PROG_SIZE                                           \
-       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *                     \
-        3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +              \
-        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +        \
-        2 * NUM_NO_OPS * DWORD_SIZE)
-
-#define ODD_FLD_NTSC_PROG_SIZE                                         \
-       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
-        NUM_NO_OPS * DWORD_SIZE)
-#endif
-
-#ifndef USE_RISC_NOOP_VIDEO
-#define PAL_US_VID_PROG_SIZE                                           \
-       ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE +                      \
-        RISC_WRITECR_INSTRUCTION_SIZE)
-
-#define PAL_RISC_BUF_SIZE                                              \
-       (2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE))
-
-#define PAL_VID_PROG_SIZE                                              \
-       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
-        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
-        JUMP_INSTRUCTION_SIZE)
-
-#define ODD_FLD_PAL_PROG_SIZE                                          \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
-
-#define ODD_FLD_NTSC_PROG_SIZE                                         \
-       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
-
-#define NTSC_US_VID_PROG_SIZE                                          \
-       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
-        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
-
-#define NTSC_RISC_BUF_SIZE                                             \
-       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
-
-#define FRAME1_VID_PROG_SIZE                                           \
-       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *                     \
-        3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +              \
-        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c
deleted file mode 100644 (file)
index 52c13e0..0000000
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "cx25821-video.h"
-#include "cx25821-video-upstream.h"
-
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/syscalls.h>
-#include <linux/file.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
-MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
-MODULE_LICENSE("GPL");
-
-static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
-                       FLD_VID_SRC_OPC_ERR;
-
-int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
-                                       struct sram_channel *ch,
-                                       unsigned int bpl, u32 risc)
-{
-       unsigned int i, lines;
-       u32 cdt;
-
-       if (ch->cmds_start == 0) {
-               cx_write(ch->ptr1_reg, 0);
-               cx_write(ch->ptr2_reg, 0);
-               cx_write(ch->cnt2_reg, 0);
-               cx_write(ch->cnt1_reg, 0);
-               return 0;
-       }
-
-       bpl = (bpl + 7) & ~7;   /* alignment */
-       cdt = ch->cdt;
-       lines = ch->fifo_size / bpl;
-
-       if (lines > 4)
-               lines = 4;
-
-       BUG_ON(lines < 2);
-
-       /* write CDT */
-       for (i = 0; i < lines; i++) {
-               cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
-               cx_write(cdt + 16 * i + 4, 0);
-               cx_write(cdt + 16 * i + 8, 0);
-               cx_write(cdt + 16 * i + 12, 0);
-       }
-
-       /* write CMDS */
-       cx_write(ch->cmds_start + 0, risc);
-
-       cx_write(ch->cmds_start + 4, 0);
-       cx_write(ch->cmds_start + 8, cdt);
-       cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
-       cx_write(ch->cmds_start + 16, ch->ctrl_start);
-
-       cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
-
-       for (i = 24; i < 80; i += 4)
-               cx_write(ch->cmds_start + i, 0);
-
-       /* fill registers */
-       cx_write(ch->ptr1_reg, ch->fifo_start);
-       cx_write(ch->ptr2_reg, cdt);
-       cx_write(ch->cnt2_reg, (lines * 16) >> 3);
-       cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
-
-       return 0;
-}
-
-static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
-                                         __le32 *rp, unsigned int offset,
-                                         unsigned int bpl, u32 sync_line,
-                                         unsigned int lines, int fifo_enable,
-                                         int field_type)
-{
-       unsigned int line, i;
-       int dist_betwn_starts = bpl * 2;
-
-       *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       if (USE_RISC_NOOP_VIDEO) {
-               for (i = 0; i < NUM_NO_OPS; i++)
-                       *(rp++) = cpu_to_le32(RISC_NOOP);
-       }
-
-       /* scan lines */
-       for (line = 0; line < lines; line++) {
-               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
-               *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
-               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-
-               if ((lines <= NTSC_FIELD_HEIGHT)
-                   || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
-                       offset += dist_betwn_starts;
-               }
-       }
-
-       return rp;
-}
-
-static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
-                                          dma_addr_t databuf_phys_addr,
-                                          unsigned int offset, u32 sync_line,
-                                          unsigned int bpl, unsigned int lines,
-                                          int fifo_enable, int field_type)
-{
-       unsigned int line, i;
-       struct sram_channel *sram_ch =
-               dev->channels[dev->_channel_upstream_select].sram_channels;
-       int dist_betwn_starts = bpl * 2;
-
-       /* sync instruction */
-       if (sync_line != NO_SYNC_LINE)
-               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       if (USE_RISC_NOOP_VIDEO) {
-               for (i = 0; i < NUM_NO_OPS; i++)
-                       *(rp++) = cpu_to_le32(RISC_NOOP);
-       }
-
-       /* scan lines */
-       for (line = 0; line < lines; line++) {
-               *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
-               *(rp++) = cpu_to_le32(databuf_phys_addr + offset);
-               *(rp++) = cpu_to_le32(0);       /* bits 63-32 */
-
-               if ((lines <= NTSC_FIELD_HEIGHT)
-                   || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC))
-                       /* to skip the other field line */
-                       offset += dist_betwn_starts;
-
-               /* check if we need to enable the FIFO after the first 4 lines
-                * For the upstream video channel, the risc engine will enable
-                * the FIFO. */
-               if (fifo_enable && line == 3) {
-                       *(rp++) = RISC_WRITECR;
-                       *(rp++) = sram_ch->dma_ctl;
-                       *(rp++) = FLD_VID_FIFO_EN;
-                       *(rp++) = 0x00000001;
-               }
-       }
-
-       return rp;
-}
-
-int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
-                                struct pci_dev *pci,
-                                unsigned int top_offset,
-                                unsigned int bpl, unsigned int lines)
-{
-       __le32 *rp;
-       int fifo_enable = 0;
-       /* get line count for single field */
-       int singlefield_lines = lines >> 1;
-       int odd_num_lines = singlefield_lines;
-       int frame = 0;
-       int frame_size = 0;
-       int databuf_offset = 0;
-       int risc_program_size = 0;
-       int risc_flag = RISC_CNT_RESET;
-       unsigned int bottom_offset = bpl;
-       dma_addr_t risc_phys_jump_addr;
-
-       if (dev->_isNTSC) {
-               odd_num_lines = singlefield_lines + 1;
-               risc_program_size = FRAME1_VID_PROG_SIZE;
-               frame_size = (bpl == Y411_LINE_SZ) ?
-                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
-       } else {
-               risc_program_size = PAL_VID_PROG_SIZE;
-               frame_size = (bpl == Y411_LINE_SZ) ?
-                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
-       }
-
-       /* Virtual address of Risc buffer program */
-       rp = dev->_dma_virt_addr;
-
-       for (frame = 0; frame < NUM_FRAMES; frame++) {
-               databuf_offset = frame_size * frame;
-
-               if (UNSET != top_offset) {
-                       fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
-                       rp = cx25821_risc_field_upstream(dev, rp,
-                                       dev->_data_buf_phys_addr +
-                                       databuf_offset, top_offset, 0, bpl,
-                                       odd_num_lines, fifo_enable, ODD_FIELD);
-               }
-
-               fifo_enable = FIFO_DISABLE;
-
-               /* Even Field */
-               rp = cx25821_risc_field_upstream(dev, rp,
-                                                dev->_data_buf_phys_addr +
-                                                databuf_offset, bottom_offset,
-                                                0x200, bpl, singlefield_lines,
-                                                fifo_enable, EVEN_FIELD);
-
-               if (frame == 0) {
-                       risc_flag = RISC_CNT_RESET;
-                       risc_phys_jump_addr = dev->_dma_phys_start_addr +
-                               risc_program_size;
-               } else {
-                       risc_phys_jump_addr = dev->_dma_phys_start_addr;
-                       risc_flag = RISC_CNT_INC;
-               }
-
-               /* Loop to 2ndFrameRISC or to Start of Risc
-                * program & generate IRQ
-                */
-               *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
-               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
-               *(rp++) = cpu_to_le32(0);
-       }
-
-       return 0;
-}
-
-void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
-{
-       struct sram_channel *sram_ch =
-               dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
-       u32 tmp = 0;
-
-       if (!dev->_is_running) {
-               pr_info("No video file is currently running so return!\n");
-               return;
-       }
-       /* Disable RISC interrupts */
-       tmp = cx_read(sram_ch->int_msk);
-       cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
-
-       /* Turn OFF risc and fifo enable */
-       tmp = cx_read(sram_ch->dma_ctl);
-       cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
-
-       /* Clear data buffer memory */
-       if (dev->_data_buf_virt_addr)
-               memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
-
-       dev->_is_running = 0;
-       dev->_is_first_frame = 0;
-       dev->_frame_count = 0;
-       dev->_file_status = END_OF_FILE;
-
-       kfree(dev->_irq_queues);
-       dev->_irq_queues = NULL;
-
-       kfree(dev->_filename);
-
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
-}
-
-void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
-{
-       if (dev->_is_running)
-               cx25821_stop_upstream_video_ch1(dev);
-
-       if (dev->_dma_virt_addr) {
-               pci_free_consistent(dev->pci, dev->_risc_size,
-                                   dev->_dma_virt_addr, dev->_dma_phys_addr);
-               dev->_dma_virt_addr = NULL;
-       }
-
-       if (dev->_data_buf_virt_addr) {
-               pci_free_consistent(dev->pci, dev->_data_buf_size,
-                                   dev->_data_buf_virt_addr,
-                                   dev->_data_buf_phys_addr);
-               dev->_data_buf_virt_addr = NULL;
-       }
-}
-
-int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
-{
-       struct file *myfile;
-       int frame_index_temp = dev->_frame_index;
-       int i = 0;
-       int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
-               Y411_LINE_SZ : Y422_LINE_SZ;
-       int frame_size = 0;
-       int frame_offset = 0;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t file_offset;
-       loff_t pos;
-       mm_segment_t old_fs;
-
-       if (dev->_file_status == END_OF_FILE)
-               return 0;
-
-       if (dev->_isNTSC)
-               frame_size = (line_size == Y411_LINE_SZ) ?
-                       FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
-       else
-               frame_size = (line_size == Y411_LINE_SZ) ?
-                       FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
-
-       frame_offset = (frame_index_temp > 0) ? frame_size : 0;
-       file_offset = dev->_frame_count * frame_size;
-
-       myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
-
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_filename, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-
-               for (i = 0; i < dev->_lines_count; i++) {
-                       pos = file_offset;
-
-                       vfs_read_retval = vfs_read(myfile, mybuf, line_size,
-                                       &pos);
-
-                       if (vfs_read_retval > 0 && vfs_read_retval == line_size
-                           && dev->_data_buf_virt_addr != NULL) {
-                               memcpy((void *)(dev->_data_buf_virt_addr +
-                                               frame_offset / 4), mybuf,
-                                      vfs_read_retval);
-                       }
-
-                       file_offset += vfs_read_retval;
-                       frame_offset += vfs_read_retval;
-
-                       if (vfs_read_retval < line_size) {
-                               pr_info("Done: exit %s() since no more bytes to read from Video file\n",
-                                       __func__);
-                               break;
-                       }
-               }
-
-               if (i > 0)
-                       dev->_frame_count++;
-
-               dev->_file_status = (vfs_read_retval == line_size) ?
-                       IN_PROGRESS : END_OF_FILE;
-
-               set_fs(old_fs);
-               filp_close(myfile, NULL);
-       }
-
-       return 0;
-}
-
-static void cx25821_vidups_handler(struct work_struct *work)
-{
-       struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
-                       _irq_work_entry);
-
-       if (!dev) {
-               pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
-                      __func__);
-               return;
-       }
-
-       cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select].
-                       sram_channels);
-}
-
-int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
-{
-       struct file *myfile;
-       int i = 0, j = 0;
-       int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
-               Y411_LINE_SZ : Y422_LINE_SZ;
-       ssize_t vfs_read_retval = 0;
-       char mybuf[line_size];
-       loff_t pos;
-       loff_t offset = (unsigned long)0;
-       mm_segment_t old_fs;
-
-       myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
-
-       if (IS_ERR(myfile)) {
-               const int open_errno = -PTR_ERR(myfile);
-               pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
-                      __func__, dev->_filename, open_errno);
-               return PTR_ERR(myfile);
-       } else {
-               if (!(myfile->f_op)) {
-                       pr_err("%s(): File has no file operations registered!\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               if (!myfile->f_op->read) {
-                       pr_err("%s(): File has no READ operations registered!  Returning\n",
-                              __func__);
-                       filp_close(myfile, NULL);
-                       return -EIO;
-               }
-
-               pos = myfile->f_pos;
-               old_fs = get_fs();
-               set_fs(KERNEL_DS);
-
-               for (j = 0; j < NUM_FRAMES; j++) {
-                       for (i = 0; i < dev->_lines_count; i++) {
-                               pos = offset;
-
-                               vfs_read_retval = vfs_read(myfile, mybuf,
-                                               line_size, &pos);
-
-                               if (vfs_read_retval > 0
-                                   && vfs_read_retval == line_size
-                                   && dev->_data_buf_virt_addr != NULL) {
-                                       memcpy((void *)(dev->
-                                                       _data_buf_virt_addr +
-                                                       offset / 4), mybuf,
-                                              vfs_read_retval);
-                               }
-
-                               offset += vfs_read_retval;
-
-                               if (vfs_read_retval < line_size) {
-                                       pr_info("Done: exit %s() since no more bytes to read from Video file\n",
-                                               __func__);
-                                       break;
-                               }
-                       }
-
-                       if (i > 0)
-                               dev->_frame_count++;
-
-                       if (vfs_read_retval < line_size)
-                               break;
-               }
-
-               dev->_file_status = (vfs_read_retval == line_size) ?
-                       IN_PROGRESS : END_OF_FILE;
-
-               set_fs(old_fs);
-               myfile->f_pos = 0;
-               filp_close(myfile, NULL);
-       }
-
-       return 0;
-}
-
-int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
-                                   struct sram_channel *sram_ch, int bpl)
-{
-       int ret = 0;
-       dma_addr_t dma_addr;
-       dma_addr_t data_dma_addr;
-
-       if (dev->_dma_virt_addr != NULL)
-               pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
-                               dev->_dma_virt_addr, dev->_dma_phys_addr);
-
-       dev->_dma_virt_addr = pci_alloc_consistent(dev->pci,
-                       dev->upstream_riscbuf_size, &dma_addr);
-       dev->_dma_virt_start_addr = dev->_dma_virt_addr;
-       dev->_dma_phys_start_addr = dma_addr;
-       dev->_dma_phys_addr = dma_addr;
-       dev->_risc_size = dev->upstream_riscbuf_size;
-
-       if (!dev->_dma_virt_addr) {
-               pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
-               return -ENOMEM;
-       }
-
-       /* Clear memory at address */
-       memset(dev->_dma_virt_addr, 0, dev->_risc_size);
-
-       if (dev->_data_buf_virt_addr != NULL)
-               pci_free_consistent(dev->pci, dev->upstream_databuf_size,
-                               dev->_data_buf_virt_addr,
-                               dev->_data_buf_phys_addr);
-       /* For Video Data buffer allocation */
-       dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci,
-                       dev->upstream_databuf_size, &data_dma_addr);
-       dev->_data_buf_phys_addr = data_dma_addr;
-       dev->_data_buf_size = dev->upstream_databuf_size;
-
-       if (!dev->_data_buf_virt_addr) {
-               pr_err("FAILED to allocate memory for data buffer! Returning\n");
-               return -ENOMEM;
-       }
-
-       /* Clear memory at address */
-       memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
-
-       ret = cx25821_openfile(dev, sram_ch);
-       if (ret < 0)
-               return ret;
-
-       /* Create RISC programs */
-       ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
-                       dev->_lines_count);
-       if (ret < 0) {
-               pr_info("Failed creating Video Upstream Risc programs!\n");
-               goto error;
-       }
-
-       return 0;
-
-error:
-       return ret;
-}
-
-int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
-                              u32 status)
-{
-       u32 int_msk_tmp;
-       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
-       int singlefield_lines = NTSC_FIELD_HEIGHT;
-       int line_size_in_bytes = Y422_LINE_SZ;
-       int odd_risc_prog_size = 0;
-       dma_addr_t risc_phys_jump_addr;
-       __le32 *rp;
-
-       if (status & FLD_VID_SRC_RISC1) {
-               /* We should only process one program per call */
-               u32 prog_cnt = cx_read(channel->gpcnt);
-
-               /* Since we've identified our IRQ, clear our bits from the
-                * interrupt mask and interrupt status registers */
-               int_msk_tmp = cx_read(channel->int_msk);
-               cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
-               cx_write(channel->int_stat, _intr_msk);
-
-               spin_lock(&dev->slock);
-
-               dev->_frame_index = prog_cnt;
-
-               queue_work(dev->_irq_queues, &dev->_irq_work_entry);
-
-               if (dev->_is_first_frame) {
-                       dev->_is_first_frame = 0;
-
-                       if (dev->_isNTSC) {
-                               singlefield_lines += 1;
-                               odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
-                       } else {
-                               singlefield_lines = PAL_FIELD_HEIGHT;
-                               odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
-                       }
-
-                       if (dev->_dma_virt_start_addr != NULL) {
-                               line_size_in_bytes =
-                                   (dev->_pixel_format ==
-                                    PIXEL_FRMT_411) ? Y411_LINE_SZ :
-                                   Y422_LINE_SZ;
-                               risc_phys_jump_addr =
-                                   dev->_dma_phys_start_addr +
-                                   odd_risc_prog_size;
-
-                               rp = cx25821_update_riscprogram(dev,
-                                       dev->_dma_virt_start_addr, TOP_OFFSET,
-                                       line_size_in_bytes, 0x0,
-                                       singlefield_lines, FIFO_DISABLE,
-                                       ODD_FIELD);
-
-                               /* Jump to Even Risc program of 1st Frame */
-                               *(rp++) = cpu_to_le32(RISC_JUMP);
-                               *(rp++) = cpu_to_le32(risc_phys_jump_addr);
-                               *(rp++) = cpu_to_le32(0);
-                       }
-               }
-
-               spin_unlock(&dev->slock);
-       } else {
-               if (status & FLD_VID_SRC_UF)
-                       pr_err("%s(): Video Received Underflow Error Interrupt!\n",
-                              __func__);
-
-               if (status & FLD_VID_SRC_SYNC)
-                       pr_err("%s(): Video Received Sync Error Interrupt!\n",
-                              __func__);
-
-               if (status & FLD_VID_SRC_OPC_ERR)
-                       pr_err("%s(): Video Received OpCode Error Interrupt!\n",
-                              __func__);
-       }
-
-       if (dev->_file_status == END_OF_FILE) {
-               pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
-               return -1;
-       }
-       /* ElSE, set the interrupt mask register, re-enable irq. */
-       int_msk_tmp = cx_read(channel->int_msk);
-       cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
-
-       return 0;
-}
-
-static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
-{
-       struct cx25821_dev *dev = dev_id;
-       u32 vid_status;
-       int handled = 0;
-       int channel_num = 0;
-       struct sram_channel *sram_ch;
-
-       if (!dev)
-               return -1;
-
-       channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
-
-       sram_ch = dev->channels[channel_num].sram_channels;
-
-       vid_status = cx_read(sram_ch->int_stat);
-
-       /* Only deal with our interrupt */
-       if (vid_status)
-               handled = cx25821_video_upstream_irq(dev, channel_num,
-                               vid_status);
-
-       if (handled < 0)
-               cx25821_stop_upstream_video_ch1(dev);
-       else
-               handled += handled;
-
-       return IRQ_RETVAL(handled);
-}
-
-void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
-                            int pix_format)
-{
-       int width = WIDTH_D1;
-       int height = dev->_lines_count;
-       int num_lines, odd_num_lines;
-       u32 value;
-       int vip_mode = OUTPUT_FRMT_656;
-
-       value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
-       value &= 0xFFFFFFEF;
-       value |= dev->_isNTSC ? 0 : 0x10;
-       cx_write(ch->vid_fmt_ctl, value);
-
-       /* set number of active pixels in each line.
-        * Default is 720 pixels in both NTSC and PAL format */
-       cx_write(ch->vid_active_ctl1, width);
-
-       num_lines = (height / 2) & 0x3FF;
-       odd_num_lines = num_lines;
-
-       if (dev->_isNTSC)
-               odd_num_lines += 1;
-
-       value = (num_lines << 16) | odd_num_lines;
-
-       /* set number of active lines in field 0 (top) and field 1 (bottom) */
-       cx_write(ch->vid_active_ctl2, value);
-
-       cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
-}
-
-int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
-                                    struct sram_channel *sram_ch)
-{
-       u32 tmp = 0;
-       int err = 0;
-
-       /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
-        * channel A-C
-        */
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
-
-       /* Set the physical start address of the RISC program in the initial
-        * program counter(IPC) member of the cmds.
-        */
-       cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
-       /* Risc IPC High 64 bits 63-32 */
-       cx_write(sram_ch->cmds_start + 4, 0);
-
-       /* reset counter */
-       cx_write(sram_ch->gpcnt_ctl, 3);
-
-       /* Clear our bits from the interrupt status register. */
-       cx_write(sram_ch->int_stat, _intr_msk);
-
-       /* Set the interrupt mask register, enable irq. */
-       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
-       tmp = cx_read(sram_ch->int_msk);
-       cx_write(sram_ch->int_msk, tmp |= _intr_msk);
-
-       err = request_irq(dev->pci->irq, cx25821_upstream_irq,
-                       IRQF_SHARED, dev->name, dev);
-       if (err < 0) {
-               pr_err("%s: can't get upstream IRQ %d\n",
-                      dev->name, dev->pci->irq);
-               goto fail_irq;
-       }
-
-       /* Start the DMA  engine */
-       tmp = cx_read(sram_ch->dma_ctl);
-       cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
-
-       dev->_is_running = 1;
-       dev->_is_first_frame = 1;
-
-       return 0;
-
-fail_irq:
-       cx25821_dev_unregister(dev);
-       return err;
-}
-
-int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
-                                int pixel_format)
-{
-       struct sram_channel *sram_ch;
-       u32 tmp;
-       int retval = 0;
-       int err = 0;
-       int data_frame_size = 0;
-       int risc_buffer_size = 0;
-       int str_length = 0;
-
-       if (dev->_is_running) {
-               pr_info("Video Channel is still running so return!\n");
-               return 0;
-       }
-
-       dev->_channel_upstream_select = channel_select;
-       sram_ch = dev->channels[channel_select].sram_channels;
-
-       INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
-       dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
-
-       if (!dev->_irq_queues) {
-               pr_err("create_singlethread_workqueue() for Video FAILED!\n");
-               return -ENOMEM;
-       }
-       /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
-        * channel A-C
-        */
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
-
-       dev->_is_running = 0;
-       dev->_frame_count = 0;
-       dev->_file_status = RESET_STATUS;
-       dev->_lines_count = dev->_isNTSC ? 480 : 576;
-       dev->_pixel_format = pixel_format;
-       dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
-               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
-       data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
-       risc_buffer_size = dev->_isNTSC ?
-               NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
-
-       if (dev->input_filename) {
-               str_length = strlen(dev->input_filename);
-               dev->_filename = kmemdup(dev->input_filename, str_length + 1,
-                                        GFP_KERNEL);
-
-               if (!dev->_filename)
-                       goto error;
-       } else {
-               str_length = strlen(dev->_defaultname);
-               dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
-                                        GFP_KERNEL);
-
-               if (!dev->_filename)
-                       goto error;
-       }
-
-       /* Default if filename is empty string */
-       if (strcmp(dev->input_filename, "") == 0) {
-               if (dev->_isNTSC) {
-                       dev->_filename =
-                               (dev->_pixel_format == PIXEL_FRMT_411) ?
-                               "/root/vid411.yuv" : "/root/vidtest.yuv";
-               } else {
-                       dev->_filename =
-                               (dev->_pixel_format == PIXEL_FRMT_411) ?
-                               "/root/pal411.yuv" : "/root/pal422.yuv";
-               }
-       }
-
-       dev->_is_running = 0;
-       dev->_frame_count = 0;
-       dev->_file_status = RESET_STATUS;
-       dev->_lines_count = dev->_isNTSC ? 480 : 576;
-       dev->_pixel_format = pixel_format;
-       dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
-               (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
-
-       retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
-                       dev->_line_size, 0);
-
-       /* setup fifo + format */
-       cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
-
-       dev->upstream_riscbuf_size = risc_buffer_size * 2;
-       dev->upstream_databuf_size = data_frame_size * 2;
-
-       /* Allocating buffers and prepare RISC program */
-       retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
-       if (retval < 0) {
-               pr_err("%s: Failed to set up Video upstream buffers!\n",
-                      dev->name);
-               goto error;
-       }
-
-       cx25821_start_video_dma_upstream(dev, sram_ch);
-
-       return 0;
-
-error:
-       cx25821_dev_unregister(dev);
-
-       return err;
-}
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.h b/drivers/media/video/cx25821/cx25821-video-upstream.h
deleted file mode 100644 (file)
index 268ec8a..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.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/mutex.h>
-#include <linux/workqueue.h>
-
-#define OUTPUT_FRMT_656       0
-#define OPEN_FILE_1           0
-#define NUM_PROGS             8
-#define NUM_FRAMES            2
-#define ODD_FIELD             0
-#define EVEN_FIELD            1
-#define TOP_OFFSET            0
-#define FIFO_DISABLE          0
-#define FIFO_ENABLE           1
-#define TEST_FRAMES           5
-#define END_OF_FILE           0
-#define IN_PROGRESS           1
-#define RESET_STATUS          -1
-#define NUM_NO_OPS            5
-
-/* PAL and NTSC line sizes and number of lines. */
-#define WIDTH_D1              720
-#define NTSC_LINES_PER_FRAME  480
-#define PAL_LINES_PER_FRAME   576
-#define PAL_LINE_SZ           1440
-#define Y422_LINE_SZ          1440
-#define Y411_LINE_SZ          1080
-#define NTSC_FIELD_HEIGHT     240
-#define NTSC_ODD_FLD_LINES    241
-#define PAL_FIELD_HEIGHT      288
-
-#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
-#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
-#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
-#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
-
-#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
-#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
-
-#define RISC_WRITECR_INSTRUCTION_SIZE   16
-#define RISC_SYNC_INSTRUCTION_SIZE      4
-#define JUMP_INSTRUCTION_SIZE           12
-#define MAXSIZE_NO_OPS                  36
-#define DWORD_SIZE                      4
-
-#define USE_RISC_NOOP_VIDEO   1
-
-#ifdef USE_RISC_NOOP_VIDEO
-#define PAL_US_VID_PROG_SIZE                                           \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +   \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)
-
-#define PAL_VID_PROG_SIZE                                              \
-       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
-        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
-        JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
-
-#define ODD_FLD_PAL_PROG_SIZE                                          \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define ODD_FLD_NTSC_PROG_SIZE                                         \
-       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +   \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define NTSC_US_VID_PROG_SIZE                                          \
-       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
-        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +        \
-        NUM_NO_OPS * DWORD_SIZE)
-
-#define NTSC_RISC_BUF_SIZE                                             \
-       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
-
-#define FRAME1_VID_PROG_SIZE                                           \
-       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +    \
-        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
-        JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
-
-#endif
-
-#ifndef USE_RISC_NOOP_VIDEO
-#define PAL_US_VID_PROG_SIZE                                           \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +   \
-        JUMP_INSTRUCTION_SIZE)
-
-#define PAL_RISC_BUF_SIZE              (2 * PAL_US_VID_PROG_SIZE)
-
-#define PAL_VID_PROG_SIZE                                              \
-       ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +                      \
-        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
-        JUMP_INSTRUCTION_SIZE)
-
-#define ODD_FLD_PAL_PROG_SIZE                                          \
-       (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +                            \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
-
-#define ODD_FLD_NTSC_PROG_SIZE                                         \
-       (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +                          \
-        RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
-
-#define NTSC_US_VID_PROG_SIZE                                          \
-       ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +                    \
-        RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
-
-#define NTSC_RISC_BUF_SIZE                                             \
-       (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
-
-#define FRAME1_VID_PROG_SIZE                                           \
-       ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +    \
-        2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
-        JUMP_INSTRUCTION_SIZE)
-
-#endif
diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c
deleted file mode 100644 (file)
index b38d437..0000000
+++ /dev/null
@@ -1,1990 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
- *  Parts adapted/taken from Eduardo Moscoso Rubino
- *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "cx25821-video.h"
-
-MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
-MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
-MODULE_LICENSE("GPL");
-
-static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-
-MODULE_PARM_DESC(video_nr, "video device numbers");
-MODULE_PARM_DESC(radio_nr, "radio device numbers");
-
-static unsigned int video_debug = VIDEO_DEBUG;
-module_param(video_debug, int, 0644);
-MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
-
-static unsigned int irq_debug;
-module_param(irq_debug, int, 0644);
-MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
-
-unsigned int vid_limit = 16;
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
-
-static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num);
-
-static const struct v4l2_file_operations video_fops;
-static const struct v4l2_ioctl_ops video_ioctl_ops;
-
-#define FORMAT_FLAGS_PACKED       0x01
-
-struct cx25821_fmt formats[] = {
-       {
-               .name = "8 bpp, gray",
-               .fourcc = V4L2_PIX_FMT_GREY,
-               .depth = 8,
-               .flags = FORMAT_FLAGS_PACKED,
-        }, {
-               .name = "4:1:1, packed, Y41P",
-               .fourcc = V4L2_PIX_FMT_Y41P,
-               .depth = 12,
-               .flags = FORMAT_FLAGS_PACKED,
-       }, {
-               .name = "4:2:2, packed, YUYV",
-               .fourcc = V4L2_PIX_FMT_YUYV,
-               .depth = 16,
-               .flags = FORMAT_FLAGS_PACKED,
-       }, {
-               .name = "4:2:2, packed, UYVY",
-               .fourcc = V4L2_PIX_FMT_UYVY,
-               .depth = 16,
-               .flags = FORMAT_FLAGS_PACKED,
-       }, {
-               .name = "4:2:0, YUV",
-               .fourcc = V4L2_PIX_FMT_YUV420,
-               .depth = 12,
-               .flags = FORMAT_FLAGS_PACKED,
-       },
-};
-
-int cx25821_get_format_size(void)
-{
-       return ARRAY_SIZE(formats);
-}
-
-struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P)
-               return formats + 1;
-
-       for (i = 0; i < ARRAY_SIZE(formats); i++)
-               if (formats[i].fourcc == fourcc)
-                       return formats + i;
-
-       pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc);
-       return NULL;
-}
-
-void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
-                         u32 count)
-{
-       struct cx25821_buffer *buf;
-       int bc;
-
-       for (bc = 0;; bc++) {
-               if (list_empty(&q->active)) {
-                       dprintk(1, "bc=%d (=0: active empty)\n", bc);
-                       break;
-               }
-
-               buf = list_entry(q->active.next, struct cx25821_buffer,
-                               vb.queue);
-
-               /* count comes from the hw and it is 16bit wide --
-                * this trick handles wrap-arounds correctly for
-                * up to 32767 buffers in flight... */
-               if ((s16) (count - buf->count) < 0)
-                       break;
-
-               do_gettimeofday(&buf->vb.ts);
-               buf->vb.state = VIDEOBUF_DONE;
-               list_del(&buf->vb.queue);
-               wake_up(&buf->vb.done);
-       }
-
-       if (list_empty(&q->active))
-               del_timer(&q->timeout);
-       else
-               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-       if (bc != 1)
-               pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc);
-}
-
-#ifdef TUNER_FLAG
-int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
-{
-       dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
-               __func__, (unsigned int)norm, v4l2_norm_to_name(norm));
-
-       dev->tvnorm = norm;
-
-       /* Tell the internal A/V decoder */
-       cx25821_call_all(dev, core, s_std, norm);
-
-       return 0;
-}
-#endif
-
-struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
-                                      struct pci_dev *pci,
-                                      struct video_device *template,
-                                      char *type)
-{
-       struct video_device *vfd;
-       dprintk(1, "%s()\n", __func__);
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-       *vfd = *template;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->release = video_device_release;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
-                cx25821_boards[dev->board].name);
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-/*
-static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
-{
-       int i;
-
-       if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       for (i = 0; i < CX25821_CTLS; i++)
-               if (cx25821_ctls[i].v.id == qctrl->id)
-                       break;
-       if (i == CX25821_CTLS) {
-               *qctrl = no_ctl;
-               return 0;
-       }
-       *qctrl = cx25821_ctls[i].v;
-       return 0;
-}
-*/
-
-/* resource management */
-int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
-                   unsigned int bit)
-{
-       dprintk(1, "%s()\n", __func__);
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       /* is it free? */
-       mutex_lock(&dev->lock);
-       if (dev->channels[fh->channel_id].resources & bit) {
-               /* no, someone else uses it */
-               mutex_unlock(&dev->lock);
-               return 0;
-       }
-       /* it's free, grab it */
-       fh->resources |= bit;
-       dev->channels[fh->channel_id].resources |= bit;
-       dprintk(1, "res: get %d\n", bit);
-       mutex_unlock(&dev->lock);
-       return 1;
-}
-
-int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit)
-{
-       return fh->resources & bit;
-}
-
-int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit)
-{
-       return fh->dev->channels[fh->channel_id].resources & bit;
-}
-
-void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
-                     unsigned int bits)
-{
-       BUG_ON((fh->resources & bits) != bits);
-       dprintk(1, "%s()\n", __func__);
-
-       mutex_lock(&dev->lock);
-       fh->resources &= ~bits;
-       dev->channels[fh->channel_id].resources &= ~bits;
-       dprintk(1, "res: put %d\n", bits);
-       mutex_unlock(&dev->lock);
-}
-
-int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
-{
-       struct v4l2_routing route;
-       memset(&route, 0, sizeof(route));
-
-       dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
-               __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
-               INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
-       dev->input = input;
-
-       route.input = INPUT(input)->vmux;
-
-       /* Tell the internal A/V decoder */
-       cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);
-
-       return 0;
-}
-
-int cx25821_start_video_dma(struct cx25821_dev *dev,
-                           struct cx25821_dmaqueue *q,
-                           struct cx25821_buffer *buf,
-                           struct sram_channel *channel)
-{
-       int tmp = 0;
-
-       /* setup fifo + format */
-       cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
-
-       /* reset counter */
-       cx_write(channel->gpcnt_ctl, 3);
-       q->count = 1;
-
-       /* enable irq */
-       cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
-       cx_set(channel->int_msk, 0x11);
-
-       /* start dma */
-       cx_write(channel->dma_ctl, 0x11);       /* FIFO and RISC enable */
-
-       /* make sure upstream setting if any is reversed */
-       tmp = cx_read(VID_CH_MODE_SEL);
-       cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
-
-       return 0;
-}
-
-int cx25821_restart_video_queue(struct cx25821_dev *dev,
-                               struct cx25821_dmaqueue *q,
-                               struct sram_channel *channel)
-{
-       struct cx25821_buffer *buf, *prev;
-       struct list_head *item;
-
-       if (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx25821_buffer,
-                               vb.queue);
-
-               cx25821_start_video_dma(dev, q, buf, channel);
-
-               list_for_each(item, &q->active) {
-                       buf = list_entry(item, struct cx25821_buffer, vb.queue);
-                       buf->count = q->count++;
-               }
-
-               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-               return 0;
-       }
-
-       prev = NULL;
-       for (;;) {
-               if (list_empty(&q->queued))
-                       return 0;
-
-               buf = list_entry(q->queued.next, struct cx25821_buffer,
-                               vb.queue);
-
-               if (NULL == prev) {
-                       list_move_tail(&buf->vb.queue, &q->active);
-                       cx25821_start_video_dma(dev, q, buf, channel);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count = q->count++;
-                       mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-               } else if (prev->vb.width == buf->vb.width &&
-                          prev->vb.height == buf->vb.height &&
-                          prev->fmt == buf->fmt) {
-                       list_move_tail(&buf->vb.queue, &q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count = q->count++;
-                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                       prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
-               } else {
-                       return 0;
-               }
-               prev = buf;
-       }
-}
-
-void cx25821_vid_timeout(unsigned long data)
-{
-       struct cx25821_data *timeout_data = (struct cx25821_data *)data;
-       struct cx25821_dev *dev = timeout_data->dev;
-       struct sram_channel *channel = timeout_data->channel;
-       struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq;
-       struct cx25821_buffer *buf;
-       unsigned long flags;
-
-       /* cx25821_sram_channel_dump(dev, channel); */
-       cx_clear(channel->dma_ctl, 0x11);
-
-       spin_lock_irqsave(&dev->slock, flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx25821_buffer,
-                               vb.queue);
-               list_del(&buf->vb.queue);
-
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-       }
-
-       cx25821_restart_video_queue(dev, q, channel);
-       spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
-{
-       u32 count = 0;
-       int handled = 0;
-       u32 mask;
-       struct sram_channel *channel = dev->channels[chan_num].sram_channels;
-
-       mask = cx_read(channel->int_msk);
-       if (0 == (status & mask))
-               return handled;
-
-       cx_write(channel->int_stat, status);
-
-       /* risc op code error */
-       if (status & (1 << 16)) {
-               pr_warn("%s, %s: video risc op code error\n",
-                       dev->name, channel->name);
-               cx_clear(channel->dma_ctl, 0x11);
-               cx25821_sram_channel_dump(dev, channel);
-       }
-
-       /* risc1 y */
-       if (status & FLD_VID_DST_RISC1) {
-               spin_lock(&dev->slock);
-               count = cx_read(channel->gpcnt);
-               cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq,
-                               count);
-               spin_unlock(&dev->slock);
-               handled++;
-       }
-
-       /* risc2 y */
-       if (status & 0x10) {
-               dprintk(2, "stopper video\n");
-               spin_lock(&dev->slock);
-               cx25821_restart_video_queue(dev,
-                               &dev->channels[channel->i].vidq, channel);
-               spin_unlock(&dev->slock);
-               handled++;
-       }
-       return handled;
-}
-
-void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
-{
-       if (dev->ioctl_dev) {
-               if (video_is_registered(dev->ioctl_dev))
-                       video_unregister_device(dev->ioctl_dev);
-               else
-                       video_device_release(dev->ioctl_dev);
-
-               dev->ioctl_dev = NULL;
-       }
-}
-
-void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
-{
-       cx_clear(PCI_INT_MSK, 1);
-
-       if (dev->channels[chan_num].video_dev) {
-               if (video_is_registered(dev->channels[chan_num].video_dev))
-                       video_unregister_device(
-                                       dev->channels[chan_num].video_dev);
-               else
-                       video_device_release(
-                                       dev->channels[chan_num].video_dev);
-
-               dev->channels[chan_num].video_dev = NULL;
-
-               btcx_riscmem_free(dev->pci,
-                               &dev->channels[chan_num].vidq.stopper);
-
-               pr_warn("device %d released!\n", chan_num);
-       }
-
-}
-
-int cx25821_video_register(struct cx25821_dev *dev)
-{
-       int err;
-       int i;
-
-       struct video_device cx25821_video_device = {
-               .name = "cx25821-video",
-               .fops = &video_fops,
-               .minor = -1,
-               .ioctl_ops = &video_ioctl_ops,
-               .tvnorms = CX25821_NORMS,
-               .current_norm = V4L2_STD_NTSC_M,
-       };
-
-       spin_lock_init(&dev->slock);
-
-       for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
-               cx25821_init_controls(dev, i);
-
-               cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
-                       dev->channels[i].sram_channels->dma_ctl, 0x11, 0);
-
-               dev->channels[i].sram_channels = &cx25821_sram_channels[i];
-               dev->channels[i].video_dev = NULL;
-               dev->channels[i].resources = 0;
-
-               cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
-
-               INIT_LIST_HEAD(&dev->channels[i].vidq.active);
-               INIT_LIST_HEAD(&dev->channels[i].vidq.queued);
-
-               dev->channels[i].timeout_data.dev = dev;
-               dev->channels[i].timeout_data.channel =
-                       &cx25821_sram_channels[i];
-               dev->channels[i].vidq.timeout.function = cx25821_vid_timeout;
-               dev->channels[i].vidq.timeout.data =
-                       (unsigned long)&dev->channels[i].timeout_data;
-               init_timer(&dev->channels[i].vidq.timeout);
-
-               /* register v4l devices */
-               dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci,
-                               &cx25821_video_device, "video");
-
-               err = video_register_device(dev->channels[i].video_dev,
-                               VFL_TYPE_GRABBER, video_nr[dev->nr]);
-
-               if (err < 0)
-                       goto fail_unreg;
-
-       }
-
-       /* set PCI interrupt */
-       cx_set(PCI_INT_MSK, 0xff);
-
-       /* initial device configuration */
-       mutex_lock(&dev->lock);
-#ifdef TUNER_FLAG
-       dev->tvnorm = cx25821_video_device.current_norm;
-       cx25821_set_tvnorm(dev, dev->tvnorm);
-#endif
-       mutex_unlock(&dev->lock);
-
-       return 0;
-
-fail_unreg:
-       cx25821_video_unregister(dev, i);
-       return err;
-}
-
-int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
-                unsigned int *size)
-{
-       struct cx25821_fh *fh = q->priv_data;
-
-       *size = fh->fmt->depth * fh->width * fh->height >> 3;
-
-       if (0 == *count)
-               *count = 32;
-
-       if (*size * *count > vid_limit * 1024 * 1024)
-               *count = (vid_limit * 1024 * 1024) / *size;
-
-       return 0;
-}
-
-int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-                  enum v4l2_field field)
-{
-       struct cx25821_fh *fh = q->priv_data;
-       struct cx25821_dev *dev = fh->dev;
-       struct cx25821_buffer *buf =
-               container_of(vb, struct cx25821_buffer, vb);
-       int rc, init_buffer = 0;
-       u32 line0_offset;
-       struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
-       int bpl_local = LINE_SIZE_D1;
-       int channel_opened = fh->channel_id;
-
-       BUG_ON(NULL == fh->fmt);
-       if (fh->width < 48 || fh->width > 720 ||
-           fh->height < 32 || fh->height > 576)
-               return -EINVAL;
-
-       buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
-
-       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;
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               init_buffer = 1;
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (0 != rc) {
-                       printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
-                       goto fail;
-               }
-       }
-
-       dprintk(1, "init_buffer=%d\n", init_buffer);
-
-       if (init_buffer) {
-
-               channel_opened = dev->channel_opened;
-               if (channel_opened < 0 || channel_opened > 7)
-                       channel_opened = 7;
-
-               if (dev->channels[channel_opened].pixel_formats ==
-                               PIXEL_FRMT_411)
-                       buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
-               else
-                       buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
-
-               if (dev->channels[channel_opened].pixel_formats ==
-                               PIXEL_FRMT_411) {
-                       bpl_local = buf->bpl;
-               } else {
-                       bpl_local = buf->bpl;   /* Default */
-
-                       if (channel_opened >= 0 && channel_opened <= 7) {
-                               if (dev->channels[channel_opened]
-                                               .use_cif_resolution) {
-                                       if (dev->tvnorm & V4L2_STD_PAL_BG ||
-                                           dev->tvnorm & V4L2_STD_PAL_DK)
-                                               bpl_local = 352 << 1;
-                                       else
-                                               bpl_local = dev->channels[
-                                                       channel_opened].
-                                                       cif_width << 1;
-                               }
-                       }
-               }
-
-               switch (buf->vb.field) {
-               case V4L2_FIELD_TOP:
-                       cx25821_risc_buffer(dev->pci, &buf->risc,
-                                           dma->sglist, 0, UNSET,
-                                           buf->bpl, 0, buf->vb.height);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       cx25821_risc_buffer(dev->pci, &buf->risc,
-                                           dma->sglist, UNSET, 0,
-                                           buf->bpl, 0, buf->vb.height);
-                       break;
-               case V4L2_FIELD_INTERLACED:
-                       /* All other formats are top field first */
-                       line0_offset = 0;
-                       dprintk(1, "top field first\n");
-
-                       cx25821_risc_buffer(dev->pci, &buf->risc,
-                                           dma->sglist, line0_offset,
-                                           bpl_local, bpl_local, bpl_local,
-                                           buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_TB:
-                       cx25821_risc_buffer(dev->pci, &buf->risc,
-                                           dma->sglist,
-                                           0, buf->bpl * (buf->vb.height >> 1),
-                                           buf->bpl, 0, buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_BT:
-                       cx25821_risc_buffer(dev->pci, &buf->risc,
-                                           dma->sglist,
-                                           buf->bpl * (buf->vb.height >> 1), 0,
-                                           buf->bpl, 0, buf->vb.height >> 1);
-                       break;
-               default:
-                       BUG();
-               }
-       }
-
-       dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-               buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth,
-               fh->fmt->name, (unsigned long)buf->risc.dma);
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-
-       return 0;
-
-fail:
-       cx25821_free_buffer(q, buf);
-       return rc;
-}
-
-void cx25821_buffer_release(struct videobuf_queue *q,
-                           struct videobuf_buffer *vb)
-{
-       struct cx25821_buffer *buf =
-               container_of(vb, struct cx25821_buffer, vb);
-
-       cx25821_free_buffer(q, buf);
-}
-
-struct videobuf_queue *get_queue(struct cx25821_fh *fh)
-{
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               return &fh->vidq;
-       default:
-               BUG();
-               return NULL;
-       }
-}
-
-int cx25821_get_resource(struct cx25821_fh *fh, int resource)
-{
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               return resource;
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct cx25821_fh *fh = file->private_data;
-
-       return videobuf_mmap_mapper(get_queue(fh), vma);
-}
-
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx25821_buffer *buf =
-               container_of(vb, struct cx25821_buffer, vb);
-       struct cx25821_buffer *prev;
-       struct cx25821_fh *fh = vq->priv_data;
-       struct cx25821_dev *dev = fh->dev;
-       struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq;
-
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
-       buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
-
-       dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
-
-       if (!list_empty(&q->queued)) {
-               list_add_tail(&buf->vb.queue, &q->queued);
-               buf->vb.state = VIDEOBUF_QUEUED;
-               dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
-                               buf->vb.i);
-
-       } else if (list_empty(&q->active)) {
-               list_add_tail(&buf->vb.queue, &q->active);
-               cx25821_start_video_dma(dev, q, buf,
-                               dev->channels[fh->channel_id].sram_channels);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count = q->count++;
-               mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
-               dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
-                               buf, buf->vb.i, buf->count, q->count);
-       } else {
-               prev = list_entry(q->active.prev, struct cx25821_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, &q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count = q->count++;
-                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-
-                       /* 64 bit bits 63-32 */
-                       prev->risc.jmp[2] = cpu_to_le32(0);
-                       dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
-                                       buf, buf->vb.i, buf->count);
-
-               } else {
-                       list_add_tail(&buf->vb.queue, &q->queued);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-                       dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
-                                       buf->vb.i);
-               }
-       }
-
-       if (list_empty(&q->active))
-               dprintk(2, "active queue empty!\n");
-}
-
-static struct videobuf_queue_ops cx25821_video_qops = {
-       .buf_setup = cx25821_buffer_setup,
-       .buf_prepare = cx25821_buffer_prepare,
-       .buf_queue = buffer_queue,
-       .buf_release = cx25821_buffer_release,
-};
-
-static int video_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx25821_dev *h, *dev = video_drvdata(file);
-       struct cx25821_fh *fh;
-       struct list_head *list;
-       int minor = video_devdata(file)->minor;
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       u32 pix_format;
-       int ch_id = 0;
-       int i;
-
-       dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev),
-                       v4l2_type_names[type]);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
-               return -ENOMEM;
-
-       mutex_lock(&cx25821_devlist_mutex);
-
-       list_for_each(list, &cx25821_devlist)
-       {
-               h = list_entry(list, struct cx25821_dev, devlist);
-
-               for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
-                       if (h->channels[i].video_dev &&
-                           h->channels[i].video_dev->minor == minor) {
-                               dev = h;
-                               ch_id = i;
-                               type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       }
-               }
-       }
-
-       if (NULL == dev) {
-               mutex_unlock(&cx25821_devlist_mutex);
-               kfree(fh);
-               return -ENODEV;
-       }
-
-       file->private_data = fh;
-       fh->dev = dev;
-       fh->type = type;
-       fh->width = 720;
-       fh->channel_id = ch_id;
-
-       if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
-               fh->height = 576;
-       else
-               fh->height = 480;
-
-       dev->channel_opened = fh->channel_id;
-       if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411)
-               pix_format = V4L2_PIX_FMT_Y41P;
-       else
-               pix_format = V4L2_PIX_FMT_YUYV;
-       fh->fmt = cx25821_format_by_fourcc(pix_format);
-
-       v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
-
-       videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev,
-                       &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                       V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer),
-                       fh, NULL);
-
-       dprintk(1, "post videobuf_queue_init()\n");
-       mutex_unlock(&cx25821_devlist_mutex);
-
-       return 0;
-}
-
-static ssize_t video_read(struct file *file, char __user * data, size_t count,
-                        loff_t *ppos)
-{
-       struct cx25821_fh *fh = file->private_data;
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (cx25821_res_locked(fh, RESOURCE_VIDEO0))
-                       return -EBUSY;
-
-               return videobuf_read_one(&fh->vidq, data, count, ppos,
-                                       file->f_flags & O_NONBLOCK);
-
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static unsigned int video_poll(struct file *file,
-                             struct poll_table_struct *wait)
-{
-       struct cx25821_fh *fh = file->private_data;
-       struct cx25821_buffer *buf;
-
-       if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
-               /* streaming capture */
-               if (list_empty(&fh->vidq.stream))
-                       return POLLERR;
-               buf = list_entry(fh->vidq.stream.next,
-                               struct cx25821_buffer, vb.stream);
-       } else {
-               /* read() capture */
-               buf = (struct cx25821_buffer *)fh->vidq.read_buf;
-               if (NULL == buf)
-                       return POLLERR;
-       }
-
-       poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
-               if (buf->vb.state == VIDEOBUF_DONE) {
-                       struct cx25821_dev *dev = fh->dev;
-
-                       if (dev && dev->channels[fh->channel_id]
-                                       .use_cif_resolution) {
-                               u8 cam_id = *((char *)buf->vb.baddr + 3);
-                               memcpy((char *)buf->vb.baddr,
-                                     (char *)buf->vb.baddr + (fh->width * 2),
-                                     (fh->width * 2));
-                               *((char *)buf->vb.baddr + 3) = cam_id;
-                       }
-               }
-
-               return POLLIN | POLLRDNORM;
-       }
-
-       return 0;
-}
-
-static int video_release(struct file *file)
-{
-       struct cx25821_fh *fh = file->private_data;
-       struct cx25821_dev *dev = fh->dev;
-
-       /* stop the risc engine and fifo */
-       cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
-
-       /* stop video capture */
-       if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
-               videobuf_queue_cancel(&fh->vidq);
-               cx25821_res_free(dev, fh, RESOURCE_VIDEO0);
-       }
-
-       if (fh->vidq.read_buf) {
-               cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf);
-               kfree(fh->vidq.read_buf);
-       }
-
-       videobuf_mmap_free(&fh->vidq);
-
-       v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio);
-       file->private_data = NULL;
-       kfree(fh);
-
-       return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = fh->dev;
-
-       if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
-               return -EINVAL;
-
-       if (unlikely(i != fh->type))
-               return -EINVAL;
-
-       if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh,
-                                               RESOURCE_VIDEO0))))
-               return -EBUSY;
-
-       return videobuf_streamon(get_queue(fh));
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = fh->dev;
-       int err, res;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (i != fh->type)
-               return -EINVAL;
-
-       res = cx25821_get_resource(fh, RESOURCE_VIDEO0);
-       err = videobuf_streamoff(get_queue(fh));
-       if (err < 0)
-               return err;
-       cx25821_res_free(dev, fh, res);
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       int err;
-       int pix_format = PIXEL_FRMT_422;
-
-       if (fh) {
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       }
-
-       dprintk(2, "%s()\n", __func__);
-       err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
-
-       if (0 != err)
-               return err;
-
-       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
-       fh->vidq.field = f->fmt.pix.field;
-
-       /* check if width and height is valid based on set standard */
-       if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm))
-               fh->width = f->fmt.pix.width;
-
-       if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm))
-               fh->height = f->fmt.pix.height;
-
-       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
-               pix_format = PIXEL_FRMT_411;
-       else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
-               pix_format = PIXEL_FRMT_422;
-       else
-               return -EINVAL;
-
-       cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
-
-       /* check if cif resolution */
-       if (fh->width == 320 || fh->width == 352)
-               dev->channels[fh->channel_id].use_cif_resolution = 1;
-       else
-               dev->channels[fh->channel_id].use_cif_resolution = 0;
-
-       dev->channels[fh->channel_id].cif_width = fh->width;
-       medusa_set_resolution(dev, fh->width, SRAM_CH00);
-
-       dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width,
-               fh->height, fh->vidq.field);
-       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
-       cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
-
-       return 0;
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       int ret_val = 0;
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-
-       ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
-
-       p->sequence = dev->channels[fh->channel_id].vidq.count;
-
-       return ret_val;
-}
-
-static int vidioc_log_status(struct file *file, void *priv)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       struct cx25821_fh *fh = priv;
-       char name[32 + 2];
-
-       struct sram_channel *sram_ch = dev->channels[fh->channel_id]
-                                                               .sram_channels;
-       u32 tmp = 0;
-
-       snprintf(name, sizeof(name), "%s/2", dev->name);
-       pr_info("%s/2: ============  START LOG STATUS  ============\n",
-               dev->name);
-       cx25821_call_all(dev, core, log_status);
-       tmp = cx_read(sram_ch->dma_ctl);
-       pr_info("Video input 0 is %s\n",
-               (tmp & 0x11) ? "streaming" : "stopped");
-       pr_info("%s/2: =============  END LOG STATUS  =============\n",
-               dev->name);
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                       struct v4l2_control *ctl)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       int err;
-
-       if (fh) {
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       }
-
-       return cx25821_set_control(dev, ctl, fh->channel_id);
-}
-
-/* VIDEO IOCTLS */
-int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                struct v4l2_format *f)
-{
-       struct cx25821_fh *fh = priv;
-
-       f->fmt.pix.width = fh->width;
-       f->fmt.pix.height = fh->height;
-       f->fmt.pix.field = fh->vidq.field;
-       f->fmt.pix.pixelformat = fh->fmt->fourcc;
-       f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                  struct v4l2_format *f)
-{
-       struct cx25821_fmt *fmt;
-       enum v4l2_field field;
-       unsigned int maxw, maxh;
-
-       fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-       maxw = 720;
-       maxh = 576;
-
-       if (V4L2_FIELD_ANY == field) {
-               if (f->fmt.pix.height > maxh / 2)
-                       field = V4L2_FIELD_INTERLACED;
-               else
-                       field = V4L2_FIELD_TOP;
-       }
-
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       f->fmt.pix.field = field;
-       if (f->fmt.pix.height < 32)
-               f->fmt.pix.height = 32;
-       if (f->fmt.pix.height > maxh)
-               f->fmt.pix.height = maxh;
-       if (f->fmt.pix.width < 48)
-               f->fmt.pix.width = 48;
-       if (f->fmt.pix.width > maxw)
-               f->fmt.pix.width = maxw;
-       f->fmt.pix.width &= ~0x03;
-       f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-int cx25821_vidioc_querycap(struct file *file, void *priv,
-                           struct v4l2_capability *cap)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-
-       strcpy(cap->driver, "cx25821");
-       strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
-       sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
-       cap->version = CX25821_VERSION_CODE;
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING;
-       if (UNSET != dev->tuner_type)
-               cap->capabilities |= V4L2_CAP_TUNER;
-       return 0;
-}
-
-int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-                           struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(formats)))
-               return -EINVAL;
-
-       strlcpy(f->description, formats[f->index].name, sizeof(f->description));
-       f->pixelformat = formats[f->index].fourcc;
-
-       return 0;
-}
-
-int cx25821_vidioc_reqbufs(struct file *file, void *priv,
-                          struct v4l2_requestbuffers *p)
-{
-       struct cx25821_fh *fh = priv;
-       return videobuf_reqbufs(get_queue(fh), p);
-}
-
-int cx25821_vidioc_querybuf(struct file *file, void *priv,
-                           struct v4l2_buffer *p)
-{
-       struct cx25821_fh *fh = priv;
-       return videobuf_querybuf(get_queue(fh), p);
-}
-
-int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct cx25821_fh *fh = priv;
-       return videobuf_qbuf(get_queue(fh), p);
-}
-
-int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
-       struct cx25821_fh *fh = f;
-
-       *p = v4l2_prio_max(&dev->channels[fh->channel_id].prio);
-
-       return 0;
-}
-
-int cx25821_vidioc_s_priority(struct file *file, void *f,
-                             enum v4l2_priority prio)
-{
-       struct cx25821_fh *fh = f;
-       struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
-
-       return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio,
-                       prio);
-}
-
-#ifdef TUNER_FLAG
-int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       int err;
-
-       dprintk(1, "%s()\n", __func__);
-
-       if (fh) {
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       }
-
-       if (dev->tvnorm == *tvnorms)
-               return 0;
-
-       mutex_lock(&dev->lock);
-       cx25821_set_tvnorm(dev, *tvnorms);
-       mutex_unlock(&dev->lock);
-
-       medusa_set_videostandard(dev);
-
-       return 0;
-}
-#endif
-
-int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
-{
-       static const char * const iname[] = {
-               [CX25821_VMUX_COMPOSITE] = "Composite",
-               [CX25821_VMUX_SVIDEO] = "S-Video",
-               [CX25821_VMUX_DEBUG] = "for debug only",
-       };
-       unsigned int n;
-       dprintk(1, "%s()\n", __func__);
-
-       n = i->index;
-       if (n >= 2)
-               return -EINVAL;
-
-       if (0 == INPUT(n)->type)
-               return -EINVAL;
-
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-       strcpy(i->name, iname[INPUT(n)->type]);
-
-       i->std = CX25821_NORMS;
-       return 0;
-}
-
-int cx25821_vidioc_enum_input(struct file *file, void *priv,
-                             struct v4l2_input *i)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       dprintk(1, "%s()\n", __func__);
-       return cx25821_enum_input(dev, i);
-}
-
-int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-
-       *i = dev->input;
-       dprintk(1, "%s(): returns %d\n", __func__, *i);
-       return 0;
-}
-
-int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       int err;
-
-       dprintk(1, "%s(%d)\n", __func__, i);
-
-       if (fh) {
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       }
-
-       if (i >= CX25821_NR_INPUT) {
-               dprintk(1, "%s(): -EINVAL\n", __func__);
-               return -EINVAL;
-       }
-
-       mutex_lock(&dev->lock);
-       cx25821_video_mux(dev, i);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-#ifdef TUNER_FLAG
-int cx25821_vidioc_g_frequency(struct file *file, void *priv,
-                              struct v4l2_frequency *f)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev = fh->dev;
-
-       f->frequency = dev->freq;
-
-       cx25821_call_all(dev, tuner, g_frequency, f);
-
-       return 0;
-}
-
-int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
-{
-       mutex_lock(&dev->lock);
-       dev->freq = f->frequency;
-
-       cx25821_call_all(dev, tuner, s_frequency, f);
-
-       /* When changing channels it is required to reset TVAUDIO */
-       msleep(10);
-
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-int cx25821_vidioc_s_frequency(struct file *file, void *priv,
-                              struct v4l2_frequency *f)
-{
-       struct cx25821_fh *fh = priv;
-       struct cx25821_dev *dev;
-       int err;
-
-       if (fh) {
-               dev = fh->dev;
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       } else {
-               pr_err("Invalid fh pointer!\n");
-               return -EINVAL;
-       }
-
-       return cx25821_set_freq(dev, f);
-}
-#endif
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-int cx25821_vidioc_g_register(struct file *file, void *fh,
-                     struct v4l2_dbg_register *reg)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-
-       cx25821_call_all(dev, core, g_register, reg);
-
-       return 0;
-}
-
-int cx25821_vidioc_s_register(struct file *file, void *fh,
-                     struct v4l2_dbg_register *reg)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-
-       cx25821_call_all(dev, core, s_register, reg);
-
-       return 0;
-}
-
-#endif
-
-#ifdef TUNER_FLAG
-int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Television");
-       t->type = V4L2_TUNER_ANALOG_TV;
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->rangehigh = 0xffffffffUL;
-
-       t->signal = 0xffff;     /* LOCKED */
-       return 0;
-}
-
-int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       struct cx25821_fh *fh = priv;
-       int err;
-
-       if (fh) {
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       }
-
-       dprintk(1, "%s()\n", __func__);
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       return 0;
-}
-
-#endif
-/*****************************************************************************/
-static const struct v4l2_queryctrl no_ctl = {
-       .name = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-static struct v4l2_queryctrl cx25821_ctls[] = {
-       /* --- video --- */
-       {
-               .id = V4L2_CID_BRIGHTNESS,
-               .name = "Brightness",
-               .minimum = 0,
-               .maximum = 10000,
-               .step = 1,
-               .default_value = 6200,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-       }, {
-               .id = V4L2_CID_CONTRAST,
-               .name = "Contrast",
-               .minimum = 0,
-               .maximum = 10000,
-               .step = 1,
-               .default_value = 5000,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-       }, {
-               .id = V4L2_CID_SATURATION,
-               .name = "Saturation",
-               .minimum = 0,
-               .maximum = 10000,
-               .step = 1,
-               .default_value = 5000,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-       }, {
-               .id = V4L2_CID_HUE,
-               .name = "Hue",
-               .minimum = 0,
-               .maximum = 10000,
-               .step = 1,
-               .default_value = 5000,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-       }
-};
-static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
-
-static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
-{
-       int i;
-
-       if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       for (i = 0; i < CX25821_CTLS; i++)
-               if (cx25821_ctls[i].id == qctrl->id)
-                       break;
-       if (i == CX25821_CTLS) {
-               *qctrl = no_ctl;
-               return 0;
-       }
-       *qctrl = cx25821_ctls[i];
-       return 0;
-}
-
-int cx25821_vidioc_queryctrl(struct file *file, void *priv,
-                    struct v4l2_queryctrl *qctrl)
-{
-       return cx25821_ctrl_query(qctrl);
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO CTRL IOCTLS                                                  */
-
-static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
-{
-       unsigned int i;
-
-       for (i = 0; i < CX25821_CTLS; i++)
-               if (cx25821_ctls[i].id == id)
-                       return cx25821_ctls + i;
-       return NULL;
-}
-
-int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
-                         struct v4l2_control *ctl)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       struct cx25821_fh *fh = priv;
-
-       const struct v4l2_queryctrl *ctrl;
-
-       ctrl = ctrl_by_id(ctl->id);
-
-       if (NULL == ctrl)
-               return -EINVAL;
-       switch (ctl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               ctl->value = dev->channels[fh->channel_id].ctl_bright;
-               break;
-       case V4L2_CID_HUE:
-               ctl->value = dev->channels[fh->channel_id].ctl_hue;
-               break;
-       case V4L2_CID_CONTRAST:
-               ctl->value = dev->channels[fh->channel_id].ctl_contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               ctl->value = dev->channels[fh->channel_id].ctl_saturation;
-               break;
-       }
-       return 0;
-}
-
-int cx25821_set_control(struct cx25821_dev *dev,
-                       struct v4l2_control *ctl, int chan_num)
-{
-       int err;
-       const struct v4l2_queryctrl *ctrl;
-
-       err = -EINVAL;
-
-       ctrl = ctrl_by_id(ctl->id);
-
-       if (NULL == ctrl)
-               return err;
-
-       switch (ctrl->type) {
-       case V4L2_CTRL_TYPE_BOOLEAN:
-       case V4L2_CTRL_TYPE_MENU:
-       case V4L2_CTRL_TYPE_INTEGER:
-               if (ctl->value < ctrl->minimum)
-                       ctl->value = ctrl->minimum;
-               if (ctl->value > ctrl->maximum)
-                       ctl->value = ctrl->maximum;
-               break;
-       default:
-               /* nothing */ ;
-       }
-
-       switch (ctl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               dev->channels[chan_num].ctl_bright = ctl->value;
-               medusa_set_brightness(dev, ctl->value, chan_num);
-               break;
-       case V4L2_CID_HUE:
-               dev->channels[chan_num].ctl_hue = ctl->value;
-               medusa_set_hue(dev, ctl->value, chan_num);
-               break;
-       case V4L2_CID_CONTRAST:
-               dev->channels[chan_num].ctl_contrast = ctl->value;
-               medusa_set_contrast(dev, ctl->value, chan_num);
-               break;
-       case V4L2_CID_SATURATION:
-               dev->channels[chan_num].ctl_saturation = ctl->value;
-               medusa_set_saturation(dev, ctl->value, chan_num);
-               break;
-       }
-
-       err = 0;
-
-       return err;
-}
-
-static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num)
-{
-       struct v4l2_control ctrl;
-       int i;
-       for (i = 0; i < CX25821_CTLS; i++) {
-               ctrl.id = cx25821_ctls[i].id;
-               ctrl.value = cx25821_ctls[i].default_value;
-
-               cx25821_set_control(dev, &ctrl, chan_num);
-       }
-}
-
-int cx25821_vidioc_cropcap(struct file *file, void *priv,
-                          struct v4l2_cropcap *cropcap)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-
-       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       cropcap->bounds.top = 0;
-       cropcap->bounds.left = 0;
-       cropcap->bounds.width = 720;
-       cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
-       cropcap->pixelaspect.numerator =
-               dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
-       cropcap->pixelaspect.denominator =
-               dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
-       cropcap->defrect = cropcap->bounds;
-       return 0;
-}
-
-int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
-{
-       struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
-       struct cx25821_fh *fh = priv;
-       int err;
-
-       if (fh) {
-               err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
-                                     fh->prio);
-               if (0 != err)
-                       return err;
-       }
-       /* cx25821_vidioc_s_crop not supported */
-       return -EINVAL;
-}
-
-int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
-{
-       /* cx25821_vidioc_g_crop not supported */
-       return -EINVAL;
-}
-
-int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm)
-{
-       /* medusa does not support video standard sensing of current input */
-       *norm = CX25821_NORMS;
-
-       return 0;
-}
-
-int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm)
-{
-       if (tvnorm == V4L2_STD_PAL_BG) {
-               if (width == 352 || width == 720)
-                       return 1;
-               else
-                       return 0;
-       }
-
-       if (tvnorm == V4L2_STD_NTSC_M) {
-               if (width == 320 || width == 352 || width == 720)
-                       return 1;
-               else
-                       return 0;
-       }
-       return 0;
-}
-
-int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm)
-{
-       if (tvnorm == V4L2_STD_PAL_BG) {
-               if (height == 576 || height == 288)
-                       return 1;
-               else
-                       return 0;
-       }
-
-       if (tvnorm == V4L2_STD_NTSC_M) {
-               if (height == 480 || height == 240)
-                       return 1;
-               else
-                       return 0;
-       }
-
-       return 0;
-}
-
-static long video_ioctl_upstream9(struct file *file, unsigned int cmd,
-                                unsigned long arg)
-{
-       struct cx25821_fh *fh = file->private_data;
-       struct cx25821_dev *dev = fh->dev;
-       int command = 0;
-       struct upstream_user_struct *data_from_user;
-
-       data_from_user = (struct upstream_user_struct *)arg;
-
-       if (!data_from_user) {
-               pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
-               return 0;
-       }
-
-       command = data_from_user->command;
-
-       if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
-               return 0;
-
-       dev->input_filename = data_from_user->input_filename;
-       dev->input_audiofilename = data_from_user->input_filename;
-       dev->vid_stdname = data_from_user->vid_stdname;
-       dev->pixel_format = data_from_user->pixel_format;
-       dev->channel_select = data_from_user->channel_select;
-       dev->command = data_from_user->command;
-
-       switch (command) {
-       case UPSTREAM_START_VIDEO:
-               cx25821_start_upstream_video_ch1(dev, data_from_user);
-               break;
-
-       case UPSTREAM_STOP_VIDEO:
-               cx25821_stop_upstream_video_ch1(dev);
-               break;
-       }
-
-       return 0;
-}
-
-static long video_ioctl_upstream10(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       struct cx25821_fh *fh = file->private_data;
-       struct cx25821_dev *dev = fh->dev;
-       int command = 0;
-       struct upstream_user_struct *data_from_user;
-
-       data_from_user = (struct upstream_user_struct *)arg;
-
-       if (!data_from_user) {
-               pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
-               return 0;
-       }
-
-       command = data_from_user->command;
-
-       if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
-               return 0;
-
-       dev->input_filename_ch2 = data_from_user->input_filename;
-       dev->input_audiofilename = data_from_user->input_filename;
-       dev->vid_stdname_ch2 = data_from_user->vid_stdname;
-       dev->pixel_format_ch2 = data_from_user->pixel_format;
-       dev->channel_select_ch2 = data_from_user->channel_select;
-       dev->command_ch2 = data_from_user->command;
-
-       switch (command) {
-       case UPSTREAM_START_VIDEO:
-               cx25821_start_upstream_video_ch2(dev, data_from_user);
-               break;
-
-       case UPSTREAM_STOP_VIDEO:
-               cx25821_stop_upstream_video_ch2(dev);
-               break;
-       }
-
-       return 0;
-}
-
-static long video_ioctl_upstream11(struct file *file, unsigned int cmd,
-                                 unsigned long arg)
-{
-       struct cx25821_fh *fh = file->private_data;
-       struct cx25821_dev *dev = fh->dev;
-       int command = 0;
-       struct upstream_user_struct *data_from_user;
-
-       data_from_user = (struct upstream_user_struct *)arg;
-
-       if (!data_from_user) {
-               pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
-               return 0;
-       }
-
-       command = data_from_user->command;
-
-       if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO)
-               return 0;
-
-       dev->input_filename = data_from_user->input_filename;
-       dev->input_audiofilename = data_from_user->input_filename;
-       dev->vid_stdname = data_from_user->vid_stdname;
-       dev->pixel_format = data_from_user->pixel_format;
-       dev->channel_select = data_from_user->channel_select;
-       dev->command = data_from_user->command;
-
-       switch (command) {
-       case UPSTREAM_START_AUDIO:
-               cx25821_start_upstream_audio(dev, data_from_user);
-               break;
-
-       case UPSTREAM_STOP_AUDIO:
-               cx25821_stop_upstream_audio(dev);
-               break;
-       }
-
-       return 0;
-}
-
-static long video_ioctl_set(struct file *file, unsigned int cmd,
-                          unsigned long arg)
-{
-       struct cx25821_fh *fh = file->private_data;
-       struct cx25821_dev *dev = fh->dev;
-       struct downstream_user_struct *data_from_user;
-       int command;
-       int width = 720;
-       int selected_channel = 0;
-       int pix_format = 0;
-       int i = 0;
-       int cif_enable = 0;
-       int cif_width = 0;
-
-       data_from_user = (struct downstream_user_struct *)arg;
-
-       if (!data_from_user) {
-               pr_err("%s(): User data is INVALID. Returning\n", __func__);
-               return 0;
-       }
-
-       command = data_from_user->command;
-
-       if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT
-          && command != ENABLE_CIF_RESOLUTION && command != REG_READ
-          && command != REG_WRITE && command != MEDUSA_READ
-          && command != MEDUSA_WRITE) {
-               return 0;
-       }
-
-       switch (command) {
-       case SET_VIDEO_STD:
-               if (!strcmp(data_from_user->vid_stdname, "PAL"))
-                       dev->tvnorm = V4L2_STD_PAL_BG;
-               else
-                       dev->tvnorm = V4L2_STD_NTSC_M;
-               medusa_set_videostandard(dev);
-               break;
-
-       case SET_PIXEL_FORMAT:
-               selected_channel = data_from_user->decoder_select;
-               pix_format = data_from_user->pixel_format;
-
-               if (!(selected_channel <= 7 && selected_channel >= 0)) {
-                       selected_channel -= 4;
-                       selected_channel = selected_channel % 8;
-               }
-
-               if (selected_channel >= 0)
-                       cx25821_set_pixel_format(dev, selected_channel,
-                                               pix_format);
-
-               break;
-
-       case ENABLE_CIF_RESOLUTION:
-               selected_channel = data_from_user->decoder_select;
-               cif_enable = data_from_user->cif_resolution_enable;
-               cif_width = data_from_user->cif_width;
-
-               if (cif_enable) {
-                       if (dev->tvnorm & V4L2_STD_PAL_BG
-                           || dev->tvnorm & V4L2_STD_PAL_DK) {
-                               width = 352;
-                       } else {
-                               width = cif_width;
-                               if (cif_width != 320 && cif_width != 352)
-                                       width = 320;
-                       }
-               }
-
-               if (!(selected_channel <= 7 && selected_channel >= 0)) {
-                       selected_channel -= 4;
-                       selected_channel = selected_channel % 8;
-               }
-
-               if (selected_channel <= 7 && selected_channel >= 0) {
-                       dev->channels[selected_channel].use_cif_resolution =
-                               cif_enable;
-                       dev->channels[selected_channel].cif_width = width;
-               } else {
-                       for (i = 0; i < VID_CHANNEL_NUM; i++) {
-                               dev->channels[i].use_cif_resolution =
-                                       cif_enable;
-                               dev->channels[i].cif_width = width;
-                       }
-               }
-
-               medusa_set_resolution(dev, width, selected_channel);
-               break;
-       case REG_READ:
-               data_from_user->reg_data = cx_read(data_from_user->reg_address);
-               break;
-       case REG_WRITE:
-               cx_write(data_from_user->reg_address, data_from_user->reg_data);
-               break;
-       case MEDUSA_READ:
-               cx25821_i2c_read(&dev->i2c_bus[0],
-                                        (u16) data_from_user->reg_address,
-                                        &data_from_user->reg_data);
-               break;
-       case MEDUSA_WRITE:
-               cx25821_i2c_write(&dev->i2c_bus[0],
-                                 (u16) data_from_user->reg_address,
-                                 data_from_user->reg_data);
-               break;
-       }
-
-       return 0;
-}
-
-static long cx25821_video_ioctl(struct file *file,
-                               unsigned int cmd, unsigned long arg)
-{
-       int ret = 0;
-
-       struct cx25821_fh *fh = file->private_data;
-
-       /* check to see if it's the video upstream */
-       if (fh->channel_id == SRAM_CH09) {
-               ret = video_ioctl_upstream9(file, cmd, arg);
-               return ret;
-       } else if (fh->channel_id == SRAM_CH10) {
-               ret = video_ioctl_upstream10(file, cmd, arg);
-               return ret;
-       } else if (fh->channel_id == SRAM_CH11) {
-               ret = video_ioctl_upstream11(file, cmd, arg);
-               ret = video_ioctl_set(file, cmd, arg);
-               return ret;
-       }
-
-       return video_ioctl2(file, cmd, arg);
-}
-
-/* exported stuff */
-static const struct v4l2_file_operations video_fops = {
-       .owner = THIS_MODULE,
-       .open = video_open,
-       .release = video_release,
-       .read = video_read,
-       .poll = video_poll,
-       .mmap = cx25821_video_mmap,
-       .ioctl = cx25821_video_ioctl,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap = cx25821_vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
-       .vidioc_reqbufs = cx25821_vidioc_reqbufs,
-       .vidioc_querybuf = cx25821_vidioc_querybuf,
-       .vidioc_qbuf = cx25821_vidioc_qbuf,
-       .vidioc_dqbuf = vidioc_dqbuf,
-#ifdef TUNER_FLAG
-       .vidioc_s_std = cx25821_vidioc_s_std,
-       .vidioc_querystd = cx25821_vidioc_querystd,
-#endif
-       .vidioc_cropcap = cx25821_vidioc_cropcap,
-       .vidioc_s_crop = cx25821_vidioc_s_crop,
-       .vidioc_g_crop = cx25821_vidioc_g_crop,
-       .vidioc_enum_input = cx25821_vidioc_enum_input,
-       .vidioc_g_input = cx25821_vidioc_g_input,
-       .vidioc_s_input = cx25821_vidioc_s_input,
-       .vidioc_g_ctrl = cx25821_vidioc_g_ctrl,
-       .vidioc_s_ctrl = vidioc_s_ctrl,
-       .vidioc_queryctrl = cx25821_vidioc_queryctrl,
-       .vidioc_streamon = vidioc_streamon,
-       .vidioc_streamoff = vidioc_streamoff,
-       .vidioc_log_status = vidioc_log_status,
-       .vidioc_g_priority = cx25821_vidioc_g_priority,
-       .vidioc_s_priority = cx25821_vidioc_s_priority,
-#ifdef TUNER_FLAG
-       .vidioc_g_tuner = cx25821_vidioc_g_tuner,
-       .vidioc_s_tuner = cx25821_vidioc_s_tuner,
-       .vidioc_g_frequency = cx25821_vidioc_g_frequency,
-       .vidioc_s_frequency = cx25821_vidioc_s_frequency,
-#endif
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register = cx25821_vidioc_g_register,
-       .vidioc_s_register = cx25821_vidioc_s_register,
-#endif
-};
-
-struct video_device cx25821_videoioctl_template = {
-       .name = "cx25821-videoioctl",
-       .fops = &video_fops,
-       .ioctl_ops = &video_ioctl_ops,
-       .tvnorms = CX25821_NORMS,
-       .current_norm = V4L2_STD_NTSC_M,
-};
diff --git a/drivers/media/video/cx25821/cx25821-video.h b/drivers/media/video/cx25821/cx25821-video.h
deleted file mode 100644 (file)
index 9652a5e..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
- *
- *  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 CX25821_VIDEO_H_
-#define CX25821_VIDEO_H_
-
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <asm/div64.h>
-
-#include "cx25821.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-#define TUNER_FLAG
-
-#define VIDEO_DEBUG 0
-
-#define dprintk(level, fmt, arg...)                                    \
-do {                                                                   \
-       if (VIDEO_DEBUG >= level)                                       \
-               printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);      \
-} while (0)
-
-/* For IOCTL to identify running upstream */
-#define UPSTREAM_START_VIDEO        700
-#define UPSTREAM_STOP_VIDEO         701
-#define UPSTREAM_START_AUDIO        702
-#define UPSTREAM_STOP_AUDIO         703
-#define UPSTREAM_DUMP_REGISTERS     702
-#define SET_VIDEO_STD               800
-#define SET_PIXEL_FORMAT            1000
-#define ENABLE_CIF_RESOLUTION       1001
-
-#define REG_READ                   900
-#define REG_WRITE                  901
-#define MEDUSA_READ                910
-#define MEDUSA_WRITE               911
-
-extern struct sram_channel *channel0;
-extern struct sram_channel *channel1;
-extern struct sram_channel *channel2;
-extern struct sram_channel *channel3;
-extern struct sram_channel *channel4;
-extern struct sram_channel *channel5;
-extern struct sram_channel *channel6;
-extern struct sram_channel *channel7;
-extern struct sram_channel *channel9;
-extern struct sram_channel *channel10;
-extern struct sram_channel *channel11;
-extern struct video_device cx25821_videoioctl_template;
-/* extern const u32 *ctrl_classes[]; */
-
-extern unsigned int vid_limit;
-
-#define FORMAT_FLAGS_PACKED       0x01
-extern struct cx25821_fmt formats[];
-extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
-extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
-
-extern void cx25821_video_wakeup(struct cx25821_dev *dev,
-                                struct cx25821_dmaqueue *q, u32 count);
-
-#ifdef TUNER_FLAG
-extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
-#endif
-
-extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
-                          unsigned int bit);
-extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit);
-extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit);
-extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
-                            unsigned int bits);
-extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
-extern int cx25821_start_video_dma(struct cx25821_dev *dev,
-                                  struct cx25821_dmaqueue *q,
-                                  struct cx25821_buffer *buf,
-                                  struct sram_channel *channel);
-
-extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width,
-                            unsigned int height, enum v4l2_field field);
-extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
-extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
-extern int cx25821_video_register(struct cx25821_dev *dev);
-extern int cx25821_get_format_size(void);
-
-extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
-                               unsigned int *size);
-extern int cx25821_buffer_prepare(struct videobuf_queue *q,
-                                 struct videobuf_buffer *vb,
-                                 enum v4l2_field field);
-extern void cx25821_buffer_release(struct videobuf_queue *q,
-                                  struct videobuf_buffer *vb);
-extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
-extern int cx25821_get_resource(struct cx25821_fh *fh, int resource);
-extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma);
-extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                         struct v4l2_format *f);
-extern int cx25821_vidioc_querycap(struct file *file, void *priv,
-                                  struct v4l2_capability *cap);
-extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-                                          struct v4l2_fmtdesc *f);
-extern int cx25821_vidioc_reqbufs(struct file *file, void *priv,
-                                 struct v4l2_requestbuffers *p);
-extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
-                                  struct v4l2_buffer *p);
-extern int cx25821_vidioc_qbuf(struct file *file, void *priv,
-                              struct v4l2_buffer *p);
-extern int cx25821_vidioc_s_std(struct file *file, void *priv,
-                               v4l2_std_id *tvnorms);
-extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
-extern int cx25821_vidioc_enum_input(struct file *file, void *priv,
-                                    struct v4l2_input *i);
-extern int cx25821_vidioc_g_input(struct file *file, void *priv,
-                                 unsigned int *i);
-extern int cx25821_vidioc_s_input(struct file *file, void *priv,
-                                 unsigned int i);
-extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
-                                struct v4l2_control *ctl);
-extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f);
-extern int cx25821_vidioc_g_frequency(struct file *file, void *priv,
-                                     struct v4l2_frequency *f);
-extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
-extern int cx25821_vidioc_s_frequency(struct file *file, void *priv,
-                                     struct v4l2_frequency *f);
-extern int cx25821_vidioc_g_register(struct file *file, void *fh,
-                                    struct v4l2_dbg_register *reg);
-extern int cx25821_vidioc_s_register(struct file *file, void *fh,
-                                    struct v4l2_dbg_register *reg);
-extern int cx25821_vidioc_g_tuner(struct file *file, void *priv,
-                                 struct v4l2_tuner *t);
-extern int cx25821_vidioc_s_tuner(struct file *file, void *priv,
-                                 struct v4l2_tuner *t);
-
-extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm);
-extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm);
-
-extern int cx25821_vidioc_g_priority(struct file *file, void *f,
-                                    enum v4l2_priority *p);
-extern int cx25821_vidioc_s_priority(struct file *file, void *f,
-                                    enum v4l2_priority prio);
-
-extern int cx25821_vidioc_queryctrl(struct file *file, void *priv,
-                                   struct v4l2_queryctrl *qctrl);
-extern int cx25821_set_control(struct cx25821_dev *dev,
-                              struct v4l2_control *ctrl, int chan_num);
-
-extern int cx25821_vidioc_cropcap(struct file *file, void *fh,
-                                 struct v4l2_cropcap *cropcap);
-extern int cx25821_vidioc_s_crop(struct file *file, void *priv,
-                                struct v4l2_crop *crop);
-extern int cx25821_vidioc_g_crop(struct file *file, void *priv,
-                                struct v4l2_crop *crop);
-
-extern int cx25821_vidioc_querystd(struct file *file, void *priv,
-                                  v4l2_std_id *norm);
-#endif
diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h
deleted file mode 100644 (file)
index 8a9c0c8..0000000
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- *  Driver for the Conexant CX25821 PCIe bridge
- *
- *  Copyright (C) 2009 Conexant Systems Inc.
- *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
- *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
- *
- *  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 CX25821_H_
-#define CX25821_H_
-
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/kdev_t.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/tuner.h>
-#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/videobuf-dvb.h>
-
-#include "btcx-risc.h"
-#include "cx25821-reg.h"
-#include "cx25821-medusa-reg.h"
-#include "cx25821-sram.h"
-#include "cx25821-audio.h"
-#include "media/cx2341x.h"
-
-#include <linux/version.h>
-#include <linux/mutex.h>
-
-#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
-
-#define UNSET (-1U)
-#define NO_SYNC_LINE (-1U)
-
-#define CX25821_MAXBOARDS 2
-
-#define TRUE    1
-#define FALSE   0
-#define LINE_SIZE_D1    1440
-
-/* Number of decoders and encoders */
-#define MAX_DECODERS            8
-#define MAX_ENCODERS            2
-#define QUAD_DECODERS           4
-#define MAX_CAMERAS             16
-
-/* Max number of inputs by card */
-#define MAX_CX25821_INPUT     8
-#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
-#define RESOURCE_VIDEO0       1
-#define RESOURCE_VIDEO1       2
-#define RESOURCE_VIDEO2       4
-#define RESOURCE_VIDEO3       8
-#define RESOURCE_VIDEO4       16
-#define RESOURCE_VIDEO5       32
-#define RESOURCE_VIDEO6       64
-#define RESOURCE_VIDEO7       128
-#define RESOURCE_VIDEO8       256
-#define RESOURCE_VIDEO9       512
-#define RESOURCE_VIDEO10      1024
-#define RESOURCE_VIDEO11      2048
-#define RESOURCE_VIDEO_IOCTL  4096
-
-#define BUFFER_TIMEOUT     (HZ)        /* 0.5 seconds */
-
-#define UNKNOWN_BOARD        0
-#define CX25821_BOARD        1
-
-/* Currently supported by the driver */
-#define CX25821_NORMS (\
-       V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
-       V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
-       V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_H    | \
-       V4L2_STD_PAL_Nc)
-
-#define CX25821_BOARD_CONEXANT_ATHENA10 1
-#define MAX_VID_CHANNEL_NUM     12
-#define VID_CHANNEL_NUM 8
-#define CX25821_NR_INPUT 2
-
-struct cx25821_fmt {
-       char *name;
-       u32 fourcc;             /* v4l2 format id */
-       int depth;
-       int flags;
-       u32 cxformat;
-};
-
-struct cx25821_ctrl {
-       struct v4l2_queryctrl v;
-       u32 off;
-       u32 reg;
-       u32 mask;
-       u32 shift;
-};
-
-struct cx25821_tvnorm {
-       char *name;
-       v4l2_std_id id;
-       u32 cxiformat;
-       u32 cxoformat;
-};
-
-struct cx25821_fh {
-       struct cx25821_dev *dev;
-       enum v4l2_buf_type type;
-       int radio;
-       u32 resources;
-
-       enum v4l2_priority prio;
-
-       /* video overlay */
-       struct v4l2_window win;
-       struct v4l2_clip *clips;
-       unsigned int nclips;
-
-       /* video capture */
-       struct cx25821_fmt *fmt;
-       unsigned int width, height;
-       int channel_id;
-
-       /* vbi capture */
-       struct videobuf_queue vidq;
-       struct videobuf_queue vbiq;
-
-       /* H264 Encoder specifics ONLY */
-       struct videobuf_queue mpegq;
-       atomic_t v4l_reading;
-};
-
-enum cx25821_itype {
-       CX25821_VMUX_COMPOSITE = 1,
-       CX25821_VMUX_SVIDEO,
-       CX25821_VMUX_DEBUG,
-       CX25821_RADIO,
-};
-
-enum cx25821_src_sel_type {
-       CX25821_SRC_SEL_EXT_656_VIDEO = 0,
-       CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
-};
-
-/* buffer for one video frame */
-struct cx25821_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       /* cx25821 specific */
-       unsigned int bpl;
-       struct btcx_riscmem risc;
-       struct cx25821_fmt *fmt;
-       u32 count;
-};
-
-struct cx25821_input {
-       enum cx25821_itype type;
-       unsigned int vmux;
-       u32 gpio0, gpio1, gpio2, gpio3;
-};
-
-enum port {
-       CX25821_UNDEFINED = 0,
-       CX25821_RAW,
-       CX25821_264
-};
-
-struct cx25821_board {
-       const char *name;
-       enum port porta;
-       enum port portb;
-       enum port portc;
-       unsigned int tuner_type;
-       unsigned int radio_type;
-       unsigned char tuner_addr;
-       unsigned char radio_addr;
-
-       u32 clk_freq;
-       struct cx25821_input input[CX25821_NR_INPUT];
-};
-
-struct cx25821_subid {
-       u16 subvendor;
-       u16 subdevice;
-       u32 card;
-};
-
-struct cx25821_i2c {
-       struct cx25821_dev *dev;
-
-       int nr;
-
-       /* i2c i/o */
-       struct i2c_adapter i2c_adap;
-       struct i2c_client i2c_client;
-       u32 i2c_rc;
-
-       /* cx25821 registers used for raw addess */
-       u32 i2c_period;
-       u32 reg_ctrl;
-       u32 reg_stat;
-       u32 reg_addr;
-       u32 reg_rdata;
-       u32 reg_wdata;
-};
-
-struct cx25821_dmaqueue {
-       struct list_head active;
-       struct list_head queued;
-       struct timer_list timeout;
-       struct btcx_riscmem stopper;
-       u32 count;
-};
-
-struct cx25821_data {
-       struct cx25821_dev *dev;
-       struct sram_channel *channel;
-};
-
-struct cx25821_channel {
-       struct v4l2_prio_state prio;
-
-       int ctl_bright;
-       int ctl_contrast;
-       int ctl_hue;
-       int ctl_saturation;
-       struct cx25821_data timeout_data;
-
-       struct video_device *video_dev;
-       struct cx25821_dmaqueue vidq;
-
-       struct sram_channel *sram_channels;
-
-       struct mutex lock;
-       int resources;
-
-       int pixel_formats;
-       int use_cif_resolution;
-       int cif_width;
-};
-
-struct cx25821_dev {
-       struct list_head devlist;
-       atomic_t refcount;
-       struct v4l2_device v4l2_dev;
-
-       /* pci stuff */
-       struct pci_dev *pci;
-       unsigned char pci_rev, pci_lat;
-       int pci_bus, pci_slot;
-       u32 base_io_addr;
-       u32 __iomem *lmmio;
-       u8 __iomem *bmmio;
-       int pci_irqmask;
-       int hwrevision;
-
-       u32 clk_freq;
-
-       /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
-       struct cx25821_i2c i2c_bus[3];
-
-       int nr;
-       struct mutex lock;
-
-       struct cx25821_channel channels[MAX_VID_CHANNEL_NUM];
-
-       /* board details */
-       unsigned int board;
-       char name[32];
-
-       /* Analog video */
-       u32 resources;
-       unsigned int input;
-       u32 tvaudio;
-       v4l2_std_id tvnorm;
-       unsigned int tuner_type;
-       unsigned char tuner_addr;
-       unsigned int radio_type;
-       unsigned char radio_addr;
-       unsigned int has_radio;
-       unsigned int videc_type;
-       unsigned char videc_addr;
-       unsigned short _max_num_decoders;
-
-       /* Analog Audio Upstream */
-       int _audio_is_running;
-       int _audiopixel_format;
-       int _is_first_audio_frame;
-       int _audiofile_status;
-       int _audio_lines_count;
-       int _audioframe_count;
-       int _audio_upstream_channel;
-       int _last_index_irq;    /* The last interrupt index processed. */
-
-       __le32 *_risc_audio_jmp_addr;
-       __le32 *_risc_virt_start_addr;
-       __le32 *_risc_virt_addr;
-       dma_addr_t _risc_phys_addr;
-       dma_addr_t _risc_phys_start_addr;
-
-       unsigned int _audiorisc_size;
-       unsigned int _audiodata_buf_size;
-       __le32 *_audiodata_buf_virt_addr;
-       dma_addr_t _audiodata_buf_phys_addr;
-       char *_audiofilename;
-
-       /* V4l */
-       u32 freq;
-       struct video_device *vbi_dev;
-       struct video_device *radio_dev;
-       struct video_device *ioctl_dev;
-
-       spinlock_t slock;
-
-       /* Video Upstream */
-       int _line_size;
-       int _prog_cnt;
-       int _pixel_format;
-       int _is_first_frame;
-       int _is_running;
-       int _file_status;
-       int _lines_count;
-       int _frame_count;
-       int _channel_upstream_select;
-       unsigned int _risc_size;
-
-       __le32 *_dma_virt_start_addr;
-       __le32 *_dma_virt_addr;
-       dma_addr_t _dma_phys_addr;
-       dma_addr_t _dma_phys_start_addr;
-
-       unsigned int _data_buf_size;
-       __le32 *_data_buf_virt_addr;
-       dma_addr_t _data_buf_phys_addr;
-       char *_filename;
-       char *_defaultname;
-
-       int _line_size_ch2;
-       int _prog_cnt_ch2;
-       int _pixel_format_ch2;
-       int _is_first_frame_ch2;
-       int _is_running_ch2;
-       int _file_status_ch2;
-       int _lines_count_ch2;
-       int _frame_count_ch2;
-       int _channel2_upstream_select;
-       unsigned int _risc_size_ch2;
-
-       __le32 *_dma_virt_start_addr_ch2;
-       __le32 *_dma_virt_addr_ch2;
-       dma_addr_t _dma_phys_addr_ch2;
-       dma_addr_t _dma_phys_start_addr_ch2;
-
-       unsigned int _data_buf_size_ch2;
-       __le32 *_data_buf_virt_addr_ch2;
-       dma_addr_t _data_buf_phys_addr_ch2;
-       char *_filename_ch2;
-       char *_defaultname_ch2;
-
-       /* MPEG Encoder ONLY settings */
-       u32 cx23417_mailbox;
-       struct cx2341x_mpeg_params mpeg_params;
-       struct video_device *v4l_device;
-       atomic_t v4l_reader_count;
-       struct cx25821_tvnorm encodernorm;
-
-       u32 upstream_riscbuf_size;
-       u32 upstream_databuf_size;
-       u32 upstream_riscbuf_size_ch2;
-       u32 upstream_databuf_size_ch2;
-       u32 audio_upstream_riscbuf_size;
-       u32 audio_upstream_databuf_size;
-       int _isNTSC;
-       int _frame_index;
-       int _audioframe_index;
-       struct workqueue_struct *_irq_queues;
-       struct work_struct _irq_work_entry;
-       struct workqueue_struct *_irq_queues_ch2;
-       struct work_struct _irq_work_entry_ch2;
-       struct workqueue_struct *_irq_audio_queues;
-       struct work_struct _audio_work_entry;
-       char *input_filename;
-       char *input_filename_ch2;
-       int _frame_index_ch2;
-       int _isNTSC_ch2;
-       char *vid_stdname_ch2;
-       int pixel_format_ch2;
-       int channel_select_ch2;
-       int command_ch2;
-       char *input_audiofilename;
-       char *vid_stdname;
-       int pixel_format;
-       int channel_select;
-       int command;
-       int channel_opened;
-};
-
-struct upstream_user_struct {
-       char *input_filename;
-       char *vid_stdname;
-       int pixel_format;
-       int channel_select;
-       int command;
-};
-
-struct downstream_user_struct {
-       char *vid_stdname;
-       int pixel_format;
-       int cif_resolution_enable;
-       int cif_width;
-       int decoder_select;
-       int command;
-       int reg_address;
-       int reg_data;
-};
-
-extern struct upstream_user_struct *up_data;
-
-static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
-}
-
-#define cx25821_call_all(dev, o, f, args...) \
-       v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
-
-extern struct list_head cx25821_devlist;
-extern struct mutex cx25821_devlist_mutex;
-
-extern struct cx25821_board cx25821_boards[];
-extern struct cx25821_subid cx25821_subids[];
-
-#define SRAM_CH00  0           /* Video A */
-#define SRAM_CH01  1           /* Video B */
-#define SRAM_CH02  2           /* Video C */
-#define SRAM_CH03  3           /* Video D */
-#define SRAM_CH04  4           /* Video E */
-#define SRAM_CH05  5           /* Video F */
-#define SRAM_CH06  6           /* Video G */
-#define SRAM_CH07  7           /* Video H */
-
-#define SRAM_CH08  8           /* Audio A */
-#define SRAM_CH09  9           /* Video Upstream I */
-#define SRAM_CH10  10          /* Video Upstream J */
-#define SRAM_CH11  11          /* Audio Upstream AUD_CHANNEL_B */
-
-#define VID_UPSTREAM_SRAM_CHANNEL_I     SRAM_CH09
-#define VID_UPSTREAM_SRAM_CHANNEL_J     SRAM_CH10
-#define AUDIO_UPSTREAM_SRAM_CHANNEL_B   SRAM_CH11
-#define VIDEO_IOCTL_CH  11
-
-struct sram_channel {
-       char *name;
-       u32 i;
-       u32 cmds_start;
-       u32 ctrl_start;
-       u32 cdt;
-       u32 fifo_start;
-       u32 fifo_size;
-       u32 ptr1_reg;
-       u32 ptr2_reg;
-       u32 cnt1_reg;
-       u32 cnt2_reg;
-       u32 int_msk;
-       u32 int_stat;
-       u32 int_mstat;
-       u32 dma_ctl;
-       u32 gpcnt_ctl;
-       u32 gpcnt;
-       u32 aud_length;
-       u32 aud_cfg;
-       u32 fld_aud_fifo_en;
-       u32 fld_aud_risc_en;
-
-       /* For Upstream Video */
-       u32 vid_fmt_ctl;
-       u32 vid_active_ctl1;
-       u32 vid_active_ctl2;
-       u32 vid_cdt_size;
-
-       u32 vip_ctl;
-       u32 pix_frmt;
-       u32 jumponly;
-       u32 irq_bit;
-};
-extern struct sram_channel cx25821_sram_channels[];
-
-#define STATUS_SUCCESS         0
-#define STATUS_UNSUCCESSFUL    -1
-
-#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
-#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
-
-#define cx_andor(reg, mask, value) \
-       writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
-       ((value) & (mask)), dev->lmmio+((reg)>>2))
-
-#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
-#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
-
-#define Set_GPIO_Bit(Bit)                       (1 << Bit)
-#define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
-
-#define CX25821_ERR(fmt, args...)                      \
-       pr_err("(%d): " fmt, dev->board, ##args)
-#define CX25821_WARN(fmt, args...)                     \
-       pr_warn("(%d): " fmt, dev->board, ##args)
-#define CX25821_INFO(fmt, args...)                     \
-       pr_info("(%d): " fmt, dev->board, ##args)
-
-extern int cx25821_i2c_register(struct cx25821_i2c *bus);
-extern void cx25821_card_setup(struct cx25821_dev *dev);
-extern int cx25821_ir_init(struct cx25821_dev *dev);
-extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
-extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
-extern int cx25821_i2c_unregister(struct cx25821_i2c *bus);
-extern void cx25821_gpio_init(struct cx25821_dev *dev);
-extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
-                                         int pin_number, int pin_logic_value);
-
-extern int medusa_video_init(struct cx25821_dev *dev);
-extern int medusa_set_videostandard(struct cx25821_dev *dev);
-extern void medusa_set_resolution(struct cx25821_dev *dev, int width,
-                                 int decoder_select);
-extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness,
-                                int decoder);
-extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast,
-                              int decoder);
-extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
-extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation,
-                                int decoder);
-
-extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
-                                     struct sram_channel *ch, unsigned int bpl,
-                                     u32 risc);
-
-extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                              struct scatterlist *sglist,
-                              unsigned int top_offset,
-                              unsigned int bottom_offset,
-                              unsigned int bpl,
-                              unsigned int padding, unsigned int lines);
-extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
-                                        struct btcx_riscmem *risc,
-                                        struct scatterlist *sglist,
-                                        unsigned int bpl,
-                                        unsigned int lines, unsigned int lpi);
-extern void cx25821_free_buffer(struct videobuf_queue *q,
-                               struct cx25821_buffer *buf);
-extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-                               u32 reg, u32 mask, u32 value);
-extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
-                                     struct sram_channel *ch);
-extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
-                                           struct sram_channel *ch);
-
-extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci);
-extern void cx25821_print_irqbits(char *name, char *tag, char **strings,
-                                 int len, u32 bits, u32 mask);
-extern void cx25821_dev_unregister(struct cx25821_dev *dev);
-extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
-                                           struct sram_channel *ch,
-                                           unsigned int bpl, u32 risc);
-
-extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev,
-                                       int channel_select, int pixel_format);
-extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev,
-                                       int channel_select, int pixel_format);
-extern int cx25821_audio_upstream_init(struct cx25821_dev *dev,
-                                      int channel_select);
-extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);
-extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);
-extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);
-extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
-                                            struct upstream_user_struct
-                                            *up_data);
-extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
-                                            struct upstream_user_struct
-                                            *up_data);
-extern void cx25821_start_upstream_audio(struct cx25821_dev *dev,
-                                        struct upstream_user_struct *up_data);
-extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);
-extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);
-extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev);
-extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
-                                              struct sram_channel *ch,
-                                              unsigned int bpl, u32 risc);
-extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
-                                    u32 format);
-extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
-extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
-                                             struct pci_dev *pci,
-                                             struct video_device *template,
-                                             char *type);
-#endif
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
deleted file mode 100644 (file)
index 3598dc0..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-config VIDEO_CX88
-       tristate "Conexant 2388x (bt878 successor) support"
-       depends on VIDEO_DEV && PCI && I2C && RC_CORE
-       select I2C_ALGOBIT
-       select VIDEO_BTCX
-       select VIDEOBUF_DMA_SG
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         This is a video4linux driver for Conexant 2388x based
-         TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx8800
-
-config VIDEO_CX88_ALSA
-       tristate "Conexant 2388x DMA audio support"
-       depends on VIDEO_CX88 && SND
-       select SND_PCM
-       ---help---
-         This is a video4linux driver for direct (DMA) audio on
-         Conexant 2388x based TV cards using ALSA.
-
-         It only works with boards with function 01 enabled.
-         To check if your board supports, use lspci -n.
-         If supported, you should see 14f1:8801 or 14f1:8811
-         PCI device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx88-alsa.
-
-config VIDEO_CX88_BLACKBIRD
-       tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
-       depends on VIDEO_CX88
-       select VIDEO_CX2341X
-       ---help---
-         This adds support for MPEG encoder cards based on the
-         Blackbird reference design, using the Conexant 2388x
-         and 23416 chips.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx88-blackbird.
-
-config VIDEO_CX88_DVB
-       tristate "DVB/ATSC Support for cx2388x based TV cards"
-       depends on VIDEO_CX88 && DVB_CORE
-       select VIDEOBUF_DVB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_OR51132 if !DVB_FE_CUSTOMISE
-       select DVB_CX22702 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_NXT200X if !DVB_FE_CUSTOMISE
-       select DVB_CX24123 if !DVB_FE_CUSTOMISE
-       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_STV0288 if !DVB_FE_CUSTOMISE
-       select DVB_STB6000 if !DVB_FE_CUSTOMISE
-       select DVB_STV0900 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         This adds support for DVB/ATSC cards based on the
-         Conexant 2388x chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx88-dvb.
-
-config VIDEO_CX88_VP3054
-       tristate "VP-3054 Secondary I2C Bus Support"
-       default m
-       depends on VIDEO_CX88_DVB && DVB_MT352
-       ---help---
-         This adds DVB-T support for cards based on the
-         Conexant 2388x chip and the MT352 demodulator,
-         which also require support for the VP-3054
-         Secondary I2C bus, such at DNTV Live! DVB-T Pro.
-
-config VIDEO_CX88_MPEG
-       tristate
-       depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
-       default y
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
deleted file mode 100644 (file)
index 884b4cd..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-cx88xx-objs    := cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
-                  cx88-dsp.o cx88-input.o
-cx8800-objs    := cx88-video.o cx88-vbi.o
-cx8802-objs    := cx88-mpeg.o
-
-obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o
-obj-$(CONFIG_VIDEO_CX88_MPEG) += cx8802.o
-obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
-obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
-obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
deleted file mode 100644 (file)
index 3aa6856..0000000
+++ /dev/null
@@ -1,975 +0,0 @@
-/*
- *
- *  Support for audio capture
- *  PCI function #1 of the cx2388x.
- *
- *    (c) 2007 Trent Piepho <xyzzy@speakeasy.org>
- *    (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
- *    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
- *    Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
- *    Based on dummy.c by Jaroslav Kysela <perex@perex.cz>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  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/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/dma-mapping.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/delay.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-#include <media/wm8775.h>
-
-#include "cx88.h"
-#include "cx88-reg.h"
-
-#define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
-
-#define dprintk_core(level,fmt, arg...)        if (debug >= level) \
-       printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
-
-/****************************************************************************
-       Data type declarations - Can be moded to a header file later
- ****************************************************************************/
-
-struct cx88_audio_buffer {
-       unsigned int               bpl;
-       struct btcx_riscmem        risc;
-       struct videobuf_dmabuf     dma;
-};
-
-struct cx88_audio_dev {
-       struct cx88_core           *core;
-       struct cx88_dmaqueue       q;
-
-       /* pci i/o */
-       struct pci_dev             *pci;
-
-       /* audio controls */
-       int                        irq;
-
-       struct snd_card            *card;
-
-       spinlock_t                 reg_lock;
-       atomic_t                   count;
-
-       unsigned int               dma_size;
-       unsigned int               period_size;
-       unsigned int               num_periods;
-
-       struct videobuf_dmabuf     *dma_risc;
-
-       struct cx88_audio_buffer   *buf;
-
-       struct snd_pcm_substream   *substream;
-};
-typedef struct cx88_audio_dev snd_cx88_card_t;
-
-
-
-/****************************************************************************
-                       Module global static vars
- ****************************************************************************/
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;        /* ID for this card */
-static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
-
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
-
-
-/****************************************************************************
-                               Module macros
- ****************************************************************************/
-
-MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
-MODULE_AUTHOR("Ricardo Cerqueira");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CX88_VERSION);
-
-MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
-                       "{{Conexant,23882},"
-                       "{{Conexant,23883}");
-static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
-
-/****************************************************************************
-                       Module specific funtions
- ****************************************************************************/
-
-/*
- * BOARD Specific: Sets audio DMA
- */
-
-static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
-{
-       struct cx88_audio_buffer *buf = chip->buf;
-       struct cx88_core *core=chip->core;
-       const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
-
-       /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
-       cx_clear(MO_AUD_DMACNTRL, 0x11);
-
-       /* setup fifo + format - out channel */
-       cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma);
-
-       /* sets bpl size */
-       cx_write(MO_AUDD_LNGTH, buf->bpl);
-
-       /* reset counter */
-       cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
-       atomic_set(&chip->count, 0);
-
-       dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
-               "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1,
-               chip->num_periods, buf->bpl * chip->num_periods);
-
-       /* Enables corresponding bits at AUD_INT_STAT */
-       cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
-                               AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
-
-       /* Clean any pending interrupt bits already set */
-       cx_write(MO_AUD_INTSTAT, ~0);
-
-       /* enable audio irqs */
-       cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
-
-       /* start dma */
-       cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
-       cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
-
-       if (debug)
-               cx88_sram_channel_dump(chip->core, audio_ch);
-
-       return 0;
-}
-
-/*
- * BOARD Specific: Resets audio DMA
- */
-static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
-{
-       struct cx88_core *core=chip->core;
-       dprintk(1, "Stopping audio DMA\n");
-
-       /* stop dma */
-       cx_clear(MO_AUD_DMACNTRL, 0x11);
-
-       /* disable irqs */
-       cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
-       cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
-                               AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
-
-       if (debug)
-               cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
-
-       return 0;
-}
-
-#define MAX_IRQ_LOOP 50
-
-/*
- * BOARD Specific: IRQ dma bits
- */
-static const char *cx88_aud_irqs[32] = {
-       "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
-       NULL,                                     /* reserved */
-       "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
-       NULL,                                     /* reserved */
-       "dnf_of", "upf_uf", "rds_dnf_uf",         /* 8-10 */
-       NULL,                                     /* reserved */
-       "dn_sync", "up_sync", "rds_dn_sync",      /* 12-14 */
-       NULL,                                     /* reserved */
-       "opc_err", "par_err", "rip_err",          /* 16-18 */
-       "pci_abort", "ber_irq", "mchg_irq"        /* 19-21 */
-};
-
-/*
- * BOARD Specific: Threats IRQ audio specific calls
- */
-static void cx8801_aud_irq(snd_cx88_card_t *chip)
-{
-       struct cx88_core *core = chip->core;
-       u32 status, mask;
-
-       status = cx_read(MO_AUD_INTSTAT);
-       mask   = cx_read(MO_AUD_INTMSK);
-       if (0 == (status & mask))
-               return;
-       cx_write(MO_AUD_INTSTAT, status);
-       if (debug > 1  ||  (status & mask & ~0xff))
-               cx88_print_irqbits(core->name, "irq aud",
-                                  cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
-                                  status, mask);
-       /* risc op code error */
-       if (status & AUD_INT_OPC_ERR) {
-               printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name);
-               cx_clear(MO_AUD_DMACNTRL, 0x11);
-               cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
-       }
-       if (status & AUD_INT_DN_SYNC) {
-               dprintk(1, "Downstream sync error\n");
-               cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
-               return;
-       }
-       /* risc1 downstream */
-       if (status & AUD_INT_DN_RISCI1) {
-               atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT));
-               snd_pcm_period_elapsed(chip->substream);
-       }
-       /* FIXME: Any other status should deserve a special handling? */
-}
-
-/*
- * BOARD Specific: Handles IRQ calls
- */
-static irqreturn_t cx8801_irq(int irq, void *dev_id)
-{
-       snd_cx88_card_t *chip = dev_id;
-       struct cx88_core *core = chip->core;
-       u32 status;
-       int loop, handled = 0;
-
-       for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
-               status = cx_read(MO_PCI_INTSTAT) &
-                       (core->pci_irqmask | PCI_INT_AUDINT);
-               if (0 == status)
-                       goto out;
-               dprintk(3, "cx8801_irq loop %d/%d, status %x\n",
-                       loop, MAX_IRQ_LOOP, status);
-               handled = 1;
-               cx_write(MO_PCI_INTSTAT, status);
-
-               if (status & core->pci_irqmask)
-                       cx88_core_irq(core, status);
-               if (status & PCI_INT_AUDINT)
-                       cx8801_aud_irq(chip);
-       }
-
-       if (MAX_IRQ_LOOP == loop) {
-               printk(KERN_ERR
-                      "%s/1: IRQ loop detected, disabling interrupts\n",
-                      core->name);
-               cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
-       }
-
- out:
-       return IRQ_RETVAL(handled);
-}
-
-
-static int dsp_buffer_free(snd_cx88_card_t *chip)
-{
-       BUG_ON(!chip->dma_size);
-
-       dprintk(2,"Freeing buffer\n");
-       videobuf_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);
-
-       chip->dma_risc = NULL;
-       chip->dma_size = 0;
-
-       return 0;
-}
-
-/****************************************************************************
-                               ALSA PCM Interface
- ****************************************************************************/
-
-/*
- * Digital hardware definition
- */
-#define DEFAULT_FIFO_SIZE      4096
-static const struct snd_pcm_hardware snd_cx88_digital_hw = {
-       .info = SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP_VALID,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates =                SNDRV_PCM_RATE_48000,
-       .rate_min =             48000,
-       .rate_max =             48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       /* Analog audio output will be full of clicks and pops if there
-          are not exactly four lines in the SRAM FIFO buffer.  */
-       .period_bytes_min = DEFAULT_FIFO_SIZE/4,
-       .period_bytes_max = DEFAULT_FIFO_SIZE/4,
-       .periods_min = 1,
-       .periods_max = 1024,
-       .buffer_bytes_max = (1024*1024),
-};
-
-/*
- * audio pcm capture open callback
- */
-static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
-{
-       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int err;
-
-       if (!chip) {
-               printk(KERN_ERR "BUG: cx88 can't find device struct."
-                               " Can't proceed with open\n");
-               return -ENODEV;
-       }
-
-       err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
-       if (err < 0)
-               goto _error;
-
-       chip->substream = substream;
-
-       runtime->hw = snd_cx88_digital_hw;
-
-       if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) {
-               unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
-               bpl &= ~7; /* must be multiple of 8 */
-               runtime->hw.period_bytes_min = bpl;
-               runtime->hw.period_bytes_max = bpl;
-       }
-
-       return 0;
-_error:
-       dprintk(1,"Error opening PCM!\n");
-       return err;
-}
-
-/*
- * audio close callback
- */
-static int snd_cx88_close(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
-/*
- * hw_params callback
- */
-static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
-                             struct snd_pcm_hw_params * hw_params)
-{
-       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
-       struct videobuf_dmabuf *dma;
-
-       struct cx88_audio_buffer *buf;
-       int ret;
-
-       if (substream->runtime->dma_area) {
-               dsp_buffer_free(chip);
-               substream->runtime->dma_area = NULL;
-       }
-
-       chip->period_size = params_period_bytes(hw_params);
-       chip->num_periods = params_periods(hw_params);
-       chip->dma_size = chip->period_size * params_periods(hw_params);
-
-       BUG_ON(!chip->dma_size);
-       BUG_ON(chip->num_periods & (chip->num_periods-1));
-
-       buf = kzalloc(sizeof(*buf), GFP_KERNEL);
-       if (NULL == buf)
-               return -ENOMEM;
-
-       buf->bpl = chip->period_size;
-
-       dma = &buf->dma;
-       videobuf_dma_init(dma);
-       ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
-                       (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
-       if (ret < 0)
-               goto error;
-
-       ret = videobuf_dma_map(&chip->pci->dev, dma);
-       if (ret < 0)
-               goto error;
-
-       ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
-                                  chip->period_size, chip->num_periods, 1);
-       if (ret < 0)
-               goto error;
-
-       /* Loop back to start of program */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-
-       chip->buf = buf;
-       chip->dma_risc = dma;
-
-       substream->runtime->dma_area = chip->dma_risc->vaddr;
-       substream->runtime->dma_bytes = chip->dma_size;
-       substream->runtime->dma_addr = 0;
-       return 0;
-
-error:
-       kfree(buf);
-       return ret;
-}
-
-/*
- * hw free callback
- */
-static int snd_cx88_hw_free(struct snd_pcm_substream * substream)
-{
-
-       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
-
-       if (substream->runtime->dma_area) {
-               dsp_buffer_free(chip);
-               substream->runtime->dma_area = NULL;
-       }
-
-       return 0;
-}
-
-/*
- * prepare callback
- */
-static int snd_cx88_prepare(struct snd_pcm_substream *substream)
-{
-       return 0;
-}
-
-/*
- * trigger callback
- */
-static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
-       int err;
-
-       /* Local interrupts are already disabled by ALSA */
-       spin_lock(&chip->reg_lock);
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               err=_cx88_start_audio_dma(chip);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               err=_cx88_stop_audio_dma(chip);
-               break;
-       default:
-               err=-EINVAL;
-               break;
-       }
-
-       spin_unlock(&chip->reg_lock);
-
-       return err;
-}
-
-/*
- * pointer callback
- */
-static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
-{
-       snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       u16 count;
-
-       count = atomic_read(&chip->count);
-
-//     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));
-}
-
-/*
- * page callback (needed for mmap)
- */
-static struct page *snd_cx88_page(struct snd_pcm_substream *substream,
-                               unsigned long offset)
-{
-       void *pageptr = substream->runtime->dma_area + offset;
-       return vmalloc_to_page(pageptr);
-}
-
-/*
- * operators
- */
-static struct snd_pcm_ops snd_cx88_pcm_ops = {
-       .open = snd_cx88_pcm_open,
-       .close = snd_cx88_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_cx88_hw_params,
-       .hw_free = snd_cx88_hw_free,
-       .prepare = snd_cx88_prepare,
-       .trigger = snd_cx88_card_trigger,
-       .pointer = snd_cx88_pointer,
-       .page = snd_cx88_page,
-};
-
-/*
- * create a PCM device
- */
-static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
-{
-       int err;
-       struct snd_pcm *pcm;
-
-       err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
-       if (err < 0)
-               return err;
-       pcm->private_data = chip;
-       strcpy(pcm->name, name);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);
-
-       return 0;
-}
-
-/****************************************************************************
-                               CONTROL INTERFACE
- ****************************************************************************/
-static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_info *info)
-{
-       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       info->count = 2;
-       info->value.integer.min = 0;
-       info->value.integer.max = 0x3f;
-
-       return 0;
-}
-
-static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core=chip->core;
-       int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
-           bal = cx_read(AUD_BAL_CTL);
-
-       value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol;
-       vol -= (bal & 0x3f);
-       value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol;
-
-       return 0;
-}
-
-static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       int left = value->value.integer.value[0];
-       int right = value->value.integer.value[1];
-       int v, b;
-
-       /* Pass volume & balance onto any WM8775 */
-       if (left >= right) {
-               v = left << 10;
-               b = left ? (0x8000 * right) / left : 0x8000;
-       } else {
-               v = right << 10;
-               b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
-       }
-       wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
-       wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
-}
-
-/* OK - TODO: test it */
-static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core=chip->core;
-       int left, right, v, b;
-       int changed = 0;
-       u32 old;
-
-       if (core->board.audio_chip == V4L2_IDENT_WM8775)
-               snd_cx88_wm8775_volume_put(kcontrol, value);
-
-       left = value->value.integer.value[0] & 0x3f;
-       right = value->value.integer.value[1] & 0x3f;
-       b = right - left;
-       if (b < 0) {
-               v = 0x3f - left;
-               b = (-b) | 0x40;
-       } else {
-               v = 0x3f - right;
-       }
-       /* Do we really know this will always be called with IRQs on? */
-       spin_lock_irq(&chip->reg_lock);
-       old = cx_read(AUD_VOL_CTL);
-       if (v != (old & 0x3f)) {
-               cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
-               changed = 1;
-       }
-       if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
-               cx_write(AUD_BAL_CTL, b);
-               changed = 1;
-       }
-       spin_unlock_irq(&chip->reg_lock);
-
-       return changed;
-}
-
-static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
-
-static const struct snd_kcontrol_new snd_cx88_volume = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-       .name = "Analog-TV Volume",
-       .info = snd_cx88_volume_info,
-       .get = snd_cx88_volume_get,
-       .put = snd_cx88_volume_put,
-       .tlv.p = snd_cx88_db_scale,
-};
-
-static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       u32 bit = kcontrol->private_value;
-
-       value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit);
-       return 0;
-}
-
-static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
-                                      struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       u32 bit = kcontrol->private_value;
-       int ret = 0;
-       u32 vol;
-
-       spin_lock_irq(&chip->reg_lock);
-       vol = cx_read(AUD_VOL_CTL);
-       if (value->value.integer.value[0] != !(vol & bit)) {
-               vol ^= bit;
-               cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
-               /* Pass mute onto any WM8775 */
-               if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
-                   ((1<<6) == bit))
-                       wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
-               ret = 1;
-       }
-       spin_unlock_irq(&chip->reg_lock);
-       return ret;
-}
-
-static const struct snd_kcontrol_new snd_cx88_dac_switch = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Audio-Out Switch",
-       .info = snd_ctl_boolean_mono_info,
-       .get = snd_cx88_switch_get,
-       .put = snd_cx88_switch_put,
-       .private_value = (1<<8),
-};
-
-static const struct snd_kcontrol_new snd_cx88_source_switch = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Analog-TV Switch",
-       .info = snd_ctl_boolean_mono_info,
-       .get = snd_cx88_switch_get,
-       .put = snd_cx88_switch_put,
-       .private_value = (1<<6),
-};
-
-static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       s32 val;
-
-       val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
-       value->value.integer.value[0] = val ? 1 : 0;
-       return 0;
-}
-
-static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
-                                      struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       struct v4l2_control client_ctl;
-
-       memset(&client_ctl, 0, sizeof(client_ctl));
-       client_ctl.value = 0 != value->value.integer.value[0];
-       client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
-       call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
-       return 0;
-}
-
-static struct snd_kcontrol_new snd_cx88_alc_switch = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Line-In ALC Switch",
-       .info = snd_ctl_boolean_mono_info,
-       .get = snd_cx88_alc_get,
-       .put = snd_cx88_alc_put,
-};
-
-/****************************************************************************
-                       Basic Flow for Sound Devices
- ****************************************************************************/
-
-/*
- * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
- * Only boards with eeprom and byte 1 at eeprom=1 have it
- */
-
-static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
-       {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
-       {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
-       {0, }
-};
-MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
-
-/*
- * Chip-specific destructor
- */
-
-static int snd_cx88_free(snd_cx88_card_t *chip)
-{
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, chip);
-
-       cx88_core_put(chip->core,chip->pci);
-
-       pci_disable_device(chip->pci);
-       return 0;
-}
-
-/*
- * Component Destructor
- */
-static void snd_cx88_dev_free(struct snd_card * card)
-{
-       snd_cx88_card_t *chip = card->private_data;
-
-       snd_cx88_free(chip);
-}
-
-
-/*
- * Alsa Constructor - Component probe
- */
-
-static int devno;
-static int __devinit snd_cx88_create(struct snd_card *card,
-                                    struct pci_dev *pci,
-                                    snd_cx88_card_t **rchip,
-                                    struct cx88_core **core_ptr)
-{
-       snd_cx88_card_t   *chip;
-       struct cx88_core  *core;
-       int               err;
-       unsigned char     pci_lat;
-
-       *rchip = NULL;
-
-       err = pci_enable_device(pci);
-       if (err < 0)
-               return err;
-
-       pci_set_master(pci);
-
-       chip = card->private_data;
-
-       core = cx88_core_get(pci);
-       if (NULL == core) {
-               err = -EINVAL;
-               return err;
-       }
-
-       if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
-               dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
-               err = -EIO;
-               cx88_core_put(core, pci);
-               return err;
-       }
-
-
-       /* pci init */
-       chip->card = card;
-       chip->pci = pci;
-       chip->irq = -1;
-       spin_lock_init(&chip->reg_lock);
-
-       chip->core = core;
-
-       /* get irq */
-       err = request_irq(chip->pci->irq, cx8801_irq,
-                         IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip);
-       if (err < 0) {
-               dprintk(0, "%s: can't get IRQ %d\n",
-                      chip->core->name, chip->pci->irq);
-               return err;
-       }
-
-       /* print pci info */
-       pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat);
-
-       dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
-              "latency: %d, mmio: 0x%llx\n", core->name, devno,
-              pci_name(pci), pci->revision, pci->irq,
-              pci_lat, (unsigned long long)pci_resource_start(pci,0));
-
-       chip->irq = pci->irq;
-       synchronize_irq(chip->irq);
-
-       snd_card_set_dev(card, &pci->dev);
-
-       *rchip = chip;
-       *core_ptr = core;
-
-       return 0;
-}
-
-static int __devinit cx88_audio_initdev(struct pci_dev *pci,
-                                   const struct pci_device_id *pci_id)
-{
-       struct snd_card  *card;
-       snd_cx88_card_t  *chip;
-       struct cx88_core *core = NULL;
-       int              err;
-
-       if (devno >= SNDRV_CARDS)
-               return (-ENODEV);
-
-       if (!enable[devno]) {
-               ++devno;
-               return (-ENOENT);
-       }
-
-       err = snd_card_create(index[devno], id[devno], THIS_MODULE,
-                             sizeof(snd_cx88_card_t), &card);
-       if (err < 0)
-               return err;
-
-       card->private_free = snd_cx88_dev_free;
-
-       err = snd_cx88_create(card, pci, &chip, &core);
-       if (err < 0)
-               goto error;
-
-       err = snd_cx88_pcm(chip, 0, "CX88 Digital");
-       if (err < 0)
-               goto error;
-
-       err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip));
-       if (err < 0)
-               goto error;
-       err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip));
-       if (err < 0)
-               goto error;
-       err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
-       if (err < 0)
-               goto error;
-
-       /* If there's a wm8775 then add a Line-In ALC switch */
-       if (core->board.audio_chip == V4L2_IDENT_WM8775)
-               snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
-
-       strcpy (card->driver, "CX88x");
-       sprintf(card->shortname, "Conexant CX%x", pci->device);
-       sprintf(card->longname, "%s at %#llx",
-               card->shortname,(unsigned long long)pci_resource_start(pci, 0));
-       strcpy (card->mixername, "CX88");
-
-       dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
-              card->driver,devno);
-
-       err = snd_card_register(card);
-       if (err < 0)
-               goto error;
-       pci_set_drvdata(pci,card);
-
-       devno++;
-       return 0;
-
-error:
-       snd_card_free(card);
-       return err;
-}
-/*
- * ALSA destructor
- */
-static void __devexit cx88_audio_finidev(struct pci_dev *pci)
-{
-       struct cx88_audio_dev *card = pci_get_drvdata(pci);
-
-       snd_card_free((void *)card);
-
-       pci_set_drvdata(pci, NULL);
-
-       devno--;
-}
-
-/*
- * PCI driver definition
- */
-
-static struct pci_driver cx88_audio_pci_driver = {
-       .name     = "cx88_audio",
-       .id_table = cx88_audio_pci_tbl,
-       .probe    = cx88_audio_initdev,
-       .remove   = __devexit_p(cx88_audio_finidev),
-};
-
-/****************************************************************************
-                               LINUX MODULE INIT
- ****************************************************************************/
-
-/*
- * module init
- */
-static int __init cx88_audio_init(void)
-{
-       printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
-              CX88_VERSION);
-       return pci_register_driver(&cx88_audio_pci_driver);
-}
-
-/*
- * module remove
- */
-static void __exit cx88_audio_fini(void)
-{
-       pci_unregister_driver(&cx88_audio_pci_driver);
-}
-
-module_init(cx88_audio_init);
-module_exit(cx88_audio_fini);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
deleted file mode 100644 (file)
index 843ffd9..0000000
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*
- *
- *  Support for a cx23416 mpeg encoder via cx2388x host port.
- *  "blackbird" reference design.
- *
- *    (c) 2004 Jelle Foks <jelle@foks.us>
- *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
- *
- *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
- *        - video_ioctl2 conversion
- *
- *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
- *
- *  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/slab.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-#include <media/cx2341x.h>
-
-#include "cx88.h"
-
-MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
-MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CX88_VERSION);
-
-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;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
-
-#define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
-
-
-/* ------------------------------------------------------------------ */
-
-#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
-
-/* defines below are from ivtv-driver.h */
-
-#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
-
-/* Firmware API commands */
-#define IVTV_API_STD_TIMEOUT 500
-
-enum blackbird_capture_type {
-       BLACKBIRD_MPEG_CAPTURE,
-       BLACKBIRD_RAW_CAPTURE,
-       BLACKBIRD_RAW_PASSTHRU_CAPTURE
-};
-enum blackbird_capture_bits {
-       BLACKBIRD_RAW_BITS_NONE             = 0x00,
-       BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
-       BLACKBIRD_RAW_BITS_PCM_CAPTURE      = 0x02,
-       BLACKBIRD_RAW_BITS_VBI_CAPTURE      = 0x04,
-       BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
-       BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
-};
-enum blackbird_capture_end {
-       BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
-       BLACKBIRD_END_NOW, /* stop immediately, no irq */
-};
-enum blackbird_framerate {
-       BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
-       BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
-};
-enum blackbird_stream_port {
-       BLACKBIRD_OUTPUT_PORT_MEMORY,
-       BLACKBIRD_OUTPUT_PORT_STREAMING,
-       BLACKBIRD_OUTPUT_PORT_SERIAL
-};
-enum blackbird_data_xfer_status {
-       BLACKBIRD_MORE_BUFFERS_FOLLOW,
-       BLACKBIRD_LAST_BUFFER,
-};
-enum blackbird_picture_mask {
-       BLACKBIRD_PICTURE_MASK_NONE,
-       BLACKBIRD_PICTURE_MASK_I_FRAMES,
-       BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
-       BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
-};
-enum blackbird_vbi_mode_bits {
-       BLACKBIRD_VBI_BITS_SLICED,
-       BLACKBIRD_VBI_BITS_RAW,
-};
-enum blackbird_vbi_insertion_bits {
-       BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
-       BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
-       BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
-       BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
-       BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
-};
-enum blackbird_dma_unit {
-       BLACKBIRD_DMA_BYTES,
-       BLACKBIRD_DMA_FRAMES,
-};
-enum blackbird_dma_transfer_status_bits {
-       BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
-       BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
-       BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
-};
-enum blackbird_pause {
-       BLACKBIRD_PAUSE_ENCODING,
-       BLACKBIRD_RESUME_ENCODING,
-};
-enum blackbird_copyright {
-       BLACKBIRD_COPYRIGHT_OFF,
-       BLACKBIRD_COPYRIGHT_ON,
-};
-enum blackbird_notification_type {
-       BLACKBIRD_NOTIFICATION_REFRESH,
-};
-enum blackbird_notification_status {
-       BLACKBIRD_NOTIFICATION_OFF,
-       BLACKBIRD_NOTIFICATION_ON,
-};
-enum blackbird_notification_mailbox {
-       BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
-};
-enum blackbird_field1_lines {
-       BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
-       BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
-       BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
-};
-enum blackbird_field2_lines {
-       BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
-       BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
-       BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
-};
-enum blackbird_custom_data_type {
-       BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
-       BLACKBIRD_CUSTOM_PRIVATE_PACKET,
-};
-enum blackbird_mute {
-       BLACKBIRD_UNMUTE,
-       BLACKBIRD_MUTE,
-};
-enum blackbird_mute_video_mask {
-       BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
-       BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
-       BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
-};
-enum blackbird_mute_video_shift {
-       BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
-       BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
-       BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
-};
-
-/* Registers */
-#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
-#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
-#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
-#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
-#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
-#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
-
-/* ------------------------------------------------------------------ */
-
-static void host_setup(struct cx88_core *core)
-{
-       /* toggle reset of the host */
-       cx_write(MO_GPHST_SOFT_RST, 1);
-       udelay(100);
-       cx_write(MO_GPHST_SOFT_RST, 0);
-       udelay(100);
-
-       /* host port setup */
-       cx_write(MO_GPHST_WSC, 0x44444444U);
-       cx_write(MO_GPHST_XFR, 0);
-       cx_write(MO_GPHST_WDTH, 15);
-       cx_write(MO_GPHST_HDSHK, 0);
-       cx_write(MO_GPHST_MUX16, 0x44448888U);
-       cx_write(MO_GPHST_MODE, 0);
-}
-
-/* ------------------------------------------------------------------ */
-
-#define P1_MDATA0 0x390000
-#define P1_MDATA1 0x390001
-#define P1_MDATA2 0x390002
-#define P1_MDATA3 0x390003
-#define P1_MADDR2 0x390004
-#define P1_MADDR1 0x390005
-#define P1_MADDR0 0x390006
-#define P1_RDATA0 0x390008
-#define P1_RDATA1 0x390009
-#define P1_RDATA2 0x39000A
-#define P1_RDATA3 0x39000B
-#define P1_RADDR0 0x39000C
-#define P1_RADDR1 0x39000D
-#define P1_RRDWR  0x39000E
-
-static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(1);
-       u32 gpio0,need;
-
-       need = state ? 2 : 0;
-       for (;;) {
-               gpio0 = cx_read(MO_GP0_IO) & 2;
-               if (need == gpio0)
-                       return 0;
-               if (time_after(jiffies,timeout))
-                       return -1;
-               udelay(1);
-       }
-}
-
-static int memory_write(struct cx88_core *core, u32 address, u32 value)
-{
-       /* Warning: address is dword address (4 bytes) */
-       cx_writeb(P1_MDATA0, (unsigned int)value);
-       cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
-       cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
-       cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
-       cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
-       cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
-       cx_writeb(P1_MADDR0, (unsigned int)address);
-       cx_read(P1_MDATA0);
-       cx_read(P1_MADDR0);
-
-       return wait_ready_gpio0_bit1(core,1);
-}
-
-static int memory_read(struct cx88_core *core, u32 address, u32 *value)
-{
-       int retval;
-       u32 val;
-
-       /* Warning: address is dword address (4 bytes) */
-       cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
-       cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
-       cx_writeb(P1_MADDR0, (unsigned int)address);
-       cx_read(P1_MADDR0);
-
-       retval = wait_ready_gpio0_bit1(core,1);
-
-       cx_writeb(P1_MDATA3, 0);
-       val     = (unsigned char)cx_read(P1_MDATA3) << 24;
-       cx_writeb(P1_MDATA2, 0);
-       val    |= (unsigned char)cx_read(P1_MDATA2) << 16;
-       cx_writeb(P1_MDATA1, 0);
-       val    |= (unsigned char)cx_read(P1_MDATA1) << 8;
-       cx_writeb(P1_MDATA0, 0);
-       val    |= (unsigned char)cx_read(P1_MDATA0);
-
-       *value  = val;
-       return retval;
-}
-
-static int register_write(struct cx88_core *core, u32 address, u32 value)
-{
-       cx_writeb(P1_RDATA0, (unsigned int)value);
-       cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
-       cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
-       cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
-       cx_writeb(P1_RADDR0, (unsigned int)address);
-       cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
-       cx_writeb(P1_RRDWR, 1);
-       cx_read(P1_RDATA0);
-       cx_read(P1_RADDR0);
-
-       return wait_ready_gpio0_bit1(core,1);
-}
-
-
-static int register_read(struct cx88_core *core, u32 address, u32 *value)
-{
-       int retval;
-       u32 val;
-
-       cx_writeb(P1_RADDR0, (unsigned int)address);
-       cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
-       cx_writeb(P1_RRDWR, 0);
-       cx_read(P1_RADDR0);
-
-       retval  = wait_ready_gpio0_bit1(core,1);
-       val     = (unsigned char)cx_read(P1_RDATA0);
-       val    |= (unsigned char)cx_read(P1_RDATA1) << 8;
-       val    |= (unsigned char)cx_read(P1_RDATA2) << 16;
-       val    |= (unsigned char)cx_read(P1_RDATA3) << 24;
-
-       *value  = val;
-       return retval;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
-{
-       struct cx8802_dev *dev = priv;
-       unsigned long timeout;
-       u32 value, flag, retval;
-       int i;
-
-       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 */
-       memory_read(dev->core, dev->mailbox - 4, &value);
-       if (value != 0x12345678) {
-               dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
-               return -1;
-       }
-
-       memory_read(dev->core, dev->mailbox, &flag);
-       if (flag) {
-               dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
-               return -1;
-       }
-
-       flag |= 1; /* tell 'em we're working on it */
-       memory_write(dev->core, dev->mailbox, flag);
-
-       /* write command + args + fill remaining with zeros */
-       memory_write(dev->core, dev->mailbox + 1, command); /* command code */
-       memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
-       for (i = 0; i < in; i++) {
-               memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
-               dprintk(1, "API Input %d = %d\n", i, data[i]);
-       }
-       for (; i < CX2341X_MBOX_MAX_DATA; i++)
-               memory_write(dev->core, dev->mailbox + 4 + i, 0);
-
-       flag |= 3; /* tell 'em we're done writing */
-       memory_write(dev->core, dev->mailbox, flag);
-
-       /* wait for firmware to handle the API command */
-       timeout = jiffies + msecs_to_jiffies(10);
-       for (;;) {
-               memory_read(dev->core, dev->mailbox, &flag);
-               if (0 != (flag & 4))
-                       break;
-               if (time_after(jiffies,timeout)) {
-                       dprintk(0, "ERROR: API Mailbox timeout\n");
-                       return -1;
-               }
-               udelay(10);
-       }
-
-       /* read output values */
-       for (i = 0; i < out; i++) {
-               memory_read(dev->core, dev->mailbox + 4 + i, data + i);
-               dprintk(1, "API Output %d = %d\n", i, data[i]);
-       }
-
-       memory_read(dev->core, dev->mailbox + 2, &retval);
-       dprintk(1, "API result = %d\n",retval);
-
-       flag = 0;
-       memory_write(dev->core, dev->mailbox, flag);
-       return retval;
-}
-/* ------------------------------------------------------------------ */
-
-/* We don't need to call the API often, so using just one mailbox will probably suffice */
-static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
-                            u32 inputcnt, u32 outputcnt, ...)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       va_list vargs;
-       int i, err;
-
-       va_start(vargs, outputcnt);
-
-       for (i = 0; i < inputcnt; i++) {
-               data[i] = va_arg(vargs, int);
-       }
-       err = blackbird_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 blackbird_find_mailbox(struct cx8802_dev *dev)
-{
-       u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
-       int signaturecnt=0;
-       u32 value;
-       int i;
-
-       for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
-               memory_read(dev->core, i, &value);
-               if (value == signature[signaturecnt])
-                       signaturecnt++;
-               else
-                       signaturecnt = 0;
-               if (4 == signaturecnt) {
-                       dprintk(1, "Mailbox signature found\n");
-                       return i+1;
-               }
-       }
-       dprintk(0, "Mailbox signature values not found!\n");
-       return -1;
-}
-
-static int blackbird_load_firmware(struct cx8802_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 checksum = 0;
-       u32 *dataptr;
-
-       retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
-       retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
-       retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
-       retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
-       msleep(1);
-       retval |= register_write(dev->core, IVTV_REG_APU, 0);
-
-       if (retval < 0)
-               dprintk(0, "Error with register_write\n");
-
-       retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
-                                 &dev->pci->dev);
-
-
-       if (retval != 0) {
-               dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
-                       CX2341X_FIRM_ENC_FILENAME);
-               dprintk(0, "Please fix your hotplug setup, the board will "
-                       "not work without firmware loaded!\n");
-               return -1;
-       }
-
-       if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
-               dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
-                       firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
-               release_firmware(firmware);
-               return -1;
-       }
-
-       if (0 != memcmp(firmware->data, magic, 8)) {
-               dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
-               release_firmware(firmware);
-               return -1;
-       }
-
-       /* transfer to the chip */
-       dprintk(1,"Loading firmware ...\n");
-       dataptr = (u32*)firmware->data;
-       for (i = 0; i < (firmware->size >> 2); i++) {
-               value = le32_to_cpu(*dataptr);
-               checksum += ~value;
-               memory_write(dev->core, i, value);
-               dataptr++;
-       }
-
-       /* read back to verify with the checksum */
-       for (i--; i >= 0; i--) {
-               memory_read(dev->core, i, &value);
-               checksum -= ~value;
-       }
-       if (checksum) {
-               dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
-               release_firmware(firmware);
-               return -1;
-       }
-       release_firmware(firmware);
-       dprintk(0, "Firmware upload successful.\n");
-
-       retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
-       retval |= register_read(dev->core, IVTV_REG_SPU, &value);
-       retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
-       msleep(1);
-
-       retval |= register_read(dev->core, IVTV_REG_VPU, &value);
-       retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
-
-       if (retval < 0)
-               dprintk(0, "Error with register_write\n");
-       return 0;
-}
-
-/**
- Settings used by the windows tv app for PVR2000:
-=================================================================================================================
-Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
------------------------------------------------------------------------------------------------------------------
-MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-=================================================================================================================
-*DB: "DirectBurn"
-*/
-
-static void blackbird_codec_settings(struct cx8802_dev *dev)
-{
-       /* assign frame size */
-       blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-                               dev->height, dev->width);
-
-       dev->cxhdl.width = dev->width;
-       dev->cxhdl.height = dev->height;
-       cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
-       cx2341x_handler_setup(&dev->cxhdl);
-}
-
-static int blackbird_initialize_codec(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       int version;
-       int retval;
-
-       dprintk(1,"Initialize codec\n");
-       retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
-       if (retval < 0) {
-
-               dev->mpeg_active = 0;
-
-               /* ping was not successful, reset and upload firmware */
-               cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
-               cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
-               retval = blackbird_load_firmware(dev);
-               if (retval < 0)
-                       return retval;
-
-               retval = blackbird_find_mailbox(dev);
-               if (retval < 0)
-                       return -1;
-
-               dev->mailbox = retval;
-
-               retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
-               if (retval < 0) {
-                       dprintk(0, "ERROR: Firmware ping failed!\n");
-                       return -1;
-               }
-
-               retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
-               if (retval < 0) {
-                       dprintk(0, "ERROR: Firmware get encoder version failed!\n");
-                       return -1;
-               }
-               dprintk(0, "Firmware version is 0x%08x\n", version);
-       }
-
-       cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
-       cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
-       cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
-       cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
-
-       blackbird_codec_settings(dev);
-
-       blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
-                       BLACKBIRD_FIELD1_SAA7115,
-                       BLACKBIRD_FIELD2_SAA7115
-               );
-
-       blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
-                       BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
-       return 0;
-}
-
-static int blackbird_start_codec(struct file *file, void *priv)
-{
-       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
-       struct cx88_core *core = dev->core;
-       /* start capturing to the host interface */
-       u32 reg;
-
-       int i;
-       int lastchange = -1;
-       int lastval = 0;
-
-       for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) {
-               reg = cx_read(AUD_STATUS);
-
-               dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg);
-               if ((reg & 0x0F) != lastval) {
-                       lastval = reg & 0x0F;
-                       lastchange = i;
-               }
-               msleep(100);
-       }
-
-       /* unmute audio source */
-       cx_clear(AUD_VOL_CTL, (1 << 6));
-
-       blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0);
-
-       /* initialize the video input */
-       blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
-
-       cx2341x_handler_set_busy(&dev->cxhdl, 1);
-
-       /* start capturing to the host interface */
-       blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
-                       BLACKBIRD_MPEG_CAPTURE,
-                       BLACKBIRD_RAW_BITS_NONE
-               );
-
-       dev->mpeg_active = 1;
-       return 0;
-}
-
-static int blackbird_stop_codec(struct cx8802_dev *dev)
-{
-       blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-                       BLACKBIRD_END_NOW,
-                       BLACKBIRD_MPEG_CAPTURE,
-                       BLACKBIRD_RAW_BITS_NONE
-               );
-
-       cx2341x_handler_set_busy(&dev->cxhdl, 0);
-
-       dev->mpeg_active = 0;
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int bb_buf_setup(struct videobuf_queue *q,
-                       unsigned int *count, unsigned int *size)
-{
-       struct cx8802_fh *fh = q->priv_data;
-
-       fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
-       fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
-
-       *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
-       *count = fh->dev->ts_packet_count;
-       return 0;
-}
-
-static int
-bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-              enum v4l2_field field)
-{
-       struct cx8802_fh *fh = q->priv_data;
-       return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
-}
-
-static void
-bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx8802_fh *fh = q->priv_data;
-       cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
-}
-
-static void
-bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       cx88_free_buffer(q, (struct cx88_buffer*)vb);
-}
-
-static struct videobuf_queue_ops blackbird_qops = {
-       .buf_setup    = bb_buf_setup,
-       .buf_prepare  = bb_buf_prepare,
-       .buf_queue    = bb_buf_queue,
-       .buf_release  = bb_buf_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
-       struct cx88_core  *core = dev->core;
-
-       strcpy(cap->driver, "cx88_blackbird");
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cx88_querycap(file, core, cap);
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, "MPEG", sizeof(f->description));
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx8802_dev *dev  = fh->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
-       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.width        = dev->width;
-       f->fmt.pix.height       = dev->height;
-       f->fmt.pix.field        = fh->mpegq.field;
-       dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
-               dev->width, dev->height, fh->mpegq.field );
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx8802_dev *dev  = fh->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
-       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
-               dev->width, dev->height, fh->mpegq.field );
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx8802_dev *dev  = fh->dev;
-       struct cx88_core  *core = dev->core;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
-       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
-       dev->width              = f->fmt.pix.width;
-       dev->height             = f->fmt.pix.height;
-       fh->mpegq.field         = f->fmt.pix.field;
-       cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-       blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-                               f->fmt.pix.height, f->fmt.pix.width);
-       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;
-}
-
-static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
-{
-       struct cx8802_fh  *fh   = priv;
-       return (videobuf_reqbufs(&fh->mpegq, p));
-}
-
-static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct cx8802_fh  *fh   = priv;
-       return (videobuf_querybuf(&fh->mpegq, p));
-}
-
-static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct cx8802_fh  *fh   = priv;
-       return (videobuf_qbuf(&fh->mpegq, p));
-}
-
-static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct cx8802_fh  *fh   = priv;
-       return (videobuf_dqbuf(&fh->mpegq, p,
-                               file->f_flags & O_NONBLOCK));
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx8802_dev *dev  = fh->dev;
-
-       if (!dev->mpeg_active)
-               blackbird_start_codec(file, fh);
-       return videobuf_streamon(&fh->mpegq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx8802_dev *dev  = fh->dev;
-
-       if (dev->mpeg_active)
-               blackbird_stop_codec(dev);
-       return videobuf_streamoff(&fh->mpegq);
-}
-
-static int vidioc_s_frequency (struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx8802_dev *dev  = fh->dev;
-       struct cx88_core  *core = dev->core;
-
-       if (unlikely(UNSET == core->board.tuner_type))
-               return -EINVAL;
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-       if (dev->mpeg_active)
-               blackbird_stop_codec(dev);
-
-       cx88_set_freq (core,f);
-       blackbird_initialize_codec(dev);
-       cx88_set_scale(dev->core, dev->width, dev->height,
-                       fh->mpegq.field);
-       return 0;
-}
-
-static int vidioc_log_status (struct file *file, void *priv)
-{
-       struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
-       struct cx88_core  *core = dev->core;
-       char name[32 + 2];
-
-       snprintf(name, sizeof(name), "%s/2", core->name);
-       call_all(core, core, log_status);
-       v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
-       return 0;
-}
-
-static int vidioc_enum_input (struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
-       return cx88_enum_input (core,i);
-}
-
-static int vidioc_g_frequency (struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct cx8802_fh  *fh   = priv;
-       struct cx88_core  *core = fh->dev->core;
-
-       if (unlikely(UNSET == core->board.tuner_type))
-               return -EINVAL;
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-
-       f->frequency = core->freq;
-       call_all(core, tuner, g_frequency, f);
-
-       return 0;
-}
-
-static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
-{
-       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
-
-       *i = core->input;
-       return 0;
-}
-
-static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
-{
-       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
-
-       if (i >= 4)
-               return -EINVAL;
-       if (0 == INPUT(i).type)
-               return -EINVAL;
-
-       mutex_lock(&core->lock);
-       cx88_newstation(core);
-       cx88_video_mux(core,i);
-       mutex_unlock(&core->lock);
-       return 0;
-}
-
-static int vidioc_g_tuner (struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
-       u32 reg;
-
-       if (unlikely(UNSET == core->board.tuner_type))
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Television");
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->rangehigh  = 0xffffffffUL;
-       call_all(core, tuner, g_tuner, t);
-
-       cx88_get_stereo(core ,t);
-       reg = cx_read(MO_DEVICE_STATUS);
-       t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
-       return 0;
-}
-
-static int vidioc_s_tuner (struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
-
-       if (UNSET == core->board.tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       cx88_set_stereo(core, t->audmode, 1);
-       return 0;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
-{
-       struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
-
-       *tvnorm = core->tvnorm;
-       return 0;
-}
-
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
-
-       mutex_lock(&core->lock);
-       cx88_set_tvnorm(core,*id);
-       mutex_unlock(&core->lock);
-       return 0;
-}
-
-/* FIXME: cx88_ioctl_hook not implemented */
-
-static int mpeg_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8802_dev *dev = video_drvdata(file);
-       struct cx8802_fh *fh;
-       struct cx8802_driver *drv = NULL;
-       int err;
-
-       dprintk( 1, "%s\n", __func__);
-
-       mutex_lock(&dev->core->lock);
-
-       /* Make sure we can acquire the hardware */
-       drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
-       if (!drv) {
-               dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
-               mutex_unlock(&dev->core->lock);
-               return -ENODEV;
-       }
-
-       err = drv->request_acquire(drv);
-       if (err != 0) {
-               dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
-               mutex_unlock(&dev->core->lock);
-               return err;
-       }
-
-       if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
-               drv->request_release(drv);
-               mutex_unlock(&dev->core->lock);
-               return -EINVAL;
-       }
-       dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh) {
-               drv->request_release(drv);
-               mutex_unlock(&dev->core->lock);
-               return -ENOMEM;
-       }
-       v4l2_fh_init(&fh->fh, vdev);
-       file->private_data = fh;
-       fh->dev      = dev;
-
-       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),
-                           fh, NULL);
-
-       /* FIXME: locking against other video device */
-       cx88_set_scale(dev->core, dev->width, dev->height,
-                       fh->mpegq.field);
-
-       dev->core->mpeg_users++;
-       mutex_unlock(&dev->core->lock);
-       v4l2_fh_add(&fh->fh);
-       return 0;
-}
-
-static int mpeg_release(struct file *file)
-{
-       struct cx8802_fh  *fh  = file->private_data;
-       struct cx8802_dev *dev = fh->dev;
-       struct cx8802_driver *drv = NULL;
-
-       mutex_lock(&dev->core->lock);
-
-       if (dev->mpeg_active && dev->core->mpeg_users == 1)
-               blackbird_stop_codec(dev);
-
-       cx8802_cancel_buffers(fh->dev);
-       /* stop mpeg capture */
-       videobuf_stop(&fh->mpegq);
-
-       videobuf_mmap_free(&fh->mpegq);
-
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-       file->private_data = NULL;
-       kfree(fh);
-
-       /* Make sure we release the hardware */
-       drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
-       WARN_ON(!drv);
-       if (drv)
-               drv->request_release(drv);
-
-       dev->core->mpeg_users--;
-
-       mutex_unlock(&dev->core->lock);
-
-       return 0;
-}
-
-static ssize_t
-mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct cx8802_fh *fh = file->private_data;
-       struct cx8802_dev *dev = fh->dev;
-
-       if (!dev->mpeg_active)
-               blackbird_start_codec(file, fh);
-
-       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)
-{
-       unsigned long req_events = poll_requested_events(wait);
-       struct cx8802_fh *fh = file->private_data;
-       struct cx8802_dev *dev = fh->dev;
-
-       if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
-               blackbird_start_codec(file, fh);
-
-       return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
-}
-
-static int
-mpeg_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       struct cx8802_fh *fh = file->private_data;
-
-       return videobuf_mmap_mapper(&fh->mpegq, vma);
-}
-
-static const struct v4l2_file_operations mpeg_fops =
-{
-       .owner         = THIS_MODULE,
-       .open          = mpeg_open,
-       .release       = mpeg_release,
-       .read          = mpeg_read,
-       .poll          = mpeg_poll,
-       .mmap          = mpeg_mmap,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_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_s_frequency   = vidioc_s_frequency,
-       .vidioc_log_status    = vidioc_log_status,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_g_tuner       = vidioc_g_tuner,
-       .vidioc_s_tuner       = vidioc_s_tuner,
-       .vidioc_g_std         = vidioc_g_std,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
-};
-
-static struct video_device cx8802_mpeg_template = {
-       .name                 = "cx8802",
-       .fops                 = &mpeg_fops,
-       .ioctl_ops            = &mpeg_ioctl_ops,
-       .tvnorms              = CX88_NORMS,
-};
-
-/* ------------------------------------------------------------------ */
-
-/* The CX8802 MPEG API will call this when we can use the hardware */
-static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       int err = 0;
-
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               /* By default, core setup will leave the cx22702 out of reset, on the bus.
-                * We left the hardware on power up with the cx22702 active.
-                * We're being given access to re-arrange the GPIOs.
-                * Take the bus off the cx22702 and put the cx23416 on it.
-                */
-               /* Toggle reset on cx22702 leaving i2c active */
-               cx_set(MO_GP0_IO, 0x00000080);
-               udelay(1000);
-               cx_clear(MO_GP0_IO, 0x00000080);
-               udelay(50);
-               cx_set(MO_GP0_IO, 0x00000080);
-               udelay(1000);
-               /* tri-state the cx22702 pins */
-               cx_set(MO_GP0_IO, 0x00000004);
-               udelay(1000);
-               break;
-       default:
-               err = -ENODEV;
-       }
-       return err;
-}
-
-/* The CX8802 MPEG API will call this when we need to release the hardware */
-static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       int err = 0;
-
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               /* Exit leaving the cx23416 on the bus */
-               break;
-       default:
-               err = -ENODEV;
-       }
-       return err;
-}
-
-static void blackbird_unregister_video(struct cx8802_dev *dev)
-{
-       if (dev->mpeg_dev) {
-               if (video_is_registered(dev->mpeg_dev))
-                       video_unregister_device(dev->mpeg_dev);
-               else
-                       video_device_release(dev->mpeg_dev);
-               dev->mpeg_dev = NULL;
-       }
-}
-
-static int blackbird_register_video(struct cx8802_dev *dev)
-{
-       int err;
-
-       dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
-                                      &cx8802_mpeg_template,"mpeg");
-       dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
-       video_set_drvdata(dev->mpeg_dev, dev);
-       err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
-       if (err < 0) {
-               printk(KERN_INFO "%s/2: can't register mpeg device\n",
-                      dev->core->name);
-               return err;
-       }
-       printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
-              dev->core->name, video_device_node_name(dev->mpeg_dev));
-       return 0;
-}
-
-/* ----------------------------------------------------------- */
-
-static int cx8802_blackbird_probe(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       struct cx8802_dev *dev = core->dvbdev;
-       int err;
-
-       dprintk( 1, "%s\n", __func__);
-       dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
-               core->boardnr,
-               core->name,
-               core->pci_bus,
-               core->pci_slot);
-
-       err = -ENODEV;
-       if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
-               goto fail_core;
-
-       dev->width = 720;
-       if (core->tvnorm & V4L2_STD_525_60) {
-               dev->height = 480;
-       } else {
-               dev->height = 576;
-       }
-       dev->cxhdl.port = CX2341X_PORT_STREAMING;
-       dev->cxhdl.width = dev->width;
-       dev->cxhdl.height = dev->height;
-       dev->cxhdl.func = blackbird_mbox_func;
-       dev->cxhdl.priv = dev;
-       err = cx2341x_handler_init(&dev->cxhdl, 36);
-       if (err)
-               goto fail_core;
-       v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl);
-
-       /* blackbird stuff */
-       printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
-              core->name);
-       host_setup(dev->core);
-
-       blackbird_initialize_codec(dev);
-
-       /* initial device configuration: needed ? */
-//     init_controls(core);
-       cx88_set_tvnorm(core,core->tvnorm);
-       cx88_video_mux(core,0);
-       cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
-       cx2341x_handler_setup(&dev->cxhdl);
-       blackbird_register_video(dev);
-
-       return 0;
-
- fail_core:
-       return err;
-}
-
-static int cx8802_blackbird_remove(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       struct cx8802_dev *dev = core->dvbdev;
-
-       /* blackbird */
-       blackbird_unregister_video(drv->core->dvbdev);
-       v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
-
-       return 0;
-}
-
-static struct cx8802_driver cx8802_blackbird_driver = {
-       .type_id        = CX88_MPEG_BLACKBIRD,
-       .hw_access      = CX8802_DRVCTL_SHARED,
-       .probe          = cx8802_blackbird_probe,
-       .remove         = cx8802_blackbird_remove,
-       .advise_acquire = cx8802_blackbird_advise_acquire,
-       .advise_release = cx8802_blackbird_advise_release,
-};
-
-static int __init blackbird_init(void)
-{
-       printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
-              CX88_VERSION);
-       return cx8802_register_driver(&cx8802_blackbird_driver);
-}
-
-static void __exit blackbird_fini(void)
-{
-       cx8802_unregister_driver(&cx8802_blackbird_driver);
-}
-
-module_init(blackbird_init);
-module_exit(blackbird_fini);
-
-module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages [video]");
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
deleted file mode 100644 (file)
index 4e9d4f7..0000000
+++ /dev/null
@@ -1,3811 +0,0 @@
-/*
- *
- * device driver for Conexant 2388x based TV cards
- * card-specific stuff.
- *
- * (c) 2003 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, 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/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include "cx88.h"
-#include "tea5767.h"
-#include "xc4000.h"
-
-static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-static unsigned int card[]  = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(tuner, int, NULL, 0444);
-module_param_array(radio, int, NULL, 0444);
-module_param_array(card,  int, NULL, 0444);
-
-MODULE_PARM_DESC(tuner,"tuner type");
-MODULE_PARM_DESC(radio,"radio tuner type");
-MODULE_PARM_DESC(card,"card type");
-
-static unsigned int latency = UNSET;
-module_param(latency,int,0444);
-MODULE_PARM_DESC(latency,"pci latency timer");
-
-static int disable_ir;
-module_param(disable_ir, int, 0444);
-MODULE_PARM_DESC(disable_ir, "Disable IR support");
-
-#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                                                  */
-
-/* If radio_type !=UNSET, radio_addr should be specified
- */
-
-static const struct cx88_board cx88_boards[] = {
-       [CX88_BOARD_UNKNOWN] = {
-               .name           = "UNKNOWN/GENERIC",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE2,
-                       .vmux   = 1,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE3,
-                       .vmux   = 2,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE4,
-                       .vmux   = 3,
-               }},
-       },
-       [CX88_BOARD_HAUPPAUGE] = {
-               .name           = "Hauppauge WinTV 34xxx models",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xff00,  // internal decoder
-               },{
-                       .type   = CX88_VMUX_DEBUG,
-                       .vmux   = 0,
-                       .gpio0  = 0xff01,  // mono from tuner chip
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xff02,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xff02,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0xff01,
-               },
-       },
-       [CX88_BOARD_GDI] = {
-               .name           = "GDI Black Gold",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-               }},
-       },
-       [CX88_BOARD_PIXELVIEW] = {
-               .name           = "PixelView",
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xff00,  // internal decoder
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-               }},
-               .radio = {
-                        .type  = CX88_RADIO,
-                        .gpio0 = 0xff10,
-               },
-       },
-       [CX88_BOARD_ATI_WONDER_PRO] = {
-               .name           = "ATI TV Wonder Pro",
-               .tuner_type     = TUNER_PHILIPS_4IN1,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x03ff,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x03fe,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x03fe,
-               }},
-       },
-       [CX88_BOARD_WINFAST2000XP_EXPERT] = {
-               .name           = "Leadtek Winfast 2000XP Expert",
-               .tuner_type     = TUNER_PHILIPS_4IN1,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00F5e700,
-                       .gpio1  = 0x00003004,
-                       .gpio2  = 0x00F5e700,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00F5c700,
-                       .gpio1  = 0x00003004,
-                       .gpio2  = 0x00F5c700,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00F5c700,
-                       .gpio1  = 0x00003004,
-                       .gpio2  = 0x00F5c700,
-                       .gpio3  = 0x02000000,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x00F5d700,
-                       .gpio1  = 0x00003004,
-                       .gpio2  = 0x00F5d700,
-                       .gpio3  = 0x02000000,
-               },
-       },
-       [CX88_BOARD_AVERTV_STUDIO_303] = {
-               .name           = "AverTV Studio 303 (M126)",
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio1  = 0xe09f,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio1  = 0xe05f,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio1  = 0xe05f,
-               }},
-               .radio = {
-                       .gpio1  = 0xe0df,
-                       .type   = CX88_RADIO,
-               },
-       },
-       [CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
-               // added gpio values thanks to Michal
-               // values for PAL from DScaler
-               .name           = "MSI TV-@nywhere Master",
-               .tuner_type     = TUNER_MT2032,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x000040bf,
-                       .gpio1  = 0x000080c0,
-                       .gpio2  = 0x0000ff40,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x000040bf,
-                       .gpio1  = 0x000080c0,
-                       .gpio2  = 0x0000ff40,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x000040bf,
-                       .gpio1  = 0x000080c0,
-                       .gpio2  = 0x0000ff40,
-               }},
-               .radio = {
-                        .type   = CX88_RADIO,
-                        .vmux   = 3,
-                        .gpio0  = 0x000040bf,
-                        .gpio1  = 0x000080c0,
-                        .gpio2  = 0x0000ff20,
-               },
-       },
-       [CX88_BOARD_WINFAST_DV2000] = {
-               .name           = "Leadtek Winfast DV2000",
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0035e700,
-                       .gpio1  = 0x00003004,
-                       .gpio2  = 0x0035e700,
-                       .gpio3  = 0x02000000,
-               },{
-
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0035c700,
-                       .gpio1  = 0x00003004,
-                       .gpio2  = 0x0035c700,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0035c700,
-                       .gpio1  = 0x0035c700,
-                       .gpio2  = 0x02000000,
-                       .gpio3  = 0x02000000,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0035d700,
-                       .gpio1  = 0x00007004,
-                       .gpio2  = 0x0035d700,
-                       .gpio3  = 0x02000000,
-               },
-       },
-       [CX88_BOARD_LEADTEK_PVR2000] = {
-               // gpio values for PAL version from regspy by DScaler
-               .name           = "Leadtek PVR 2000",
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0000bde2,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0000bde6,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0000bde6,
-                       .audioroute = 1,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0000bd62,
-                       .audioroute = 1,
-               },
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_IODATA_GVVCP3PCI] = {
-               .name           = "IODATA GV-VCP3/PCI",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE2,
-                       .vmux   = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-               }},
-       },
-       [CX88_BOARD_PROLINK_PLAYTVPVR] = {
-               .name           = "Prolink PlayTV PVR",
-               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xbff0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xbff3,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xbff3,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0xbff0,
-               },
-       },
-       [CX88_BOARD_ASUS_PVR_416] = {
-               .name           = "ASUS PVR-416",
-               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0000fde6,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
-                       .audioroute = 1,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0000fde2,
-               },
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_MSI_TVANYWHERE] = {
-               .name           = "MSI TV-@nywhere",
-               .tuner_type     = TUNER_MT2032,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00000fbf,
-                       .gpio2  = 0x0000fc08,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00000fbf,
-                       .gpio2  = 0x0000fc68,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00000fbf,
-                       .gpio2  = 0x0000fc68,
-               }},
-       },
-       [CX88_BOARD_KWORLD_DVB_T] = {
-               .name           = "KWorld/VStream XPert DVB-T",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0700,
-                       .gpio2  = 0x0101,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0700,
-                       .gpio2  = 0x0101,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
-               .name           = "DViCO FusionHDTV DVB-T1",
-               .tuner_type     = TUNER_ABSENT, /* No analog tuner */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x000027df,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x000027df,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_KWORLD_LTV883] = {
-               .name           = "KWorld LTV883RF",
-               .tuner_type     = TUNER_TNF_8831BGFF,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x07f8,
-               },{
-                       .type   = CX88_VMUX_DEBUG,
-                       .vmux   = 0,
-                       .gpio0  = 0x07f9,  // mono from tuner chip
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x000007fa,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x000007fa,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x000007f8,
-               },
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = {
-               .name           = "DViCO FusionHDTV 3 Gold-Q",
-               .tuner_type     = TUNER_MICROTUNE_4042FI5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               /*
-                  GPIO[0] resets DT3302 DTV receiver
-                   0 - reset asserted
-                   1 - normal operation
-                  GPIO[1] mutes analog audio output connector
-                   0 - enable selected source
-                   1 - mute
-                  GPIO[2] selects source for analog audio output connector
-                   0 - analog audio input connector on tab
-                   1 - analog DAC output from CX23881 chip
-                  GPIO[3] selects RF input connector on tuner module
-                   0 - RF connector labeled CABLE
-                   1 - RF connector labeled ANT
-                  GPIO[4] selects high RF for QAM256 mode
-                   0 - normal RF
-                   1 - high RF
-               */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0f0d,
-               },{
-                       .type   = CX88_VMUX_CABLE,
-                       .vmux   = 0,
-                       .gpio0  = 0x0f05,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0f00,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0f00,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
-               .name           = "Hauppauge Nova-T DVB-T",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_CONEXANT_DVB_T1] = {
-               .name           = "Conexant DVB-T reference design",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_PROVIDEO_PV259] = {
-               .name           = "Provideo PV259",
-               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .audioroute = 1,
-               }},
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
-               .name           = "DViCO FusionHDTV DVB-T Plus",
-               .tuner_type     = TUNER_ABSENT, /* No analog tuner */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x000027df,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x000027df,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_DNTV_LIVE_DVB_T] = {
-               .name           = "digitalnow DNTV Live! DVB-T",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00000700,
-                       .gpio2  = 0x00000101,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00000700,
-                       .gpio2  = 0x00000101,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_PCHDTV_HD3000] = {
-               .name           = "pcHDTV HD3000 HDTV",
-               .tuner_type     = TUNER_THOMSON_DTT761X,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               /* GPIO[2] = audio source for analog audio out connector
-                *  0 = analog audio input connector
-                *  1 = CX88 audio DACs
-                *
-                * GPIO[7] = input to CX88's audio/chroma ADC
-                *  0 = FM 10.7 MHz IF
-                *  1 = Sound 4.5 MHz IF
-                *
-                * GPIO[1,5,6] = Oren 51132 pins 27,35,28 respectively
-                *
-                * GPIO[16] = Remote control input
-                */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00008484,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00008400,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00008400,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x00008404,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_ROSLYN] = {
-               // entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
-               // GPIO values obtained from regspy, courtesy Sean Covel
-               .name           = "Hauppauge WinTV 28xxx (Roslyn) models",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xed1a,
-                       .gpio2  = 0x00ff,
-               },{
-                       .type   = CX88_VMUX_DEBUG,
-                       .vmux   = 0,
-                       .gpio0  = 0xff01,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xff02,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xed92,
-                       .gpio2  = 0x00ff,
-               }},
-               .radio = {
-                        .type   = CX88_RADIO,
-                        .gpio0  = 0xed96,
-                        .gpio2  = 0x00ff,
-                },
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_DIGITALLOGIC_MEC] = {
-               .name           = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00009d80,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00009d76,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00009d76,
-                       .audioroute = 1,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x00009d00,
-                       .audioroute = 1,
-               },
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_IODATA_GVBCTV7E] = {
-               .name           = "IODATA GV/BCTV7E",
-               .tuner_type     = TUNER_PHILIPS_FQ1286,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 1,
-                       .gpio1  = 0x0000e03f,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 2,
-                       .gpio1  = 0x0000e07f,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 3,
-                       .gpio1  = 0x0000e07f,
-               }}
-       },
-       [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
-               .name           = "PixelView PlayTV Ultra Pro (Stereo)",
-               /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               /* Some variants use a tda9874 and so need the tvaudio module. */
-               .audio_chip     = V4L2_IDENT_TVAUDIO,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xbf61,  /* internal decoder */
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xbf63,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xbf63,
-               }},
-               .radio = {
-                        .type  = CX88_RADIO,
-                        .gpio0 = 0xbf60,
-                },
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
-               .name           = "DViCO FusionHDTV 3 Gold-T",
-               .tuner_type     = TUNER_THOMSON_DTT761X,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x97ed,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x97e9,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x97e9,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_ADSTECH_DVB_T_PCI] = {
-               .name           = "ADS Tech Instant TV DVB-T PCI",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0700,
-                       .gpio2  = 0x0101,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0700,
-                       .gpio2  = 0x0101,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
-               .name           = "TerraTec Cinergy 1400 DVB-T",
-               .tuner_type     = TUNER_ABSENT,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 2,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
-               .name           = "DViCO FusionHDTV 5 Gold",
-               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x87fd,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x87f9,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x87f9,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = {
-               .name           = "AverMedia UltraTV Media Center PCI 550",
-               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 0,
-                       .gpio0  = 0x0000cd73,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 1,
-                       .gpio0  = 0x0000cd73,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 3,
-                       .gpio0  = 0x0000cdb3,
-                       .audioroute = 1,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0000cdf3,
-                       .audioroute = 1,
-               },
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
-                /* Alexander Wold <awold@bigfoot.com> */
-                .name           = "Kworld V-Stream Xpert DVD",
-                .tuner_type     = UNSET,
-                .input          = {{
-                        .type   = CX88_VMUX_COMPOSITE1,
-                        .vmux   = 1,
-                        .gpio0  = 0x03000000,
-                        .gpio1  = 0x01000000,
-                        .gpio2  = 0x02000000,
-                        .gpio3  = 0x00100000,
-                },{
-                        .type   = CX88_VMUX_SVIDEO,
-                        .vmux   = 2,
-                        .gpio0  = 0x03000000,
-                        .gpio1  = 0x01000000,
-                        .gpio2  = 0x02000000,
-                        .gpio3  = 0x00100000,
-                }},
-       },
-       [CX88_BOARD_ATI_HDTVWONDER] = {
-               .name           = "ATI HDTV Wonder",
-               .tuner_type     = TUNER_PHILIPS_TUV1236D,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00000ff7,
-                       .gpio1  = 0x000000ff,
-                       .gpio2  = 0x00000001,
-                       .gpio3  = 0x00000000,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00000ffe,
-                       .gpio1  = 0x000000ff,
-                       .gpio2  = 0x00000001,
-                       .gpio3  = 0x00000000,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00000ffe,
-                       .gpio1  = 0x000000ff,
-                       .gpio2  = 0x00000001,
-                       .gpio3  = 0x00000000,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_WINFAST_DTV1000] = {
-               .name           = "WinFast DTV1000-T",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_AVERTV_303] = {
-               .name           = "AVerTV 303 (M126)",
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00ff,
-                       .gpio1  = 0xe09f,
-                       .gpio2  = 0x0010,
-                       .gpio3  = 0x0000,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00ff,
-                       .gpio1  = 0xe05f,
-                       .gpio2  = 0x0010,
-                       .gpio3  = 0x0000,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00ff,
-                       .gpio1  = 0xe05f,
-                       .gpio2  = 0x0010,
-                       .gpio3  = 0x0000,
-               }},
-       },
-       [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
-               .name           = "Hauppauge Nova-S-Plus DVB-S",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .audio_chip     = V4L2_IDENT_WM8775,
-               .i2sinputcntl   = 2,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
-               .name           = "Hauppauge Nova-SE2 DVB-S",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_KWORLD_DVBS_100] = {
-               .name           = "KWorld DVB-S 100",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .audio_chip = V4L2_IDENT_WM8775,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_HVR1100] = {
-               .name           = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-               }},
-               /* fixme: Add radio support */
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
-               .name           = "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-               }},
-               /* fixme: Add radio support */
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
-               .name           = "digitalnow DNTV Live! DVB-T Pro",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
-                                 TDA9887_PORT2_ACTIVE,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xf80808,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xf80808,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xf80808,
-               }},
-               .radio = {
-                        .type  = CX88_RADIO,
-                        .gpio0 = 0xf80808,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_KWORLD_DVB_T_CX22702] = {
-               /* Kworld V-stream Xpert DVB-T with Thomson tuner */
-               /* DTT 7579 Conexant CX22702-19 Conexant CX2388x  */
-               /* Manenti Marco <marco_manenti@colman.it> */
-               .name           = "KWorld/VStream XPert DVB-T with cx22702",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0700,
-                       .gpio2  = 0x0101,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0700,
-                       .gpio2  = 0x0101,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
-               .name           = "DViCO FusionHDTV DVB-T Dual Digital",
-               .tuner_type     = TUNER_ABSENT, /* No analog tuner */
-               .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_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
-               .name           = "KWorld HardwareMpegTV XPert",
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x3de2,
-                       .gpio2  = 0x00ff,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x3de6,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x3de6,
-                       .audioroute = 1,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x3de6,
-                       .gpio2  = 0x00ff,
-               },
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
-               .name           = "DViCO FusionHDTV DVB-T Hybrid",
-               .tuner_type     = TUNER_THOMSON_FE6600,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0000a75f,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0000a75b,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0000a75b,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_PCHDTV_HD5500] = {
-               .name           = "pcHDTV HD5500 HDTV",
-               .tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x87fd,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x87f9,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x87f9,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_KWORLD_MCE200_DELUXE] = {
-               /* FIXME: tested TV input only, disabled composite,
-                  svideo and radio until they can be tested also. */
-               .name           = "Kworld MCE 200 Deluxe",
-               .tuner_type     = TUNER_TENA_9533_DI,
-               .radio_type     = UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0000BDE6
-               }},
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
-               /* FIXME: SVideo, Composite and FM inputs are untested */
-               .name           = "PixelView PlayTV P7000",
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
-                                 TDA9887_PORT2_ACTIVE,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x5da6,
-               }},
-               .mpeg           = CX88_MPEG_BLACKBIRD,
-       },
-       [CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
-               .name           = "NPG Tech Real TV FM Top 10",
-               .tuner_type     = TUNER_TNF_5335MF, /* Actually a TNF9535 */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0788,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x078b,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x078b,
-               }},
-               .radio = {
-                        .type  = CX88_RADIO,
-                        .gpio0 = 0x074a,
-               },
-       },
-       [CX88_BOARD_WINFAST_DTV2000H] = {
-               .name           = "WinFast DTV2000 H",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00017304,
-                       .gpio1  = 0x00008203,
-                       .gpio2  = 0x00017304,
-                       .gpio3  = 0x02000000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0001d701,
-                       .gpio1  = 0x0000b207,
-                       .gpio2  = 0x0001d701,
-                       .gpio3  = 0x02000000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE2,
-                       .vmux   = 2,
-                       .gpio0  = 0x0001d503,
-                       .gpio1  = 0x0000b207,
-                       .gpio2  = 0x0001d503,
-                       .gpio3  = 0x02000000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 3,
-                       .gpio0  = 0x0001d701,
-                       .gpio1  = 0x0000b207,
-                       .gpio2  = 0x0001d701,
-                       .gpio3  = 0x02000000,
-               }},
-               .radio = {
-                        .type  = CX88_RADIO,
-                        .gpio0 = 0x00015702,
-                        .gpio1 = 0x0000f207,
-                        .gpio2 = 0x00015702,
-                        .gpio3 = 0x02000000,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_WINFAST_DTV2000H_J] = {
-               .name           = "WinFast DTV2000 H rev. J",
-               .tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00017300,
-                       .gpio1  = 0x00008207,
-                       .gpio2  = 0x00000000,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x00018300,
-                       .gpio1  = 0x0000f207,
-                       .gpio2  = 0x00017304,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x00018301,
-                       .gpio1  = 0x0000f207,
-                       .gpio2  = 0x00017304,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x00018301,
-                       .gpio1  = 0x0000f207,
-                       .gpio2  = 0x00017304,
-                       .gpio3  = 0x02000000,
-               }},
-               .radio = {
-                        .type  = CX88_RADIO,
-                        .gpio0 = 0x00015702,
-                        .gpio1 = 0x0000f207,
-                        .gpio2 = 0x00015702,
-                        .gpio3 = 0x02000000,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_GENIATECH_DVBS] = {
-               .name          = "Geniatech DVB-S",
-               .tuner_type    = TUNER_ABSENT,
-               .radio_type    = UNSET,
-               .tuner_addr    = ADDR_UNSET,
-               .radio_addr    = ADDR_UNSET,
-               .input  = {{
-                       .type  = CX88_VMUX_DVB,
-                       .vmux  = 0,
-               },{
-                       .type  = CX88_VMUX_COMPOSITE1,
-                       .vmux  = 1,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_HVR3000] = {
-               .name           = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .audio_chip     = V4L2_IDENT_WM8775,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x84bf,
-                       /* 1: TV Audio / FM Mono */
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x84bf,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x84bf,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x84bf,
-                       /* 4: FM Stereo (untested) */
-                       .audioroute = 8,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-               .num_frontends  = 2,
-       },
-       [CX88_BOARD_NORWOOD_MICRO] = {
-               .name           = "Norwood Micro TV Tuner",
-               .tuner_type     = TUNER_TNF_5335MF,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0709,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x070b,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x070b,
-               }},
-       },
-       [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
-               .name           = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x003fffff,
-                       .gpio1  = 0x00e00000,
-                       .gpio2  = 0x003fffff,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x003fffff,
-                       .gpio1  = 0x00e00000,
-                       .gpio2  = 0x003fffff,
-                       .gpio3  = 0x02000000,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x003fffff,
-                       .gpio1  = 0x00e00000,
-                       .gpio2  = 0x003fffff,
-                       .gpio3  = 0x02000000,
-               }},
-       },
-       [CX88_BOARD_HAUPPAUGE_HVR1300] = {
-               .name           = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .audio_chip     = V4L2_IDENT_WM8775,
-               /*
-                * gpio0 as reported by Mike Crash <mike AT mikecrash.com>
-                */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xef88,
-                       /* 1: TV Audio / FM Mono */
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xef88,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xef88,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               }},
-               .mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0xef88,
-                       /* 4: FM Stereo (untested) */
-                       .audioroute = 8,
-               },
-       },
-       [CX88_BOARD_SAMSUNG_SMT_7020] = {
-               .name           = "Samsung SMT 7020 DVB-S",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_ADSTECH_PTV_390] = {
-               .name           = "ADS Tech Instant Video PCI",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DEBUG,
-                       .vmux   = 3,
-                       .gpio0  = 0x04ff,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x07fa,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x07fa,
-               }},
-       },
-       [CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
-               .name           = "Pinnacle PCTV HD 800i",
-               .tuner_type     = TUNER_XC5000,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x04fb,
-                       .gpio1  = 0x10ff,
-               },{
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x04fb,
-                       .gpio1  = 0x10ef,
-                       .audioroute = 1,
-               },{
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x04fb,
-                       .gpio1  = 0x10ef,
-                       .audioroute = 1,
-               }},
-               .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,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x004ff,
-                       .gpio1  = 0x010ff,
-                       .gpio2  = 0x00001,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x004fb,
-                       .gpio1  = 0x010ef,
-                       .audioroute = 1,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x004fb,
-                       .gpio1  = 0x010ef,
-                       .audioroute = 1,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x004ff,
-                       .gpio1  = 0x010ff,
-                       .gpio2  = 0x0ff,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       /* Terry Wu <terrywu2009@gmail.com> */
-       /* TV Audio :      set GPIO 2, 18, 19 value to 0, 1, 0 */
-       /* FM Audio :      set GPIO 2, 18, 19 value to 0, 0, 0 */
-       /* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */
-       /* Mute Audio :    set GPIO 2 value to 1               */
-       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
-               .name           = "Leadtek TV2000 XP Global",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_addr     = 0x61,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
-                       .gpio3  = 0x0000,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0400,        /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
-                       .gpio3  = 0x0000,
-               },
-       },
-       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = {
-               .name           = "Leadtek TV2000 XP Global (SC4100)",
-               .tuner_type     = TUNER_XC4000,
-               .tuner_addr     = 0x61,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
-                       .gpio3  = 0x0000,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0400,        /* pin 2 = 0 */
-                       .gpio1  = 0x0000,
-                       .gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
-                       .gpio3  = 0x0000,
-               },
-       },
-       [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = {
-               .name           = "Leadtek TV2000 XP Global (XC4100)",
-               .tuner_type     = TUNER_XC4000,
-               .tuner_addr     = 0x61,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6040,       /* pin 14 = 1, pin 13 = 0 */
-                       .gpio2  = 0x0000,
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
-                       .gpio2  = 0x0000,
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
-                       .gpio2  = 0x0000,
-                       .gpio3  = 0x0000,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0400,        /* pin 2 = 0 */
-                       .gpio1  = 0x6000,        /* pin 14 = 1, pin 13 = 0 */
-                       .gpio2  = 0x0000,
-                       .gpio3  = 0x0000,
-               },
-       },
-       [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
-               .name           = "PowerColor RA330",   /* Long names may confuse LIRC. */
-               .tuner_type     = TUNER_XC2028,
-               .tuner_addr     = 0x61,
-               .input          = { {
-                       .type   = CX88_VMUX_DEBUG,
-                       .vmux   = 3,            /* Due to the way the cx88 driver is written,   */
-                       .gpio0 = 0x00ff,        /* there is no way to deactivate audio pass-    */
-                       .gpio1 = 0xf39d,        /* through without this entry. Furthermore, if  */
-                       .gpio3 = 0x0000,        /* the TV mux entry is first, you get audio     */
-               }, {                            /* from the tuner on boot for a little while.   */
-                       .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_XC2028,
-               .tuner_addr     = 0x61,
-               .radio_type     = 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,
-               }},
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [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,
-               },
-       },
-       [CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
-               .name           = "Prolink Pixelview Global Extreme",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_addr     = 0x61,
-               .input          = { {
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0 = 0x04fb,
-                       .gpio1 = 0x04080,
-                       .gpio2 = 0x0cf7,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0 = 0x04fb,
-                       .gpio1 = 0x04080,
-                       .gpio2 = 0x0cfb,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0 = 0x04fb,
-                       .gpio1 = 0x04080,
-                       .gpio2 = 0x0cfb,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0 = 0x04ff,
-                       .gpio1 = 0x04080,
-                       .gpio2 = 0x0cf7,
-               },
-       },
-       /* 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,
-       },
-       [CX88_BOARD_HAUPPAUGE_HVR4000] = {
-               .name           = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .audio_chip     = V4L2_IDENT_WM8775,
-               /*
-                * GPIO0 (WINTV2000)
-                *
-                * Analogue     SAT     DVB-T
-                * Antenna      0xc4bf  0xc4bb
-                * Composite    0xc4bf  0xc4bb
-                * S-Video      0xc4bf  0xc4bb
-                * Composite1   0xc4ff  0xc4fb
-                * S-Video1     0xc4ff  0xc4fb
-                *
-                * BIT  VALUE   FUNCTION GP{x}_IO
-                * 0    1       I:?
-                * 1    1       I:?
-                * 2    1       O:MPEG PORT 0=DVB-T 1=DVB-S
-                * 3    1       I:?
-                * 4    1       I:?
-                * 5    1       I:?
-                * 6    0       O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
-                * 7    1       O:DVB-T DEMOD RESET LOW
-                *
-                * BIT  VALUE   FUNCTION GP{x}_OE
-                * 8    0       I
-                * 9    0       I
-                * a    1       O
-                * b    0       I
-                * c    0       I
-                * d    0       I
-                * e    1       O
-                * f    1       O
-                *
-                * WM8775 ADC
-                *
-                * 1: TV Audio / FM Mono
-                * 2: Line-In
-                * 3: Line-In Expansion
-                * 4: FM Stereo
-                */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0xc4bf,
-                       /* 1: TV Audio / FM Mono */
-                       .audioroute = 1,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0xc4bf,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0xc4bf,
-                       /* 2: Line-In */
-                       .audioroute = 2,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0xc4bf,
-                       /* 4: FM Stereo */
-                       .audioroute = 8,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-               .num_frontends  = 2,
-       },
-       [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
-               .name           = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TEVII_S420] = {
-               .name           = "TeVii S420 DVB-S",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TEVII_S460] = {
-               .name           = "TeVii S460 DVB-S/S2",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TEVII_S464] = {
-               .name           = "TeVii S464 DVB-S/S2",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_OMICOM_SS4_PCI] = {
-               .name           = "Omicom SS4 DVB-S/S2 PCI",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TBS_8910] = {
-               .name           = "TBS 8910 DVB-S",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TBS_8920] = {
-               .name           = "TBS 8920 DVB-S/S2",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-                       .gpio0  = 0x8080,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_PROF_6200] = {
-               .name           = "Prof 6200 DVB-S",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_PROF_7300] = {
-               .name           = "PROF 7300 DVB-S/S2",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_SATTRADE_ST4200] = {
-               .name           = "SATTRADE ST4200 DVB-S/S2",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII] = {
-               .name           = "Terratec Cinergy HT PCI MKII",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_addr     = 0x61,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x004ff,
-                       .gpio1  = 0x010ff,
-                       .gpio2  = 0x00001,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x004fb,
-                       .gpio1  = 0x010ef,
-                       .audioroute = 1,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x004fb,
-                       .gpio1  = 0x010ef,
-                       .audioroute = 1,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x004ff,
-                       .gpio1  = 0x010ff,
-                       .gpio2  = 0x0ff,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_HAUPPAUGE_IRONLY] = {
-               .name           = "Hauppauge WinTV-IR Only",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-       },
-       [CX88_BOARD_WINFAST_DTV1800H] = {
-               .name           = "Leadtek WinFast DTV1800 Hybrid",
-               .tuner_type     = TUNER_XC2028,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x61,
-               .radio_addr     = ADDR_UNSET,
-               /*
-                * GPIO setting
-                *
-                *  2: mute (0=off,1=on)
-                * 12: tuner reset pin
-                * 13: audio source (0=tuner audio,1=line in)
-                * 14: FM (0=on,1=off ???)
-                */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
-                       .gpio2  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
-                       .gpio2  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
-                       .gpio2  = 0x0000,
-               } },
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
-                       .gpio2  = 0x0000,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
-               .name           = "Leadtek WinFast DTV1800 H (XC4000)",
-               .tuner_type     = TUNER_XC4000,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x61,
-               .radio_addr     = ADDR_UNSET,
-               /*
-                * GPIO setting
-                *
-                *  2: mute (0=off,1=on)
-                * 12: tuner reset pin
-                * 13: audio source (0=tuner audio,1=line in)
-                * 14: FM (0=on,1=off ???)
-                */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
-                       .gpio2  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
-                       .gpio2  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
-                       .gpio2  = 0x0000,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0400,       /* pin 2 = 0 */
-                       .gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
-                       .gpio2  = 0x0000,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
-               .name           = "Leadtek WinFast DTV2000 H PLUS",
-               .tuner_type     = TUNER_XC4000,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x61,
-               .radio_addr     = ADDR_UNSET,
-               /*
-                * GPIO
-                *   2: 1: mute audio
-                *  12: 0: reset XC4000
-                *  13: 1: audio input is line in (0: tuner)
-                *  14: 0: FM radio
-                *  16: 0: RF input is cable
-                */
-               .input          = {{
-                       .type   = CX88_VMUX_TELEVISION,
-                       .vmux   = 0,
-                       .gpio0  = 0x0403,
-                       .gpio1  = 0xF0D7,
-                       .gpio2  = 0x0101,
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_CABLE,
-                       .vmux   = 0,
-                       .gpio0  = 0x0403,
-                       .gpio1  = 0xF0D7,
-                       .gpio2  = 0x0100,
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_COMPOSITE1,
-                       .vmux   = 1,
-                       .gpio0  = 0x0403,       /* was 0x0407 */
-                       .gpio1  = 0xF0F7,
-                       .gpio2  = 0x0101,
-                       .gpio3  = 0x0000,
-               }, {
-                       .type   = CX88_VMUX_SVIDEO,
-                       .vmux   = 2,
-                       .gpio0  = 0x0403,       /* was 0x0407 */
-                       .gpio1  = 0xF0F7,
-                       .gpio2  = 0x0101,
-                       .gpio3  = 0x0000,
-               }},
-               .radio = {
-                       .type   = CX88_RADIO,
-                       .gpio0  = 0x0403,
-                       .gpio1  = 0xF097,
-                       .gpio2  = 0x0100,
-                       .gpio3  = 0x0000,
-               },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_PROF_7301] = {
-               .name           = "Prof 7301 DVB-S/S2",
-               .tuner_type     = UNSET,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = { {
-                       .type   = CX88_VMUX_DVB,
-                       .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-       [CX88_BOARD_TWINHAN_VP1027_DVBS] = {
-               .name           = "Twinhan VP-1027 DVB-S",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .input          = {{
-                      .type   = CX88_VMUX_DVB,
-                      .vmux   = 0,
-               } },
-               .mpeg           = CX88_MPEG_DVB,
-       },
-};
-
-/* ------------------------------------------------------------------ */
-/* PCI subsystem IDs                                                  */
-
-static const struct cx88_subid cx88_subids[] = {
-       {
-               .subvendor = 0x0070,
-               .subdevice = 0x3400,
-               .card      = CX88_BOARD_HAUPPAUGE,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x3401,
-               .card      = CX88_BOARD_HAUPPAUGE,
-       },{
-               .subvendor = 0x14c7,
-               .subdevice = 0x0106,
-               .card      = CX88_BOARD_GDI,
-       },{
-               .subvendor = 0x14c7,
-               .subdevice = 0x0107, /* with mpeg encoder */
-               .card      = CX88_BOARD_GDI,
-       },{
-               .subvendor = PCI_VENDOR_ID_ATI,
-               .subdevice = 0x00f8,
-               .card      = CX88_BOARD_ATI_WONDER_PRO,
-       }, {
-               .subvendor = PCI_VENDOR_ID_ATI,
-               .subdevice = 0x00f9,
-               .card      = CX88_BOARD_ATI_WONDER_PRO,
-       }, {
-               .subvendor = 0x107d,
-               .subdevice = 0x6611,
-               .card      = CX88_BOARD_WINFAST2000XP_EXPERT,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x6613,    /* NTSC */
-               .card      = CX88_BOARD_WINFAST2000XP_EXPERT,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x6620,
-               .card      = CX88_BOARD_WINFAST_DV2000,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x663b,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x663c,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       },{
-               .subvendor = 0x1461,
-               .subdevice = 0x000b,
-               .card      = CX88_BOARD_AVERTV_STUDIO_303,
-       },{
-               .subvendor = 0x1462,
-               .subdevice = 0x8606,
-               .card      = CX88_BOARD_MSI_TVANYWHERE_MASTER,
-       },{
-               .subvendor = 0x10fc,
-               .subdevice = 0xd003,
-               .card      = CX88_BOARD_IODATA_GVVCP3PCI,
-       },{
-               .subvendor = 0x1043,
-               .subdevice = 0x4823,  /* with mpeg encoder */
-               .card      = CX88_BOARD_ASUS_PVR_416,
-       },{
-               .subvendor = 0x17de,
-               .subdevice = 0x08a6,
-               .card      = CX88_BOARD_KWORLD_DVB_T,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xd810,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xd820,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb00,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9002,
-               .card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
-       },{
-               .subvendor = 0x14f1,
-               .subdevice = 0x0187,
-               .card      = CX88_BOARD_CONEXANT_DVB_T1,
-       },{
-               .subvendor = 0x1540,
-               .subdevice = 0x2580,
-               .card      = CX88_BOARD_PROVIDEO_PV259,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb10,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
-       },{
-               .subvendor = 0x1554,
-               .subdevice = 0x4811,
-               .card      = CX88_BOARD_PIXELVIEW,
-       },{
-               .subvendor = 0x7063,
-               .subdevice = 0x3000, /* HD-3000 card */
-               .card      = CX88_BOARD_PCHDTV_HD3000,
-       },{
-               .subvendor = 0x17de,
-               .subdevice = 0xa8a6,
-               .card      = CX88_BOARD_DNTV_LIVE_DVB_T,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x2801,
-               .card      = CX88_BOARD_HAUPPAUGE_ROSLYN,
-       },{
-               .subvendor = 0x14f1,
-               .subdevice = 0x0342,
-               .card      = CX88_BOARD_DIGITALLOGIC_MEC,
-       },{
-               .subvendor = 0x10fc,
-               .subdevice = 0xd035,
-               .card      = CX88_BOARD_IODATA_GVBCTV7E,
-       },{
-               .subvendor = 0x1421,
-               .subdevice = 0x0334,
-               .card      = CX88_BOARD_ADSTECH_DVB_T_PCI,
-       },{
-               .subvendor = 0x153b,
-               .subdevice = 0x1166,
-               .card      = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xd500,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
-       },{
-               .subvendor = 0x1461,
-               .subdevice = 0x8011,
-               .card      = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550,
-       },{
-               .subvendor = PCI_VENDOR_ID_ATI,
-               .subdevice = 0xa101,
-               .card      = CX88_BOARD_ATI_HDTVWONDER,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x665f,
-               .card      = CX88_BOARD_WINFAST_DTV1000,
-       },{
-               .subvendor = 0x1461,
-               .subdevice = 0x000a,
-               .card      = CX88_BOARD_AVERTV_303,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9200,
-               .card      = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9201,
-               .card      = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9202,
-               .card      = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
-       },{
-               .subvendor = 0x17de,
-               .subdevice = 0x08b2,
-               .card      = CX88_BOARD_KWORLD_DVBS_100,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9400,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1100,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9402,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1100,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9800,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1100LP,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9802,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1100LP,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9001,
-               .card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
-       },{
-               .subvendor = 0x1822,
-               .subdevice = 0x0025,
-               .card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
-       },{
-               .subvendor = 0x17de,
-               .subdevice = 0x08a1,
-               .card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb50,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb54,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
-               /* Re-branded DViCO: DigitalNow DVB-T Dual */
-       },{
-               .subvendor = 0x18ac,
-               .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,
-       },{
-               .subvendor = 0x1421,
-               .subdevice = 0x0305,
-               .card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb40,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xdb44,
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
-       },{
-               .subvendor = 0x7063,
-               .subdevice = 0x5500,
-               .card      = CX88_BOARD_PCHDTV_HD5500,
-       },{
-               .subvendor = 0x17de,
-               .subdevice = 0x0841,
-               .card      = CX88_BOARD_KWORLD_MCE200_DELUXE,
-       },{
-               .subvendor = 0x1822,
-               .subdevice = 0x0019,
-               .card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
-       },{
-               .subvendor = 0x1554,
-               .subdevice = 0x4813,
-               .card      = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
-       },{
-               .subvendor = 0x14f1,
-               .subdevice = 0x0842,
-               .card      = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x665e,
-               .card      = CX88_BOARD_WINFAST_DTV2000H,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x6f2b,
-               .card      = CX88_BOARD_WINFAST_DTV2000H_J,
-       },{
-               .subvendor = 0x18ac,
-               .subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
-               .card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
-       },{
-               .subvendor = 0x14f1,
-               .subdevice = 0x0084,
-               .card      = CX88_BOARD_GENIATECH_DVBS,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x1404,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
-       }, {
-               .subvendor = 0x18ac,
-               .subdevice = 0xdc00,
-               .card      = CX88_BOARD_SAMSUNG_SMT_7020,
-       }, {
-               .subvendor = 0x18ac,
-               .subdevice = 0xdccd,
-               .card      = CX88_BOARD_SAMSUNG_SMT_7020,
-       },{
-               .subvendor = 0x1461,
-               .subdevice = 0xc111, /* AverMedia M150-D */
-               /* This board is known to work with the ASUS PVR416 config */
-               .card      = CX88_BOARD_ASUS_PVR_416,
-       },{
-               .subvendor = 0xc180,
-               .subdevice = 0xc980,
-               .card      = CX88_BOARD_TE_DTV_250_OEM_SWANN,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9600,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9601,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9602,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR1300,
-       },{
-               .subvendor = 0x107d,
-               .subdevice = 0x6632,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       },{
-               .subvendor = 0x12ab,
-               .subdevice = 0x2300, /* Club3D Zap TV2100 */
-               .card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x9000,
-               .card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x1400,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x1401,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
-       },{
-               .subvendor = 0x0070,
-               .subdevice = 0x1402,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR3000,
-       },{
-               .subvendor = 0x1421,
-               .subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */
-               .card      = CX88_BOARD_KWORLD_DVBS_100,
-       },{
-               .subvendor = 0x1421,
-               .subdevice = 0x0390,
-               .card      = CX88_BOARD_ADSTECH_PTV_390,
-       },{
-               .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 = 0x1554,
-               .subdevice = 0x4976,
-               .card      = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
-       }, {
-               .subvendor = 0x17de,
-               .subdevice = 0x08c1,
-               .card      = CX88_BOARD_KWORLD_ATSC_120,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x6900,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x6904,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x6902,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR4000,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x6905,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x6906,
-               .card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
-       }, {
-               .subvendor = 0xd420,
-               .subdevice = 0x9022,
-               .card      = CX88_BOARD_TEVII_S420,
-       }, {
-               .subvendor = 0xd460,
-               .subdevice = 0x9022,
-               .card      = CX88_BOARD_TEVII_S460,
-       }, {
-               .subvendor = 0xd464,
-               .subdevice = 0x9022,
-               .card      = CX88_BOARD_TEVII_S464,
-       }, {
-               .subvendor = 0xA044,
-               .subdevice = 0x2011,
-               .card      = CX88_BOARD_OMICOM_SS4_PCI,
-       }, {
-               .subvendor = 0x8910,
-               .subdevice = 0x8888,
-               .card      = CX88_BOARD_TBS_8910,
-       }, {
-               .subvendor = 0x8920,
-               .subdevice = 0x8888,
-               .card      = CX88_BOARD_TBS_8920,
-       }, {
-               .subvendor = 0xb022,
-               .subdevice = 0x3022,
-               .card      = CX88_BOARD_PROF_6200,
-       }, {
-               .subvendor = 0xB033,
-               .subdevice = 0x3033,
-               .card      = CX88_BOARD_PROF_7300,
-       }, {
-               .subvendor = 0xb200,
-               .subdevice = 0x4200,
-               .card      = CX88_BOARD_SATTRADE_ST4200,
-       }, {
-               .subvendor = 0x153b,
-               .subdevice = 0x1177,
-               .card      = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x9290,
-               .card      = CX88_BOARD_HAUPPAUGE_IRONLY,
-       }, {
-               .subvendor = 0x107d,
-               .subdevice = 0x6654,
-               .card      = CX88_BOARD_WINFAST_DTV1800H,
-       }, {
-               /* WinFast DTV1800 H with XC4000 tuner */
-               .subvendor = 0x107d,
-               .subdevice = 0x6f38,
-               .card      = CX88_BOARD_WINFAST_DTV1800H_XC4000,
-       }, {
-               .subvendor = 0x107d,
-               .subdevice = 0x6f42,
-               .card      = CX88_BOARD_WINFAST_DTV2000H_PLUS,
-       }, {
-               /* PVR2000 PAL Model [107d:6630] */
-               .subvendor = 0x107d,
-               .subdevice = 0x6630,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       }, {
-               /* PVR2000 PAL Model [107d:6638] */
-               .subvendor = 0x107d,
-               .subdevice = 0x6638,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       }, {
-               /* PVR2000 NTSC Model [107d:6631] */
-               .subvendor = 0x107d,
-               .subdevice = 0x6631,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       }, {
-               /* PVR2000 NTSC Model [107d:6637] */
-               .subvendor = 0x107d,
-               .subdevice = 0x6637,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       }, {
-               /* PVR2000 NTSC Model [107d:663d] */
-               .subvendor = 0x107d,
-               .subdevice = 0x663d,
-               .card      = CX88_BOARD_LEADTEK_PVR2000,
-       }, {
-               /* DV2000 NTSC Model [107d:6621] */
-               .subvendor = 0x107d,
-               .subdevice = 0x6621,
-               .card      = CX88_BOARD_WINFAST_DV2000,
-       }, {
-               /* TV2000 XP Global [107d:6618]  */
-               .subvendor = 0x107d,
-               .subdevice = 0x6618,
-               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
-       }, {
-               /* TV2000 XP Global [107d:6618] */
-               .subvendor = 0x107d,
-               .subdevice = 0x6619,
-               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
-       }, {
-               /* WinFast TV2000 XP Global with XC4000 tuner */
-               .subvendor = 0x107d,
-               .subdevice = 0x6f36,
-               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36,
-       }, {
-               /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */
-               .subvendor = 0x107d,
-               .subdevice = 0x6f43,
-               .card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43,
-       }, {
-               .subvendor = 0xb034,
-               .subdevice = 0x3034,
-               .card      = CX88_BOARD_PROF_7301,
-       }, {
-               .subvendor = 0x1822,
-               .subdevice = 0x0023,
-               .card      = CX88_BOARD_TWINHAN_VP1027_DVBS,
-       },
-};
-
-/* ----------------------------------------------------------------------- */
-/* some leadtek specific stuff                                             */
-
-static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
-{
-       if (eeprom_data[4] != 0x7d ||
-           eeprom_data[5] != 0x10 ||
-           eeprom_data[7] != 0x66) {
-               warn_printk(core, "Leadtek eeprom invalid.\n");
-               return;
-       }
-
-       /* Terry Wu <terrywu2009@gmail.com> */
-       switch (eeprom_data[6]) {
-       case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
-       case 0x21: /* SSID 6621 for DV2000 NTSC Model */
-       case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
-       case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
-       case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
-               core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
-               break;
-       default:
-               core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
-               break;
-       }
-
-       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)
-{
-       struct tveeprom tv;
-
-       tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
-       core->board.tuner_type = tv.tuner_type;
-       core->tuner_formats = tv.tuner_formats;
-       core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
-
-       /* Make sure we support the board model */
-       switch (tv.model)
-       {
-       case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
-       case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
-       case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
-       case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */
-       case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */
-       case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */
-       case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
-       case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */
-       case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
-       case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
-       case 34519: /* WinTV-PCI-FM */
-       case 69009:
-               /* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
-       case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
-       case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
-       case 69559:
-               /* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
-       case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
-       case 90002: /* Nova-T-PCI (9002) */
-       case 92001: /* Nova-S-Plus (Video and IR) */
-       case 92002: /* Nova-S-Plus (Video and IR) */
-       case 90003: /* Nova-T-PCI (9002 No RF out) */
-       case 90500: /* Nova-T-PCI (oem) */
-       case 90501: /* Nova-T-PCI (oem/IR) */
-       case 92000: /* Nova-SE2 (OEM, No Video or IR) */
-       case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
-       case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
-       case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
-       case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
-       case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */
-       case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */
-       case 96569: /* WinTV-HVR1300 () */
-       case 96659: /* WinTV-HVR1300 () */
-       case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
-               /* known */
-               break;
-       case CX88_BOARD_SAMSUNG_SMT_7020:
-               cx_set(MO_GP0_IO, 0x008989FF);
-               break;
-       default:
-               warn_printk(core, "warning: unknown hauppauge model #%d\n",
-                           tv.model);
-               break;
-       }
-
-       info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
-}
-
-/* ----------------------------------------------------------------------- */
-/* some GDI (was: Modular Technology) specific stuff                       */
-
-static const struct {
-       int  id;
-       int  fm;
-       const char *name;
-} gdi_tuner[] = {
-       [ 0x01 ] = { .id   = TUNER_ABSENT,
-                    .name = "NTSC_M" },
-       [ 0x02 ] = { .id   = TUNER_ABSENT,
-                    .name = "PAL_B" },
-       [ 0x03 ] = { .id   = TUNER_ABSENT,
-                    .name = "PAL_I" },
-       [ 0x04 ] = { .id   = TUNER_ABSENT,
-                    .name = "PAL_D" },
-       [ 0x05 ] = { .id   = TUNER_ABSENT,
-                    .name = "SECAM" },
-
-       [ 0x10 ] = { .id   = TUNER_ABSENT,
-                    .fm   = 1,
-                    .name = "TEMIC_4049" },
-       [ 0x11 ] = { .id   = TUNER_TEMIC_4136FY5,
-                    .name = "TEMIC_4136" },
-       [ 0x12 ] = { .id   = TUNER_ABSENT,
-                    .name = "TEMIC_4146" },
-
-       [ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME,
-                    .fm   = 1,
-                    .name = "PHILIPS_FQ1216_MK3" },
-       [ 0x21 ] = { .id   = TUNER_ABSENT, .fm = 1,
-                    .name = "PHILIPS_FQ1236_MK3" },
-       [ 0x22 ] = { .id   = TUNER_ABSENT,
-                    .name = "PHILIPS_FI1236_MK3" },
-       [ 0x23 ] = { .id   = TUNER_ABSENT,
-                    .name = "PHILIPS_FI1216_MK3" },
-};
-
-static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
-{
-       const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
-               ? gdi_tuner[eeprom_data[0x0d]].name : NULL;
-
-       info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
-       if (NULL == name)
-               return;
-       core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
-       core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
-               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:
-               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;
-               default:
-                       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;
-}
-
-static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
-                                            int command, int arg)
-{
-       switch (command) {
-       case XC2028_TUNER_RESET:
-               /* GPIO 12 (xc3028 tuner reset) */
-               cx_set(MO_GP1_IO, 0x1010);
-               mdelay(50);
-               cx_clear(MO_GP1_IO, 0x10);
-               mdelay(50);
-               cx_set(MO_GP1_IO, 0x10);
-               mdelay(50);
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
-                                                 int command, int arg)
-{
-       switch (command) {
-       case XC4000_TUNER_RESET:
-               /* GPIO 12 (xc4000 tuner reset) */
-               cx_set(MO_GP1_IO, 0x1010);
-               mdelay(50);
-               cx_clear(MO_GP1_IO, 0x10);
-               mdelay(75);
-               cx_set(MO_GP1_IO, 0x10);
-               mdelay(75);
-               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                                               */
-
-static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
-{
-       struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
-       int i, err;
-       static u8 init_bufs[13][5] = {
-               { 0x10, 0x00, 0x20, 0x01, 0x03 },
-               { 0x10, 0x10, 0x01, 0x00, 0x21 },
-               { 0x10, 0x10, 0x10, 0x00, 0xCA },
-               { 0x10, 0x10, 0x12, 0x00, 0x08 },
-               { 0x10, 0x10, 0x13, 0x00, 0x0A },
-               { 0x10, 0x10, 0x16, 0x01, 0xC0 },
-               { 0x10, 0x10, 0x22, 0x01, 0x3D },
-               { 0x10, 0x10, 0x73, 0x01, 0x2E },
-               { 0x10, 0x10, 0x72, 0x00, 0xC5 },
-               { 0x10, 0x10, 0x71, 0x01, 0x97 },
-               { 0x10, 0x10, 0x70, 0x00, 0x0F },
-               { 0x10, 0x10, 0xB0, 0x00, 0x01 },
-               { 0x03, 0x0C },
-       };
-
-       for (i = 0; i < ARRAY_SIZE(init_bufs); i++) {
-               msg.buf = init_bufs[i];
-               msg.len = (i != 12 ? 5 : 2);
-               err = i2c_transfer(&core->i2c_adap, &msg, 1);
-               if (err != 1) {
-                       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_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:
-       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
-               return cx88_pv_8000gt_callback(core, command, arg);
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
-       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
-               return cx88_dvico_xc2028_callback(core, command, arg);
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
-       case CX88_BOARD_WINFAST_DTV1800H:
-               return cx88_xc3028_winfast1800h_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;
-}
-
-static int cx88_xc4000_tuner_callback(struct cx88_core *core,
-                                     int command, int arg)
-{
-       /* Board-specific callbacks */
-       switch (core->boardnr) {
-       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
-       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
-               return cx88_xc4000_winfast2000h_plus_callback(core,
-                                                             command, arg);
-       }
-       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)    */
-
-static int cx88_xc5000_tuner_callback(struct cx88_core *core,
-                                     int command, int arg)
-{
-       switch (core->boardnr) {
-       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-               if (command == 0) { /* This is the reset command from xc5000 */
-
-                       /* djh - According to the engineer at PCTV Systems,
-                          the xc5000 reset pin is supposed to be on GPIO12.
-                          However, despite three nights of effort, pulling
-                          that GPIO low didn't reset the xc5000.  While
-                          pulling MO_SRST_IO low does reset the xc5000, this
-                          also resets in the s5h1409 being reset as well.
-                          This causes tuning to always fail since the internal
-                          state of the s5h1409 does not match the driver's
-                          state.  Given that the only two conditions in which
-                          the driver performs a reset is during firmware load
-                          and powering down the chip, I am taking out the
-                          reset.  We know that the chip is being reset
-                          when the cx88 comes online, and not being able to
-                          do power management for this board is worse than
-                          not having any tuning at all. */
-                       return 0;
-               } else {
-                       err_printk(core, "xc5000: unknown tuner "
-                                  "callback command.\n");
-                       return -EINVAL;
-               }
-               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;
-               }
-               break;
-       }
-       return 0; /* Should never be here */
-}
-
-int cx88_tuner_callback(void *priv, int component, 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;
-       }
-
-       if (component != DVB_FRONTEND_COMPONENT_TUNER)
-               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_XC4000:
-                       info_printk(core, "Calling XC4000 callback\n");
-                       return cx88_xc4000_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);
-
-/* ----------------------------------------------------------------------- */
-
-static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
-{
-       int i;
-
-       if (0 == pci->subsystem_vendor &&
-           0 == pci->subsystem_device) {
-               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(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);
-       }
-       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(KERN_ERR "%s:    card=%d -> %s\n",
-                      core->name, i, cx88_boards[i].name);
-}
-
-static void cx88_card_setup_pre_i2c(struct cx88_core *core)
-{
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               /*
-                * Bring the 702 demod up before i2c scanning/attach or devices are hidden
-                * We leave here with the 702 on the bus
-                *
-                * "reset the IR receiver on GPIO[3]"
-                * Reported by Mike Crash <mike AT mikecrash.com>
-                */
-               cx_write(MO_GP0_IO, 0x0000ef88);
-               udelay(1000);
-               cx_clear(MO_GP0_IO, 0x00000088);
-               udelay(50);
-               cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
-               udelay(1000);
-               break;
-
-       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
-       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;
-
-       case CX88_BOARD_WINFAST_DTV2000H_J:
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-       case CX88_BOARD_HAUPPAUGE_HVR4000:
-               /* Init GPIO */
-               cx_write(MO_GP0_IO, core->board.input[0].gpio0);
-               udelay(1000);
-               cx_clear(MO_GP0_IO, 0x00000080);
-               udelay(50);
-               cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
-               udelay(1000);
-               break;
-
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
-       case CX88_BOARD_WINFAST_DTV1800H:
-               cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
-               break;
-
-       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
-       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
-               cx88_xc4000_winfast2000h_plus_callback(core,
-                                                      XC4000_TUNER_RESET, 0);
-               break;
-
-       case CX88_BOARD_TWINHAN_VP1027_DVBS:
-               cx_write(MO_GP0_IO, 0x00003230);
-               cx_write(MO_GP0_IO, 0x00003210);
-               msleep(1);
-               cx_write(MO_GP0_IO, 0x00001230);
-               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:
-               /* Now works with firmware version 2.7 */
-               if (core->i2c_algo.udelay < 16)
-                       core->i2c_algo.udelay = 16;
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
-       case CX88_BOARD_WINFAST_DTV1800H:
-               ctl->demod = 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_GENIATECH_X8000_MT:
-               /* FIXME: For this board, the xc3028 never recovers after being
-                  powered down (the reset GPIO probably is not set properly).
-                  We don't have access to the hardware so we cannot determine
-                  which GPIO is used for xc3028, so just disable power xc3028
-                  power management for now */
-               ctl->disable_power_mgmt = 1;
-               break;
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
-       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
-       case CX88_BOARD_PROLINK_PV_8000GT:
-               /*
-                * Those boards uses non-MTS firmware
-                */
-               break;
-       case CX88_BOARD_PINNACLE_HYBRID_PCTV:
-       case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
-               ctl->demod = XC3028_FE_ZARLINK456;
-               ctl->mts = 1;
-               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];
-       struct tuner_setup tun_setup;
-       unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
-
-       memset(&tun_setup, 0, sizeof(tun_setup));
-
-       if (0 == core->i2c_rc) {
-               core->i2c_client.addr = 0xa0 >> 1;
-               tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
-       }
-
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE:
-       case CX88_BOARD_HAUPPAUGE_ROSLYN:
-               if (0 == core->i2c_rc)
-                       hauppauge_eeprom(core, eeprom+8);
-               break;
-       case CX88_BOARD_GDI:
-               if (0 == core->i2c_rc)
-                       gdi_eeprom(core, eeprom);
-               break;
-       case CX88_BOARD_LEADTEK_PVR2000:
-       case CX88_BOARD_WINFAST_DV2000:
-       case CX88_BOARD_WINFAST2000XP_EXPERT:
-               if (0 == core->i2c_rc)
-                       leadtek_eeprom(core, eeprom);
-               break;
-       case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
-       case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-       case CX88_BOARD_HAUPPAUGE_DVB_T1:
-       case CX88_BOARD_HAUPPAUGE_HVR1100:
-       case CX88_BOARD_HAUPPAUGE_HVR1100LP:
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-       case CX88_BOARD_HAUPPAUGE_HVR4000:
-       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
-       case CX88_BOARD_HAUPPAUGE_IRONLY:
-               if (0 == core->i2c_rc)
-                       hauppauge_eeprom(core, eeprom);
-               break;
-       case CX88_BOARD_KWORLD_DVBS_100:
-               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);
-               cx_clear(MO_GP0_IO, 0x00000040);
-               msleep(1000);
-               cx_set(MO_GP0_IO, 0x00004040);
-               /* FALLTHROUGH */
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
-               /* GPIO0:0 is hooked to mt352 reset pin */
-               cx_set(MO_GP0_IO, 0x00000101);
-               cx_clear(MO_GP0_IO, 0x00000001);
-               msleep(1);
-               cx_set(MO_GP0_IO, 0x00000101);
-               if (0 == core->i2c_rc &&
-                   core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
-                       dvico_fusionhdtv_hybrid_init(core);
-               break;
-       case CX88_BOARD_KWORLD_DVB_T:
-       case CX88_BOARD_DNTV_LIVE_DVB_T:
-               cx_set(MO_GP0_IO, 0x00000707);
-               cx_set(MO_GP2_IO, 0x00000101);
-               cx_clear(MO_GP2_IO, 0x00000001);
-               msleep(1);
-               cx_clear(MO_GP0_IO, 0x00000007);
-               cx_set(MO_GP2_IO, 0x00000101);
-               break;
-       case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-               cx_write(MO_GP0_IO, 0x00080808);
-               break;
-       case CX88_BOARD_ATI_HDTVWONDER:
-               if (0 == core->i2c_rc) {
-                       /* enable tuner */
-                       int i;
-                       static const u8 buffer [][2] = {
-                               {0x10,0x12},
-                               {0x13,0x04},
-                               {0x16,0x00},
-                               {0x14,0x04},
-                               {0x17,0x00}
-                       };
-                       core->i2c_client.addr = 0x0a;
-
-                       for (i = 0; i < ARRAY_SIZE(buffer); i++)
-                               if (2 != i2c_master_send(&core->i2c_client,
-                                                       buffer[i],2))
-                                       warn_printk(core, "Unable to enable "
-                                                   "tuner(%i).\n", i);
-               }
-               break;
-       case CX88_BOARD_MSI_TVANYWHERE_MASTER:
-       {
-               struct v4l2_priv_tun_config tea5767_cfg;
-               struct tea5767_ctrl ctl;
-
-               memset(&ctl, 0, sizeof(ctl));
-
-               ctl.high_cut  = 1;
-               ctl.st_noise  = 1;
-               ctl.deemph_75 = 1;
-               ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
-
-               tea5767_cfg.tuner = TUNER_TEA5767;
-               tea5767_cfg.priv  = &ctl;
-
-               call_all(core, tuner, s_config, &tea5767_cfg);
-               break;
-       }
-       case  CX88_BOARD_TEVII_S420:
-       case  CX88_BOARD_TEVII_S460:
-       case  CX88_BOARD_TEVII_S464:
-       case  CX88_BOARD_OMICOM_SS4_PCI:
-       case  CX88_BOARD_TBS_8910:
-       case  CX88_BOARD_TBS_8920:
-       case  CX88_BOARD_PROF_6200:
-       case  CX88_BOARD_PROF_7300:
-       case  CX88_BOARD_PROF_7301:
-       case  CX88_BOARD_SATTRADE_ST4200:
-               cx_write(MO_GP0_IO, 0x8000);
-               msleep(100);
-               cx_write(MO_SRST_IO, 0);
-               msleep(10);
-               cx_write(MO_GP0_IO, 0x8080);
-               msleep(100);
-               cx_write(MO_SRST_IO, 1);
-               msleep(100);
-               break;
-       } /*end switch() */
-
-
-       /* Setup tuners */
-       if ((core->board.radio_type != UNSET)) {
-               tun_setup.mode_mask      = T_RADIO;
-               tun_setup.type           = core->board.radio_type;
-               tun_setup.addr           = core->board.radio_addr;
-               tun_setup.tuner_callback = cx88_tuner_callback;
-               call_all(core, tuner, s_type_addr, &tun_setup);
-               mode_mask &= ~T_RADIO;
-       }
-
-       if (core->board.tuner_type != TUNER_ABSENT) {
-               tun_setup.mode_mask      = mode_mask;
-               tun_setup.type           = core->board.tuner_type;
-               tun_setup.addr           = core->board.tuner_addr;
-               tun_setup.tuner_callback = cx88_tuner_callback;
-
-               call_all(core, tuner, s_type_addr, &tun_setup);
-       }
-
-       if (core->board.tda9887_conf) {
-               struct v4l2_priv_tun_config tda9887_cfg;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv  = &core->board.tda9887_conf;
-
-               call_all(core, tuner, s_config, &tda9887_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);
-               call_all(core, tuner, s_config, &xc2028_cfg);
-       }
-       call_all(core, core, s_power, 0);
-}
-
-/* ------------------------------------------------------------------ */
-
-static int cx88_pci_quirks(const char *name, struct pci_dev *pci)
-{
-       unsigned int lat = UNSET;
-       u8 ctrl = 0;
-       u8 value;
-
-       /* check pci quirks */
-       if (pci_pci_problems & PCIPCI_TRITON) {
-               printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
-                      name);
-               ctrl |= CX88X_EN_TBFX;
-       }
-       if (pci_pci_problems & PCIPCI_NATOMA) {
-               printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
-                      name);
-               ctrl |= CX88X_EN_TBFX;
-       }
-       if (pci_pci_problems & PCIPCI_VIAETBF) {
-               printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
-                      name);
-               ctrl |= CX88X_EN_TBFX;
-       }
-       if (pci_pci_problems & PCIPCI_VSFX) {
-               printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
-                      name);
-               ctrl |= CX88X_EN_VSFX;
-       }
-#ifdef PCIPCI_ALIMAGIK
-       if (pci_pci_problems & PCIPCI_ALIMAGIK) {
-               printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
-                      name);
-               lat = 0x0A;
-       }
-#endif
-
-       /* check insmod options */
-       if (UNSET != latency)
-               lat = latency;
-
-       /* apply stuff */
-       if (ctrl) {
-               pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
-               value |= ctrl;
-               pci_write_config_byte(pci, CX88X_DEVCTRL, value);
-       }
-       if (UNSET != lat) {
-               printk(KERN_INFO "%s: setting pci latency timer to %d\n",
-                      name, latency);
-               pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
-       }
-       return 0;
-}
-
-int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci)
-{
-       if (request_mem_region(pci_resource_start(pci,0),
-                              pci_resource_len(pci,0),
-                              core->name))
-               return 0;
-       printk(KERN_ERR
-              "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
-              core->name, PCI_FUNC(pci->devfn),
-              (unsigned long long)pci_resource_start(pci, 0),
-              pci->subsystem_vendor, pci->subsystem_device);
-       return -EBUSY;
-}
-
-/* Allocate and initialize the cx88 core struct.  One should hold the
- * devlist mutex before calling this.  */
-struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
-{
-       struct cx88_core *core;
-       int i;
-
-       core = kzalloc(sizeof(*core), GFP_KERNEL);
-       if (core == NULL)
-               return NULL;
-
-       atomic_inc(&core->refcount);
-       core->pci_bus  = pci->bus->number;
-       core->pci_slot = PCI_SLOT(pci->devfn);
-       core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT |
-                           PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT |
-                           PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT;
-       mutex_init(&core->lock);
-
-       core->nr = nr;
-       sprintf(core->name, "cx88[%d]", core->nr);
-
-       strcpy(core->v4l2_dev.name, core->name);
-       if (v4l2_device_register(NULL, &core->v4l2_dev)) {
-               kfree(core);
-               return NULL;
-       }
-
-       if (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
-               v4l2_device_unregister(&core->v4l2_dev);
-               kfree(core);
-               return NULL;
-       }
-
-       if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
-               v4l2_ctrl_handler_free(&core->video_hdl);
-               v4l2_device_unregister(&core->v4l2_dev);
-               kfree(core);
-               return NULL;
-       }
-
-       if (0 != cx88_get_resources(core, pci)) {
-               v4l2_ctrl_handler_free(&core->video_hdl);
-               v4l2_ctrl_handler_free(&core->audio_hdl);
-               v4l2_device_unregister(&core->v4l2_dev);
-               kfree(core);
-               return NULL;
-       }
-
-       /* PCI stuff */
-       cx88_pci_quirks(core->name, pci);
-       core->lmmio = ioremap(pci_resource_start(pci, 0),
-                             pci_resource_len(pci, 0));
-       core->bmmio = (u8 __iomem *)core->lmmio;
-
-       if (core->lmmio == NULL) {
-               release_mem_region(pci_resource_start(pci, 0),
-                          pci_resource_len(pci, 0));
-               v4l2_ctrl_handler_free(&core->video_hdl);
-               v4l2_ctrl_handler_free(&core->audio_hdl);
-               v4l2_device_unregister(&core->v4l2_dev);
-               kfree(core);
-               return NULL;
-       }
-
-       /* board config */
-       core->boardnr = UNSET;
-       if (card[core->nr] < ARRAY_SIZE(cx88_boards))
-               core->boardnr = card[core->nr];
-       for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++)
-               if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
-                   pci->subsystem_device == cx88_subids[i].subdevice)
-                       core->boardnr = cx88_subids[i].card;
-       if (UNSET == core->boardnr) {
-               core->boardnr = CX88_BOARD_UNKNOWN;
-               cx88_card_list(core, pci);
-       }
-
-       memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
-
-       if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
-               core->board.num_frontends = 1;
-
-       info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
-               pci->subsystem_vendor, pci->subsystem_device, core->board.name,
-               core->boardnr, card[core->nr] == core->boardnr ?
-               "insmod option" : "autodetected",
-               core->board.num_frontends);
-
-       if (tuner[core->nr] != UNSET)
-               core->board.tuner_type = tuner[core->nr];
-       if (radio[core->nr] != UNSET)
-               core->board.radio_type = radio[core->nr];
-
-       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);
-       cx88_card_setup_pre_i2c(core);
-       cx88_i2c_init(core, pci);
-
-       /* load tuner module, if needed */
-       if (TUNER_ABSENT != core->board.tuner_type) {
-               /* Ignore 0x6b and 0x6f on cx88 boards.
-                * FusionHDTV5 RT Gold has an ir receiver at 0x6b
-                * and an RTC at 0x6f which can get corrupted if probed. */
-               static const unsigned short tv_addrs[] = {
-                       0x42, 0x43, 0x4a, 0x4b,         /* tda8290 */
-                       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-                       0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e,
-                       I2C_CLIENT_END
-               };
-               int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
-
-               /* I don't trust the radio_type as is stored in the card
-                  definitions, so we just probe for it.
-                  The radio_type is sometimes missing, or set to UNSET but
-                  later code configures a tea5767.
-                */
-               v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
-               if (has_demod)
-                       v4l2_i2c_new_subdev(&core->v4l2_dev,
-                               &core->i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-               if (core->board.tuner_addr == ADDR_UNSET) {
-                       v4l2_i2c_new_subdev(&core->v4l2_dev,
-                               &core->i2c_adap, "tuner",
-                               0, has_demod ? tv_addrs + 4 : tv_addrs);
-               } else {
-                       v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               "tuner", core->board.tuner_addr, NULL);
-               }
-       }
-
-       cx88_card_setup(core);
-       if (!disable_ir) {
-               cx88_i2c_init_ir(core);
-               cx88_ir_init(core, pci);
-       }
-
-       return core;
-}
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
deleted file mode 100644 (file)
index c97b174..0000000
+++ /dev/null
@@ -1,1131 +0,0 @@
-/*
- *
- * device driver for Conexant 2388x based TV cards
- * driver core
- *
- * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
- *
- * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
- *     - Multituner support
- *     - video_ioctl2 conversion
- *     - PAL/M fixes
- *
- *  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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/kmod.h>
-#include <linux/sound.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <linux/mutex.h>
-
-#include "cx88.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int core_debug;
-module_param(core_debug,int,0644);
-MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
-
-static unsigned int nicam;
-module_param(nicam,int,0644);
-MODULE_PARM_DESC(nicam,"tv audio is nicam");
-
-static unsigned int nocomb;
-module_param(nocomb,int,0644);
-MODULE_PARM_DESC(nocomb,"disable comb filter");
-
-#define dprintk(level,fmt, arg...)     if (core_debug >= level)        \
-       printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
-
-static unsigned int cx88_devcount;
-static LIST_HEAD(cx88_devlist);
-static DEFINE_MUTEX(devlist);
-
-#define NO_SYNC_LINE (-1U)
-
-/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
-        generated _after_ lpi lines are transferred. */
-static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
-                           unsigned int offset, u32 sync_line,
-                           unsigned int bpl, unsigned int padding,
-                           unsigned int lines, unsigned int lpi)
-{
-       struct scatterlist *sg;
-       unsigned int line,todo,sol;
-
-       /* sync instruction */
-       if (sync_line != NO_SYNC_LINE)
-               *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
-
-       /* scan lines */
-       sg = sglist;
-       for (line = 0; line < lines; line++) {
-               while (offset && offset >= sg_dma_len(sg)) {
-                       offset -= sg_dma_len(sg);
-                       sg++;
-               }
-               if (lpi && line>0 && !(line % lpi))
-                       sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
-               else
-                       sol = RISC_SOL;
-               if (bpl <= sg_dma_len(sg)-offset) {
-                       /* fits into current chunk */
-                       *(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
-                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-                       offset+=bpl;
-               } else {
-                       /* scanline needs to be split */
-                       todo = bpl;
-                       *(rp++)=cpu_to_le32(RISC_WRITE|sol|
-                                           (sg_dma_len(sg)-offset));
-                       *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
-                       todo -= (sg_dma_len(sg)-offset);
-                       offset = 0;
-                       sg++;
-                       while (todo > sg_dma_len(sg)) {
-                               *(rp++)=cpu_to_le32(RISC_WRITE|
-                                                   sg_dma_len(sg));
-                               *(rp++)=cpu_to_le32(sg_dma_address(sg));
-                               todo -= sg_dma_len(sg);
-                               sg++;
-                       }
-                       *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
-                       *(rp++)=cpu_to_le32(sg_dma_address(sg));
-                       offset += todo;
-               }
-               offset += padding;
-       }
-
-       return rp;
-}
-
-int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                    struct scatterlist *sglist,
-                    unsigned int top_offset, unsigned int bottom_offset,
-                    unsigned int bpl, unsigned int padding, unsigned int lines)
-{
-       u32 instructions,fields;
-       __le32 *rp;
-       int rc;
-
-       fields = 0;
-       if (UNSET != top_offset)
-               fields++;
-       if (UNSET != bottom_offset)
-               fields++;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Padding
-          can cause next bpl to start close to a page border.  First DMA
-          region may be smaller than PAGE_SIZE */
-       instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
-       instructions += 2;
-       if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       if (UNSET != top_offset)
-               rp = cx88_risc_field(rp, sglist, top_offset, 0,
-                                    bpl, padding, lines, 0);
-       if (UNSET != bottom_offset)
-               rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
-                                    bpl, padding, lines, 0);
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
-       return 0;
-}
-
-int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                        struct scatterlist *sglist, unsigned int bpl,
-                        unsigned int lines, unsigned int lpi)
-{
-       u32 instructions;
-       __le32 *rp;
-       int rc;
-
-       /* estimate risc mem: worst case is one write per page border +
-          one write per scan line + syncs + jump (all 2 dwords).  Here
-          there is no padding and no sync.  First DMA region may be smaller
-          than PAGE_SIZE */
-       instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
-       instructions += 1;
-       if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
-
-       /* save pointer to jmp instruction address */
-       risc->jmp = rp;
-       BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
-       return 0;
-}
-
-int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-                     u32 reg, u32 mask, u32 value)
-{
-       __le32 *rp;
-       int rc;
-
-       if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
-               return rc;
-
-       /* write risc instructions */
-       rp = risc->cpu;
-       *(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
-       *(rp++) = cpu_to_le32(reg);
-       *(rp++) = cpu_to_le32(value);
-       *(rp++) = cpu_to_le32(mask);
-       *(rp++) = cpu_to_le32(RISC_JUMP);
-       *(rp++) = cpu_to_le32(risc->dma);
-       return 0;
-}
-
-void
-cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
-{
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-       BUG_ON(in_interrupt());
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_dma_unmap(q->dev, dma);
-       videobuf_dma_free(dma);
-       btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-/* ------------------------------------------------------------------ */
-/* our SRAM memory layout                                             */
-
-/* we are going to put all thr risc programs into host memory, so we
- * can use the whole SDRAM for the DMA fifos.  To simplify things, we
- * use a static memory layout.  That surely will waste memory in case
- * we don't use all DMA channels at the same time (which will be the
- * case most of the time).  But that still gives us enough FIFO space
- * to be able to deal with insane long pci latencies ...
- *
- * FIFO space allocations:
- *    channel  21    (y video)  - 10.0k
- *    channel  22    (u video)  -  2.0k
- *    channel  23    (v video)  -  2.0k
- *    channel  24    (vbi)      -  4.0k
- *    channels 25+26 (audio)    -  4.0k
- *    channel  28    (mpeg)     -  4.0k
- *    channel  27    (audio rds)-  3.0k
- *    TOTAL                     = 29.0k
- *
- * Every channel has 160 bytes control data (64 bytes instruction
- * queue and 6 CDT entries), which is close to 2k total.
- *
- * Address layout:
- *    0x0000 - 0x03ff    CMDs / reserved
- *    0x0400 - 0x0bff    instruction queues + CDs
- *    0x0c00 -           FIFOs
- */
-
-const struct sram_channel cx88_sram_channels[] = {
-       [SRAM_CH21] = {
-               .name       = "video y / packed",
-               .cmds_start = 0x180040,
-               .ctrl_start = 0x180400,
-               .cdt        = 0x180400 + 64,
-               .fifo_start = 0x180c00,
-               .fifo_size  = 0x002800,
-               .ptr1_reg   = MO_DMA21_PTR1,
-               .ptr2_reg   = MO_DMA21_PTR2,
-               .cnt1_reg   = MO_DMA21_CNT1,
-               .cnt2_reg   = MO_DMA21_CNT2,
-       },
-       [SRAM_CH22] = {
-               .name       = "video u",
-               .cmds_start = 0x180080,
-               .ctrl_start = 0x1804a0,
-               .cdt        = 0x1804a0 + 64,
-               .fifo_start = 0x183400,
-               .fifo_size  = 0x000800,
-               .ptr1_reg   = MO_DMA22_PTR1,
-               .ptr2_reg   = MO_DMA22_PTR2,
-               .cnt1_reg   = MO_DMA22_CNT1,
-               .cnt2_reg   = MO_DMA22_CNT2,
-       },
-       [SRAM_CH23] = {
-               .name       = "video v",
-               .cmds_start = 0x1800c0,
-               .ctrl_start = 0x180540,
-               .cdt        = 0x180540 + 64,
-               .fifo_start = 0x183c00,
-               .fifo_size  = 0x000800,
-               .ptr1_reg   = MO_DMA23_PTR1,
-               .ptr2_reg   = MO_DMA23_PTR2,
-               .cnt1_reg   = MO_DMA23_CNT1,
-               .cnt2_reg   = MO_DMA23_CNT2,
-       },
-       [SRAM_CH24] = {
-               .name       = "vbi",
-               .cmds_start = 0x180100,
-               .ctrl_start = 0x1805e0,
-               .cdt        = 0x1805e0 + 64,
-               .fifo_start = 0x184400,
-               .fifo_size  = 0x001000,
-               .ptr1_reg   = MO_DMA24_PTR1,
-               .ptr2_reg   = MO_DMA24_PTR2,
-               .cnt1_reg   = MO_DMA24_CNT1,
-               .cnt2_reg   = MO_DMA24_CNT2,
-       },
-       [SRAM_CH25] = {
-               .name       = "audio from",
-               .cmds_start = 0x180140,
-               .ctrl_start = 0x180680,
-               .cdt        = 0x180680 + 64,
-               .fifo_start = 0x185400,
-               .fifo_size  = 0x001000,
-               .ptr1_reg   = MO_DMA25_PTR1,
-               .ptr2_reg   = MO_DMA25_PTR2,
-               .cnt1_reg   = MO_DMA25_CNT1,
-               .cnt2_reg   = MO_DMA25_CNT2,
-       },
-       [SRAM_CH26] = {
-               .name       = "audio to",
-               .cmds_start = 0x180180,
-               .ctrl_start = 0x180720,
-               .cdt        = 0x180680 + 64,  /* same as audio IN */
-               .fifo_start = 0x185400,       /* same as audio IN */
-               .fifo_size  = 0x001000,       /* same as audio IN */
-               .ptr1_reg   = MO_DMA26_PTR1,
-               .ptr2_reg   = MO_DMA26_PTR2,
-               .cnt1_reg   = MO_DMA26_CNT1,
-               .cnt2_reg   = MO_DMA26_CNT2,
-       },
-       [SRAM_CH28] = {
-               .name       = "mpeg",
-               .cmds_start = 0x180200,
-               .ctrl_start = 0x1807C0,
-               .cdt        = 0x1807C0 + 64,
-               .fifo_start = 0x186400,
-               .fifo_size  = 0x001000,
-               .ptr1_reg   = MO_DMA28_PTR1,
-               .ptr2_reg   = MO_DMA28_PTR2,
-               .cnt1_reg   = MO_DMA28_CNT1,
-               .cnt2_reg   = MO_DMA28_CNT2,
-       },
-       [SRAM_CH27] = {
-               .name       = "audio rds",
-               .cmds_start = 0x1801C0,
-               .ctrl_start = 0x180860,
-               .cdt        = 0x180860 + 64,
-               .fifo_start = 0x187400,
-               .fifo_size  = 0x000C00,
-               .ptr1_reg   = MO_DMA27_PTR1,
-               .ptr2_reg   = MO_DMA27_PTR2,
-               .cnt1_reg   = MO_DMA27_CNT1,
-               .cnt2_reg   = MO_DMA27_CNT2,
-       },
-};
-
-int cx88_sram_channel_setup(struct cx88_core *core,
-                           const struct sram_channel *ch,
-                           unsigned int bpl, u32 risc)
-{
-       unsigned int i,lines;
-       u32 cdt;
-
-       bpl   = (bpl + 7) & ~7; /* alignment */
-       cdt   = ch->cdt;
-       lines = ch->fifo_size / bpl;
-       if (lines > 6)
-               lines = 6;
-       BUG_ON(lines < 2);
-
-       /* write CDT */
-       for (i = 0; i < lines; i++)
-               cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
-
-       /* write CMDS */
-       cx_write(ch->cmds_start +  0, risc);
-       cx_write(ch->cmds_start +  4, cdt);
-       cx_write(ch->cmds_start +  8, (lines*16) >> 3);
-       cx_write(ch->cmds_start + 12, ch->ctrl_start);
-       cx_write(ch->cmds_start + 16, 64 >> 2);
-       for (i = 20; i < 64; i += 4)
-               cx_write(ch->cmds_start + i, 0);
-
-       /* fill registers */
-       cx_write(ch->ptr1_reg, ch->fifo_start);
-       cx_write(ch->ptr2_reg, cdt);
-       cx_write(ch->cnt1_reg, (bpl >> 3) -1);
-       cx_write(ch->cnt2_reg, (lines*16) >> 3);
-
-       dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-/* debug helper code                                                  */
-
-static int cx88_risc_decode(u32 risc)
-{
-       static const char * const 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",
-       };
-       static int const incr[16] = {
-               [ RISC_WRITE   >> 28 ] = 2,
-               [ RISC_JUMP    >> 28 ] = 2,
-               [ RISC_WRITERM >> 28 ] = 3,
-               [ RISC_WRITECM >> 28 ] = 3,
-               [ RISC_WRITECR >> 28 ] = 4,
-       };
-       static const char * const bits[] = {
-               "12",   "13",   "14",   "resync",
-               "cnt0", "cnt1", "18",   "19",
-               "20",   "21",   "22",   "23",
-               "irq1", "irq2", "eol",  "sol",
-       };
-       int i;
-
-       printk("0x%08x [ %s", risc,
-              instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
-       for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
-               if (risc & (1 << (i + 12)))
-                       printk(" %s",bits[i]);
-       printk(" count=%d ]\n", risc & 0xfff);
-       return incr[risc >> 28] ? incr[risc >> 28] : 1;
-}
-
-
-void cx88_sram_channel_dump(struct cx88_core *core,
-                           const struct sram_channel *ch)
-{
-       static const char * const name[] = {
-               "initial risc",
-               "cdt base",
-               "cdt size",
-               "iq base",
-               "iq size",
-               "risc pc",
-               "iq wr ptr",
-               "iq rd ptr",
-               "cdt current",
-               "pci target",
-               "line / byte",
-       };
-       u32 risc;
-       unsigned int i,j,n;
-
-       printk("%s: %s - dma channel status dump\n",
-              core->name,ch->name);
-       for (i = 0; i < ARRAY_SIZE(name); i++)
-               printk("%s:   cmds: %-12s: 0x%08x\n",
-                      core->name,name[i],
-                      cx_read(ch->cmds_start + 4*i));
-       for (n = 1, i = 0; i < 4; i++) {
-               risc = cx_read(ch->cmds_start + 4 * (i+11));
-               printk("%s:   risc%d: ", core->name, i);
-               if (--n)
-                       printk("0x%08x [ arg #%d ]\n", risc, n);
-               else
-                       n = cx88_risc_decode(risc);
-       }
-       for (i = 0; i < 16; i += n) {
-               risc = cx_read(ch->ctrl_start + 4 * i);
-               printk("%s:   iq %x: ", core->name, i);
-               n = cx88_risc_decode(risc);
-               for (j = 1; j < n; j++) {
-                       risc = cx_read(ch->ctrl_start + 4 * (i+j));
-                       printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
-                              core->name, i+j, risc, j);
-               }
-       }
-
-       printk("%s: fifo: 0x%08x -> 0x%x\n",
-              core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
-       printk("%s: ctrl: 0x%08x -> 0x%x\n",
-              core->name, ch->ctrl_start, ch->ctrl_start+6*16);
-       printk("%s:   ptr1_reg: 0x%08x\n",
-              core->name,cx_read(ch->ptr1_reg));
-       printk("%s:   ptr2_reg: 0x%08x\n",
-              core->name,cx_read(ch->ptr2_reg));
-       printk("%s:   cnt1_reg: 0x%08x\n",
-              core->name,cx_read(ch->cnt1_reg));
-       printk("%s:   cnt2_reg: 0x%08x\n",
-              core->name,cx_read(ch->cnt2_reg));
-}
-
-static const char *cx88_pci_irqs[32] = {
-       "vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
-       "src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
-       "brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
-       "i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
-};
-
-void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
-                       int len, u32 bits, u32 mask)
-{
-       unsigned int i;
-
-       printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
-       for (i = 0; i < len; i++) {
-               if (!(bits & (1 << i)))
-                       continue;
-               if (strings[i])
-                       printk(" %s", strings[i]);
-               else
-                       printk(" %d", i);
-               if (!(mask & (1 << i)))
-                       continue;
-               printk("*");
-       }
-       printk("\n");
-}
-
-/* ------------------------------------------------------------------ */
-
-int cx88_core_irq(struct cx88_core *core, u32 status)
-{
-       int handled = 0;
-
-       if (status & PCI_INT_IR_SMPINT) {
-               cx88_ir_irq(core);
-               handled++;
-       }
-       if (!handled)
-               cx88_print_irqbits(core->name, "irq pci",
-                                  cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
-                                  status, core->pci_irqmask);
-       return handled;
-}
-
-void cx88_wakeup(struct cx88_core *core,
-                struct cx88_dmaqueue *q, u32 count)
-{
-       struct cx88_buffer *buf;
-       int bc;
-
-       for (bc = 0;; bc++) {
-               if (list_empty(&q->active))
-                       break;
-               buf = list_entry(q->active.next,
-                                struct cx88_buffer, vb.queue);
-               /* count comes from the hw and is is 16bit wide --
-                * this trick handles wrap-arounds correctly for
-                * up to 32767 buffers in flight... */
-               if ((s16) (count - buf->count) < 0)
-                       break;
-               do_gettimeofday(&buf->vb.ts);
-               dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
-                       count, buf->count);
-               buf->vb.state = VIDEOBUF_DONE;
-               list_del(&buf->vb.queue);
-               wake_up(&buf->vb.done);
-       }
-       if (list_empty(&q->active)) {
-               del_timer(&q->timeout);
-       } else {
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-       }
-       if (bc != 1)
-               dprintk(2, "%s: %d buffers handled (should be 1)\n",
-                       __func__, bc);
-}
-
-void cx88_shutdown(struct cx88_core *core)
-{
-       /* disable RISC controller + IRQs */
-       cx_write(MO_DEV_CNTRL2, 0);
-
-       /* stop dma transfers */
-       cx_write(MO_VID_DMACNTRL, 0x0);
-       cx_write(MO_AUD_DMACNTRL, 0x0);
-       cx_write(MO_TS_DMACNTRL, 0x0);
-       cx_write(MO_VIP_DMACNTRL, 0x0);
-       cx_write(MO_GPHST_DMACNTRL, 0x0);
-
-       /* stop interrupts */
-       cx_write(MO_PCI_INTMSK, 0x0);
-       cx_write(MO_VID_INTMSK, 0x0);
-       cx_write(MO_AUD_INTMSK, 0x0);
-       cx_write(MO_TS_INTMSK, 0x0);
-       cx_write(MO_VIP_INTMSK, 0x0);
-       cx_write(MO_GPHST_INTMSK, 0x0);
-
-       /* stop capturing */
-       cx_write(VID_CAPTURE_CONTROL, 0);
-}
-
-int cx88_reset(struct cx88_core *core)
-{
-       dprintk(1,"%s\n",__func__);
-       cx88_shutdown(core);
-
-       /* clear irq status */
-       cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
-       cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
-       cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int
-
-       /* wait a bit */
-       msleep(100);
-
-       /* init sram */
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
-
-       /* misc init ... */
-       cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
-                                  (1 << 12) |   // agc gain
-                                  (1 << 11) |   // adaptibe agc
-                                  (0 << 10) |   // chroma agc
-                                  (0 <<  9) |   // ckillen
-                                  (7)));
-
-       /* setup image format */
-       cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
-
-       /* setup FIFO Thresholds */
-       cx_write(MO_PDMA_STHRSH,   0x0807);
-       cx_write(MO_PDMA_DTHRSH,   0x0807);
-
-       /* fixes flashing of image */
-       cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
-       cx_write(MO_AGC_BACK_VBI,  0x00E00555);
-
-       cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int
-       cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
-       cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
-
-       /* Reset on-board parts */
-       cx_write(MO_SRST_IO, 0);
-       msleep(10);
-       cx_write(MO_SRST_IO, 1);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int inline norm_swidth(v4l2_std_id norm)
-{
-       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
-}
-
-static unsigned int inline norm_hdelay(v4l2_std_id norm)
-{
-       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
-}
-
-static unsigned int inline norm_vdelay(v4l2_std_id norm)
-{
-       return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
-}
-
-static unsigned int inline norm_fsc8(v4l2_std_id norm)
-{
-       if (norm & V4L2_STD_PAL_M)
-               return 28604892;      // 3.575611 MHz
-
-       if (norm & (V4L2_STD_PAL_Nc))
-               return 28656448;      // 3.582056 MHz
-
-       if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
-               return 28636360;      // 3.57954545 MHz +/- 10 Hz
-
-       /* SECAM have also different sub carrier for chroma,
-          but step_db and step_dr, at cx88_set_tvnorm already handles that.
-
-          The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
-        */
-
-       return 35468950;      // 4.43361875 MHz +/- 5 Hz
-}
-
-static unsigned int inline norm_htotal(v4l2_std_id norm)
-{
-
-       unsigned int fsc4=norm_fsc8(norm)/2;
-
-       /* returns 4*FSC / vtotal / frames per seconds */
-       return (norm & V4L2_STD_625_50) ?
-                               ((fsc4+312)/625+12)/25 :
-                               ((fsc4+262)/525*1001+15000)/30000;
-}
-
-static unsigned int inline norm_vbipack(v4l2_std_id norm)
-{
-       return (norm & V4L2_STD_625_50) ? 511 : 400;
-}
-
-int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
-                  enum v4l2_field field)
-{
-       unsigned int swidth  = norm_swidth(core->tvnorm);
-       unsigned int sheight = norm_maxh(core->tvnorm);
-       u32 value;
-
-       dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
-               V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
-               V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
-               v4l2_norm_to_name(core->tvnorm));
-       if (!V4L2_FIELD_HAS_BOTH(field))
-               height *= 2;
-
-       // recalc H delay and scale registers
-       value = (width * norm_hdelay(core->tvnorm)) / swidth;
-       value &= 0x3fe;
-       cx_write(MO_HDELAY_EVEN,  value);
-       cx_write(MO_HDELAY_ODD,   value);
-       dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
-
-       value = (swidth * 4096 / width) - 4096;
-       cx_write(MO_HSCALE_EVEN,  value);
-       cx_write(MO_HSCALE_ODD,   value);
-       dprintk(1,"set_scale: hscale  0x%04x\n", value);
-
-       cx_write(MO_HACTIVE_EVEN, width);
-       cx_write(MO_HACTIVE_ODD,  width);
-       dprintk(1,"set_scale: hactive 0x%04x\n", width);
-
-       // recalc V scale Register (delay is constant)
-       cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
-       cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
-       dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
-
-       value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
-       cx_write(MO_VSCALE_EVEN,  value);
-       cx_write(MO_VSCALE_ODD,   value);
-       dprintk(1,"set_scale: vscale  0x%04x\n", value);
-
-       cx_write(MO_VACTIVE_EVEN, sheight);
-       cx_write(MO_VACTIVE_ODD,  sheight);
-       dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
-
-       // setup filters
-       value = 0;
-       value |= (1 << 19);        // CFILT (default)
-       if (core->tvnorm & V4L2_STD_SECAM) {
-               value |= (1 << 15);
-               value |= (1 << 16);
-       }
-       if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
-               value |= (1 << 13) | (1 << 5);
-       if (V4L2_FIELD_INTERLACED == field)
-               value |= (1 << 3); // VINT (interlaced vertical scaling)
-       if (width < 385)
-               value |= (1 << 0); // 3-tap interpolation
-       if (width < 193)
-               value |= (1 << 1); // 5-tap interpolation
-       if (nocomb)
-               value |= (3 << 5); // disable comb filter
-
-       cx_andor(MO_FILTER_EVEN,  0x7ffc7f, value); /* preserve PEAKEN, PSEL */
-       cx_andor(MO_FILTER_ODD,   0x7ffc7f, value);
-       dprintk(1,"set_scale: filter  0x%04x\n", value);
-
-       return 0;
-}
-
-static const u32 xtal = 28636363;
-
-static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
-{
-       static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
-       u64 pll;
-       u32 reg;
-       int i;
-
-       if (prescale < 2)
-               prescale = 2;
-       if (prescale > 5)
-               prescale = 5;
-
-       pll = ofreq * 8 * prescale * (u64)(1 << 20);
-       do_div(pll,xtal);
-       reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
-       if (((reg >> 20) & 0x3f) < 14) {
-               printk("%s/0: pll out of range\n",core->name);
-               return -1;
-       }
-
-       dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
-               reg, cx_read(MO_PLL_REG), ofreq);
-       cx_write(MO_PLL_REG, reg);
-       for (i = 0; i < 100; i++) {
-               reg = cx_read(MO_DEVICE_STATUS);
-               if (reg & (1<<2)) {
-                       dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
-                               prescale,ofreq);
-                       return 0;
-               }
-               dprintk(1,"pll not locked yet, waiting ...\n");
-               msleep(10);
-       }
-       dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
-       return -1;
-}
-
-int cx88_start_audio_dma(struct cx88_core *core)
-{
-       /* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
-       int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
-
-       int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
-
-       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
-       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
-               return 0;
-
-       /* setup fifo + format */
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
-                               rds_bpl, 0);
-
-       cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
-       cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
-
-       /* enable Up, Down and Audio RDS fifo */
-       cx_write(MO_AUD_DMACNTRL, 0x0007);
-
-       return 0;
-}
-
-int cx88_stop_audio_dma(struct cx88_core *core)
-{
-       /* If downstream RISC is enabled, bail out; ALSA is managing DMA */
-       if (cx_read(MO_AUD_DMACNTRL) & 0x10)
-               return 0;
-
-       /* stop dma */
-       cx_write(MO_AUD_DMACNTRL, 0x0000);
-
-       return 0;
-}
-
-static int set_tvaudio(struct cx88_core *core)
-{
-       v4l2_std_id norm = core->tvnorm;
-
-       if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
-           CX88_VMUX_CABLE != INPUT(core->input).type)
-               return 0;
-
-       if (V4L2_STD_PAL_BG & norm) {
-               core->tvaudio = WW_BG;
-
-       } else if (V4L2_STD_PAL_DK & norm) {
-               core->tvaudio = WW_DK;
-
-       } else if (V4L2_STD_PAL_I & norm) {
-               core->tvaudio = WW_I;
-
-       } else if (V4L2_STD_SECAM_L & norm) {
-               core->tvaudio = WW_L;
-
-       } else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
-               core->tvaudio = WW_BG;
-
-       } else if (V4L2_STD_SECAM_DK & norm) {
-               core->tvaudio = WW_DK;
-
-       } else if ((V4L2_STD_NTSC_M & norm) ||
-                  (V4L2_STD_PAL_M  & norm)) {
-               core->tvaudio = WW_BTSC;
-
-       } else if (V4L2_STD_NTSC_M_JP & norm) {
-               core->tvaudio = WW_EIAJ;
-
-       } else {
-               printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
-                      core->name, v4l2_norm_to_name(core->tvnorm));
-               core->tvaudio = WW_NONE;
-               return 0;
-       }
-
-       cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
-       cx88_set_tvaudio(core);
-       /* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
-
-/*
-   This should be needed only on cx88-alsa. It seems that some cx88 chips have
-   bugs and does require DMA enabled for it to work.
- */
-       cx88_start_audio_dma(core);
-       return 0;
-}
-
-
-
-int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
-{
-       u32 fsc8;
-       u32 adc_clock;
-       u32 vdec_clock;
-       u32 step_db,step_dr;
-       u64 tmp64;
-       u32 bdelay,agcdelay,htotal;
-       u32 cxiformat, cxoformat;
-
-       core->tvnorm = norm;
-       fsc8       = norm_fsc8(norm);
-       adc_clock  = xtal;
-       vdec_clock = fsc8;
-       step_db    = fsc8;
-       step_dr    = fsc8;
-
-       if (norm & V4L2_STD_NTSC_M_JP) {
-               cxiformat = VideoFormatNTSCJapan;
-               cxoformat = 0x181f0008;
-       } else if (norm & V4L2_STD_NTSC_443) {
-               cxiformat = VideoFormatNTSC443;
-               cxoformat = 0x181f0008;
-       } else if (norm & V4L2_STD_PAL_M) {
-               cxiformat = VideoFormatPALM;
-               cxoformat = 0x1c1f0008;
-       } else if (norm & V4L2_STD_PAL_N) {
-               cxiformat = VideoFormatPALN;
-               cxoformat = 0x1c1f0008;
-       } else if (norm & V4L2_STD_PAL_Nc) {
-               cxiformat = VideoFormatPALNC;
-               cxoformat = 0x1c1f0008;
-       } else if (norm & V4L2_STD_PAL_60) {
-               cxiformat = VideoFormatPAL60;
-               cxoformat = 0x181f0008;
-       } else if (norm & V4L2_STD_NTSC) {
-               cxiformat = VideoFormatNTSC;
-               cxoformat = 0x181f0008;
-       } else if (norm & V4L2_STD_SECAM) {
-               step_db = 4250000 * 8;
-               step_dr = 4406250 * 8;
-
-               cxiformat = VideoFormatSECAM;
-               cxoformat = 0x181f0008;
-       } else { /* PAL */
-               cxiformat = VideoFormatPAL;
-               cxoformat = 0x181f0008;
-       }
-
-       dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
-               v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
-               step_db, step_dr);
-       set_pll(core,2,vdec_clock);
-
-       dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
-               cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
-       /* 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",
-               cxoformat, cx_read(MO_OUTPUT_FORMAT));
-       cx_write(MO_OUTPUT_FORMAT, cxoformat);
-
-       // MO_SCONV_REG = adc clock / video dec clock * 2^17
-       tmp64  = adc_clock * (u64)(1 << 17);
-       do_div(tmp64, vdec_clock);
-       dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
-               (u32)tmp64, cx_read(MO_SCONV_REG));
-       cx_write(MO_SCONV_REG, (u32)tmp64);
-
-       // MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
-       tmp64  = step_db * (u64)(1 << 22);
-       do_div(tmp64, vdec_clock);
-       dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
-               (u32)tmp64, cx_read(MO_SUB_STEP));
-       cx_write(MO_SUB_STEP, (u32)tmp64);
-
-       // MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
-       tmp64  = step_dr * (u64)(1 << 22);
-       do_div(tmp64, vdec_clock);
-       dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
-               (u32)tmp64, cx_read(MO_SUB_STEP_DR));
-       cx_write(MO_SUB_STEP_DR, (u32)tmp64);
-
-       // bdelay + agcdelay
-       bdelay   = vdec_clock * 65 / 20000000 + 21;
-       agcdelay = vdec_clock * 68 / 20000000 + 15;
-       dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
-               (bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
-       cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
-
-       // htotal
-       tmp64 = norm_htotal(norm) * (u64)vdec_clock;
-       do_div(tmp64, fsc8);
-       htotal = (u32)tmp64;
-       dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
-               htotal, cx_read(MO_HTOTAL), (u32)tmp64);
-       cx_andor(MO_HTOTAL, 0x07ff, htotal);
-
-       // vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
-       // the effective vbi offset ~244 samples, the same as the Bt8x8
-       cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
-
-       // this is needed as well to set all tvnorm parameter
-       cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
-
-       // audio
-       set_tvaudio(core);
-
-       // tell i2c chips
-       call_all(core, core, s_std, norm);
-
-       /* The chroma_agc control should be inaccessible if the video format is SECAM */
-       v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
-
-       // done
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-struct video_device *cx88_vdev_init(struct cx88_core *core,
-                                   struct pci_dev *pci,
-                                   const struct video_device *template_,
-                                   const char *type)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-       *vfd = *template_;
-       vfd->v4l2_dev = &core->v4l2_dev;
-       vfd->release = video_device_release;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
-                core->name, type, core->board.name);
-       set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
-       return vfd;
-}
-
-struct cx88_core* cx88_core_get(struct pci_dev *pci)
-{
-       struct cx88_core *core;
-
-       mutex_lock(&devlist);
-       list_for_each_entry(core, &cx88_devlist, devlist) {
-               if (pci->bus->number != core->pci_bus)
-                       continue;
-               if (PCI_SLOT(pci->devfn) != core->pci_slot)
-                       continue;
-
-               if (0 != cx88_get_resources(core, pci)) {
-                       mutex_unlock(&devlist);
-                       return NULL;
-               }
-               atomic_inc(&core->refcount);
-               mutex_unlock(&devlist);
-               return core;
-       }
-
-       core = cx88_core_create(pci, cx88_devcount);
-       if (NULL != core) {
-               cx88_devcount++;
-               list_add_tail(&core->devlist, &cx88_devlist);
-       }
-
-       mutex_unlock(&devlist);
-       return core;
-}
-
-void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
-{
-       release_mem_region(pci_resource_start(pci,0),
-                          pci_resource_len(pci,0));
-
-       if (!atomic_dec_and_test(&core->refcount))
-               return;
-
-       mutex_lock(&devlist);
-       cx88_ir_fini(core);
-       if (0 == core->i2c_rc) {
-               if (core->i2c_rtc)
-                       i2c_unregister_device(core->i2c_rtc);
-               i2c_del_adapter(&core->i2c_adap);
-       }
-       list_del(&core->devlist);
-       iounmap(core->lmmio);
-       cx88_devcount--;
-       mutex_unlock(&devlist);
-       v4l2_ctrl_handler_free(&core->video_hdl);
-       v4l2_ctrl_handler_free(&core->audio_hdl);
-       v4l2_device_unregister(&core->v4l2_dev);
-       kfree(core);
-}
-
-/* ------------------------------------------------------------------ */
-
-EXPORT_SYMBOL(cx88_print_irqbits);
-
-EXPORT_SYMBOL(cx88_core_irq);
-EXPORT_SYMBOL(cx88_wakeup);
-EXPORT_SYMBOL(cx88_reset);
-EXPORT_SYMBOL(cx88_shutdown);
-
-EXPORT_SYMBOL(cx88_risc_buffer);
-EXPORT_SYMBOL(cx88_risc_databuffer);
-EXPORT_SYMBOL(cx88_risc_stopper);
-EXPORT_SYMBOL(cx88_free_buffer);
-
-EXPORT_SYMBOL(cx88_sram_channels);
-EXPORT_SYMBOL(cx88_sram_channel_setup);
-EXPORT_SYMBOL(cx88_sram_channel_dump);
-
-EXPORT_SYMBOL(cx88_set_tvnorm);
-EXPORT_SYMBOL(cx88_set_scale);
-
-EXPORT_SYMBOL(cx88_vdev_init);
-EXPORT_SYMBOL(cx88_core_get);
-EXPORT_SYMBOL(cx88_core_put);
-
-EXPORT_SYMBOL(cx88_ir_start);
-EXPORT_SYMBOL(cx88_ir_stop);
-
-/*
- * 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
- */
diff --git a/drivers/media/video/cx88/cx88-dsp.c b/drivers/media/video/cx88/cx88-dsp.c
deleted file mode 100644 (file)
index a990726..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- *
- *  Stereo and SAP detection for cx88
- *
- *  Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
- *
- *  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>
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <asm/div64.h>
-
-#include "cx88.h"
-#include "cx88-reg.h"
-
-#define INT_PI                 ((s32)(3.141592653589 * 32768.0))
-
-#define compat_remainder(a, b) \
-        ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
-
-#define baseband_freq(carrier, srate, tone) ((s32)( \
-        (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
-
-/* We calculate the baseband frequencies of the carrier and the pilot tones
- * based on the the sampling rate of the audio rds fifo. */
-
-#define FREQ_A2_CARRIER         baseband_freq(54687.5, 2689.36, 0.0)
-#define FREQ_A2_DUAL            baseband_freq(54687.5, 2689.36, 274.1)
-#define FREQ_A2_STEREO          baseband_freq(54687.5, 2689.36, 117.5)
-
-/* The frequencies below are from the reference driver. They probably need
- * further adjustments, because they are not tested at all. You may even need
- * to play a bit with the registers of the chip to select the proper signal
- * for the input of the audio rds fifo, and measure it's sampling rate to
- * calculate the proper baseband frequencies... */
-
-#define FREQ_A2M_CARRIER       ((s32)(2.114516 * 32768.0))
-#define FREQ_A2M_DUAL          ((s32)(2.754916 * 32768.0))
-#define FREQ_A2M_STEREO                ((s32)(2.462326 * 32768.0))
-
-#define FREQ_EIAJ_CARRIER      ((s32)(1.963495 * 32768.0)) /* 5pi/8  */
-#define FREQ_EIAJ_DUAL         ((s32)(2.562118 * 32768.0))
-#define FREQ_EIAJ_STEREO       ((s32)(2.601053 * 32768.0))
-
-#define FREQ_BTSC_DUAL         ((s32)(1.963495 * 32768.0)) /* 5pi/8  */
-#define FREQ_BTSC_DUAL_REF     ((s32)(1.374446 * 32768.0)) /* 7pi/16 */
-
-#define FREQ_BTSC_SAP          ((s32)(2.471532 * 32768.0))
-#define FREQ_BTSC_SAP_REF      ((s32)(1.730072 * 32768.0))
-
-/* The spectrum of the signal should be empty between these frequencies. */
-#define FREQ_NOISE_START       ((s32)(0.100000 * 32768.0))
-#define FREQ_NOISE_END         ((s32)(1.200000 * 32768.0))
-
-static unsigned int dsp_debug;
-module_param(dsp_debug, int, 0644);
-MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
-
-#define dprintk(level, fmt, arg...)    if (dsp_debug >= level) \
-       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
-
-static s32 int_cos(u32 x)
-{
-       u32 t2, t4, t6, t8;
-       s32 ret;
-       u16 period = x / INT_PI;
-       if (period % 2)
-               return -int_cos(x - INT_PI);
-       x = x % INT_PI;
-       if (x > INT_PI/2)
-               return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
-       /* Now x is between 0 and INT_PI/2.
-        * To calculate cos(x) we use it's Taylor polinom. */
-       t2 = x*x/32768/2;
-       t4 = t2*x/32768*x/32768/3/4;
-       t6 = t4*x/32768*x/32768/5/6;
-       t8 = t6*x/32768*x/32768/7/8;
-       ret = 32768-t2+t4-t6+t8;
-       return ret;
-}
-
-static u32 int_goertzel(s16 x[], u32 N, u32 freq)
-{
-       /* We use the Goertzel algorithm to determine the power of the
-        * given frequency in the signal */
-       s32 s_prev = 0;
-       s32 s_prev2 = 0;
-       s32 coeff = 2*int_cos(freq);
-       u32 i;
-
-       u64 tmp;
-       u32 divisor;
-
-       for (i = 0; i < N; i++) {
-               s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
-               s_prev2 = s_prev;
-               s_prev = s;
-       }
-
-       tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
-                     (s64)coeff * s_prev2 * s_prev / 32768;
-
-       /* XXX: N must be low enough so that N*N fits in s32.
-        * Else we need two divisions. */
-       divisor = N * N;
-       do_div(tmp, divisor);
-
-       return (u32) tmp;
-}
-
-static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
-{
-       u32 sum = int_goertzel(x, N, freq);
-       return (u32)int_sqrt(sum);
-}
-
-static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end)
-{
-       int i;
-       u32 sum = 0;
-       u32 freq_step;
-       int samples = 5;
-
-       if (N > 192) {
-               /* The last 192 samples are enough for noise detection */
-               x += (N-192);
-               N = 192;
-       }
-
-       freq_step = (freq_end - freq_start) / (samples - 1);
-
-       for (i = 0; i < samples; i++) {
-               sum += int_goertzel(x, N, freq_start);
-               freq_start += freq_step;
-       }
-
-       return (u32)int_sqrt(sum / samples);
-}
-
-static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
-{
-       s32 carrier, stereo, dual, noise;
-       s32 carrier_freq, stereo_freq, dual_freq;
-       s32 ret;
-
-       switch (core->tvaudio) {
-       case WW_BG:
-       case WW_DK:
-               carrier_freq = FREQ_A2_CARRIER;
-               stereo_freq = FREQ_A2_STEREO;
-               dual_freq = FREQ_A2_DUAL;
-               break;
-       case WW_M:
-               carrier_freq = FREQ_A2M_CARRIER;
-               stereo_freq = FREQ_A2M_STEREO;
-               dual_freq = FREQ_A2M_DUAL;
-               break;
-       case WW_EIAJ:
-               carrier_freq = FREQ_EIAJ_CARRIER;
-               stereo_freq = FREQ_EIAJ_STEREO;
-               dual_freq = FREQ_EIAJ_DUAL;
-               break;
-       default:
-               printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
-                      core->name, core->tvaudio, __func__);
-               return UNSET;
-       }
-
-       carrier = freq_magnitude(x, N, carrier_freq);
-       stereo  = freq_magnitude(x, N, stereo_freq);
-       dual    = freq_magnitude(x, N, dual_freq);
-       noise   = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
-
-       dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
-                  "noise=%d\n", carrier, stereo, dual, noise);
-
-       if (stereo > dual)
-               ret = V4L2_TUNER_SUB_STEREO;
-       else
-               ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-
-       if (core->tvaudio == WW_EIAJ) {
-               /* EIAJ checks may need adjustments */
-               if ((carrier > max(stereo, dual)*2) &&
-                   (carrier < max(stereo, dual)*6) &&
-                   (carrier > 20 && carrier < 200) &&
-                   (max(stereo, dual) > min(stereo, dual))) {
-                       /* For EIAJ the carrier is always present,
-                          so we probably don't need noise detection */
-                       return ret;
-               }
-       } else {
-               if ((carrier > max(stereo, dual)*2) &&
-                   (carrier < max(stereo, dual)*8) &&
-                   (carrier > 20 && carrier < 200) &&
-                   (noise < 10) &&
-                   (max(stereo, dual) > min(stereo, dual)*2)) {
-                       return ret;
-               }
-       }
-       return V4L2_TUNER_SUB_MONO;
-}
-
-static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N)
-{
-       s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF);
-       s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
-       s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
-       s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
-       dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
-                  "\n", dual_ref, dual, sap_ref, sap);
-       /* FIXME: Currently not supported */
-       return UNSET;
-}
-
-static s16 *read_rds_samples(struct cx88_core *core, u32 *N)
-{
-       const struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27];
-       s16 *samples;
-
-       unsigned int i;
-       unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
-       unsigned int spl = bpl/4;
-       unsigned int sample_count = spl*(AUD_RDS_LINES-1);
-
-       u32 current_address = cx_read(srch->ptr1_reg);
-       u32 offset = (current_address - srch->fifo_start + bpl);
-
-       dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
-               "sample_count=%d, aud_intstat=%08x\n", current_address,
-               current_address - srch->fifo_start, sample_count,
-               cx_read(MO_AUD_INTSTAT));
-
-       samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
-       if (!samples)
-               return NULL;
-
-       *N = sample_count;
-
-       for (i = 0; i < sample_count; i++)  {
-               offset = offset % (AUD_RDS_LINES*bpl);
-               samples[i] = cx_read(srch->fifo_start + offset);
-               offset += 4;
-       }
-
-       if (dsp_debug >= 2) {
-               dprintk(2, "RDS samples dump: ");
-               for (i = 0; i < sample_count; i++)
-                       printk("%hd ", samples[i]);
-               printk(".\n");
-       }
-
-       return samples;
-}
-
-s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core)
-{
-       s16 *samples;
-       u32 N = 0;
-       s32 ret = UNSET;
-
-       /* If audio RDS fifo is disabled, we can't read the samples */
-       if (!(cx_read(MO_AUD_DMACNTRL) & 0x04))
-               return ret;
-       if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS))
-               return ret;
-
-       /* Wait at least 500 ms after an audio standard change */
-       if (time_before(jiffies, core->last_change + msecs_to_jiffies(500)))
-               return ret;
-
-       samples = read_rds_samples(core, &N);
-
-       if (!samples)
-               return ret;
-
-       switch (core->tvaudio) {
-       case WW_BG:
-       case WW_DK:
-       case WW_EIAJ:
-       case WW_M:
-               ret = detect_a2_a2m_eiaj(core, samples, N);
-               break;
-       case WW_BTSC:
-               ret = detect_btsc(core, samples, N);
-               break;
-       case WW_NONE:
-       case WW_I:
-       case WW_L:
-       case WW_I2SPT:
-       case WW_FM:
-       case WW_I2SADC:
-               break;
-       }
-
-       kfree(samples);
-
-       if (UNSET != ret)
-               dprintk(1, "stereo/sap detection result:%s%s%s\n",
-                          (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
-                          (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
-                          (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
-
-       return ret;
-}
-EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap);
-
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
deleted file mode 100644 (file)
index d803bba..0000000
+++ /dev/null
@@ -1,1778 +0,0 @@
-/*
- *
- * device driver for Conexant 2388x based TV cards
- * MPEG Transport Stream (DVB) routines
- *
- * (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, 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/fs.h>
-#include <linux/kthread.h>
-#include <linux/file.h>
-#include <linux/suspend.h>
-
-#include "cx88.h"
-#include "dvb-pll.h"
-#include <media/v4l2-common.h>
-
-#include "mt352.h"
-#include "mt352_priv.h"
-#include "cx88-vp3054-i2c.h"
-#include "zl10353.h"
-#include "cx22702.h"
-#include "or51132.h"
-#include "lgdt330x.h"
-#include "s5h1409.h"
-#include "xc4000.h"
-#include "xc5000.h"
-#include "nxt200x.h"
-#include "cx24123.h"
-#include "isl6421.h"
-#include "tuner-simple.h"
-#include "tda9887.h"
-#include "s5h1411.h"
-#include "stv0299.h"
-#include "z0194a.h"
-#include "stv0288.h"
-#include "stb6000.h"
-#include "cx24116.h"
-#include "stv0900.h"
-#include "stb6100.h"
-#include "stb6100_proc.h"
-#include "mb86a16.h"
-#include "ds3000.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");
-MODULE_VERSION(CX88_VERSION);
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
-
-static unsigned int dvb_buf_tscnt = 32;
-module_param(dvb_buf_tscnt, int, 0644);
-MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [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)
-
-/* ------------------------------------------------------------------ */
-
-static int dvb_buf_setup(struct videobuf_queue *q,
-                        unsigned int *count, unsigned int *size)
-{
-       struct cx8802_dev *dev = q->priv_data;
-
-       dev->ts_packet_size  = 188 * 4;
-       dev->ts_packet_count = dvb_buf_tscnt;
-
-       *size  = dev->ts_packet_size * dev->ts_packet_count;
-       *count = dvb_buf_tscnt;
-       return 0;
-}
-
-static int dvb_buf_prepare(struct videobuf_queue *q,
-                          struct videobuf_buffer *vb, enum v4l2_field field)
-{
-       struct cx8802_dev *dev = q->priv_data;
-       return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
-}
-
-static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx8802_dev *dev = q->priv_data;
-       cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
-}
-
-static void dvb_buf_release(struct videobuf_queue *q,
-                           struct videobuf_buffer *vb)
-{
-       cx88_free_buffer(q, (struct cx88_buffer*)vb);
-}
-
-static const struct videobuf_queue_ops dvb_qops = {
-       .buf_setup    = dvb_buf_setup,
-       .buf_prepare  = dvb_buf_prepare,
-       .buf_queue    = dvb_buf_queue,
-       .buf_release  = dvb_buf_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct cx8802_driver *drv = NULL;
-       int ret = 0;
-       int fe_id;
-
-       fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
-       if (!fe_id) {
-               printk(KERN_ERR "%s() No frontend found\n", __func__);
-               return -EINVAL;
-       }
-
-       mutex_lock(&dev->core->lock);
-       drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
-       if (drv) {
-               if (acquire){
-                       dev->frontends.active_fe_id = fe_id;
-                       ret = drv->request_acquire(drv);
-               } else {
-                       ret = drv->request_release(drv);
-                       dev->frontends.active_fe_id = 0;
-               }
-       }
-       mutex_unlock(&dev->core->lock);
-
-       return ret;
-}
-
-static void cx88_dvb_gate_ctrl(struct cx88_core  *core, int open)
-{
-       struct videobuf_dvb_frontends *f;
-       struct videobuf_dvb_frontend *fe;
-
-       if (!core->dvbdev)
-               return;
-
-       f = &core->dvbdev->frontends;
-
-       if (!f)
-               return;
-
-       if (f->gate <= 1) /* undefined or fe0 */
-               fe = videobuf_dvb_get_frontend(f, 1);
-       else
-               fe = videobuf_dvb_get_frontend(f, f->gate);
-
-       if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
-               fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
-}
-
-/* ------------------------------------------------------------------ */
-
-static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
-{
-       static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
-       static const u8 reset []         = { RESET,      0x80 };
-       static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-       static const u8 agc_cfg []       = { AGC_TARGET, 0x24, 0x20 };
-       static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
-       static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
-
-       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, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
-       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-       return 0;
-}
-
-static int dvico_dual_demod_init(struct dvb_frontend *fe)
-{
-       static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
-       static const u8 reset []         = { RESET,      0x80 };
-       static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-       static const u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
-       static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
-       static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
-
-       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, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
-       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-
-       return 0;
-}
-
-static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
-{
-       static const u8 clock_config []  = { 0x89, 0x38, 0x39 };
-       static const u8 reset []         = { 0x50, 0x80 };
-       static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-       static const u8 agc_cfg []       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
-                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
-       static const u8 dntv_extra[]     = { 0xB5, 0x7A };
-       static const u8 capt_range_cfg[] = { 0x75, 0x32 };
-
-       mt352_write(fe, clock_config,   sizeof(clock_config));
-       udelay(2000);
-       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));
-       udelay(2000);
-       mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
-       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-
-       return 0;
-}
-
-static const struct mt352_config dvico_fusionhdtv = {
-       .demod_address = 0x0f,
-       .demod_init    = dvico_fusionhdtv_demod_init,
-};
-
-static const struct mt352_config dntv_live_dvbt_config = {
-       .demod_address = 0x0f,
-       .demod_init    = dntv_live_dvbt_demod_init,
-};
-
-static const struct mt352_config dvico_fusionhdtv_dual = {
-       .demod_address = 0x0f,
-       .demod_init    = dvico_dual_demod_init,
-};
-
-static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
-       .demod_address = (0x1e >> 1),
-       .no_tuner      = 1,
-       .if2           = 45600,
-};
-
-static struct mb86a16_config twinhan_vp1027 = {
-       .demod_address  = 0x08,
-};
-
-#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
-static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
-{
-       static const u8 clock_config []  = { 0x89, 0x38, 0x38 };
-       static const u8 reset []         = { 0x50, 0x80 };
-       static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-       static const u8 agc_cfg []       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
-                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
-       static const u8 dntv_extra[]     = { 0xB5, 0x7A };
-       static const u8 capt_range_cfg[] = { 0x75, 0x32 };
-
-       mt352_write(fe, clock_config,   sizeof(clock_config));
-       udelay(2000);
-       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));
-       udelay(2000);
-       mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
-       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-
-       return 0;
-}
-
-static const struct mt352_config dntv_live_dvbt_pro_config = {
-       .demod_address = 0x0f,
-       .no_tuner      = 1,
-       .demod_init    = dntv_live_dvbt_pro_demod_init,
-};
-#endif
-
-static const struct zl10353_config dvico_fusionhdtv_hybrid = {
-       .demod_address = 0x0f,
-       .no_tuner      = 1,
-};
-
-static const struct zl10353_config dvico_fusionhdtv_xc3028 = {
-       .demod_address = 0x0f,
-       .if2           = 45600,
-       .no_tuner      = 1,
-};
-
-static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
-       .demod_address = 0x0f,
-       .if2 = 4560,
-       .no_tuner = 1,
-       .demod_init = dvico_fusionhdtv_demod_init,
-};
-
-static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
-       .demod_address = 0x0f,
-};
-
-static const struct cx22702_config connexant_refboard_config = {
-       .demod_address = 0x43,
-       .output_mode   = CX22702_SERIAL_OUTPUT,
-};
-
-static const struct cx22702_config hauppauge_hvr_config = {
-       .demod_address = 0x63,
-       .output_mode   = CX22702_SERIAL_OUTPUT,
-};
-
-static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
-       return 0;
-}
-
-static const struct or51132_config pchdtv_hd3000 = {
-       .demod_address = 0x15,
-       .set_ts_params = or51132_set_ts_param,
-};
-
-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", __func__, index);
-       if (index == 0)
-               cx_clear(MO_GP0_IO, 8);
-       else
-               cx_set(MO_GP0_IO, 8);
-       return 0;
-}
-
-static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       if (is_punctured)
-               dev->ts_gen_cntrl |= 0x04;
-       else
-               dev->ts_gen_cntrl &= ~0x04;
-       return 0;
-}
-
-static struct lgdt330x_config fusionhdtv_3_gold = {
-       .demod_address = 0x0e,
-       .demod_chip    = LGDT3302,
-       .serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
-       .set_ts_params = lgdt330x_set_ts_param,
-};
-
-static const struct lgdt330x_config fusionhdtv_5_gold = {
-       .demod_address = 0x0e,
-       .demod_chip    = LGDT3303,
-       .serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .set_ts_params = lgdt330x_set_ts_param,
-};
-
-static const struct lgdt330x_config pchdtv_hd5500 = {
-       .demod_address = 0x59,
-       .demod_chip    = LGDT3303,
-       .serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .set_ts_params = lgdt330x_set_ts_param,
-};
-
-static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
-       return 0;
-}
-
-static const struct nxt200x_config ati_hdtvwonder = {
-       .demod_address = 0x0a,
-       .set_ts_params = nxt200x_set_ts_param,
-};
-
-static int cx24123_set_ts_param(struct dvb_frontend* fe,
-       int is_punctured)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       dev->ts_gen_cntrl = 0x02;
-       return 0;
-}
-
-static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
-                                      fe_sec_voltage_t voltage)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       if (voltage == SEC_VOLTAGE_OFF)
-               cx_write(MO_GP0_IO, 0x000006fb);
-       else
-               cx_write(MO_GP0_IO, 0x000006f9);
-
-       if (core->prev_set_voltage)
-               return core->prev_set_voltage(fe, voltage);
-       return 0;
-}
-
-static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
-                                     fe_sec_voltage_t voltage)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       if (voltage == SEC_VOLTAGE_OFF) {
-               dprintk(1,"LNB Voltage OFF\n");
-               cx_write(MO_GP0_IO, 0x0000efff);
-       }
-
-       if (core->prev_set_voltage)
-               return core->prev_set_voltage(fe, voltage);
-       return 0;
-}
-
-static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
-                                     fe_sec_voltage_t voltage)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       cx_set(MO_GP0_IO, 0x6040);
-       switch (voltage) {
-       case SEC_VOLTAGE_13:
-               cx_clear(MO_GP0_IO, 0x20);
-               break;
-       case SEC_VOLTAGE_18:
-               cx_set(MO_GP0_IO, 0x20);
-               break;
-       case SEC_VOLTAGE_OFF:
-               cx_clear(MO_GP0_IO, 0x20);
-               break;
-       }
-
-       if (core->prev_set_voltage)
-               return core->prev_set_voltage(fe, voltage);
-       return 0;
-}
-
-static int vp1027_set_voltage(struct dvb_frontend *fe,
-                                   fe_sec_voltage_t voltage)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       switch (voltage) {
-       case SEC_VOLTAGE_13:
-               dprintk(1, "LNB SEC Voltage=13\n");
-               cx_write(MO_GP0_IO, 0x00001220);
-               break;
-       case SEC_VOLTAGE_18:
-               dprintk(1, "LNB SEC Voltage=18\n");
-               cx_write(MO_GP0_IO, 0x00001222);
-               break;
-       case SEC_VOLTAGE_OFF:
-               dprintk(1, "LNB Voltage OFF\n");
-               cx_write(MO_GP0_IO, 0x00001230);
-               break;
-       }
-
-       if (core->prev_set_voltage)
-               return core->prev_set_voltage(fe, voltage);
-       return 0;
-}
-
-static const struct cx24123_config geniatech_dvbs_config = {
-       .demod_address = 0x55,
-       .set_ts_params = cx24123_set_ts_param,
-};
-
-static const struct cx24123_config hauppauge_novas_config = {
-       .demod_address = 0x55,
-       .set_ts_params = cx24123_set_ts_param,
-};
-
-static const struct cx24123_config kworld_dvbs_100_config = {
-       .demod_address = 0x15,
-       .set_ts_params = cx24123_set_ts_param,
-       .lnb_polarity  = 1,
-};
-
-static const struct s5h1409_config pinnacle_pctv_hd_800i_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_PARALLEL_OUTPUT,
-       .gpio          = S5H1409_GPIO_ON,
-       .qam_if        = 44000,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
-};
-
-static const 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 const 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 const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
-       .i2c_address    = 0x64,
-       .if_khz         = 5380,
-};
-
-static const struct zl10353_config cx88_pinnacle_hybrid_pctv = {
-       .demod_address = (0x1e >> 1),
-       .no_tuner      = 1,
-       .if2           = 45600,
-};
-
-static const struct zl10353_config cx88_geniatech_x8000_mt = {
-       .demod_address = (0x1e >> 1),
-       .no_tuner = 1,
-       .disable_i2c_gate_ctrl = 1,
-};
-
-static const struct s5h1411_config dvico_fusionhdtv7_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_ON,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-       .qam_if        = S5H1411_IF_44000,
-       .vsb_if        = S5H1411_IF_44000,
-       .inversion     = S5H1411_INVERSION_OFF,
-       .status_mode   = S5H1411_DEMODLOCKING
-};
-
-static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
-       .i2c_address    = 0xc2 >> 1,
-       .if_khz         = 5380,
-};
-
-static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
-{
-       struct dvb_frontend *fe;
-       struct videobuf_dvb_frontend *fe0 = NULL;
-       struct xc2028_ctrl ctl;
-       struct xc2028_config cfg = {
-               .i2c_adap  = &dev->core->i2c_adap,
-               .i2c_addr  = addr,
-               .ctrl      = &ctl,
-       };
-
-       /* Get the first frontend */
-       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
-       if (!fe0)
-               return -EINVAL;
-
-       if (!fe0->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, fe0->dvb.frontend, &cfg);
-       if (!fe) {
-               printk(KERN_ERR "%s/2: xc3028 attach failed\n",
-                      dev->core->name);
-               dvb_frontend_detach(fe0->dvb.frontend);
-               dvb_unregister_frontend(fe0->dvb.frontend);
-               fe0->dvb.frontend = NULL;
-               return -EINVAL;
-       }
-
-       printk(KERN_INFO "%s/2: xc3028 attached\n",
-              dev->core->name);
-
-       return 0;
-}
-
-static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
-{
-       struct dvb_frontend *fe;
-       struct videobuf_dvb_frontend *fe0 = NULL;
-
-       /* Get the first frontend */
-       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
-       if (!fe0)
-               return -EINVAL;
-
-       if (!fe0->dvb.frontend) {
-               printk(KERN_ERR "%s/2: dvb frontend not attached. "
-                               "Can't attach xc4000\n",
-                      dev->core->name);
-               return -EINVAL;
-       }
-
-       fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
-                       cfg);
-       if (!fe) {
-               printk(KERN_ERR "%s/2: xc4000 attach failed\n",
-                      dev->core->name);
-               dvb_frontend_detach(fe0->dvb.frontend);
-               dvb_unregister_frontend(fe0->dvb.frontend);
-               fe0->dvb.frontend = NULL;
-               return -EINVAL;
-       }
-
-       printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
-
-       return 0;
-}
-
-static int cx24116_set_ts_param(struct dvb_frontend *fe,
-       int is_punctured)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       dev->ts_gen_cntrl = 0x2;
-
-       return 0;
-}
-
-static int stv0900_set_ts_param(struct dvb_frontend *fe,
-       int is_punctured)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       dev->ts_gen_cntrl = 0;
-
-       return 0;
-}
-
-static int cx24116_reset_device(struct dvb_frontend *fe)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       /* Reset the part */
-       /* Put the cx24116 into reset */
-       cx_write(MO_SRST_IO, 0);
-       msleep(10);
-       /* Take the cx24116 out of reset */
-       cx_write(MO_SRST_IO, 1);
-       msleep(10);
-
-       return 0;
-}
-
-static const struct cx24116_config hauppauge_hvr4000_config = {
-       .demod_address          = 0x05,
-       .set_ts_params          = cx24116_set_ts_param,
-       .reset_device           = cx24116_reset_device,
-};
-
-static const struct cx24116_config tevii_s460_config = {
-       .demod_address = 0x55,
-       .set_ts_params = cx24116_set_ts_param,
-       .reset_device  = cx24116_reset_device,
-};
-
-static int ds3000_set_ts_param(struct dvb_frontend *fe,
-       int is_punctured)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       dev->ts_gen_cntrl = 4;
-
-       return 0;
-}
-
-static struct ds3000_config tevii_ds3000_config = {
-       .demod_address = 0x68,
-       .set_ts_params = ds3000_set_ts_param,
-};
-
-static const struct stv0900_config prof_7301_stv0900_config = {
-       .demod_address = 0x6a,
-/*     demod_mode = 0,*/
-       .xtal = 27000000,
-       .clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
-       .diseqc_mode = 2,/* 2/3 PWM */
-       .tun1_maddress = 0,/* 0x60 */
-       .tun1_adc = 0,/* 2 Vpp */
-       .path1_mode = 3,
-       .set_ts_params = stv0900_set_ts_param,
-};
-
-static const struct stb6100_config prof_7301_stb6100_config = {
-       .tuner_address = 0x60,
-       .refclock = 27000000,
-};
-
-static const struct stv0299_config tevii_tuner_sharp_config = {
-       .demod_address = 0x68,
-       .inittab = sharp_z0194a_inittab,
-       .mclk = 88000000UL,
-       .invert = 1,
-       .skip_reinit = 0,
-       .lock_output = 1,
-       .volt13_op0_op1 = STV0299_VOLT13_OP1,
-       .min_delay_ms = 100,
-       .set_symbol_rate = sharp_z0194a_set_symbol_rate,
-       .set_ts_params = cx24116_set_ts_param,
-};
-
-static const struct stv0288_config tevii_tuner_earda_config = {
-       .demod_address = 0x68,
-       .min_delay_ms = 100,
-       .set_ts_params = cx24116_set_ts_param,
-};
-
-static int cx8802_alloc_frontends(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       struct videobuf_dvb_frontend *fe = NULL;
-       int i;
-
-       mutex_init(&dev->frontends.lock);
-       INIT_LIST_HEAD(&dev->frontends.felist);
-
-       if (!core->board.num_frontends)
-               return -ENODEV;
-
-       printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
-                        core->board.num_frontends);
-       for (i = 1; i <= core->board.num_frontends; i++) {
-               fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
-               if (!fe) {
-                       printk(KERN_ERR "%s() failed to alloc\n", __func__);
-                       videobuf_dvb_dealloc_frontends(&dev->frontends);
-                       return -ENOMEM;
-               }
-       }
-       return 0;
-}
-
-
-
-static const u8 samsung_smt_7020_inittab[] = {
-            0x01, 0x15,
-            0x02, 0x00,
-            0x03, 0x00,
-            0x04, 0x7D,
-            0x05, 0x0F,
-            0x06, 0x02,
-            0x07, 0x00,
-            0x08, 0x60,
-
-            0x0A, 0xC2,
-            0x0B, 0x00,
-            0x0C, 0x01,
-            0x0D, 0x81,
-            0x0E, 0x44,
-            0x0F, 0x09,
-            0x10, 0x3C,
-            0x11, 0x84,
-            0x12, 0xDA,
-            0x13, 0x99,
-            0x14, 0x8D,
-            0x15, 0xCE,
-            0x16, 0xE8,
-            0x17, 0x43,
-            0x18, 0x1C,
-            0x19, 0x1B,
-            0x1A, 0x1D,
-
-            0x1C, 0x12,
-            0x1D, 0x00,
-            0x1E, 0x00,
-            0x1F, 0x00,
-            0x20, 0x00,
-            0x21, 0x00,
-            0x22, 0x00,
-            0x23, 0x00,
-
-            0x28, 0x02,
-            0x29, 0x28,
-            0x2A, 0x14,
-            0x2B, 0x0F,
-            0x2C, 0x09,
-            0x2D, 0x05,
-
-            0x31, 0x1F,
-            0x32, 0x19,
-            0x33, 0xFC,
-            0x34, 0x13,
-            0xff, 0xff,
-};
-
-
-static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
-{
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct cx8802_dev *dev = fe->dvb->priv;
-       u8 buf[4];
-       u32 div;
-       struct i2c_msg msg = {
-               .addr = 0x61,
-               .flags = 0,
-               .buf = buf,
-               .len = sizeof(buf) };
-
-       div = c->frequency / 125;
-
-       buf[0] = (div >> 8) & 0x7f;
-       buf[1] = div & 0xff;
-       buf[2] = 0x84;  /* 0xC4 */
-       buf[3] = 0x00;
-
-       if (c->frequency < 1500000)
-               buf[3] |= 0x10;
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-
-       if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1)
-               return -EIO;
-
-       return 0;
-}
-
-static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
-       fe_sec_tone_mode_t tone)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       cx_set(MO_GP0_IO, 0x0800);
-
-       switch (tone) {
-       case SEC_TONE_ON:
-               cx_set(MO_GP0_IO, 0x08);
-               break;
-       case SEC_TONE_OFF:
-               cx_clear(MO_GP0_IO, 0x08);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
-       fe_sec_voltage_t voltage)
-{
-       struct cx8802_dev *dev = fe->dvb->priv;
-       struct cx88_core *core = dev->core;
-
-       u8 data;
-       struct i2c_msg msg = {
-               .addr = 8,
-               .flags = 0,
-               .buf = &data,
-               .len = sizeof(data) };
-
-       cx_set(MO_GP0_IO, 0x8000);
-
-       switch (voltage) {
-       case SEC_VOLTAGE_OFF:
-               break;
-       case SEC_VOLTAGE_13:
-               data = ISL6421_EN1 | ISL6421_LLC1;
-               cx_clear(MO_GP0_IO, 0x80);
-               break;
-       case SEC_VOLTAGE_18:
-               data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1;
-               cx_clear(MO_GP0_IO, 0x80);
-               break;
-       default:
-               return -EINVAL;
-       };
-
-       return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
-       u32 srate, u32 ratio)
-{
-       u8 aclk = 0;
-       u8 bclk = 0;
-
-       if (srate < 1500000) {
-               aclk = 0xb7;
-               bclk = 0x47;
-       } else if (srate < 3000000) {
-               aclk = 0xb7;
-               bclk = 0x4b;
-       } else if (srate < 7000000) {
-               aclk = 0xb7;
-               bclk = 0x4f;
-       } else if (srate < 14000000) {
-               aclk = 0xb7;
-               bclk = 0x53;
-       } else if (srate < 30000000) {
-               aclk = 0xb6;
-               bclk = 0x53;
-       } else if (srate < 45000000) {
-               aclk = 0xb4;
-               bclk = 0x51;
-       }
-
-       stv0299_writereg(fe, 0x13, aclk);
-       stv0299_writereg(fe, 0x14, bclk);
-       stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-       stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
-       stv0299_writereg(fe, 0x21, ratio & 0xf0);
-
-       return 0;
-}
-
-
-static const struct stv0299_config samsung_stv0299_config = {
-       .demod_address = 0x68,
-       .inittab = samsung_smt_7020_inittab,
-       .mclk = 88000000UL,
-       .invert = 0,
-       .skip_reinit = 0,
-       .lock_output = STV0299_LOCKOUTPUT_LK,
-       .volt13_op0_op1 = STV0299_VOLT13_OP1,
-       .min_delay_ms = 100,
-       .set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate,
-};
-
-static int dvb_register(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
-       int mfe_shared = 0; /* bus not shared by default */
-       int res = -EINVAL;
-
-       if (0 != core->i2c_rc) {
-               printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
-               goto frontend_detach;
-       }
-
-       /* Get the first frontend */
-       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
-       if (!fe0)
-               goto frontend_detach;
-
-       /* multi-frontend gate control is undefined or defaults to fe0 */
-       dev->frontends.gate = 0;
-
-       /* Sets the gate control callback to be used by i2c command calls */
-       core->gate_ctrl = cx88_dvb_gate_ctrl;
-
-       /* init frontend(s) */
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE_DVB_T1:
-               fe0->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &connexant_refboard_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x61, &core->i2c_adap,
-                                       DVB_PLL_THOMSON_DTT759X))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
-       case CX88_BOARD_CONEXANT_DVB_T1:
-       case CX88_BOARD_KWORLD_DVB_T_CX22702:
-       case CX88_BOARD_WINFAST_DTV1000:
-               fe0->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &connexant_refboard_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x60, &core->i2c_adap,
-                                       DVB_PLL_THOMSON_DTT7579))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_WINFAST_DTV2000H:
-       case CX88_BOARD_HAUPPAUGE_HVR1100:
-       case CX88_BOARD_HAUPPAUGE_HVR1100LP:
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               fe0->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &hauppauge_hvr_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &core->i2c_adap, 0x61,
-                                  TUNER_PHILIPS_FMD1216ME_MK3))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_WINFAST_DTV2000H_J:
-               fe0->dvb.frontend = dvb_attach(cx22702_attach,
-                                              &hauppauge_hvr_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &core->i2c_adap, 0x61,
-                                  TUNER_PHILIPS_FMD1216MEX_MK3))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-               /* MFE frontend 1 */
-               mfe_shared = 1;
-               dev->frontends.gate = 2;
-               /* DVB-S init */
-               fe0->dvb.frontend = dvb_attach(cx24123_attach,
-                                       &hauppauge_novas_config,
-                                       &dev->core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (!dvb_attach(isl6421_attach,
-                                       fe0->dvb.frontend,
-                                       &dev->core->i2c_adap,
-                                       0x08, ISL6421_DCL, 0x00))
-                               goto frontend_detach;
-               }
-               /* MFE frontend 2 */
-               fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
-               if (!fe1)
-                       goto frontend_detach;
-               /* DVB-T init */
-               fe1->dvb.frontend = dvb_attach(cx22702_attach,
-                                       &hauppauge_hvr_config,
-                                       &dev->core->i2c_adap);
-               if (fe1->dvb.frontend) {
-                       fe1->dvb.frontend->id = 1;
-                       if (!dvb_attach(simple_tuner_attach,
-                                       fe1->dvb.frontend,
-                                       &dev->core->i2c_adap,
-                                       0x61, TUNER_PHILIPS_FMD1216ME_MK3))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                              &dvico_fusionhdtv,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x60, NULL, DVB_PLL_THOMSON_DTT7579))
-                               goto frontend_detach;
-                       break;
-               }
-               /* ZL10353 replaces MT352 on later cards */
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &dvico_fusionhdtv_plus_v1_1,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x60, NULL, DVB_PLL_THOMSON_DTT7579))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
-               /* The tin box says DEE1601, but it seems to be DTT7579
-                * compatible, with a slightly different MT352 AGC gain. */
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                              &dvico_fusionhdtv_dual,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x61, NULL, DVB_PLL_THOMSON_DTT7579))
-                               goto frontend_detach;
-                       break;
-               }
-               /* ZL10353 replaces MT352 on later cards */
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &dvico_fusionhdtv_plus_v1_1,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x61, NULL, DVB_PLL_THOMSON_DTT7579))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                              &dvico_fusionhdtv,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x61, NULL, DVB_PLL_LG_Z201))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_KWORLD_DVB_T:
-       case CX88_BOARD_DNTV_LIVE_DVB_T:
-       case CX88_BOARD_ADSTECH_DVB_T_PCI:
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                              &dntv_live_dvbt_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
-                                       0x61, NULL, DVB_PLL_UNKNOWN_1))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
-               /* MT352 is on a secondary I2C bus made from some GPIO lines */
-               fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
-                                              &dev->vp3054->adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_PHILIPS_FMD1216ME_MK3))
-                               goto frontend_detach;
-               }
-#else
-               printk(KERN_ERR "%s/2: built without vp3054 support\n",
-                               core->name);
-#endif
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &dvico_fusionhdtv_hybrid,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &core->i2c_adap, 0x61,
-                                  TUNER_THOMSON_FE6600))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &dvico_fusionhdtv_xc3028,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend == NULL)
-                       fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                               &dvico_fusionhdtv_mt352_xc3028,
-                                               &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 (fe0->dvb.frontend)
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
-               if (attach_xc3028(0x61, dev) < 0)
-                       goto frontend_detach;
-               break;
-       case CX88_BOARD_PCHDTV_HD3000:
-               fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_THOMSON_DTT761X))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
-               dev->ts_gen_cntrl = 0x08;
-
-               /* Do a hardware reset of chip before using it. */
-               cx_clear(MO_GP0_IO, 1);
-               mdelay(100);
-               cx_set(MO_GP0_IO, 1);
-               mdelay(200);
-
-               /* Select RF connector callback */
-               fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
-               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
-                                              &fusionhdtv_3_gold,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_MICROTUNE_4042FI5))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
-               dev->ts_gen_cntrl = 0x08;
-
-               /* Do a hardware reset of chip before using it. */
-               cx_clear(MO_GP0_IO, 1);
-               mdelay(100);
-               cx_set(MO_GP0_IO, 9);
-               mdelay(200);
-               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
-                                              &fusionhdtv_3_gold,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_THOMSON_DTT761X))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-               dev->ts_gen_cntrl = 0x08;
-
-               /* Do a hardware reset of chip before using it. */
-               cx_clear(MO_GP0_IO, 1);
-               mdelay(100);
-               cx_set(MO_GP0_IO, 1);
-               mdelay(200);
-               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
-                                              &fusionhdtv_5_gold,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_LG_TDVS_H06XF))
-                               goto frontend_detach;
-                       if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
-                                  &core->i2c_adap, 0x43))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_PCHDTV_HD5500:
-               dev->ts_gen_cntrl = 0x08;
-
-               /* Do a hardware reset of chip before using it. */
-               cx_clear(MO_GP0_IO, 1);
-               mdelay(100);
-               cx_set(MO_GP0_IO, 1);
-               mdelay(200);
-               fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
-                                              &pchdtv_hd5500,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_LG_TDVS_H06XF))
-                               goto frontend_detach;
-                       if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
-                                  &core->i2c_adap, 0x43))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_ATI_HDTVWONDER:
-               fe0->dvb.frontend = dvb_attach(nxt200x_attach,
-                                              &ati_hdtvwonder,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x61,
-                                       TUNER_PHILIPS_TUV1236D))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
-       case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-               fe0->dvb.frontend = dvb_attach(cx24123_attach,
-                                              &hauppauge_novas_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_KWORLD_DVBS_100:
-               fe0->dvb.frontend = dvb_attach(cx24123_attach,
-                                              &kworld_dvbs_100_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
-                       fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
-               }
-               break;
-       case CX88_BOARD_GENIATECH_DVBS:
-               fe0->dvb.frontend = dvb_attach(cx24123_attach,
-                                              &geniatech_dvbs_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
-                       fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
-               }
-               break;
-       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                              &pinnacle_pctv_hd_800i_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap,
-                                       &pinnacle_pctv_hd_800i_tuner_config))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                               &dvico_hdtv5_pci_nano_config,
-                                               &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       struct dvb_frontend *fe;
-                       struct xc2028_config cfg = {
-                               .i2c_adap  = &core->i2c_adap,
-                               .i2c_addr  = 0x61,
-                       };
-                       static struct xc2028_ctrl ctl = {
-                               .fname       = XC2028_DEFAULT_FIRMWARE,
-                               .max_len     = 64,
-                               .scode_table = XC3028_FE_OREN538,
-                       };
-
-                       fe = dvb_attach(xc2028_attach,
-                                       fe0->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:
-       case CX88_BOARD_WINFAST_DTV1800H:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &cx88_pinnacle_hybrid_pctv,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
-                       if (attach_xc3028(0x61, dev) < 0)
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
-       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &cx88_pinnacle_hybrid_pctv,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       struct xc4000_config cfg = {
-                               .i2c_address      = 0x61,
-                               .default_pm       = 0,
-                               .dvb_amplitude    = 134,
-                               .set_smoothedcvbs = 1,
-                               .if_khz           = 4560
-                       };
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
-                       if (attach_xc4000(dev, &cfg) < 0)
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_GENIATECH_X8000_MT:
-               dev->ts_gen_cntrl = 0x00;
-
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &cx88_geniatech_x8000_mt,
-                                              &core->i2c_adap);
-               if (attach_xc3028(0x61, dev) < 0)
-                       goto frontend_detach;
-               break;
-        case CX88_BOARD_KWORLD_ATSC_120:
-               fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-                                              &kworld_atsc_120_config,
-                                              &core->i2c_adap);
-               if (attach_xc3028(0x61, dev) < 0)
-                       goto frontend_detach;
-               break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
-               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
-                                              &dvico_fusionhdtv7_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
-                                       &core->i2c_adap,
-                                       &dvico_fusionhdtv7_tuner_config))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_HAUPPAUGE_HVR4000:
-               /* MFE frontend 1 */
-               mfe_shared = 1;
-               dev->frontends.gate = 2;
-               /* DVB-S/S2 Init */
-               fe0->dvb.frontend = dvb_attach(cx24116_attach,
-                                       &hauppauge_hvr4000_config,
-                                       &dev->core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (!dvb_attach(isl6421_attach,
-                                       fe0->dvb.frontend,
-                                       &dev->core->i2c_adap,
-                                       0x08, ISL6421_DCL, 0x00))
-                               goto frontend_detach;
-               }
-               /* MFE frontend 2 */
-               fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
-               if (!fe1)
-                       goto frontend_detach;
-               /* DVB-T Init */
-               fe1->dvb.frontend = dvb_attach(cx22702_attach,
-                                       &hauppauge_hvr_config,
-                                       &dev->core->i2c_adap);
-               if (fe1->dvb.frontend) {
-                       fe1->dvb.frontend->id = 1;
-                       if (!dvb_attach(simple_tuner_attach,
-                                       fe1->dvb.frontend,
-                                       &dev->core->i2c_adap,
-                                       0x61, TUNER_PHILIPS_FMD1216ME_MK3))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
-               fe0->dvb.frontend = dvb_attach(cx24116_attach,
-                                       &hauppauge_hvr4000_config,
-                                       &dev->core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (!dvb_attach(isl6421_attach,
-                                       fe0->dvb.frontend,
-                                       &dev->core->i2c_adap,
-                                       0x08, ISL6421_DCL, 0x00))
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_PROF_6200:
-       case CX88_BOARD_TBS_8910:
-       case CX88_BOARD_TEVII_S420:
-               fe0->dvb.frontend = dvb_attach(stv0299_attach,
-                                               &tevii_tuner_sharp_config,
-                                               &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
-                                       &core->i2c_adap, DVB_PLL_OPERA1))
-                               goto frontend_detach;
-                       core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
-                       fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
-
-               } else {
-                       fe0->dvb.frontend = dvb_attach(stv0288_attach,
-                                                           &tevii_tuner_earda_config,
-                                                           &core->i2c_adap);
-                               if (fe0->dvb.frontend != NULL) {
-                                       if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
-                                               &core->i2c_adap))
-                                       goto frontend_detach;
-                               core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
-                               fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
-                       }
-               }
-               break;
-       case CX88_BOARD_TEVII_S460:
-               fe0->dvb.frontend = dvb_attach(cx24116_attach,
-                                              &tevii_s460_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
-               break;
-       case CX88_BOARD_TEVII_S464:
-               fe0->dvb.frontend = dvb_attach(ds3000_attach,
-                                               &tevii_ds3000_config,
-                                               &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       fe0->dvb.frontend->ops.set_voltage =
-                                                       tevii_dvbs_set_voltage;
-               break;
-       case CX88_BOARD_OMICOM_SS4_PCI:
-       case CX88_BOARD_TBS_8920:
-       case CX88_BOARD_PROF_7300:
-       case CX88_BOARD_SATTRADE_ST4200:
-               fe0->dvb.frontend = dvb_attach(cx24116_attach,
-                                              &hauppauge_hvr4000_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend != NULL)
-                       fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
-               break;
-       case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                              &cx88_terratec_cinergy_ht_pci_mkii_config,
-                                              &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
-                       if (attach_xc3028(0x61, dev) < 0)
-                               goto frontend_detach;
-               }
-               break;
-       case CX88_BOARD_PROF_7301:{
-               struct dvb_tuner_ops *tuner_ops = NULL;
-
-               fe0->dvb.frontend = dvb_attach(stv0900_attach,
-                                               &prof_7301_stv0900_config,
-                                               &core->i2c_adap, 0);
-               if (fe0->dvb.frontend != NULL) {
-                       if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
-                                       &prof_7301_stb6100_config,
-                                       &core->i2c_adap))
-                               goto frontend_detach;
-
-                       tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
-                       tuner_ops->set_frequency = stb6100_set_freq;
-                       tuner_ops->get_frequency = stb6100_get_freq;
-                       tuner_ops->set_bandwidth = stb6100_set_bandw;
-                       tuner_ops->get_bandwidth = stb6100_get_bandw;
-
-                       core->prev_set_voltage =
-                                       fe0->dvb.frontend->ops.set_voltage;
-                       fe0->dvb.frontend->ops.set_voltage =
-                                       tevii_dvbs_set_voltage;
-               }
-               break;
-               }
-       case CX88_BOARD_SAMSUNG_SMT_7020:
-               dev->ts_gen_cntrl = 0x08;
-
-               cx_set(MO_GP0_IO, 0x0101);
-
-               cx_clear(MO_GP0_IO, 0x01);
-               mdelay(100);
-               cx_set(MO_GP0_IO, 0x01);
-               mdelay(200);
-
-               fe0->dvb.frontend = dvb_attach(stv0299_attach,
-                                       &samsung_stv0299_config,
-                                       &dev->core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.tuner_ops.set_params =
-                               samsung_smt_7020_tuner_set_params;
-                       fe0->dvb.frontend->tuner_priv =
-                               &dev->core->i2c_adap;
-                       fe0->dvb.frontend->ops.set_voltage =
-                               samsung_smt_7020_set_voltage;
-                       fe0->dvb.frontend->ops.set_tone =
-                               samsung_smt_7020_set_tone;
-               }
-
-               break;
-       case CX88_BOARD_TWINHAN_VP1027_DVBS:
-               dev->ts_gen_cntrl = 0x00;
-               fe0->dvb.frontend = dvb_attach(mb86a16_attach,
-                                               &twinhan_vp1027,
-                                               &core->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       core->prev_set_voltage =
-                                       fe0->dvb.frontend->ops.set_voltage;
-                       fe0->dvb.frontend->ops.set_voltage =
-                                       vp1027_set_voltage;
-               }
-               break;
-
-       default:
-               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
-                      core->name);
-               break;
-       }
-
-       if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
-               printk(KERN_ERR
-                      "%s/2: frontend initialization failed\n",
-                      core->name);
-               goto frontend_detach;
-       }
-       /* define general-purpose callback pointer */
-       fe0->dvb.frontend->callback = cx88_tuner_callback;
-
-       /* Ensure all frontends negotiate bus access */
-       fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
-       if (fe1)
-               fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
-
-       /* Put the analog decoder in standby to keep it quiet */
-       call_all(core, core, s_power, 0);
-
-       /* register everything */
-       res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-               &dev->pci->dev, adapter_nr, mfe_shared);
-       if (res)
-               goto frontend_detach;
-       return res;
-
-frontend_detach:
-       core->gate_ctrl = NULL;
-       videobuf_dvb_dealloc_frontends(&dev->frontends);
-       return res;
-}
-
-/* ----------------------------------------------------------- */
-
-/* CX8802 MPEG -> mini driver - We have been given the hardware */
-static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       int err = 0;
-       dprintk( 1, "%s\n", __func__);
-
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               /* We arrive here with either the cx23416 or the cx22702
-                * on the bus. Take the bus from the cx23416 and enable the
-                * cx22702 demod
-                */
-               /* Toggle reset on cx22702 leaving i2c active */
-               cx_set(MO_GP0_IO, 0x00000080);
-               udelay(1000);
-               cx_clear(MO_GP0_IO, 0x00000080);
-               udelay(50);
-               cx_set(MO_GP0_IO, 0x00000080);
-               udelay(1000);
-               /* enable the cx22702 pins */
-               cx_clear(MO_GP0_IO, 0x00000004);
-               udelay(1000);
-               break;
-
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-       case CX88_BOARD_HAUPPAUGE_HVR4000:
-               /* Toggle reset on cx22702 leaving i2c active */
-               cx_set(MO_GP0_IO, 0x00000080);
-               udelay(1000);
-               cx_clear(MO_GP0_IO, 0x00000080);
-               udelay(50);
-               cx_set(MO_GP0_IO, 0x00000080);
-               udelay(1000);
-               switch (core->dvbdev->frontends.active_fe_id) {
-               case 1: /* DVB-S/S2 Enabled */
-                       /* tri-state the cx22702 pins */
-                       cx_set(MO_GP0_IO, 0x00000004);
-                       /* Take the cx24116/cx24123 out of reset */
-                       cx_write(MO_SRST_IO, 1);
-                       core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
-                       break;
-               case 2: /* DVB-T Enabled */
-                       /* Put the cx24116/cx24123 into reset */
-                       cx_write(MO_SRST_IO, 0);
-                       /* enable the cx22702 pins */
-                       cx_clear(MO_GP0_IO, 0x00000004);
-                       core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
-                       break;
-               }
-               udelay(1000);
-               break;
-
-       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
-               /* set RF input to AIR for DVB-T (GPIO 16) */
-               cx_write(MO_GP2_IO, 0x0101);
-               break;
-
-       default:
-               err = -ENODEV;
-       }
-       return err;
-}
-
-/* CX8802 MPEG -> mini driver - We no longer have the hardware */
-static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       int err = 0;
-       dprintk( 1, "%s\n", __func__);
-
-       switch (core->boardnr) {
-       case CX88_BOARD_HAUPPAUGE_HVR1300:
-               /* Do Nothing, leave the cx22702 on the bus. */
-               break;
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-       case CX88_BOARD_HAUPPAUGE_HVR4000:
-               break;
-       default:
-               err = -ENODEV;
-       }
-       return err;
-}
-
-static int cx8802_dvb_probe(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       struct cx8802_dev *dev = drv->core->dvbdev;
-       int err;
-       struct videobuf_dvb_frontend *fe;
-       int i;
-
-       dprintk( 1, "%s\n", __func__);
-       dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
-               core->boardnr,
-               core->name,
-               core->pci_bus,
-               core->pci_slot);
-
-       err = -ENODEV;
-       if (!(core->board.mpeg & CX88_MPEG_DVB))
-               goto fail_core;
-
-       /* If vp3054 isn't enabled, a stub will just return 0 */
-       err = vp3054_i2c_probe(dev);
-       if (0 != err)
-               goto fail_core;
-
-       /* dvb stuff */
-       printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
-       dev->ts_gen_cntrl = 0x0c;
-
-       err = cx8802_alloc_frontends(dev);
-       if (err)
-               goto fail_core;
-
-       err = -ENODEV;
-       for (i = 1; i <= core->board.num_frontends; i++) {
-               fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
-               if (fe == NULL) {
-                       printk(KERN_ERR "%s() failed to get frontend(%d)\n",
-                                       __func__, i);
-                       goto fail_probe;
-               }
-               videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
-                                   &dev->pci->dev, &dev->slock,
-                                   V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                                   V4L2_FIELD_TOP,
-                                   sizeof(struct cx88_buffer),
-                                   dev, NULL);
-               /* init struct videobuf_dvb */
-               fe->dvb.name = dev->core->name;
-       }
-
-       err = dvb_register(dev);
-       if (err)
-               /* frontends/adapter de-allocated in dvb_register */
-               printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
-                      core->name, err);
-       return err;
-fail_probe:
-       videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
-fail_core:
-       return err;
-}
-
-static int cx8802_dvb_remove(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       struct cx8802_dev *dev = drv->core->dvbdev;
-
-       dprintk( 1, "%s\n", __func__);
-
-       videobuf_dvb_unregister_bus(&dev->frontends);
-
-       vp3054_i2c_remove(dev);
-
-       core->gate_ctrl = NULL;
-
-       return 0;
-}
-
-static struct cx8802_driver cx8802_dvb_driver = {
-       .type_id        = CX88_MPEG_DVB,
-       .hw_access      = CX8802_DRVCTL_SHARED,
-       .probe          = cx8802_dvb_probe,
-       .remove         = cx8802_dvb_remove,
-       .advise_acquire = cx8802_dvb_advise_acquire,
-       .advise_release = cx8802_dvb_advise_release,
-};
-
-static int __init dvb_init(void)
-{
-       printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
-              CX88_VERSION);
-       return cx8802_register_driver(&cx8802_dvb_driver);
-}
-
-static void __exit dvb_fini(void)
-{
-       cx8802_unregister_driver(&cx8802_dvb_driver);
-}
-
-module_init(dvb_init);
-module_exit(dvb_fini);
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
deleted file mode 100644 (file)
index de0f1af..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-
-/*
-
-    cx88-i2c.c  --  all the i2c code is here
-
-    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
-                          & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
-    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
-
-    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
-       - Multituner support and i2c address binding
-
-    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 <asm/io.h>
-
-#include "cx88.h"
-#include <media/v4l2-common.h>
-
-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;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
-
-static unsigned int i2c_udelay = 5;
-module_param(i2c_udelay, int, 0644);
-MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "
-               "(should be 5 or higher). Lower value means higher bus speed.");
-
-#define dprintk(level,fmt, arg...)     if (i2c_debug >= level) \
-       printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
-
-/* ----------------------------------------------------------------------- */
-
-static void cx8800_bit_setscl(void *data, int state)
-{
-       struct cx88_core *core = data;
-
-       if (state)
-               core->i2c_state |= 0x02;
-       else
-               core->i2c_state &= ~0x02;
-       cx_write(MO_I2C, core->i2c_state);
-       cx_read(MO_I2C);
-}
-
-static void cx8800_bit_setsda(void *data, int state)
-{
-       struct cx88_core *core = data;
-
-       if (state)
-               core->i2c_state |= 0x01;
-       else
-               core->i2c_state &= ~0x01;
-       cx_write(MO_I2C, core->i2c_state);
-       cx_read(MO_I2C);
-}
-
-static int cx8800_bit_getscl(void *data)
-{
-       struct cx88_core *core = data;
-       u32 state;
-
-       state = cx_read(MO_I2C);
-       return state & 0x02 ? 1 : 0;
-}
-
-static int cx8800_bit_getsda(void *data)
-{
-       struct cx88_core *core = data;
-       u32 state;
-
-       state = cx_read(MO_I2C);
-       return state & 0x01;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
-       .setsda  = cx8800_bit_setsda,
-       .setscl  = cx8800_bit_setscl,
-       .getsda  = cx8800_bit_getsda,
-       .getscl  = cx8800_bit_getscl,
-       .udelay  = 16,
-       .timeout = 200,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static const char * const i2c_devs[128] = {
-       [ 0x1c >> 1 ] = "lgdt330x",
-       [ 0x86 >> 1 ] = "tda9887/cx22702",
-       [ 0xa0 >> 1 ] = "eeprom",
-       [ 0xc0 >> 1 ] = "tuner (analog)",
-       [ 0xc2 >> 1 ] = "tuner (analog/dvb)",
-       [ 0xc8 >> 1 ] = "xc5000",
-};
-
-static void do_i2c_scan(const char *name, struct i2c_client *c)
-{
-       unsigned char buf;
-       int i,rc;
-
-       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
-               c->addr = i;
-               rc = i2c_master_recv(c,&buf,0);
-               if (rc < 0)
-                       continue;
-               printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
-                      name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
-       }
-}
-
-/* init + register i2c adapter */
-int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
-{
-       /* Prevents usage of invalid delay values */
-       if (i2c_udelay<5)
-               i2c_udelay=5;
-
-       memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
-              sizeof(core->i2c_algo));
-
-
-       core->i2c_adap.dev.parent = &pci->dev;
-       strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
-       core->i2c_adap.owner = THIS_MODULE;
-       core->i2c_algo.udelay = i2c_udelay;
-       core->i2c_algo.data = core;
-       i2c_set_adapdata(&core->i2c_adap, &core->v4l2_dev);
-       core->i2c_adap.algo_data = &core->i2c_algo;
-       core->i2c_client.adapter = &core->i2c_adap;
-       strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
-
-       cx8800_bit_setscl(core,1);
-       cx8800_bit_setsda(core,1);
-
-       core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
-       if (0 == core->i2c_rc) {
-               static u8 tuner_data[] =
-                       { 0x0b, 0xdc, 0x86, 0x52 };
-               static struct i2c_msg tuner_msg =
-                       { .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
-
-               dprintk(1, "i2c register ok\n");
-               switch( core->boardnr ) {
-                       case CX88_BOARD_HAUPPAUGE_HVR1300:
-                       case CX88_BOARD_HAUPPAUGE_HVR3000:
-                       case CX88_BOARD_HAUPPAUGE_HVR4000:
-                               printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
-                                       core->name);
-                               i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
-                               break;
-                       default:
-                               break;
-               }
-               if (i2c_scan)
-                       do_i2c_scan(core->name,&core->i2c_client);
-       } else
-               printk("%s: i2c register FAILED\n", core->name);
-
-       return core->i2c_rc;
-}
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
deleted file mode 100644 (file)
index ebf448c..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- *
- * Device driver for GPIO attached remote control interfaces
- * on Conexant 2388x based TV/DVB cards.
- *
- * Copyright (c) 2003 Pavel Machek
- * Copyright (c) 2004 Gerd Knorr
- * Copyright (c) 2004, 2005 Chris Pascoe
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/hrtimer.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include "cx88.h"
-#include <media/rc-core.h>
-
-#define MODULE_NAME "cx88xx"
-
-/* ---------------------------------------------------------------------- */
-
-struct cx88_IR {
-       struct cx88_core *core;
-       struct rc_dev *dev;
-
-       int users;
-
-       char name[32];
-       char phys[32];
-
-       /* sample from gpio pin 16 */
-       u32 sampling;
-
-       /* poll external decoder */
-       int polling;
-       struct hrtimer timer;
-       u32 gpio_addr;
-       u32 last_gpio;
-       u32 mask_keycode;
-       u32 mask_keydown;
-       u32 mask_keyup;
-};
-
-static unsigned ir_samplerate = 4;
-module_param(ir_samplerate, uint, 0444);
-MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");
-
-static int ir_debug;
-module_param(ir_debug, int, 0644);     /* debug level [IR] */
-MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
-
-#define ir_dprintk(fmt, arg...)        if (ir_debug) \
-       printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
-
-#define dprintk(fmt, arg...)   if (ir_debug) \
-       printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)
-
-/* ---------------------------------------------------------------------- */
-
-static void cx88_ir_handle_key(struct cx88_IR *ir)
-{
-       struct cx88_core *core = ir->core;
-       u32 gpio, data, auxgpio;
-
-       /* read gpio value */
-       gpio = cx_read(ir->gpio_addr);
-       switch (core->boardnr) {
-       case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
-               /* This board apparently uses a combination of 2 GPIO
-                  to represent the keys. Additionally, the second GPIO
-                  can be used for parity.
-
-                  Example:
-
-                  for key "5"
-                       gpio = 0x758, auxgpio = 0xe5 or 0xf5
-                  for key "Power"
-                       gpio = 0x758, auxgpio = 0xed or 0xfd
-                */
-
-               auxgpio = cx_read(MO_GP1_IO);
-               /* Take out the parity part */
-               gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
-               break;
-       case CX88_BOARD_WINFAST_DTV1000:
-       case CX88_BOARD_WINFAST_DTV1800H:
-       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
-       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
-               gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
-               auxgpio = gpio;
-               break;
-       default:
-               auxgpio = gpio;
-       }
-       if (ir->polling) {
-               if (ir->last_gpio == auxgpio)
-                       return;
-               ir->last_gpio = auxgpio;
-       }
-
-       /* extract data */
-       data = ir_extract_bits(gpio, ir->mask_keycode);
-       ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
-                  gpio, data,
-                  ir->polling ? "poll" : "irq",
-                  (gpio & ir->mask_keydown) ? " down" : "",
-                  (gpio & ir->mask_keyup) ? " up" : "");
-
-       if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
-               u32 gpio_key = cx_read(MO_GP0_IO);
-
-               data = (data << 4) | ((gpio_key & 0xf0) >> 4);
-
-               rc_keydown(ir->dev, data, 0);
-
-       } else if (ir->mask_keydown) {
-               /* bit set on keydown */
-               if (gpio & ir->mask_keydown)
-                       rc_keydown_notimeout(ir->dev, data, 0);
-               else
-                       rc_keyup(ir->dev);
-
-       } else if (ir->mask_keyup) {
-               /* bit cleared on keydown */
-               if (0 == (gpio & ir->mask_keyup))
-                       rc_keydown_notimeout(ir->dev, data, 0);
-               else
-                       rc_keyup(ir->dev);
-
-       } else {
-               /* can't distinguish keydown/up :-/ */
-               rc_keydown_notimeout(ir->dev, data, 0);
-               rc_keyup(ir->dev);
-       }
-}
-
-static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
-{
-       unsigned long missed;
-       struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
-
-       cx88_ir_handle_key(ir);
-       missed = hrtimer_forward_now(&ir->timer,
-                                    ktime_set(0, ir->polling * 1000000));
-       if (missed > 1)
-               ir_dprintk("Missed ticks %ld\n", missed - 1);
-
-       return HRTIMER_RESTART;
-}
-
-static int __cx88_ir_start(void *priv)
-{
-       struct cx88_core *core = priv;
-       struct cx88_IR *ir;
-
-       if (!core || !core->ir)
-               return -EINVAL;
-
-       ir = core->ir;
-
-       if (ir->polling) {
-               hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-               ir->timer.function = cx88_ir_work;
-               hrtimer_start(&ir->timer,
-                             ktime_set(0, ir->polling * 1000000),
-                             HRTIMER_MODE_REL);
-       }
-       if (ir->sampling) {
-               core->pci_irqmask |= PCI_INT_IR_SMPINT;
-               cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
-               cx_write(MO_DDSCFG_IO, 0x5); /* enable */
-       }
-       return 0;
-}
-
-static void __cx88_ir_stop(void *priv)
-{
-       struct cx88_core *core = priv;
-       struct cx88_IR *ir;
-
-       if (!core || !core->ir)
-               return;
-
-       ir = core->ir;
-       if (ir->sampling) {
-               cx_write(MO_DDSCFG_IO, 0x0);
-               core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
-       }
-
-       if (ir->polling)
-               hrtimer_cancel(&ir->timer);
-}
-
-int cx88_ir_start(struct cx88_core *core)
-{
-       if (core->ir->users)
-               return __cx88_ir_start(core);
-
-       return 0;
-}
-
-void cx88_ir_stop(struct cx88_core *core)
-{
-       if (core->ir->users)
-               __cx88_ir_stop(core);
-}
-
-static int cx88_ir_open(struct rc_dev *rc)
-{
-       struct cx88_core *core = rc->priv;
-
-       core->ir->users++;
-       return __cx88_ir_start(core);
-}
-
-static void cx88_ir_close(struct rc_dev *rc)
-{
-       struct cx88_core *core = rc->priv;
-
-       core->ir->users--;
-       if (!core->ir->users)
-               __cx88_ir_stop(core);
-}
-
-/* ---------------------------------------------------------------------- */
-
-int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
-{
-       struct cx88_IR *ir;
-       struct rc_dev *dev;
-       char *ir_codes = NULL;
-       u64 rc_type = RC_TYPE_OTHER;
-       int err = -ENOMEM;
-       u32 hardware_mask = 0;  /* For devices with a hardware mask, when
-                                * used with a full-code IR table
-                                */
-
-       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-       dev = rc_allocate_device();
-       if (!ir || !dev)
-               goto err_out_free;
-
-       ir->dev = dev;
-
-       /* detect & configure */
-       switch (core->boardnr) {
-       case CX88_BOARD_DNTV_LIVE_DVB_T:
-       case CX88_BOARD_KWORLD_DVB_T:
-       case CX88_BOARD_KWORLD_DVB_T_CX22702:
-               ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
-               ir->gpio_addr = MO_GP1_IO;
-               ir->mask_keycode = 0x1f;
-               ir->mask_keyup = 0x60;
-               ir->polling = 50; /* ms */
-               break;
-       case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
-               ir_codes = RC_MAP_CINERGY_1400;
-               ir->sampling = 0xeb04; /* address */
-               break;
-       case CX88_BOARD_HAUPPAUGE:
-       case CX88_BOARD_HAUPPAUGE_DVB_T1:
-       case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-       case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
-       case CX88_BOARD_HAUPPAUGE_HVR1100:
-       case CX88_BOARD_HAUPPAUGE_HVR3000:
-       case CX88_BOARD_HAUPPAUGE_HVR4000:
-       case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
-       case CX88_BOARD_PCHDTV_HD3000:
-       case CX88_BOARD_PCHDTV_HD5500:
-       case CX88_BOARD_HAUPPAUGE_IRONLY:
-               ir_codes = RC_MAP_HAUPPAUGE;
-               ir->sampling = 1;
-               break;
-       case CX88_BOARD_WINFAST_DTV2000H:
-       case CX88_BOARD_WINFAST_DTV2000H_J:
-       case CX88_BOARD_WINFAST_DTV1800H:
-       case CX88_BOARD_WINFAST_DTV1800H_XC4000:
-       case CX88_BOARD_WINFAST_DTV2000H_PLUS:
-               ir_codes = RC_MAP_WINFAST;
-               ir->gpio_addr = MO_GP0_IO;
-               ir->mask_keycode = 0x8f8;
-               ir->mask_keyup = 0x100;
-               ir->polling = 50; /* ms */
-               break;
-       case CX88_BOARD_WINFAST2000XP_EXPERT:
-       case CX88_BOARD_WINFAST_DTV1000:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
-       case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
-               ir_codes = RC_MAP_WINFAST;
-               ir->gpio_addr = MO_GP0_IO;
-               ir->mask_keycode = 0x8f8;
-               ir->mask_keyup = 0x100;
-               ir->polling = 1; /* ms */
-               break;
-       case CX88_BOARD_IODATA_GVBCTV7E:
-               ir_codes = RC_MAP_IODATA_BCTV7E;
-               ir->gpio_addr = MO_GP0_IO;
-               ir->mask_keycode = 0xfd;
-               ir->mask_keydown = 0x02;
-               ir->polling = 5; /* ms */
-               break;
-       case CX88_BOARD_PROLINK_PLAYTVPVR:
-       case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
-               /*
-                * It seems that this hardware is paired with NEC extended
-                * address 0x866b. So, unfortunately, its usage with other
-                * IR's with different address won't work. Still, there are
-                * other IR's from the same manufacturer that works, like the
-                * 002-T mini RC, provided with newer PV hardware
-                */
-               ir_codes = RC_MAP_PIXELVIEW_MK12;
-               ir->gpio_addr = MO_GP1_IO;
-               ir->mask_keyup = 0x80;
-               ir->polling = 10; /* ms */
-               hardware_mask = 0x3f;   /* Hardware returns only 6 bits from command part */
-               break;
-       case CX88_BOARD_PROLINK_PV_8000GT:
-       case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
-               ir_codes = RC_MAP_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 = RC_MAP_PIXELVIEW;
-               ir->gpio_addr = MO_GP1_IO;
-               ir->mask_keycode = 0x1f;
-               ir->mask_keyup = 0x60;
-               ir->polling = 1; /* ms */
-               break;
-       case CX88_BOARD_ADSTECH_DVB_T_PCI:
-               ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
-               ir->gpio_addr = MO_GP1_IO;
-               ir->mask_keycode = 0xbf;
-               ir->mask_keyup = 0x40;
-               ir->polling = 50; /* ms */
-               break;
-       case CX88_BOARD_MSI_TVANYWHERE_MASTER:
-               ir_codes = RC_MAP_MSI_TVANYWHERE;
-               ir->gpio_addr = MO_GP1_IO;
-               ir->mask_keycode = 0x1f;
-               ir->mask_keyup = 0x40;
-               ir->polling = 1; /* ms */
-               break;
-       case CX88_BOARD_AVERTV_303:
-       case CX88_BOARD_AVERTV_STUDIO_303:
-               ir_codes         = RC_MAP_AVERTV_303;
-               ir->gpio_addr    = MO_GP2_IO;
-               ir->mask_keycode = 0xfb;
-               ir->mask_keydown = 0x02;
-               ir->polling      = 50; /* ms */
-               break;
-       case CX88_BOARD_OMICOM_SS4_PCI:
-       case CX88_BOARD_SATTRADE_ST4200:
-       case CX88_BOARD_TBS_8920:
-       case CX88_BOARD_TBS_8910:
-       case CX88_BOARD_PROF_7300:
-       case CX88_BOARD_PROF_7301:
-       case CX88_BOARD_PROF_6200:
-               ir_codes = RC_MAP_TBS_NEC;
-               ir->sampling = 0xff00; /* address */
-               break;
-       case CX88_BOARD_TEVII_S464:
-       case CX88_BOARD_TEVII_S460:
-       case CX88_BOARD_TEVII_S420:
-               ir_codes = RC_MAP_TEVII_NEC;
-               ir->sampling = 0xff00; /* address */
-               break;
-       case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
-               ir_codes         = RC_MAP_DNTV_LIVE_DVBT_PRO;
-               ir->sampling     = 0xff00; /* address */
-               break;
-       case CX88_BOARD_NORWOOD_MICRO:
-               ir_codes         = RC_MAP_NORWOOD;
-               ir->gpio_addr    = MO_GP1_IO;
-               ir->mask_keycode = 0x0e;
-               ir->mask_keyup   = 0x80;
-               ir->polling      = 50; /* ms */
-               break;
-       case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
-               ir_codes         = RC_MAP_NPGTECH;
-               ir->gpio_addr    = MO_GP0_IO;
-               ir->mask_keycode = 0xfa;
-               ir->polling      = 50; /* ms */
-               break;
-       case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-               ir_codes         = RC_MAP_PINNACLE_PCTV_HD;
-               ir->sampling     = 1;
-               break;
-       case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
-               ir_codes         = RC_MAP_POWERCOLOR_REAL_ANGEL;
-               ir->gpio_addr    = MO_GP2_IO;
-               ir->mask_keycode = 0x7e;
-               ir->polling      = 100; /* ms */
-               break;
-       case CX88_BOARD_TWINHAN_VP1027_DVBS:
-               ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
-               rc_type          = RC_TYPE_NEC;
-               ir->sampling     = 0xff00; /* address */
-               break;
-       }
-
-       if (!ir_codes) {
-               err = -ENODEV;
-               goto err_out_free;
-       }
-
-       /*
-        * The usage of mask_keycode were very convenient, due to several
-        * reasons. Among others, the scancode tables were using the scancode
-        * as the index elements. So, the less bits it was used, the smaller
-        * the table were stored. After the input changes, the better is to use
-        * the full scancodes, since it allows replacing the IR remote by
-        * another one. Unfortunately, there are still some hardware, like
-        * Pixelview Ultra Pro, where only part of the scancode is sent via
-        * GPIO. So, there's no way to get the full scancode. Due to that,
-        * hardware_mask were introduced here: it represents those hardware
-        * that has such limits.
-        */
-       if (hardware_mask && !ir->mask_keycode)
-               ir->mask_keycode = hardware_mask;
-
-       /* init input device */
-       snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
-       snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
-
-       dev->input_name = ir->name;
-       dev->input_phys = ir->phys;
-       dev->input_id.bustype = BUS_PCI;
-       dev->input_id.version = 1;
-       if (pci->subsystem_vendor) {
-               dev->input_id.vendor = pci->subsystem_vendor;
-               dev->input_id.product = pci->subsystem_device;
-       } else {
-               dev->input_id.vendor = pci->vendor;
-               dev->input_id.product = pci->device;
-       }
-       dev->dev.parent = &pci->dev;
-       dev->map_name = ir_codes;
-       dev->driver_name = MODULE_NAME;
-       dev->priv = core;
-       dev->open = cx88_ir_open;
-       dev->close = cx88_ir_close;
-       dev->scanmask = hardware_mask;
-
-       if (ir->sampling) {
-               dev->driver_type = RC_DRIVER_IR_RAW;
-               dev->timeout = 10 * 1000 * 1000; /* 10 ms */
-       } else {
-               dev->driver_type = RC_DRIVER_SCANCODE;
-               dev->allowed_protos = rc_type;
-       }
-
-       ir->core = core;
-       core->ir = ir;
-
-       /* all done */
-       err = rc_register_device(dev);
-       if (err)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       rc_free_device(dev);
-       core->ir = NULL;
-       kfree(ir);
-       return err;
-}
-
-int cx88_ir_fini(struct cx88_core *core)
-{
-       struct cx88_IR *ir = core->ir;
-
-       /* skip detach on non attached boards */
-       if (NULL == ir)
-               return 0;
-
-       cx88_ir_stop(core);
-       rc_unregister_device(ir->dev);
-       kfree(ir);
-
-       /* done */
-       core->ir = NULL;
-       return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-void cx88_ir_irq(struct cx88_core *core)
-{
-       struct cx88_IR *ir = core->ir;
-       u32 samples;
-       unsigned todo, bits;
-       struct ir_raw_event ev;
-
-       if (!ir || !ir->sampling)
-               return;
-
-       /*
-        * Samples are stored in a 32 bit register, oldest sample in
-        * the msb. A set bit represents space and an unset bit
-        * represents a pulse.
-        */
-       samples = cx_read(MO_SAMPLE_IO);
-
-       if (samples == 0xff && ir->dev->idle)
-               return;
-
-       init_ir_raw_event(&ev);
-       for (todo = 32; todo > 0; todo -= bits) {
-               ev.pulse = samples & 0x80000000 ? false : true;
-               bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
-               ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
-               ir_raw_event_store_with_filter(ir->dev, &ev);
-               samples <<= bits;
-       }
-       ir_raw_event_handle(ir->dev);
-}
-
-static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       int flags, code;
-
-       /* poll IR chip */
-       flags = i2c_smbus_read_byte_data(ir->c, 0x10);
-       if (flags < 0) {
-               dprintk("read error\n");
-               return 0;
-       }
-       /* key pressed ? */
-       if (0 == (flags & 0x80))
-               return 0;
-
-       /* read actual key code */
-       code = i2c_smbus_read_byte_data(ir->c, 0x00);
-       if (code < 0) {
-               dprintk("read error\n");
-               return 0;
-       }
-
-       dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
-                  code & 0xff, flags & 0xff);
-
-       *ir_key = code & 0xff;
-       *ir_raw = code;
-       return 1;
-}
-
-void cx88_i2c_init_ir(struct cx88_core *core)
-{
-       struct i2c_board_info info;
-       const unsigned short default_addr_list[] = {
-               0x18, 0x6b, 0x71,
-               I2C_CLIENT_END
-       };
-       const unsigned short pvr2000_addr_list[] = {
-               0x18, 0x1a,
-               I2C_CLIENT_END
-       };
-       const unsigned short *addr_list = default_addr_list;
-       const unsigned short *addrp;
-       /* Instantiate the IR receiver device, if present */
-       if (0 != core->i2c_rc)
-               return;
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-
-       switch (core->boardnr) {
-       case CX88_BOARD_LEADTEK_PVR2000:
-               addr_list = pvr2000_addr_list;
-               core->init_data.name = "cx88 Leadtek PVR 2000 remote";
-               core->init_data.type = RC_TYPE_UNKNOWN;
-               core->init_data.get_key = get_key_pvr2000;
-               core->init_data.ir_codes = RC_MAP_EMPTY;
-               break;
-       }
-
-       /*
-        * We can't call i2c_new_probed_device() because it uses
-        * quick writes for probing and at least some RC receiver
-        * devices only reply to reads.
-        * Also, Hauppauge XVR needs to be specified, as address 0x71
-        * conflicts with another remote type used with saa7134
-        */
-       for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
-               info.platform_data = NULL;
-               memset(&core->init_data, 0, sizeof(core->init_data));
-
-               if (*addrp == 0x71) {
-                       /* Hauppauge XVR */
-                       core->init_data.name = "cx88 Hauppauge XVR remote";
-                       core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-                       core->init_data.type = RC_TYPE_RC5;
-                       core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-
-                       info.platform_data = &core->init_data;
-               }
-               if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
-                                       I2C_SMBUS_READ, 0,
-                                       I2C_SMBUS_QUICK, NULL) >= 0) {
-                       info.addr = *addrp;
-                       i2c_new_device(&core->i2c_adap, &info);
-                       break;
-               }
-       }
-}
-
-/* ---------------------------------------------------------------------- */
-
-MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
-MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
deleted file mode 100644 (file)
index cd5386e..0000000
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
- *
- *  Support for the mpeg transport stream transfers
- *  PCI function #2 of the cx2388x.
- *
- *    (c) 2004 Jelle Foks <jelle@foks.us>
- *    (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
- *    (c) 2004 Gerd Knorr <kraxel@bytesex.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/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <asm/delay.h>
-
-#include "cx88.h"
-
-/* ------------------------------------------------------------------ */
-
-MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
-MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
-MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CX88_VERSION);
-
-static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
-
-#define dprintk(level,fmt, arg...)     if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
-
-#define mpeg_dbg(level,fmt, arg...)    if (debug >= level) \
-       printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-static void request_module_async(struct work_struct *work)
-{
-       struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
-
-       if (dev->core->board.mpeg & CX88_MPEG_DVB)
-               request_module("cx88-dvb");
-       if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
-               request_module("cx88-blackbird");
-}
-
-static void request_modules(struct cx8802_dev *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_modules(struct cx8802_dev *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
-
-
-static LIST_HEAD(cx8802_devlist);
-static DEFINE_MUTEX(cx8802_mutex);
-/* ------------------------------------------------------------------ */
-
-static int cx8802_start_dma(struct cx8802_dev    *dev,
-                           struct cx88_dmaqueue *q,
-                           struct cx88_buffer   *buf)
-{
-       struct cx88_core *core = dev->core;
-
-       dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
-               buf->vb.width, buf->vb.height, buf->vb.field);
-
-       /* setup fifo + format */
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
-                               dev->ts_packet_size, buf->risc.dma);
-
-       /* write TS length to chip */
-       cx_write(MO_TS_LNGTH, buf->vb.width);
-
-       /* FIXME: this needs a review.
-        * also: move to cx88-blackbird + cx88-dvb source files? */
-
-       dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
-
-       if ( (core->active_type_id == CX88_MPEG_DVB) &&
-               (core->board.mpeg & CX88_MPEG_DVB) ) {
-
-               dprintk( 1, "cx8802_start_dma doing .dvb\n");
-               /* negedge driven & software reset */
-               cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
-               udelay(100);
-               cx_write(MO_PINMUX_IO, 0x00);
-               cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
-               switch (core->boardnr) {
-               case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
-               case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
-               case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-               case CX88_BOARD_PCHDTV_HD5500:
-                       cx_write(TS_SOP_STAT, 1<<13);
-                       break;
-               case CX88_BOARD_SAMSUNG_SMT_7020:
-                       cx_write(TS_SOP_STAT, 0x00);
-                       break;
-               case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
-               case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-                       cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
-                       udelay(100);
-                       break;
-               case CX88_BOARD_HAUPPAUGE_HVR1300:
-                       /* Enable MPEG parallel IO and video signal pins */
-                       cx_write(MO_PINMUX_IO, 0x88);
-                       cx_write(TS_SOP_STAT, 0);
-                       cx_write(TS_VALERR_CNTRL, 0);
-                       break;
-               case CX88_BOARD_PINNACLE_PCTV_HD_800i:
-                       /* Enable MPEG parallel IO and video signal pins */
-                       cx_write(MO_PINMUX_IO, 0x88);
-                       cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4));
-                       dev->ts_gen_cntrl = 5;
-                       cx_write(TS_SOP_STAT, 0);
-                       cx_write(TS_VALERR_CNTRL, 0);
-                       udelay(100);
-                       break;
-               default:
-                       cx_write(TS_SOP_STAT, 0x00);
-                       break;
-               }
-               cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
-               udelay(100);
-       } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
-               (core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
-               dprintk( 1, "cx8802_start_dma doing .blackbird\n");
-               cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
-
-               cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
-               udelay(100);
-
-               cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
-               cx_write(TS_VALERR_CNTRL, 0x2000);
-
-               cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
-               udelay(100);
-       } else {
-               printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
-                       core->board.mpeg );
-               return -EINVAL;
-       }
-
-       /* reset counter */
-       cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
-       q->count = 1;
-
-       /* enable irqs */
-       dprintk( 1, "setting the interrupt mask\n" );
-       cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
-       cx_set(MO_TS_INTMSK,  0x1f0011);
-
-       /* start dma */
-       cx_set(MO_DEV_CNTRL2, (1<<5));
-       cx_set(MO_TS_DMACNTRL, 0x11);
-       return 0;
-}
-
-static int cx8802_stop_dma(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       dprintk( 1, "cx8802_stop_dma\n" );
-
-       /* stop dma */
-       cx_clear(MO_TS_DMACNTRL, 0x11);
-
-       /* disable irqs */
-       cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT);
-       cx_clear(MO_TS_INTMSK, 0x1f0011);
-
-       /* Reset the controller */
-       cx_write(TS_GEN_CNTRL, 0xcd);
-       return 0;
-}
-
-static int cx8802_restart_queue(struct cx8802_dev    *dev,
-                               struct cx88_dmaqueue *q)
-{
-       struct cx88_buffer *buf;
-
-       dprintk( 1, "cx8802_restart_queue\n" );
-       if (list_empty(&q->active))
-       {
-               struct cx88_buffer *prev;
-               prev = NULL;
-
-               dprintk(1, "cx8802_restart_queue: queue is empty\n" );
-
-               for (;;) {
-                       if (list_empty(&q->queued))
-                               return 0;
-                       buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
-                       if (NULL == prev) {
-                               list_del(&buf->vb.queue);
-                               list_add_tail(&buf->vb.queue,&q->active);
-                               cx8802_start_dma(dev, q, buf);
-                               buf->vb.state = VIDEOBUF_ACTIVE;
-                               buf->count    = q->count++;
-                               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-                               dprintk(1,"[%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,&q->active);
-                               buf->vb.state = VIDEOBUF_ACTIVE;
-                               buf->count    = q->count++;
-                               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                               dprintk(1,"[%p/%d] restart_queue - move to active\n",
-                                       buf,buf->vb.i);
-                       } else {
-                               return 0;
-                       }
-                       prev = buf;
-               }
-               return 0;
-       }
-
-       buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
-       dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-               buf, buf->vb.i);
-       cx8802_start_dma(dev, q, buf);
-       list_for_each_entry(buf, &q->active, vb.queue)
-               buf->count = q->count++;
-       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
-                       struct cx88_buffer *buf, enum v4l2_field field)
-{
-       int size = dev->ts_packet_size * dev->ts_packet_count;
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-       int rc;
-
-       dprintk(1, "%s: %p\n", __func__, buf);
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               buf->vb.width  = dev->ts_packet_size;
-               buf->vb.height = dev->ts_packet_count;
-               buf->vb.size   = size;
-               buf->vb.field  = field /*V4L2_FIELD_TOP*/;
-
-               if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
-                       goto fail;
-               cx88_risc_databuffer(dev->pci, &buf->risc,
-                                    dma->sglist,
-                                    buf->vb.width, buf->vb.height, 0);
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       cx88_free_buffer(q,buf);
-       return rc;
-}
-
-void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
-{
-       struct cx88_buffer    *prev;
-       struct cx88_dmaqueue  *cx88q = &dev->mpegq;
-
-       dprintk( 1, "cx8802_buf_queue\n" );
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
-
-       if (list_empty(&cx88q->active)) {
-               dprintk( 1, "queue is empty - first active\n" );
-               list_add_tail(&buf->vb.queue,&cx88q->active);
-               cx8802_start_dma(dev, cx88q, buf);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = cx88q->count++;
-               mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(1,"[%p/%d] %s - first active\n",
-                       buf, buf->vb.i, __func__);
-
-       } else {
-               dprintk( 1, "queue is not empty - append to active\n" );
-               prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
-               list_add_tail(&buf->vb.queue,&cx88q->active);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               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, __func__);
-       }
-}
-
-/* ----------------------------------------------------------- */
-
-static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
-{
-       struct cx88_dmaqueue *q = &dev->mpegq;
-       struct cx88_buffer *buf;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->slock,flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
-                       buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
-       }
-       if (restart)
-       {
-               dprintk(1, "restarting queue\n" );
-               cx8802_restart_queue(dev,q);
-       }
-       spin_unlock_irqrestore(&dev->slock,flags);
-}
-
-void cx8802_cancel_buffers(struct cx8802_dev *dev)
-{
-       struct cx88_dmaqueue *q = &dev->mpegq;
-
-       dprintk( 1, "cx8802_cancel_buffers" );
-       del_timer_sync(&q->timeout);
-       cx8802_stop_dma(dev);
-       do_cancel_buffers(dev,"cancel",0);
-}
-
-static void cx8802_timeout(unsigned long data)
-{
-       struct cx8802_dev *dev = (struct cx8802_dev*)data;
-
-       dprintk(1, "%s\n",__func__);
-
-       if (debug)
-               cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
-       cx8802_stop_dma(dev);
-       do_cancel_buffers(dev,"timeout",1);
-}
-
-static const char * cx88_mpeg_irqs[32] = {
-       "ts_risci1", NULL, NULL, NULL,
-       "ts_risci2", NULL, NULL, NULL,
-       "ts_oflow",  NULL, NULL, NULL,
-       "ts_sync",   NULL, NULL, NULL,
-       "opc_err", "par_err", "rip_err", "pci_abort",
-       "ts_err?",
-};
-
-static void cx8802_mpeg_irq(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       u32 status, mask, count;
-
-       dprintk( 1, "cx8802_mpeg_irq\n" );
-       status = cx_read(MO_TS_INTSTAT);
-       mask   = cx_read(MO_TS_INTMSK);
-       if (0 == (status & mask))
-               return;
-
-       cx_write(MO_TS_INTSTAT, status);
-
-       if (debug || (status & mask & ~0xff))
-               cx88_print_irqbits(core->name, "irq mpeg ",
-                                  cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
-                                  status, mask);
-
-       /* risc op code error */
-       if (status & (1 << 16)) {
-               printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
-               cx_clear(MO_TS_DMACNTRL, 0x11);
-               cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
-       }
-
-       /* risc1 y */
-       if (status & 0x01) {
-               dprintk( 1, "wake up\n" );
-               spin_lock(&dev->slock);
-               count = cx_read(MO_TS_GPCNT);
-               cx88_wakeup(dev->core, &dev->mpegq, count);
-               spin_unlock(&dev->slock);
-       }
-
-       /* risc2 y */
-       if (status & 0x10) {
-               spin_lock(&dev->slock);
-               cx8802_restart_queue(dev,&dev->mpegq);
-               spin_unlock(&dev->slock);
-       }
-
-       /* other general errors */
-       if (status & 0x1f0100) {
-               dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
-               spin_lock(&dev->slock);
-               cx8802_stop_dma(dev);
-               cx8802_restart_queue(dev,&dev->mpegq);
-               spin_unlock(&dev->slock);
-       }
-}
-
-#define MAX_IRQ_LOOP 10
-
-static irqreturn_t cx8802_irq(int irq, void *dev_id)
-{
-       struct cx8802_dev *dev = dev_id;
-       struct cx88_core *core = dev->core;
-       u32 status;
-       int loop, handled = 0;
-
-       for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
-               status = cx_read(MO_PCI_INTSTAT) &
-                       (core->pci_irqmask | PCI_INT_TSINT);
-               if (0 == status)
-                       goto out;
-               dprintk( 1, "cx8802_irq\n" );
-               dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
-               dprintk( 1, "    status: %d\n", status );
-               handled = 1;
-               cx_write(MO_PCI_INTSTAT, status);
-
-               if (status & core->pci_irqmask)
-                       cx88_core_irq(core,status);
-               if (status & PCI_INT_TSINT)
-                       cx8802_mpeg_irq(dev);
-       };
-       if (MAX_IRQ_LOOP == loop) {
-               dprintk( 0, "clearing mask\n" );
-               printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
-                      core->name);
-               cx_write(MO_PCI_INTMSK,0);
-       }
-
- out:
-       return IRQ_RETVAL(handled);
-}
-
-static int cx8802_init_common(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       int err;
-
-       /* pci init */
-       if (pci_enable_device(dev->pci))
-               return -EIO;
-       pci_set_master(dev->pci);
-       if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
-               printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
-               return -EIO;
-       }
-
-       dev->pci_rev = dev->pci->revision;
-       pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);
-       printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
-              "latency: %d, mmio: 0x%llx\n", dev->core->name,
-              pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
-              dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
-
-       /* initialize driver struct */
-       spin_lock_init(&dev->slock);
-
-       /* init dma queue */
-       INIT_LIST_HEAD(&dev->mpegq.active);
-       INIT_LIST_HEAD(&dev->mpegq.queued);
-       dev->mpegq.timeout.function = cx8802_timeout;
-       dev->mpegq.timeout.data     = (unsigned long)dev;
-       init_timer(&dev->mpegq.timeout);
-       cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
-                         MO_TS_DMACNTRL,0x11,0x00);
-
-       /* get irq */
-       err = request_irq(dev->pci->irq, cx8802_irq,
-                         IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
-       if (err < 0) {
-               printk(KERN_ERR "%s: can't get IRQ %d\n",
-                      dev->core->name, dev->pci->irq);
-               return err;
-       }
-       cx_set(MO_PCI_INTMSK, core->pci_irqmask);
-
-       /* everything worked */
-       pci_set_drvdata(dev->pci,dev);
-       return 0;
-}
-
-static void cx8802_fini_common(struct cx8802_dev *dev)
-{
-       dprintk( 2, "cx8802_fini_common\n" );
-       cx8802_stop_dma(dev);
-       pci_disable_device(dev->pci);
-
-       /* unregister stuff */
-       free_irq(dev->pci->irq, dev);
-       pci_set_drvdata(dev->pci, NULL);
-
-       /* free memory */
-       btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
-}
-
-/* ----------------------------------------------------------- */
-
-static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
-{
-       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-       struct cx88_core *core = dev->core;
-
-       /* stop mpeg dma */
-       spin_lock(&dev->slock);
-       if (!list_empty(&dev->mpegq.active)) {
-               dprintk( 2, "suspend\n" );
-               printk("%s: suspend mpeg\n", core->name);
-               cx8802_stop_dma(dev);
-               del_timer(&dev->mpegq.timeout);
-       }
-       spin_unlock(&dev->slock);
-
-       /* FIXME -- shutdown device */
-       cx88_shutdown(dev->core);
-
-       pci_save_state(pci_dev);
-       if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
-               pci_disable_device(pci_dev);
-               dev->state.disabled = 1;
-       }
-       return 0;
-}
-
-static int cx8802_resume_common(struct pci_dev *pci_dev)
-{
-       struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-       struct cx88_core *core = dev->core;
-       int err;
-
-       if (dev->state.disabled) {
-               err=pci_enable_device(pci_dev);
-               if (err) {
-                       printk(KERN_ERR "%s: can't enable device\n",
-                                              dev->core->name);
-                       return err;
-               }
-               dev->state.disabled = 0;
-       }
-       err=pci_set_power_state(pci_dev, PCI_D0);
-       if (err) {
-               printk(KERN_ERR "%s: can't enable device\n",
-                                              dev->core->name);
-               pci_disable_device(pci_dev);
-               dev->state.disabled = 1;
-
-               return err;
-       }
-       pci_restore_state(pci_dev);
-
-       /* FIXME: re-initialize hardware */
-       cx88_reset(dev->core);
-
-       /* restart video+vbi capture */
-       spin_lock(&dev->slock);
-       if (!list_empty(&dev->mpegq.active)) {
-               printk("%s: resume mpeg\n", core->name);
-               cx8802_restart_queue(dev,&dev->mpegq);
-       }
-       spin_unlock(&dev->slock);
-
-       return 0;
-}
-
-struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
-{
-       struct cx8802_driver *d;
-
-       list_for_each_entry(d, &dev->drvlist, drvlist)
-               if (d->type_id == btype)
-                       return d;
-
-       return NULL;
-}
-
-/* Driver asked for hardware access. */
-static int cx8802_request_acquire(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-       unsigned int    i;
-
-       /* Fail a request for hardware if the device is busy. */
-       if (core->active_type_id != CX88_BOARD_NONE &&
-           core->active_type_id != drv->type_id)
-               return -EBUSY;
-
-       if (drv->type_id == CX88_MPEG_DVB) {
-               /* When switching to DVB, always set the input to the tuner */
-               core->last_analog_input = core->input;
-               core->input = 0;
-               for (i = 0;
-                    i < (sizeof(core->board.input) / sizeof(struct cx88_input));
-                    i++) {
-                       if (core->board.input[i].type == CX88_VMUX_DVB) {
-                               core->input = i;
-                               break;
-                       }
-               }
-       }
-
-       if (drv->advise_acquire)
-       {
-               core->active_ref++;
-               if (core->active_type_id == CX88_BOARD_NONE) {
-                       core->active_type_id = drv->type_id;
-                       drv->advise_acquire(drv);
-               }
-
-               mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
-       }
-
-       return 0;
-}
-
-/* Driver asked to release hardware. */
-static int cx8802_request_release(struct cx8802_driver *drv)
-{
-       struct cx88_core *core = drv->core;
-
-       if (drv->advise_release && --core->active_ref == 0)
-       {
-               if (drv->type_id == CX88_MPEG_DVB) {
-                       /* If the DVB driver is releasing, reset the input
-                          state to the last configured analog input */
-                       core->input = core->last_analog_input;
-               }
-
-               drv->advise_release(drv);
-               core->active_type_id = CX88_BOARD_NONE;
-               mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
-       }
-
-       return 0;
-}
-
-static int cx8802_check_driver(struct cx8802_driver *drv)
-{
-       if (drv == NULL)
-               return -ENODEV;
-
-       if ((drv->type_id != CX88_MPEG_DVB) &&
-               (drv->type_id != CX88_MPEG_BLACKBIRD))
-               return -EINVAL;
-
-       if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
-               (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
-               return -EINVAL;
-
-       if ((drv->probe == NULL) ||
-               (drv->remove == NULL) ||
-               (drv->advise_acquire == NULL) ||
-               (drv->advise_release == NULL))
-               return -EINVAL;
-
-       return 0;
-}
-
-int cx8802_register_driver(struct cx8802_driver *drv)
-{
-       struct cx8802_dev *dev;
-       struct cx8802_driver *driver;
-       int err, i = 0;
-
-       printk(KERN_INFO
-              "cx88/2: registering cx8802 driver, type: %s access: %s\n",
-              drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
-              drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
-
-       if ((err = cx8802_check_driver(drv)) != 0) {
-               printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
-               return err;
-       }
-
-       mutex_lock(&cx8802_mutex);
-
-       list_for_each_entry(dev, &cx8802_devlist, devlist) {
-               printk(KERN_INFO
-                      "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
-                      dev->core->name, dev->pci->subsystem_vendor,
-                      dev->pci->subsystem_device, dev->core->board.name,
-                      dev->core->boardnr);
-
-               /* Bring up a new struct for each driver instance */
-               driver = kzalloc(sizeof(*drv),GFP_KERNEL);
-               if (driver == NULL) {
-                       err = -ENOMEM;
-                       goto out;
-               }
-
-               /* Snapshot of the driver registration data */
-               drv->core = dev->core;
-               drv->suspend = cx8802_suspend_common;
-               drv->resume = cx8802_resume_common;
-               drv->request_acquire = cx8802_request_acquire;
-               drv->request_release = cx8802_request_release;
-               memcpy(driver, drv, sizeof(*driver));
-
-               mutex_lock(&drv->core->lock);
-               err = drv->probe(driver);
-               if (err == 0) {
-                       i++;
-                       list_add_tail(&driver->drvlist, &dev->drvlist);
-               } else {
-                       printk(KERN_ERR
-                              "%s/2: cx8802 probe failed, err = %d\n",
-                              dev->core->name, err);
-               }
-               mutex_unlock(&drv->core->lock);
-       }
-
-       err = i ? 0 : -ENODEV;
-out:
-       mutex_unlock(&cx8802_mutex);
-       return err;
-}
-
-int cx8802_unregister_driver(struct cx8802_driver *drv)
-{
-       struct cx8802_dev *dev;
-       struct cx8802_driver *d, *dtmp;
-       int err = 0;
-
-       printk(KERN_INFO
-              "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
-              drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
-              drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
-
-       mutex_lock(&cx8802_mutex);
-
-       list_for_each_entry(dev, &cx8802_devlist, devlist) {
-               printk(KERN_INFO
-                      "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
-                      dev->core->name, dev->pci->subsystem_vendor,
-                      dev->pci->subsystem_device, dev->core->board.name,
-                      dev->core->boardnr);
-
-               mutex_lock(&dev->core->lock);
-
-               list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
-                       /* only unregister the correct driver type */
-                       if (d->type_id != drv->type_id)
-                               continue;
-
-                       err = d->remove(d);
-                       if (err == 0) {
-                               list_del(&d->drvlist);
-                               kfree(d);
-                       } else
-                               printk(KERN_ERR "%s/2: cx8802 driver remove "
-                                      "failed (%d)\n", dev->core->name, err);
-               }
-
-               mutex_unlock(&dev->core->lock);
-       }
-
-       mutex_unlock(&cx8802_mutex);
-
-       return err;
-}
-
-/* ----------------------------------------------------------- */
-static int __devinit cx8802_probe(struct pci_dev *pci_dev,
-                              const struct pci_device_id *pci_id)
-{
-       struct cx8802_dev *dev;
-       struct cx88_core  *core;
-       int err;
-
-       /* general setup */
-       core = cx88_core_get(pci_dev);
-       if (NULL == core)
-               return -EINVAL;
-
-       printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
-
-       err = -ENODEV;
-       if (!core->board.mpeg)
-               goto fail_core;
-
-       err = -ENOMEM;
-       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-       if (NULL == dev)
-               goto fail_core;
-       dev->pci = pci_dev;
-       dev->core = core;
-
-       /* Maintain a reference so cx88-video can query the 8802 device. */
-       core->dvbdev = dev;
-
-       err = cx8802_init_common(dev);
-       if (err != 0)
-               goto fail_free;
-
-       INIT_LIST_HEAD(&dev->drvlist);
-       mutex_lock(&cx8802_mutex);
-       list_add_tail(&dev->devlist,&cx8802_devlist);
-       mutex_unlock(&cx8802_mutex);
-
-       /* now autoload cx88-dvb or cx88-blackbird */
-       request_modules(dev);
-       return 0;
-
- fail_free:
-       kfree(dev);
- fail_core:
-       core->dvbdev = NULL;
-       cx88_core_put(core,pci_dev);
-       return err;
-}
-
-static void __devexit cx8802_remove(struct pci_dev *pci_dev)
-{
-       struct cx8802_dev *dev;
-
-       dev = pci_get_drvdata(pci_dev);
-
-       dprintk( 1, "%s\n", __func__);
-
-       flush_request_modules(dev);
-
-       mutex_lock(&dev->core->lock);
-
-       if (!list_empty(&dev->drvlist)) {
-               struct cx8802_driver *drv, *tmp;
-               int err;
-
-               printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
-                      "while cx8802 sub-drivers still loaded?!\n",
-                      dev->core->name);
-
-               list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
-                       err = drv->remove(drv);
-                       if (err == 0) {
-                               list_del(&drv->drvlist);
-                       } else
-                               printk(KERN_ERR "%s/2: cx8802 driver remove "
-                                      "failed (%d)\n", dev->core->name, err);
-                       kfree(drv);
-               }
-       }
-
-       mutex_unlock(&dev->core->lock);
-
-       /* Destroy any 8802 reference. */
-       dev->core->dvbdev = NULL;
-
-       /* common */
-       cx8802_fini_common(dev);
-       cx88_core_put(dev->core,dev->pci);
-       kfree(dev);
-}
-
-static const struct pci_device_id cx8802_pci_tbl[] = {
-       {
-               .vendor       = 0x14f1,
-               .device       = 0x8802,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       },{
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
-
-static struct pci_driver cx8802_pci_driver = {
-       .name     = "cx88-mpeg driver manager",
-       .id_table = cx8802_pci_tbl,
-       .probe    = cx8802_probe,
-       .remove   = __devexit_p(cx8802_remove),
-};
-
-static int __init cx8802_init(void)
-{
-       printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
-              CX88_VERSION);
-       return pci_register_driver(&cx8802_pci_driver);
-}
-
-static void __exit cx8802_fini(void)
-{
-       pci_unregister_driver(&cx8802_pci_driver);
-}
-
-module_init(cx8802_init);
-module_exit(cx8802_fini);
-EXPORT_SYMBOL(cx8802_buf_prepare);
-EXPORT_SYMBOL(cx8802_buf_queue);
-EXPORT_SYMBOL(cx8802_cancel_buffers);
-
-EXPORT_SYMBOL(cx8802_register_driver);
-EXPORT_SYMBOL(cx8802_unregister_driver);
-EXPORT_SYMBOL(cx8802_get_driver);
-/* ----------------------------------------------------------- */
-/*
- * 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
- */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
deleted file mode 100644 (file)
index 2ec52d1..0000000
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
-
-    cx88x-hw.h - CX2388x register offsets
-
-    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
-                 2001 Michael Eskin
-                 2002 Yurij Sysoev <yurij@naturesoft.net>
-                 2003 Gerd Knorr <kraxel@bytesex.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 _CX88_REG_H_
-#define _CX88_REG_H_
-
-/* ---------------------------------------------------------------------- */
-/* PCI IDs and config space                                               */
-
-#ifndef PCI_VENDOR_ID_CONEXANT
-# define PCI_VENDOR_ID_CONEXANT                0x14F1
-#endif
-#ifndef PCI_DEVICE_ID_CX2300_VID
-# define PCI_DEVICE_ID_CX2300_VID      0x8800
-#endif
-
-#define CX88X_DEVCTRL 0x40
-#define CX88X_EN_TBFX 0x02
-#define CX88X_EN_VSFX 0x04
-
-/* ---------------------------------------------------------------------- */
-/* PCI controller registers                                               */
-
-/* Command and Status Register */
-#define F0_CMD_STAT_MM      0x2f0004
-#define F1_CMD_STAT_MM      0x2f0104
-#define F2_CMD_STAT_MM      0x2f0204
-#define F3_CMD_STAT_MM      0x2f0304
-#define F4_CMD_STAT_MM      0x2f0404
-
-/* Device Control #1 */
-#define F0_DEV_CNTRL1_MM    0x2f0040
-#define F1_DEV_CNTRL1_MM    0x2f0140
-#define F2_DEV_CNTRL1_MM    0x2f0240
-#define F3_DEV_CNTRL1_MM    0x2f0340
-#define F4_DEV_CNTRL1_MM    0x2f0440
-
-/* Device Control #1 */
-#define F0_BAR0_MM          0x2f0010
-#define F1_BAR0_MM          0x2f0110
-#define F2_BAR0_MM          0x2f0210
-#define F3_BAR0_MM          0x2f0310
-#define F4_BAR0_MM          0x2f0410
-
-/* ---------------------------------------------------------------------- */
-/* DMA Controller registers                                               */
-
-#define MO_PDMA_STHRSH      0x200000 // Source threshold
-#define MO_PDMA_STADRS      0x200004 // Source target address
-#define MO_PDMA_SIADRS      0x200008 // Source internal address
-#define MO_PDMA_SCNTRL      0x20000C // Source control
-#define MO_PDMA_DTHRSH      0x200010 // Destination threshold
-#define MO_PDMA_DTADRS      0x200014 // Destination target address
-#define MO_PDMA_DIADRS      0x200018 // Destination internal address
-#define MO_PDMA_DCNTRL      0x20001C // Destination control
-#define MO_LD_SSID          0x200030 // Load subsystem ID
-#define MO_DEV_CNTRL2       0x200034 // Device control
-#define MO_PCI_INTMSK       0x200040 // PCI interrupt mask
-#define MO_PCI_INTSTAT      0x200044 // PCI interrupt status
-#define MO_PCI_INTMSTAT     0x200048 // PCI interrupt masked status
-#define MO_VID_INTMSK       0x200050 // Video interrupt mask
-#define MO_VID_INTSTAT      0x200054 // Video interrupt status
-#define MO_VID_INTMSTAT     0x200058 // Video interrupt masked status
-#define MO_VID_INTSSTAT     0x20005C // Video interrupt set status
-#define MO_AUD_INTMSK       0x200060 // Audio interrupt mask
-#define MO_AUD_INTSTAT      0x200064 // Audio interrupt status
-#define MO_AUD_INTMSTAT     0x200068 // Audio interrupt masked status
-#define MO_AUD_INTSSTAT     0x20006C // Audio interrupt set status
-#define MO_TS_INTMSK        0x200070 // Transport stream interrupt mask
-#define MO_TS_INTSTAT       0x200074 // Transport stream interrupt status
-#define MO_TS_INTMSTAT      0x200078 // Transport stream interrupt mask status
-#define MO_TS_INTSSTAT      0x20007C // Transport stream interrupt set status
-#define MO_VIP_INTMSK       0x200080 // VIP interrupt mask
-#define MO_VIP_INTSTAT      0x200084 // VIP interrupt status
-#define MO_VIP_INTMSTAT     0x200088 // VIP interrupt masked status
-#define MO_VIP_INTSSTAT     0x20008C // VIP interrupt set status
-#define MO_GPHST_INTMSK     0x200090 // Host interrupt mask
-#define MO_GPHST_INTSTAT    0x200094 // Host interrupt status
-#define MO_GPHST_INTMSTAT   0x200098 // Host interrupt masked status
-#define MO_GPHST_INTSSTAT   0x20009C // Host interrupt set status
-
-// DMA Channels 1-6 belong to SPIPE
-#define MO_DMA7_PTR1        0x300018 // {24}RW* DMA Current Ptr : Ch#7
-#define MO_DMA8_PTR1        0x30001C // {24}RW* DMA Current Ptr : Ch#8
-
-// DMA Channels 9-20 belong to SPIPE
-#define MO_DMA21_PTR1       0x300080 // {24}R0* DMA Current Ptr : Ch#21
-#define MO_DMA22_PTR1       0x300084 // {24}R0* DMA Current Ptr : Ch#22
-#define MO_DMA23_PTR1       0x300088 // {24}R0* DMA Current Ptr : Ch#23
-#define MO_DMA24_PTR1       0x30008C // {24}R0* DMA Current Ptr : Ch#24
-#define MO_DMA25_PTR1       0x300090 // {24}R0* DMA Current Ptr : Ch#25
-#define MO_DMA26_PTR1       0x300094 // {24}R0* DMA Current Ptr : Ch#26
-#define MO_DMA27_PTR1       0x300098 // {24}R0* DMA Current Ptr : Ch#27
-#define MO_DMA28_PTR1       0x30009C // {24}R0* DMA Current Ptr : Ch#28
-#define MO_DMA29_PTR1       0x3000A0 // {24}R0* DMA Current Ptr : Ch#29
-#define MO_DMA30_PTR1       0x3000A4 // {24}R0* DMA Current Ptr : Ch#30
-#define MO_DMA31_PTR1       0x3000A8 // {24}R0* DMA Current Ptr : Ch#31
-#define MO_DMA32_PTR1       0x3000AC // {24}R0* DMA Current Ptr : Ch#32
-
-#define MO_DMA21_PTR2       0x3000C0 // {24}RW* DMA Tab Ptr : Ch#21
-#define MO_DMA22_PTR2       0x3000C4 // {24}RW* DMA Tab Ptr : Ch#22
-#define MO_DMA23_PTR2       0x3000C8 // {24}RW* DMA Tab Ptr : Ch#23
-#define MO_DMA24_PTR2       0x3000CC // {24}RW* DMA Tab Ptr : Ch#24
-#define MO_DMA25_PTR2       0x3000D0 // {24}RW* DMA Tab Ptr : Ch#25
-#define MO_DMA26_PTR2       0x3000D4 // {24}RW* DMA Tab Ptr : Ch#26
-#define MO_DMA27_PTR2       0x3000D8 // {24}RW* DMA Tab Ptr : Ch#27
-#define MO_DMA28_PTR2       0x3000DC // {24}RW* DMA Tab Ptr : Ch#28
-#define MO_DMA29_PTR2       0x3000E0 // {24}RW* DMA Tab Ptr : Ch#29
-#define MO_DMA30_PTR2       0x3000E4 // {24}RW* DMA Tab Ptr : Ch#30
-#define MO_DMA31_PTR2       0x3000E8 // {24}RW* DMA Tab Ptr : Ch#31
-#define MO_DMA32_PTR2       0x3000EC // {24}RW* DMA Tab Ptr : Ch#32
-
-#define MO_DMA21_CNT1       0x300100 // {11}RW* DMA Buffer Size : Ch#21
-#define MO_DMA22_CNT1       0x300104 // {11}RW* DMA Buffer Size : Ch#22
-#define MO_DMA23_CNT1       0x300108 // {11}RW* DMA Buffer Size : Ch#23
-#define MO_DMA24_CNT1       0x30010C // {11}RW* DMA Buffer Size : Ch#24
-#define MO_DMA25_CNT1       0x300110 // {11}RW* DMA Buffer Size : Ch#25
-#define MO_DMA26_CNT1       0x300114 // {11}RW* DMA Buffer Size : Ch#26
-#define MO_DMA27_CNT1       0x300118 // {11}RW* DMA Buffer Size : Ch#27
-#define MO_DMA28_CNT1       0x30011C // {11}RW* DMA Buffer Size : Ch#28
-#define MO_DMA29_CNT1       0x300120 // {11}RW* DMA Buffer Size : Ch#29
-#define MO_DMA30_CNT1       0x300124 // {11}RW* DMA Buffer Size : Ch#30
-#define MO_DMA31_CNT1       0x300128 // {11}RW* DMA Buffer Size : Ch#31
-#define MO_DMA32_CNT1       0x30012C // {11}RW* DMA Buffer Size : Ch#32
-
-#define MO_DMA21_CNT2       0x300140 // {11}RW* DMA Table Size : Ch#21
-#define MO_DMA22_CNT2       0x300144 // {11}RW* DMA Table Size : Ch#22
-#define MO_DMA23_CNT2       0x300148 // {11}RW* DMA Table Size : Ch#23
-#define MO_DMA24_CNT2       0x30014C // {11}RW* DMA Table Size : Ch#24
-#define MO_DMA25_CNT2       0x300150 // {11}RW* DMA Table Size : Ch#25
-#define MO_DMA26_CNT2       0x300154 // {11}RW* DMA Table Size : Ch#26
-#define MO_DMA27_CNT2       0x300158 // {11}RW* DMA Table Size : Ch#27
-#define MO_DMA28_CNT2       0x30015C // {11}RW* DMA Table Size : Ch#28
-#define MO_DMA29_CNT2       0x300160 // {11}RW* DMA Table Size : Ch#29
-#define MO_DMA30_CNT2       0x300164 // {11}RW* DMA Table Size : Ch#30
-#define MO_DMA31_CNT2       0x300168 // {11}RW* DMA Table Size : Ch#31
-#define MO_DMA32_CNT2       0x30016C // {11}RW* DMA Table Size : Ch#32
-
-
-/* ---------------------------------------------------------------------- */
-/* Video registers                                                        */
-
-#define MO_VIDY_DMA         0x310000 // {64}RWp Video Y
-#define MO_VIDU_DMA         0x310008 // {64}RWp Video U
-#define MO_VIDV_DMA         0x310010 // {64}RWp Video V
-#define MO_VBI_DMA          0x310018 // {64}RWp VBI (Vertical blanking interval)
-
-#define MO_DEVICE_STATUS    0x310100
-#define MO_INPUT_FORMAT     0x310104
-#define MO_AGC_BURST        0x31010c
-#define MO_CONTR_BRIGHT     0x310110
-#define MO_UV_SATURATION    0x310114
-#define MO_HUE              0x310118
-#define MO_HTOTAL           0x310120
-#define MO_HDELAY_EVEN      0x310124
-#define MO_HDELAY_ODD       0x310128
-#define MO_VDELAY_ODD       0x31012c
-#define MO_VDELAY_EVEN      0x310130
-#define MO_HACTIVE_EVEN     0x31013c
-#define MO_HACTIVE_ODD      0x310140
-#define MO_VACTIVE_EVEN     0x310144
-#define MO_VACTIVE_ODD      0x310148
-#define MO_HSCALE_EVEN      0x31014c
-#define MO_HSCALE_ODD       0x310150
-#define MO_VSCALE_EVEN      0x310154
-#define MO_FILTER_EVEN      0x31015c
-#define MO_VSCALE_ODD       0x310158
-#define MO_FILTER_ODD       0x310160
-#define MO_OUTPUT_FORMAT    0x310164
-
-#define MO_PLL_REG          0x310168 // PLL register
-#define MO_PLL_ADJ_CTRL     0x31016c // PLL adjust control register
-#define MO_SCONV_REG        0x310170 // sample rate conversion register
-#define MO_SCONV_FIFO       0x310174 // sample rate conversion fifo
-#define MO_SUB_STEP         0x310178 // subcarrier step size
-#define MO_SUB_STEP_DR      0x31017c // subcarrier step size for DR line
-
-#define MO_CAPTURE_CTRL     0x310180 // capture control
-#define MO_COLOR_CTRL       0x310184
-#define MO_VBI_PACKET       0x310188 // vbi packet size / delay
-#define MO_FIELD_COUNT      0x310190 // field counter
-#define MO_VIP_CONFIG       0x310194
-#define MO_VBOS_CONTROL            0x3101a8
-
-#define MO_AGC_BACK_VBI     0x310200
-#define MO_AGC_SYNC_TIP1    0x310208
-
-#define MO_VIDY_GPCNT       0x31C020 // {16}RO Video Y general purpose counter
-#define MO_VIDU_GPCNT       0x31C024 // {16}RO Video U general purpose counter
-#define MO_VIDV_GPCNT       0x31C028 // {16}RO Video V general purpose counter
-#define MO_VBI_GPCNT        0x31C02C // {16}RO VBI general purpose counter
-#define MO_VIDY_GPCNTRL     0x31C030 // {2}WO Video Y general purpose control
-#define MO_VIDU_GPCNTRL     0x31C034 // {2}WO Video U general purpose control
-#define MO_VIDV_GPCNTRL     0x31C038 // {2}WO Video V general purpose control
-#define MO_VBI_GPCNTRL      0x31C03C // {2}WO VBI general purpose counter
-#define MO_VID_DMACNTRL     0x31C040 // {8}RW Video DMA control
-#define MO_VID_XFR_STAT     0x31C044 // {1}RO Video transfer status
-
-
-/* ---------------------------------------------------------------------- */
-/* audio registers                                                        */
-
-#define MO_AUDD_DMA         0x320000 // {64}RWp Audio downstream
-#define MO_AUDU_DMA         0x320008 // {64}RWp Audio upstream
-#define MO_AUDR_DMA         0x320010 // {64}RWp Audio RDS (downstream)
-#define MO_AUDD_GPCNT       0x32C020 // {16}RO Audio down general purpose counter
-#define MO_AUDU_GPCNT       0x32C024 // {16}RO Audio up general purpose counter
-#define MO_AUDR_GPCNT       0x32C028 // {16}RO Audio RDS general purpose counter
-#define MO_AUDD_GPCNTRL     0x32C030 // {2}WO Audio down general purpose control
-#define MO_AUDU_GPCNTRL     0x32C034 // {2}WO Audio up general purpose control
-#define MO_AUDR_GPCNTRL     0x32C038 // {2}WO Audio RDS general purpose control
-#define MO_AUD_DMACNTRL     0x32C040 // {6}RW Audio DMA control
-#define MO_AUD_XFR_STAT     0x32C044 // {1}RO Audio transfer status
-#define MO_AUDD_LNGTH       0x32C048 // {12}RW Audio down line length
-#define MO_AUDR_LNGTH       0x32C04C // {12}RW Audio RDS line length
-
-#define AUD_INIT                 0x320100
-#define AUD_INIT_LD              0x320104
-#define AUD_SOFT_RESET           0x320108
-#define AUD_I2SINPUTCNTL         0x320120
-#define AUD_BAUDRATE             0x320124
-#define AUD_I2SOUTPUTCNTL        0x320128
-#define AAGC_HYST                0x320134
-#define AAGC_GAIN                0x320138
-#define AAGC_DEF                 0x32013c
-#define AUD_IIR1_0_SEL           0x320150
-#define AUD_IIR1_0_SHIFT         0x320154
-#define AUD_IIR1_1_SEL           0x320158
-#define AUD_IIR1_1_SHIFT         0x32015c
-#define AUD_IIR1_2_SEL           0x320160
-#define AUD_IIR1_2_SHIFT         0x320164
-#define AUD_IIR1_3_SEL           0x320168
-#define AUD_IIR1_3_SHIFT         0x32016c
-#define AUD_IIR1_4_SEL           0x320170
-#define AUD_IIR1_4_SHIFT         0x32017c
-#define AUD_IIR1_5_SEL           0x320180
-#define AUD_IIR1_5_SHIFT         0x320184
-#define AUD_IIR2_0_SEL           0x320190
-#define AUD_IIR2_0_SHIFT         0x320194
-#define AUD_IIR2_1_SEL           0x320198
-#define AUD_IIR2_1_SHIFT         0x32019c
-#define AUD_IIR2_2_SEL           0x3201a0
-#define AUD_IIR2_2_SHIFT         0x3201a4
-#define AUD_IIR2_3_SEL           0x3201a8
-#define AUD_IIR2_3_SHIFT         0x3201ac
-#define AUD_IIR3_0_SEL           0x3201c0
-#define AUD_IIR3_0_SHIFT         0x3201c4
-#define AUD_IIR3_1_SEL           0x3201c8
-#define AUD_IIR3_1_SHIFT         0x3201cc
-#define AUD_IIR3_2_SEL           0x3201d0
-#define AUD_IIR3_2_SHIFT         0x3201d4
-#define AUD_IIR4_0_SEL           0x3201e0
-#define AUD_IIR4_0_SHIFT         0x3201e4
-#define AUD_IIR4_1_SEL           0x3201e8
-#define AUD_IIR4_1_SHIFT         0x3201ec
-#define AUD_IIR4_2_SEL           0x3201f0
-#define AUD_IIR4_2_SHIFT         0x3201f4
-#define AUD_IIR4_0_CA0           0x320200
-#define AUD_IIR4_0_CA1           0x320204
-#define AUD_IIR4_0_CA2           0x320208
-#define AUD_IIR4_0_CB0           0x32020c
-#define AUD_IIR4_0_CB1           0x320210
-#define AUD_IIR4_1_CA0           0x320214
-#define AUD_IIR4_1_CA1           0x320218
-#define AUD_IIR4_1_CA2           0x32021c
-#define AUD_IIR4_1_CB0           0x320220
-#define AUD_IIR4_1_CB1           0x320224
-#define AUD_IIR4_2_CA0           0x320228
-#define AUD_IIR4_2_CA1           0x32022c
-#define AUD_IIR4_2_CA2           0x320230
-#define AUD_IIR4_2_CB0           0x320234
-#define AUD_IIR4_2_CB1           0x320238
-#define AUD_HP_MD_IIR4_1         0x320250
-#define AUD_HP_PROG_IIR4_1       0x320254
-#define AUD_FM_MODE_ENABLE       0x320258
-#define AUD_POLY0_DDS_CONSTANT   0x320270
-#define AUD_DN0_FREQ             0x320274
-#define AUD_DN1_FREQ             0x320278
-#define AUD_DN1_FREQ_SHIFT       0x32027c
-#define AUD_DN1_AFC              0x320280
-#define AUD_DN1_SRC_SEL          0x320284
-#define AUD_DN1_SHFT             0x320288
-#define AUD_DN2_FREQ             0x32028c
-#define AUD_DN2_FREQ_SHIFT       0x320290
-#define AUD_DN2_AFC              0x320294
-#define AUD_DN2_SRC_SEL          0x320298
-#define AUD_DN2_SHFT             0x32029c
-#define AUD_CRDC0_SRC_SEL        0x320300
-#define AUD_CRDC0_SHIFT          0x320304
-#define AUD_CORDIC_SHIFT_0       0x320308
-#define AUD_CRDC1_SRC_SEL        0x32030c
-#define AUD_CRDC1_SHIFT          0x320310
-#define AUD_CORDIC_SHIFT_1       0x320314
-#define AUD_DCOC_0_SRC           0x320320
-#define AUD_DCOC0_SHIFT          0x320324
-#define AUD_DCOC_0_SHIFT_IN0     0x320328
-#define AUD_DCOC_0_SHIFT_IN1     0x32032c
-#define AUD_DCOC_1_SRC           0x320330
-#define AUD_DCOC1_SHIFT          0x320334
-#define AUD_DCOC_1_SHIFT_IN0     0x320338
-#define AUD_DCOC_1_SHIFT_IN1     0x32033c
-#define AUD_DCOC_2_SRC           0x320340
-#define AUD_DCOC2_SHIFT          0x320344
-#define AUD_DCOC_2_SHIFT_IN0     0x320348
-#define AUD_DCOC_2_SHIFT_IN1     0x32034c
-#define AUD_DCOC_PASS_IN         0x320350
-#define AUD_PDET_SRC             0x320370
-#define AUD_PDET_SHIFT           0x320374
-#define AUD_PILOT_BQD_1_K0       0x320380
-#define AUD_PILOT_BQD_1_K1       0x320384
-#define AUD_PILOT_BQD_1_K2       0x320388
-#define AUD_PILOT_BQD_1_K3       0x32038c
-#define AUD_PILOT_BQD_1_K4       0x320390
-#define AUD_PILOT_BQD_2_K0       0x320394
-#define AUD_PILOT_BQD_2_K1       0x320398
-#define AUD_PILOT_BQD_2_K2       0x32039c
-#define AUD_PILOT_BQD_2_K3       0x3203a0
-#define AUD_PILOT_BQD_2_K4       0x3203a4
-#define AUD_THR_FR               0x3203c0
-#define AUD_X_PROG               0x3203c4
-#define AUD_Y_PROG               0x3203c8
-#define AUD_HARMONIC_MULT        0x3203cc
-#define AUD_C1_UP_THR            0x3203d0
-#define AUD_C1_LO_THR            0x3203d4
-#define AUD_C2_UP_THR            0x3203d8
-#define AUD_C2_LO_THR            0x3203dc
-#define AUD_PLL_EN               0x320400
-#define AUD_PLL_SRC              0x320404
-#define AUD_PLL_SHIFT            0x320408
-#define AUD_PLL_IF_SEL           0x32040c
-#define AUD_PLL_IF_SHIFT         0x320410
-#define AUD_BIQUAD_PLL_K0        0x320414
-#define AUD_BIQUAD_PLL_K1        0x320418
-#define AUD_BIQUAD_PLL_K2        0x32041c
-#define AUD_BIQUAD_PLL_K3        0x320420
-#define AUD_BIQUAD_PLL_K4        0x320424
-#define AUD_DEEMPH0_SRC_SEL      0x320440
-#define AUD_DEEMPH0_SHIFT        0x320444
-#define AUD_DEEMPH0_G0           0x320448
-#define AUD_DEEMPH0_A0           0x32044c
-#define AUD_DEEMPH0_B0           0x320450
-#define AUD_DEEMPH0_A1           0x320454
-#define AUD_DEEMPH0_B1           0x320458
-#define AUD_DEEMPH1_SRC_SEL      0x32045c
-#define AUD_DEEMPH1_SHIFT        0x320460
-#define AUD_DEEMPH1_G0           0x320464
-#define AUD_DEEMPH1_A0           0x320468
-#define AUD_DEEMPH1_B0           0x32046c
-#define AUD_DEEMPH1_A1           0x320470
-#define AUD_DEEMPH1_B1           0x320474
-#define AUD_OUT0_SEL             0x320490
-#define AUD_OUT0_SHIFT           0x320494
-#define AUD_OUT1_SEL             0x320498
-#define AUD_OUT1_SHIFT           0x32049c
-#define AUD_RDSI_SEL             0x3204a0
-#define AUD_RDSI_SHIFT           0x3204a4
-#define AUD_RDSQ_SEL             0x3204a8
-#define AUD_RDSQ_SHIFT           0x3204ac
-#define AUD_DBX_IN_GAIN          0x320500
-#define AUD_DBX_WBE_GAIN         0x320504
-#define AUD_DBX_SE_GAIN          0x320508
-#define AUD_DBX_RMS_WBE          0x32050c
-#define AUD_DBX_RMS_SE           0x320510
-#define AUD_DBX_SE_BYPASS        0x320514
-#define AUD_FAWDETCTL            0x320530
-#define AUD_FAWDETWINCTL         0x320534
-#define AUD_DEEMPHGAIN_R         0x320538
-#define AUD_DEEMPHNUMER1_R       0x32053c
-#define AUD_DEEMPHNUMER2_R       0x320540
-#define AUD_DEEMPHDENOM1_R       0x320544
-#define AUD_DEEMPHDENOM2_R       0x320548
-#define AUD_ERRLOGPERIOD_R       0x32054c
-#define AUD_ERRINTRPTTHSHLD1_R   0x320550
-#define AUD_ERRINTRPTTHSHLD2_R   0x320554
-#define AUD_ERRINTRPTTHSHLD3_R   0x320558
-#define AUD_NICAM_STATUS1        0x32055c
-#define AUD_NICAM_STATUS2        0x320560
-#define AUD_ERRLOG1              0x320564
-#define AUD_ERRLOG2              0x320568
-#define AUD_ERRLOG3              0x32056c
-#define AUD_DAC_BYPASS_L         0x320580
-#define AUD_DAC_BYPASS_R         0x320584
-#define AUD_DAC_BYPASS_CTL       0x320588
-#define AUD_CTL                  0x32058c
-#define AUD_STATUS               0x320590
-#define AUD_VOL_CTL              0x320594
-#define AUD_BAL_CTL              0x320598
-#define AUD_START_TIMER          0x3205b0
-#define AUD_MODE_CHG_TIMER       0x3205b4
-#define AUD_POLYPH80SCALEFAC     0x3205b8
-#define AUD_DMD_RA_DDS           0x3205bc
-#define AUD_I2S_RA_DDS           0x3205c0
-#define AUD_RATE_THRES_DMD       0x3205d0
-#define AUD_RATE_THRES_I2S       0x3205d4
-#define AUD_RATE_ADJ1            0x3205d8
-#define AUD_RATE_ADJ2            0x3205dc
-#define AUD_RATE_ADJ3            0x3205e0
-#define AUD_RATE_ADJ4            0x3205e4
-#define AUD_RATE_ADJ5            0x3205e8
-#define AUD_APB_IN_RATE_ADJ      0x3205ec
-#define AUD_I2SCNTL              0x3205ec
-#define AUD_PHASE_FIX_CTL        0x3205f0
-#define AUD_PLL_PRESCALE         0x320600
-#define AUD_PLL_DDS              0x320604
-#define AUD_PLL_INT              0x320608
-#define AUD_PLL_FRAC             0x32060c
-#define AUD_PLL_JTAG             0x320620
-#define AUD_PLL_SPMP             0x320624
-#define AUD_AFE_12DB_EN          0x320628
-
-// Audio QAM Register Addresses
-#define AUD_PDF_DDS_CNST_BYTE2   0x320d01
-#define AUD_PDF_DDS_CNST_BYTE1   0x320d02
-#define AUD_PDF_DDS_CNST_BYTE0   0x320d03
-#define AUD_PHACC_FREQ_8MSB      0x320d2a
-#define AUD_PHACC_FREQ_8LSB      0x320d2b
-#define AUD_QAM_MODE             0x320d04
-
-
-/* ---------------------------------------------------------------------- */
-/* transport stream registers                                             */
-
-#define MO_TS_DMA           0x330000 // {64}RWp Transport stream downstream
-#define MO_TS_GPCNT         0x33C020 // {16}RO TS general purpose counter
-#define MO_TS_GPCNTRL       0x33C030 // {2}WO TS general purpose control
-#define MO_TS_DMACNTRL      0x33C040 // {6}RW TS DMA control
-#define MO_TS_XFR_STAT      0x33C044 // {1}RO TS transfer status
-#define MO_TS_LNGTH         0x33C048 // {12}RW TS line length
-
-#define TS_HW_SOP_CNTRL     0x33C04C
-#define TS_GEN_CNTRL        0x33C050
-#define TS_BD_PKT_STAT      0x33C054
-#define TS_SOP_STAT         0x33C058
-#define TS_FIFO_OVFL_STAT   0x33C05C
-#define TS_VALERR_CNTRL     0x33C060
-
-
-/* ---------------------------------------------------------------------- */
-/* VIP registers                                                          */
-
-#define MO_VIPD_DMA         0x340000 // {64}RWp VIP downstream
-#define MO_VIPU_DMA         0x340008 // {64}RWp VIP upstream
-#define MO_VIPD_GPCNT       0x34C020 // {16}RO VIP down general purpose counter
-#define MO_VIPU_GPCNT       0x34C024 // {16}RO VIP up general purpose counter
-#define MO_VIPD_GPCNTRL     0x34C030 // {2}WO VIP down general purpose control
-#define MO_VIPU_GPCNTRL     0x34C034 // {2}WO VIP up general purpose control
-#define MO_VIP_DMACNTRL     0x34C040 // {6}RW VIP DMA control
-#define MO_VIP_XFR_STAT     0x34C044 // {1}RO VIP transfer status
-#define MO_VIP_CFG          0x340048 // VIP configuration
-#define MO_VIPU_CNTRL       0x34004C // VIP upstream control #1
-#define MO_VIPD_CNTRL       0x340050 // VIP downstream control #2
-#define MO_VIPD_LNGTH       0x340054 // VIP downstream line length
-#define MO_VIP_BRSTLN       0x340058 // VIP burst length
-#define MO_VIP_INTCNTRL     0x34C05C // VIP Interrupt Control
-#define MO_VIP_XFTERM       0x340060 // VIP transfer terminate
-
-
-/* ---------------------------------------------------------------------- */
-/* misc registers                                                         */
-
-#define MO_M2M_DMA          0x350000 // {64}RWp Mem2Mem DMA Bfr
-#define MO_GP0_IO           0x350010 // {32}RW* GPIOoutput enablesdata I/O
-#define MO_GP1_IO           0x350014 // {32}RW* GPIOoutput enablesdata I/O
-#define MO_GP2_IO           0x350018 // {32}RW* GPIOoutput enablesdata I/O
-#define MO_GP3_IO           0x35001C // {32}RW* GPIO Mode/Ctrloutput enables
-#define MO_GPIO             0x350020 // {32}RW* GPIO I2C Ctrldata I/O
-#define MO_GPOE             0x350024 // {32}RW  GPIO I2C Ctrloutput enables
-#define MO_GP_ISM           0x350028 // {16}WO  GPIO Intr Sens/Pol
-
-#define MO_PLL_B            0x35C008 // {32}RW* PLL Control for ASB bus clks
-#define MO_M2M_CNT          0x35C024 // {32}RW  Mem2Mem DMA Cnt
-#define MO_M2M_XSUM         0x35C028 // {32}RO  M2M XOR-Checksum
-#define MO_CRC              0x35C02C // {16}RW  CRC16 init/result
-#define MO_CRC_D            0x35C030 // {32}WO  CRC16 new data in
-#define MO_TM_CNT_LDW       0x35C034 // {32}RO  Timer : Counter low dword
-#define MO_TM_CNT_UW        0x35C038 // {16}RO  Timer : Counter high word
-#define MO_TM_LMT_LDW       0x35C03C // {32}RW  Timer : Limit low dword
-#define MO_TM_LMT_UW        0x35C040 // {32}RW  Timer : Limit high word
-#define MO_PINMUX_IO        0x35C044 // {8}RW  Pin Mux Control
-#define MO_TSTSEL_IO        0x35C048 // {2}RW  Pin Mux Control
-#define MO_AFECFG_IO        0x35C04C // AFE configuration reg
-#define MO_DDS_IO           0x35C050 // DDS Increment reg
-#define MO_DDSCFG_IO        0x35C054 // DDS Configuration reg
-#define MO_SAMPLE_IO        0x35C058 // IRIn sample reg
-#define MO_SRST_IO          0x35C05C // Output system reset reg
-
-#define MO_INT1_MSK         0x35C060 // DMA RISC interrupt mask
-#define MO_INT1_STAT        0x35C064 // DMA RISC interrupt status
-#define MO_INT1_MSTAT       0x35C068 // DMA RISC interrupt masked status
-
-
-/* ---------------------------------------------------------------------- */
-/* i2c bus registers                                                      */
-
-#define MO_I2C              0x368000 // I2C data/control
-#define MO_I2C_DIV          (0xf<<4)
-#define MO_I2C_SYNC         (1<<3)
-#define MO_I2C_W3B          (1<<2)
-#define MO_I2C_SCL          (1<<1)
-#define MO_I2C_SDA          (1<<0)
-
-
-/* ---------------------------------------------------------------------- */
-/* general purpose host registers                                         */
-/* FIXME: tyops?  s/0x35/0x38/ ??                                         */
-
-#define MO_GPHSTD_DMA       0x350000 // {64}RWp Host downstream
-#define MO_GPHSTU_DMA       0x350008 // {64}RWp Host upstream
-#define MO_GPHSTU_CNTRL     0x380048 // Host upstream control #1
-#define MO_GPHSTD_CNTRL     0x38004C // Host downstream control #2
-#define MO_GPHSTD_LNGTH     0x380050 // Host downstream line length
-#define MO_GPHST_WSC        0x380054 // Host wait state control
-#define MO_GPHST_XFR        0x380058 // Host transfer control
-#define MO_GPHST_WDTH       0x38005C // Host interface width
-#define MO_GPHST_HDSHK      0x380060 // Host peripheral handshake
-#define MO_GPHST_MUX16      0x380064 // Host muxed 16-bit transfer parameters
-#define MO_GPHST_MODE       0x380068 // Host mode select
-
-#define MO_GPHSTD_GPCNT     0x35C020 // Host down general purpose counter
-#define MO_GPHSTU_GPCNT     0x35C024 // Host up general purpose counter
-#define MO_GPHSTD_GPCNTRL   0x38C030 // Host down general purpose control
-#define MO_GPHSTU_GPCNTRL   0x38C034 // Host up general purpose control
-#define MO_GPHST_DMACNTRL   0x38C040 // Host DMA control
-#define MO_GPHST_XFR_STAT   0x38C044 // Host transfer status
-#define MO_GPHST_SOFT_RST   0x38C06C // Host software reset
-
-
-/* ---------------------------------------------------------------------- */
-/* RISC instructions                                                      */
-
-#define RISC_SYNC               0x80000000
-#define RISC_SYNC_ODD           0x80000000
-#define RISC_SYNC_EVEN          0x80000200
-#define RISC_RESYNC             0x80008000
-#define RISC_RESYNC_ODD                 0x80008000
-#define RISC_RESYNC_EVEN        0x80008200
-#define RISC_WRITE              0x10000000
-#define RISC_WRITEC             0x50000000
-#define RISC_READ               0x90000000
-#define RISC_READC              0xA0000000
-#define RISC_JUMP               0x70000000
-#define RISC_SKIP               0x20000000
-#define RISC_WRITERM            0xB0000000
-#define RISC_WRITECM            0xC0000000
-#define RISC_WRITECR            0xD0000000
-#define RISC_IMM                0x00000001
-
-#define RISC_SOL                0x08000000
-#define RISC_EOL                0x04000000
-
-#define RISC_IRQ2               0x02000000
-#define RISC_IRQ1               0x01000000
-
-#define RISC_CNT_NONE           0x00000000
-#define RISC_CNT_INC            0x00010000
-#define RISC_CNT_RSVR           0x00020000
-#define RISC_CNT_RESET          0x00030000
-#define RISC_JMP_SRP            0x01
-
-
-/* ---------------------------------------------------------------------- */
-/* various constants                                                      */
-
-// DMA
-/* Interrupt mask/status */
-#define PCI_INT_VIDINT         (1 <<  0)
-#define PCI_INT_AUDINT         (1 <<  1)
-#define PCI_INT_TSINT          (1 <<  2)
-#define PCI_INT_VIPINT         (1 <<  3)
-#define PCI_INT_HSTINT         (1 <<  4)
-#define PCI_INT_TM1INT         (1 <<  5)
-#define PCI_INT_SRCDMAINT      (1 <<  6)
-#define PCI_INT_DSTDMAINT      (1 <<  7)
-#define PCI_INT_RISC_RD_BERRINT        (1 << 10)
-#define PCI_INT_RISC_WR_BERRINT        (1 << 11)
-#define PCI_INT_BRDG_BERRINT   (1 << 12)
-#define PCI_INT_SRC_DMA_BERRINT        (1 << 13)
-#define PCI_INT_DST_DMA_BERRINT        (1 << 14)
-#define PCI_INT_IPB_DMA_BERRINT        (1 << 15)
-#define PCI_INT_I2CDONE                (1 << 16)
-#define PCI_INT_I2CRACK                (1 << 17)
-#define PCI_INT_IR_SMPINT      (1 << 18)
-#define PCI_INT_GPIO_INT0      (1 << 19)
-#define PCI_INT_GPIO_INT1      (1 << 20)
-
-#define SEL_BTSC     0x01
-#define SEL_EIAJ     0x02
-#define SEL_A2       0x04
-#define SEL_SAP      0x08
-#define SEL_NICAM    0x10
-#define SEL_FMRADIO  0x20
-
-// AUD_CTL
-#define AUD_INT_DN_RISCI1      (1 <<  0)
-#define AUD_INT_UP_RISCI1      (1 <<  1)
-#define AUD_INT_RDS_DN_RISCI1  (1 <<  2)
-#define AUD_INT_DN_RISCI2      (1 <<  4) /* yes, 3 is skipped */
-#define AUD_INT_UP_RISCI2      (1 <<  5)
-#define AUD_INT_RDS_DN_RISCI2  (1 <<  6)
-#define AUD_INT_DN_SYNC                (1 << 12)
-#define AUD_INT_UP_SYNC                (1 << 13)
-#define AUD_INT_RDS_DN_SYNC    (1 << 14)
-#define AUD_INT_OPC_ERR                (1 << 16)
-#define AUD_INT_BER_IRQ                (1 << 20)
-#define AUD_INT_MCHG_IRQ       (1 << 21)
-
-#define EN_BTSC_FORCE_MONO      0
-#define EN_BTSC_FORCE_STEREO    1
-#define EN_BTSC_FORCE_SAP       2
-#define EN_BTSC_AUTO_STEREO     3
-#define EN_BTSC_AUTO_SAP        4
-
-#define EN_A2_FORCE_MONO1       8
-#define EN_A2_FORCE_MONO2       9
-#define EN_A2_FORCE_STEREO      10
-#define EN_A2_AUTO_MONO2        11
-#define EN_A2_AUTO_STEREO       12
-
-#define EN_EIAJ_FORCE_MONO1     16
-#define EN_EIAJ_FORCE_MONO2     17
-#define EN_EIAJ_FORCE_STEREO    18
-#define EN_EIAJ_AUTO_MONO2      19
-#define EN_EIAJ_AUTO_STEREO     20
-
-#define EN_NICAM_FORCE_MONO1    32
-#define EN_NICAM_FORCE_MONO2    33
-#define EN_NICAM_FORCE_STEREO   34
-#define EN_NICAM_AUTO_MONO2     35
-#define EN_NICAM_AUTO_STEREO    36
-
-#define EN_FMRADIO_FORCE_MONO   24
-#define EN_FMRADIO_FORCE_STEREO 25
-#define EN_FMRADIO_AUTO_STEREO  26
-
-#define EN_NICAM_AUTO_FALLBACK  0x00000040
-#define EN_FMRADIO_EN_RDS       0x00000200
-#define EN_NICAM_TRY_AGAIN_BIT  0x00000400
-#define EN_DAC_ENABLE           0x00001000
-#define EN_I2SOUT_ENABLE        0x00002000
-#define EN_I2SIN_STR2DAC        0x00004000
-#define EN_I2SIN_ENABLE         0x00008000
-
-#define EN_DMTRX_SUMDIFF        (0 << 7)
-#define EN_DMTRX_SUMR           (1 << 7)
-#define EN_DMTRX_LR             (2 << 7)
-#define EN_DMTRX_MONO           (3 << 7)
-#define EN_DMTRX_BYPASS         (1 << 11)
-
-// Video
-#define VID_CAPTURE_CONTROL            0x310180
-
-#define CX23880_CAP_CTL_CAPTURE_VBI_ODD  (1<<3)
-#define CX23880_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
-#define CX23880_CAP_CTL_CAPTURE_ODD      (1<<1)
-#define CX23880_CAP_CTL_CAPTURE_EVEN     (1<<0)
-
-#define VideoInputMux0          0x0
-#define VideoInputMux1          0x1
-#define VideoInputMux2          0x2
-#define VideoInputMux3          0x3
-#define VideoInputTuner                 0x0
-#define VideoInputComposite     0x1
-#define VideoInputSVideo        0x2
-#define VideoInputOther                 0x3
-
-#define Xtal0           0x1
-#define Xtal1           0x2
-#define XtalAuto        0x3
-
-#define VideoFormatAuto                 0x0
-#define VideoFormatNTSC                 0x1
-#define VideoFormatNTSCJapan    0x2
-#define VideoFormatNTSC443      0x3
-#define VideoFormatPAL          0x4
-#define VideoFormatPALB                 0x4
-#define VideoFormatPALD                 0x4
-#define VideoFormatPALG                 0x4
-#define VideoFormatPALH                 0x4
-#define VideoFormatPALI                 0x4
-#define VideoFormatPALBDGHI     0x4
-#define VideoFormatPALM                 0x5
-#define VideoFormatPALN                 0x6
-#define VideoFormatPALNC        0x7
-#define VideoFormatPAL60        0x8
-#define VideoFormatSECAM        0x9
-
-#define VideoFormatAuto27MHz            0x10
-#define VideoFormatNTSC27MHz            0x11
-#define VideoFormatNTSCJapan27MHz       0x12
-#define VideoFormatNTSC44327MHz                 0x13
-#define VideoFormatPAL27MHz             0x14
-#define VideoFormatPALB27MHz            0x14
-#define VideoFormatPALD27MHz            0x14
-#define VideoFormatPALG27MHz            0x14
-#define VideoFormatPALH27MHz            0x14
-#define VideoFormatPALI27MHz            0x14
-#define VideoFormatPALBDGHI27MHz        0x14
-#define VideoFormatPALM27MHz            0x15
-#define VideoFormatPALN27MHz            0x16
-#define VideoFormatPALNC27MHz           0x17
-#define VideoFormatPAL6027MHz           0x18
-#define VideoFormatSECAM27MHz           0x19
-
-#define NominalUSECAM   0x87
-#define NominalVSECAM   0x85
-#define NominalUNTSC    0xFE
-#define NominalVNTSC    0xB4
-
-#define NominalContrast  0xD8
-
-#define HFilterAutoFormat       0x0
-#define HFilterCIF              0x1
-#define HFilterQCIF             0x2
-#define HFilterICON             0x3
-
-#define VFilter2TapInterpolate  0
-#define VFilter3TapInterpolate  1
-#define VFilter4TapInterpolate  2
-#define VFilter5TapInterpolate  3
-#define VFilter2TapNoInterpolate  4
-#define VFilter3TapNoInterpolate  5
-#define VFilter4TapNoInterpolate  6
-#define VFilter5TapNoInterpolate  7
-
-#define ColorFormatRGB32        0x0000
-#define ColorFormatRGB24        0x0011
-#define ColorFormatRGB16        0x0022
-#define ColorFormatRGB15        0x0033
-#define ColorFormatYUY2                 0x0044
-#define ColorFormatBTYUV        0x0055
-#define ColorFormatY8           0x0066
-#define ColorFormatRGB8                 0x0077
-#define ColorFormatPL422        0x0088
-#define ColorFormatPL411        0x0099
-#define ColorFormatYUV12        0x00AA
-#define ColorFormatYUV9                 0x00BB
-#define ColorFormatRAW          0x00EE
-#define ColorFormatBSWAP         0x0300
-#define ColorFormatWSWAP         0x0c00
-#define ColorFormatEvenMask      0x050f
-#define ColorFormatOddMask       0x0af0
-#define ColorFormatGamma         0x1000
-
-#define Interlaced              0x1
-#define NonInterlaced           0x0
-
-#define FieldEven               0x1
-#define FieldOdd                0x0
-
-#define TGReadWriteMode                 0x0
-#define TGEnableMode            0x1
-
-#define DV_CbAlign              0x0
-#define DV_Y0Align              0x1
-#define DV_CrAlign              0x2
-#define DV_Y1Align              0x3
-
-#define DVF_Analog              0x0
-#define DVF_CCIR656             0x1
-#define DVF_ByteStream          0x2
-#define DVF_ExtVSYNC            0x4
-#define DVF_ExtField            0x5
-
-#define CHANNEL_VID_Y           0x1
-#define CHANNEL_VID_U           0x2
-#define CHANNEL_VID_V           0x3
-#define CHANNEL_VID_VBI                 0x4
-#define CHANNEL_AUD_DN          0x5
-#define CHANNEL_AUD_UP          0x6
-#define CHANNEL_AUD_RDS_DN      0x7
-#define CHANNEL_MPEG_DN                 0x8
-#define CHANNEL_VIP_DN          0x9
-#define CHANNEL_VIP_UP          0xA
-#define CHANNEL_HOST_DN                 0xB
-#define CHANNEL_HOST_UP                 0xC
-#define CHANNEL_FIRST           0x1
-#define CHANNEL_LAST            0xC
-
-#define GP_COUNT_CONTROL_NONE           0x0
-#define GP_COUNT_CONTROL_INC            0x1
-#define GP_COUNT_CONTROL_RESERVED       0x2
-#define GP_COUNT_CONTROL_RESET          0x3
-
-#define PLL_PRESCALE_BY_2  2
-#define PLL_PRESCALE_BY_3  3
-#define PLL_PRESCALE_BY_4  4
-#define PLL_PRESCALE_BY_5  5
-
-#define HLNotchFilter4xFsc      0
-#define HLNotchFilterSquare     1
-#define HLNotchFilter135NTSC    2
-#define HLNotchFilter135PAL     3
-
-#define NTSC_8x_SUB_CARRIER  28.63636E6
-#define PAL_8x_SUB_CARRIER  35.46895E6
-
-// Default analog settings
-#define DEFAULT_HUE_NTSC                       0x00
-#define DEFAULT_BRIGHTNESS_NTSC                        0x00
-#define DEFAULT_CONTRAST_NTSC                  0x39
-#define DEFAULT_SAT_U_NTSC                     0x7F
-#define DEFAULT_SAT_V_NTSC                     0x5A
-
-typedef enum
-{
-       SOURCE_TUNER = 0,
-       SOURCE_COMPOSITE,
-       SOURCE_SVIDEO,
-       SOURCE_OTHER1,
-       SOURCE_OTHER2,
-       SOURCE_COMPVIASVIDEO,
-       SOURCE_CCIR656
-} VIDEOSOURCETYPE;
-
-#endif /* _CX88_REG_H_ */
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
deleted file mode 100644 (file)
index 770ec05..0000000
+++ /dev/null
@@ -1,1059 +0,0 @@
-/*
-
-    cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
-
-     (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
-     (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
-     (c) 2003 Gerd Knorr <kraxel@bytesex.org>
-
-    -----------------------------------------------------------------------
-
-    Lot of voodoo here.  Even the data sheet doesn't help to
-    understand what is going on here, the documentation for the audio
-    part of the cx2388x chip is *very* bad.
-
-    Some of this comes from party done linux driver sources I got from
-    [undocumented].
-
-    Some comes from the dscaler sources, one of the dscaler driver guy works
-    for Conexant ...
-
-    -----------------------------------------------------------------------
-
-    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/errno.h>
-#include <linux/freezer.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/poll.h>
-#include <linux/signal.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-
-#include "cx88.h"
-
-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;
-module_param(always_analog,int,0644);
-MODULE_PARM_DESC(always_analog,"force analog audio out");
-
-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)");
-
-#define dprintk(fmt, arg...)   if (audio_debug) \
-       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
-
-/* ----------------------------------------------------------- */
-
-static const char * const aud_ctl_names[64] = {
-       [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
-       [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
-       [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
-       [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
-       [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
-       [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
-       [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
-       [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
-       [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
-       [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
-       [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
-       [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
-       [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
-       [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
-       [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
-       [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
-       [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
-       [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
-       [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
-       [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
-       [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
-       [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
-       [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
-};
-
-struct rlist {
-       u32 reg;
-       u32 val;
-};
-
-static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
-{
-       int i;
-
-       for (i = 0; l[i].reg; i++) {
-               switch (l[i].reg) {
-               case AUD_PDF_DDS_CNST_BYTE2:
-               case AUD_PDF_DDS_CNST_BYTE1:
-               case AUD_PDF_DDS_CNST_BYTE0:
-               case AUD_QAM_MODE:
-               case AUD_PHACC_FREQ_8MSB:
-               case AUD_PHACC_FREQ_8LSB:
-                       cx_writeb(l[i].reg, l[i].val);
-                       break;
-               default:
-                       cx_write(l[i].reg, l[i].val);
-                       break;
-               }
-       }
-}
-
-static void set_audio_start(struct cx88_core *core, u32 mode)
-{
-       /* mute */
-       cx_write(AUD_VOL_CTL, (1 << 6));
-
-       /* start programming */
-       cx_write(AUD_INIT, mode);
-       cx_write(AUD_INIT_LD, 0x0001);
-       cx_write(AUD_SOFT_RESET, 0x0001);
-}
-
-static void set_audio_finish(struct cx88_core *core, u32 ctl)
-{
-       u32 volume;
-
-       /* restart dma; This avoids buzz in NICAM and is good in others  */
-       cx88_stop_audio_dma(core);
-       cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
-       cx88_start_audio_dma(core);
-
-       if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
-               cx_write(AUD_I2SINPUTCNTL, 4);
-               cx_write(AUD_BAUDRATE, 1);
-               /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
-               cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
-               cx_write(AUD_I2SOUTPUTCNTL, 1);
-               cx_write(AUD_I2SCNTL, 0);
-               /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
-       }
-       if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
-               ctl |= EN_DAC_ENABLE;
-               cx_write(AUD_CTL, ctl);
-       }
-
-       /* finish programming */
-       cx_write(AUD_SOFT_RESET, 0x0000);
-
-       /* unmute */
-       volume = cx_sread(SHADOW_AUD_VOL_CTL);
-       cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
-
-       core->last_change = jiffies;
-}
-
-/* ----------------------------------------------------------- */
-
-static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
-                                   u32 mode)
-{
-       static const struct rlist btsc[] = {
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AUD_OUT1_SEL, 0x00000013},
-               {AUD_OUT1_SHIFT, 0x00000000},
-               {AUD_POLY0_DDS_CONSTANT, 0x0012010c},
-               {AUD_DMD_RA_DDS, 0x00c3e7aa},
-               {AUD_DBX_IN_GAIN, 0x00004734},
-               {AUD_DBX_WBE_GAIN, 0x00004640},
-               {AUD_DBX_SE_GAIN, 0x00008d31},
-               {AUD_DCOC_0_SRC, 0x0000001a},
-               {AUD_IIR1_4_SEL, 0x00000021},
-               {AUD_DCOC_PASS_IN, 0x00000003},
-               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
-               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
-               {AUD_DN0_FREQ, 0x0000283b},
-               {AUD_DN2_SRC_SEL, 0x00000008},
-               {AUD_DN2_FREQ, 0x00003000},
-               {AUD_DN2_AFC, 0x00000002},
-               {AUD_DN2_SHFT, 0x00000000},
-               {AUD_IIR2_2_SEL, 0x00000020},
-               {AUD_IIR2_2_SHIFT, 0x00000000},
-               {AUD_IIR2_3_SEL, 0x0000001f},
-               {AUD_IIR2_3_SHIFT, 0x00000000},
-               {AUD_CRDC1_SRC_SEL, 0x000003ce},
-               {AUD_CRDC1_SHIFT, 0x00000000},
-               {AUD_CORDIC_SHIFT_1, 0x00000007},
-               {AUD_DCOC_1_SRC, 0x0000001b},
-               {AUD_DCOC1_SHIFT, 0x00000000},
-               {AUD_RDSI_SEL, 0x00000008},
-               {AUD_RDSQ_SEL, 0x00000008},
-               {AUD_RDSI_SHIFT, 0x00000000},
-               {AUD_RDSQ_SHIFT, 0x00000000},
-               {AUD_POLYPH80SCALEFAC, 0x00000003},
-               { /* end of list */ },
-       };
-       static const struct rlist btsc_sap[] = {
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AUD_DBX_IN_GAIN, 0x00007200},
-               {AUD_DBX_WBE_GAIN, 0x00006200},
-               {AUD_DBX_SE_GAIN, 0x00006200},
-               {AUD_IIR1_1_SEL, 0x00000000},
-               {AUD_IIR1_3_SEL, 0x00000001},
-               {AUD_DN1_SRC_SEL, 0x00000007},
-               {AUD_IIR1_4_SHIFT, 0x00000006},
-               {AUD_IIR2_1_SHIFT, 0x00000000},
-               {AUD_IIR2_2_SHIFT, 0x00000000},
-               {AUD_IIR3_0_SHIFT, 0x00000000},
-               {AUD_IIR3_1_SHIFT, 0x00000000},
-               {AUD_IIR3_0_SEL, 0x0000000d},
-               {AUD_IIR3_1_SEL, 0x0000000e},
-               {AUD_DEEMPH1_SRC_SEL, 0x00000014},
-               {AUD_DEEMPH1_SHIFT, 0x00000000},
-               {AUD_DEEMPH1_G0, 0x00004000},
-               {AUD_DEEMPH1_A0, 0x00000000},
-               {AUD_DEEMPH1_B0, 0x00000000},
-               {AUD_DEEMPH1_A1, 0x00000000},
-               {AUD_DEEMPH1_B1, 0x00000000},
-               {AUD_OUT0_SEL, 0x0000003f},
-               {AUD_OUT1_SEL, 0x0000003f},
-               {AUD_DN1_AFC, 0x00000002},
-               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
-               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
-               {AUD_IIR1_0_SEL, 0x0000001d},
-               {AUD_IIR1_2_SEL, 0x0000001e},
-               {AUD_IIR2_1_SEL, 0x00000002},
-               {AUD_IIR2_2_SEL, 0x00000004},
-               {AUD_IIR3_2_SEL, 0x0000000f},
-               {AUD_DCOC2_SHIFT, 0x00000001},
-               {AUD_IIR3_2_SHIFT, 0x00000001},
-               {AUD_DEEMPH0_SRC_SEL, 0x00000014},
-               {AUD_CORDIC_SHIFT_1, 0x00000006},
-               {AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
-               {AUD_DMD_RA_DDS, 0x00f696e6},
-               {AUD_IIR2_3_SEL, 0x00000025},
-               {AUD_IIR1_4_SEL, 0x00000021},
-               {AUD_DN1_FREQ, 0x0000c965},
-               {AUD_DCOC_PASS_IN, 0x00000003},
-               {AUD_DCOC_0_SRC, 0x0000001a},
-               {AUD_DCOC_1_SRC, 0x0000001b},
-               {AUD_DCOC1_SHIFT, 0x00000000},
-               {AUD_RDSI_SEL, 0x00000009},
-               {AUD_RDSQ_SEL, 0x00000009},
-               {AUD_RDSI_SHIFT, 0x00000000},
-               {AUD_RDSQ_SHIFT, 0x00000000},
-               {AUD_POLYPH80SCALEFAC, 0x00000003},
-               { /* end of list */ },
-       };
-
-       mode |= EN_FMRADIO_EN_RDS;
-
-       if (sap) {
-               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", __func__);
-               set_audio_start(core, SEL_BTSC);
-               set_audio_registers(core, btsc);
-               set_audio_finish(core, mode);
-       }
-}
-
-static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
-{
-       static const struct rlist nicam_l[] = {
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AUD_RATE_ADJ1, 0x00000060},
-               {AUD_RATE_ADJ2, 0x000000F9},
-               {AUD_RATE_ADJ3, 0x000001CC},
-               {AUD_RATE_ADJ4, 0x000002B3},
-               {AUD_RATE_ADJ5, 0x00000726},
-               {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
-               {AUD_DEEMPHDENOM2_R, 0x00000000},
-               {AUD_ERRLOGPERIOD_R, 0x00000064},
-               {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
-               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
-               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
-               {AUD_POLYPH80SCALEFAC, 0x00000003},
-               {AUD_DMD_RA_DDS, 0x00C00000},
-               {AUD_PLL_INT, 0x0000001E},
-               {AUD_PLL_DDS, 0x00000000},
-               {AUD_PLL_FRAC, 0x0000E542},
-               {AUD_START_TIMER, 0x00000000},
-               {AUD_DEEMPHNUMER1_R, 0x000353DE},
-               {AUD_DEEMPHNUMER2_R, 0x000001B1},
-               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
-               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
-               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
-               {AUD_QAM_MODE, 0x05},
-               {AUD_PHACC_FREQ_8MSB, 0x34},
-               {AUD_PHACC_FREQ_8LSB, 0x4C},
-               {AUD_DEEMPHGAIN_R, 0x00006680},
-               {AUD_RATE_THRES_DMD, 0x000000C0},
-               { /* end of list */ },
-       };
-
-       static const struct rlist nicam_bgdki_common[] = {
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AUD_RATE_ADJ1, 0x00000010},
-               {AUD_RATE_ADJ2, 0x00000040},
-               {AUD_RATE_ADJ3, 0x00000100},
-               {AUD_RATE_ADJ4, 0x00000400},
-               {AUD_RATE_ADJ5, 0x00001000},
-               {AUD_ERRLOGPERIOD_R, 0x00000fff},
-               {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
-               {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
-               {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
-               {AUD_POLYPH80SCALEFAC, 0x00000003},
-               {AUD_DEEMPHGAIN_R, 0x000023c2},
-               {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
-               {AUD_DEEMPHNUMER2_R, 0x0003023e},
-               {AUD_DEEMPHDENOM1_R, 0x0000f3d0},
-               {AUD_DEEMPHDENOM2_R, 0x00000000},
-               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
-               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
-               {AUD_QAM_MODE, 0x05},
-               { /* end of list */ },
-       };
-
-       static const struct rlist nicam_i[] = {
-               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
-               {AUD_PHACC_FREQ_8MSB, 0x3a},
-               {AUD_PHACC_FREQ_8LSB, 0x93},
-               { /* end of list */ },
-       };
-
-       static const struct rlist nicam_default[] = {
-               {AUD_PDF_DDS_CNST_BYTE0, 0x16},
-               {AUD_PHACC_FREQ_8MSB, 0x34},
-               {AUD_PHACC_FREQ_8LSB, 0x4c},
-               { /* end of list */ },
-       };
-
-       set_audio_start(core,SEL_NICAM);
-       switch (core->tvaudio) {
-       case WW_L:
-               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", __func__);
-               set_audio_registers(core, nicam_bgdki_common);
-               set_audio_registers(core, nicam_i);
-               break;
-       case WW_NONE:
-       case WW_BTSC:
-       case WW_BG:
-       case WW_DK:
-       case WW_EIAJ:
-       case WW_I2SPT:
-       case WW_FM:
-       case WW_I2SADC:
-       case WW_M:
-               dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
-               set_audio_registers(core, nicam_bgdki_common);
-               set_audio_registers(core, nicam_default);
-               break;
-       };
-
-       mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
-       set_audio_finish(core, mode);
-}
-
-static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
-{
-       static const struct rlist a2_bgdk_common[] = {
-               {AUD_ERRLOGPERIOD_R, 0x00000064},
-               {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
-               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
-               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
-               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
-               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
-               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
-               {AUD_QAM_MODE, 0x05},
-               {AUD_PHACC_FREQ_8MSB, 0x34},
-               {AUD_PHACC_FREQ_8LSB, 0x4c},
-               {AUD_RATE_ADJ1, 0x00000100},
-               {AUD_RATE_ADJ2, 0x00000200},
-               {AUD_RATE_ADJ3, 0x00000300},
-               {AUD_RATE_ADJ4, 0x00000400},
-               {AUD_RATE_ADJ5, 0x00000500},
-               {AUD_THR_FR, 0x00000000},
-               {AAGC_HYST, 0x0000001a},
-               {AUD_PILOT_BQD_1_K0, 0x0000755b},
-               {AUD_PILOT_BQD_1_K1, 0x00551340},
-               {AUD_PILOT_BQD_1_K2, 0x006d30be},
-               {AUD_PILOT_BQD_1_K3, 0xffd394af},
-               {AUD_PILOT_BQD_1_K4, 0x00400000},
-               {AUD_PILOT_BQD_2_K0, 0x00040000},
-               {AUD_PILOT_BQD_2_K1, 0x002a4841},
-               {AUD_PILOT_BQD_2_K2, 0x00400000},
-               {AUD_PILOT_BQD_2_K3, 0x00000000},
-               {AUD_PILOT_BQD_2_K4, 0x00000000},
-               {AUD_MODE_CHG_TIMER, 0x00000040},
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AUD_CORDIC_SHIFT_0, 0x00000007},
-               {AUD_CORDIC_SHIFT_1, 0x00000007},
-               {AUD_DEEMPH0_G0, 0x00000380},
-               {AUD_DEEMPH1_G0, 0x00000380},
-               {AUD_DCOC_0_SRC, 0x0000001a},
-               {AUD_DCOC0_SHIFT, 0x00000000},
-               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
-               {AUD_DCOC_PASS_IN, 0x00000003},
-               {AUD_IIR3_0_SEL, 0x00000021},
-               {AUD_DN2_AFC, 0x00000002},
-               {AUD_DCOC_1_SRC, 0x0000001b},
-               {AUD_DCOC1_SHIFT, 0x00000000},
-               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
-               {AUD_IIR3_1_SEL, 0x00000023},
-               {AUD_RDSI_SEL, 0x00000017},
-               {AUD_RDSI_SHIFT, 0x00000000},
-               {AUD_RDSQ_SEL, 0x00000017},
-               {AUD_RDSQ_SHIFT, 0x00000000},
-               {AUD_PLL_INT, 0x0000001e},
-               {AUD_PLL_DDS, 0x00000000},
-               {AUD_PLL_FRAC, 0x0000e542},
-               {AUD_POLYPH80SCALEFAC, 0x00000001},
-               {AUD_START_TIMER, 0x00000000},
-               { /* end of list */ },
-       };
-
-       static const struct rlist a2_bg[] = {
-               {AUD_DMD_RA_DDS, 0x002a4f2f},
-               {AUD_C1_UP_THR, 0x00007000},
-               {AUD_C1_LO_THR, 0x00005400},
-               {AUD_C2_UP_THR, 0x00005400},
-               {AUD_C2_LO_THR, 0x00003000},
-               { /* end of list */ },
-       };
-
-       static const struct rlist a2_dk[] = {
-               {AUD_DMD_RA_DDS, 0x002a4f2f},
-               {AUD_C1_UP_THR, 0x00007000},
-               {AUD_C1_LO_THR, 0x00005400},
-               {AUD_C2_UP_THR, 0x00005400},
-               {AUD_C2_LO_THR, 0x00003000},
-               {AUD_DN0_FREQ, 0x00003a1c},
-               {AUD_DN2_FREQ, 0x0000d2e0},
-               { /* end of list */ },
-       };
-
-       static const struct rlist a1_i[] = {
-               {AUD_ERRLOGPERIOD_R, 0x00000064},
-               {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
-               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
-               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
-               {AUD_PDF_DDS_CNST_BYTE2, 0x06},
-               {AUD_PDF_DDS_CNST_BYTE1, 0x82},
-               {AUD_PDF_DDS_CNST_BYTE0, 0x12},
-               {AUD_QAM_MODE, 0x05},
-               {AUD_PHACC_FREQ_8MSB, 0x3a},
-               {AUD_PHACC_FREQ_8LSB, 0x93},
-               {AUD_DMD_RA_DDS, 0x002a4f2f},
-               {AUD_PLL_INT, 0x0000001e},
-               {AUD_PLL_DDS, 0x00000004},
-               {AUD_PLL_FRAC, 0x0000e542},
-               {AUD_RATE_ADJ1, 0x00000100},
-               {AUD_RATE_ADJ2, 0x00000200},
-               {AUD_RATE_ADJ3, 0x00000300},
-               {AUD_RATE_ADJ4, 0x00000400},
-               {AUD_RATE_ADJ5, 0x00000500},
-               {AUD_THR_FR, 0x00000000},
-               {AUD_PILOT_BQD_1_K0, 0x0000755b},
-               {AUD_PILOT_BQD_1_K1, 0x00551340},
-               {AUD_PILOT_BQD_1_K2, 0x006d30be},
-               {AUD_PILOT_BQD_1_K3, 0xffd394af},
-               {AUD_PILOT_BQD_1_K4, 0x00400000},
-               {AUD_PILOT_BQD_2_K0, 0x00040000},
-               {AUD_PILOT_BQD_2_K1, 0x002a4841},
-               {AUD_PILOT_BQD_2_K2, 0x00400000},
-               {AUD_PILOT_BQD_2_K3, 0x00000000},
-               {AUD_PILOT_BQD_2_K4, 0x00000000},
-               {AUD_MODE_CHG_TIMER, 0x00000060},
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AAGC_HYST, 0x0000000a},
-               {AUD_CORDIC_SHIFT_0, 0x00000007},
-               {AUD_CORDIC_SHIFT_1, 0x00000007},
-               {AUD_C1_UP_THR, 0x00007000},
-               {AUD_C1_LO_THR, 0x00005400},
-               {AUD_C2_UP_THR, 0x00005400},
-               {AUD_C2_LO_THR, 0x00003000},
-               {AUD_DCOC_0_SRC, 0x0000001a},
-               {AUD_DCOC0_SHIFT, 0x00000000},
-               {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
-               {AUD_DCOC_PASS_IN, 0x00000003},
-               {AUD_IIR3_0_SEL, 0x00000021},
-               {AUD_DN2_AFC, 0x00000002},
-               {AUD_DCOC_1_SRC, 0x0000001b},
-               {AUD_DCOC1_SHIFT, 0x00000000},
-               {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
-               {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
-               {AUD_IIR3_1_SEL, 0x00000023},
-               {AUD_DN0_FREQ, 0x000035a3},
-               {AUD_DN2_FREQ, 0x000029c7},
-               {AUD_CRDC0_SRC_SEL, 0x00000511},
-               {AUD_IIR1_0_SEL, 0x00000001},
-               {AUD_IIR1_1_SEL, 0x00000000},
-               {AUD_IIR3_2_SEL, 0x00000003},
-               {AUD_IIR3_2_SHIFT, 0x00000000},
-               {AUD_IIR3_0_SEL, 0x00000002},
-               {AUD_IIR2_0_SEL, 0x00000021},
-               {AUD_IIR2_0_SHIFT, 0x00000002},
-               {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
-               {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
-               {AUD_POLYPH80SCALEFAC, 0x00000001},
-               {AUD_START_TIMER, 0x00000000},
-               { /* end of list */ },
-       };
-
-       static const struct rlist am_l[] = {
-               {AUD_ERRLOGPERIOD_R, 0x00000064},
-               {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
-               {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
-               {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
-               {AUD_PDF_DDS_CNST_BYTE2, 0x48},
-               {AUD_PDF_DDS_CNST_BYTE1, 0x3D},
-               {AUD_QAM_MODE, 0x00},
-               {AUD_PDF_DDS_CNST_BYTE0, 0xf5},
-               {AUD_PHACC_FREQ_8MSB, 0x3a},
-               {AUD_PHACC_FREQ_8LSB, 0x4a},
-               {AUD_DEEMPHGAIN_R, 0x00006680},
-               {AUD_DEEMPHNUMER1_R, 0x000353DE},
-               {AUD_DEEMPHNUMER2_R, 0x000001B1},
-               {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
-               {AUD_DEEMPHDENOM2_R, 0x00000000},
-               {AUD_FM_MODE_ENABLE, 0x00000007},
-               {AUD_POLYPH80SCALEFAC, 0x00000003},
-               {AUD_AFE_12DB_EN, 0x00000001},
-               {AAGC_GAIN, 0x00000000},
-               {AAGC_HYST, 0x00000018},
-               {AAGC_DEF, 0x00000020},
-               {AUD_DN0_FREQ, 0x00000000},
-               {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
-               {AUD_DCOC_0_SRC, 0x00000021},
-               {AUD_IIR1_0_SEL, 0x00000000},
-               {AUD_IIR1_0_SHIFT, 0x00000007},
-               {AUD_IIR1_1_SEL, 0x00000002},
-               {AUD_IIR1_1_SHIFT, 0x00000000},
-               {AUD_DCOC_1_SRC, 0x00000003},
-               {AUD_DCOC1_SHIFT, 0x00000000},
-               {AUD_DCOC_PASS_IN, 0x00000000},
-               {AUD_IIR1_2_SEL, 0x00000023},
-               {AUD_IIR1_2_SHIFT, 0x00000000},
-               {AUD_IIR1_3_SEL, 0x00000004},
-               {AUD_IIR1_3_SHIFT, 0x00000007},
-               {AUD_IIR1_4_SEL, 0x00000005},
-               {AUD_IIR1_4_SHIFT, 0x00000007},
-               {AUD_IIR3_0_SEL, 0x00000007},
-               {AUD_IIR3_0_SHIFT, 0x00000000},
-               {AUD_DEEMPH0_SRC_SEL, 0x00000011},
-               {AUD_DEEMPH0_SHIFT, 0x00000000},
-               {AUD_DEEMPH0_G0, 0x00007000},
-               {AUD_DEEMPH0_A0, 0x00000000},
-               {AUD_DEEMPH0_B0, 0x00000000},
-               {AUD_DEEMPH0_A1, 0x00000000},
-               {AUD_DEEMPH0_B1, 0x00000000},
-               {AUD_DEEMPH1_SRC_SEL, 0x00000011},
-               {AUD_DEEMPH1_SHIFT, 0x00000000},
-               {AUD_DEEMPH1_G0, 0x00007000},
-               {AUD_DEEMPH1_A0, 0x00000000},
-               {AUD_DEEMPH1_B0, 0x00000000},
-               {AUD_DEEMPH1_A1, 0x00000000},
-               {AUD_DEEMPH1_B1, 0x00000000},
-               {AUD_OUT0_SEL, 0x0000003F},
-               {AUD_OUT1_SEL, 0x0000003F},
-               {AUD_DMD_RA_DDS, 0x00F5C285},
-               {AUD_PLL_INT, 0x0000001E},
-               {AUD_PLL_DDS, 0x00000000},
-               {AUD_PLL_FRAC, 0x0000E542},
-               {AUD_RATE_ADJ1, 0x00000100},
-               {AUD_RATE_ADJ2, 0x00000200},
-               {AUD_RATE_ADJ3, 0x00000300},
-               {AUD_RATE_ADJ4, 0x00000400},
-               {AUD_RATE_ADJ5, 0x00000500},
-               {AUD_RATE_THRES_DMD, 0x000000C0},
-               { /* end of list */ },
-       };
-
-       static const struct rlist a2_deemph50[] = {
-               {AUD_DEEMPH0_G0, 0x00000380},
-               {AUD_DEEMPH1_G0, 0x00000380},
-               {AUD_DEEMPHGAIN_R, 0x000011e1},
-               {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
-               {AUD_DEEMPHNUMER2_R, 0x0003023c},
-               { /* end of list */ },
-       };
-
-       set_audio_start(core, SEL_A2);
-       switch (core->tvaudio) {
-       case WW_BG:
-               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", __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", __func__);
-               set_audio_registers(core, a1_i);
-               set_audio_registers(core, a2_deemph50);
-               break;
-       case WW_L:
-               dprintk("%s AM-L (status: devel)\n", __func__);
-               set_audio_registers(core, am_l);
-               break;
-       case WW_NONE:
-       case WW_BTSC:
-       case WW_EIAJ:
-       case WW_I2SPT:
-       case WW_FM:
-       case WW_I2SADC:
-       case WW_M:
-               dprintk("%s Warning: wrong value\n", __func__);
-               return;
-               break;
-       };
-
-       mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
-       set_audio_finish(core, mode);
-}
-
-static void set_audio_standard_EIAJ(struct cx88_core *core)
-{
-       static const struct rlist eiaj[] = {
-               /* TODO: eiaj register settings are not there yet ... */
-
-               { /* end of list */ },
-       };
-       dprintk("%s (status: unknown)\n", __func__);
-
-       set_audio_start(core, SEL_EIAJ);
-       set_audio_registers(core, eiaj);
-       set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
-}
-
-static void set_audio_standard_FM(struct cx88_core *core,
-                                 enum cx88_deemph_type deemph)
-{
-       static const struct rlist fm_deemph_50[] = {
-               {AUD_DEEMPH0_G0, 0x0C45},
-               {AUD_DEEMPH0_A0, 0x6262},
-               {AUD_DEEMPH0_B0, 0x1C29},
-               {AUD_DEEMPH0_A1, 0x3FC66},
-               {AUD_DEEMPH0_B1, 0x399A},
-
-               {AUD_DEEMPH1_G0, 0x0D80},
-               {AUD_DEEMPH1_A0, 0x6262},
-               {AUD_DEEMPH1_B0, 0x1C29},
-               {AUD_DEEMPH1_A1, 0x3FC66},
-               {AUD_DEEMPH1_B1, 0x399A},
-
-               {AUD_POLYPH80SCALEFAC, 0x0003},
-               { /* end of list */ },
-       };
-       static const struct rlist fm_deemph_75[] = {
-               {AUD_DEEMPH0_G0, 0x091B},
-               {AUD_DEEMPH0_A0, 0x6B68},
-               {AUD_DEEMPH0_B0, 0x11EC},
-               {AUD_DEEMPH0_A1, 0x3FC66},
-               {AUD_DEEMPH0_B1, 0x399A},
-
-               {AUD_DEEMPH1_G0, 0x0AA0},
-               {AUD_DEEMPH1_A0, 0x6B68},
-               {AUD_DEEMPH1_B0, 0x11EC},
-               {AUD_DEEMPH1_A1, 0x3FC66},
-               {AUD_DEEMPH1_B1, 0x399A},
-
-               {AUD_POLYPH80SCALEFAC, 0x0003},
-               { /* end of list */ },
-       };
-
-       /* It is enough to leave default values? */
-       /* No, it's not!  The deemphasis registers are reset to the 75us
-        * values by default.  Analyzing the spectrum of the decoded audio
-        * reveals that "no deemphasis" is the same as 75 us, while the 50 us
-        * setting results in less deemphasis.  */
-       static const struct rlist fm_no_deemph[] = {
-
-               {AUD_POLYPH80SCALEFAC, 0x0003},
-               { /* end of list */ },
-       };
-
-       dprintk("%s (status: unknown)\n", __func__);
-       set_audio_start(core, SEL_FMRADIO);
-
-       switch (deemph) {
-       default:
-       case FM_NO_DEEMPH:
-               set_audio_registers(core, fm_no_deemph);
-               break;
-
-       case FM_DEEMPH_50:
-               set_audio_registers(core, fm_deemph_50);
-               break;
-
-       case FM_DEEMPH_75:
-               set_audio_registers(core, fm_deemph_75);
-               break;
-       }
-
-       set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
-}
-
-/* ----------------------------------------------------------- */
-
-static int cx88_detect_nicam(struct cx88_core *core)
-{
-       int i, j = 0;
-
-       dprintk("start nicam autodetect.\n");
-
-       for (i = 0; i < 6; i++) {
-               /* if bit1=1 then nicam is detected */
-               j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
-
-               if (j == 1) {
-                       dprintk("nicam is detected.\n");
-                       return 1;
-               }
-
-               /* wait a little bit for next reading status */
-               msleep(10);
-       }
-
-       dprintk("nicam is not detected.\n");
-       return 0;
-}
-
-void cx88_set_tvaudio(struct cx88_core *core)
-{
-       switch (core->tvaudio) {
-       case WW_BTSC:
-               set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
-               break;
-       case WW_BG:
-       case WW_DK:
-       case WW_M:
-       case WW_I:
-       case WW_L:
-               /* prepare all dsp registers */
-               set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
-
-               /* set nicam mode - otherwise
-                  AUD_NICAM_STATUS2 contains wrong values */
-               set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
-               if (0 == cx88_detect_nicam(core)) {
-                       /* fall back to fm / am mono */
-                       set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
-                       core->audiomode_current = V4L2_TUNER_MODE_MONO;
-                       core->use_nicam = 0;
-               } else {
-                       core->use_nicam = 1;
-               }
-               break;
-       case WW_EIAJ:
-               set_audio_standard_EIAJ(core);
-               break;
-       case WW_FM:
-               set_audio_standard_FM(core, radio_deemphasis);
-               break;
-       case WW_I2SADC:
-               set_audio_start(core, 0x01);
-               /*
-                * Slave/Philips/Autobaud
-                * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
-                *      0= Sony, 1=Philips
-                */
-               cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
-               /* Switch to "I2S ADC mode" */
-               cx_write(AUD_I2SCNTL, 0x1);
-               set_audio_finish(core, EN_I2SIN_ENABLE);
-               break;
-       case WW_NONE:
-       case WW_I2SPT:
-               printk("%s/0: unknown tv audio mode [%d]\n",
-                      core->name, core->tvaudio);
-               break;
-       }
-       return;
-}
-
-void cx88_newstation(struct cx88_core *core)
-{
-       core->audiomode_manual = UNSET;
-       core->last_change = jiffies;
-}
-
-void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
-{
-       static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
-       static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
-       u32 reg, mode, pilot;
-
-       reg = cx_read(AUD_STATUS);
-       mode = reg & 0x03;
-       pilot = (reg >> 2) & 0x03;
-
-       if (core->astat != reg)
-               dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
-                       reg, m[mode], p[pilot],
-                       aud_ctl_names[cx_read(AUD_CTL) & 63]);
-       core->astat = reg;
-
-       t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
-           V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
-       t->rxsubchans = UNSET;
-       t->audmode = V4L2_TUNER_MODE_MONO;
-
-       switch (mode) {
-       case 0:
-               t->audmode = V4L2_TUNER_MODE_STEREO;
-               break;
-       case 1:
-               t->audmode = V4L2_TUNER_MODE_LANG2;
-               break;
-       case 2:
-               t->audmode = V4L2_TUNER_MODE_MONO;
-               break;
-       case 3:
-               t->audmode = V4L2_TUNER_MODE_SAP;
-               break;
-       }
-
-       switch (core->tvaudio) {
-       case WW_BTSC:
-       case WW_BG:
-       case WW_DK:
-       case WW_M:
-       case WW_EIAJ:
-               if (!core->use_nicam) {
-                       t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
-                       break;
-               }
-               break;
-       case WW_NONE:
-       case WW_I:
-       case WW_L:
-       case WW_I2SPT:
-       case WW_FM:
-       case WW_I2SADC:
-               /* nothing */
-               break;
-       }
-
-       /* If software stereo detection is not supported... */
-       if (UNSET == t->rxsubchans) {
-               t->rxsubchans = V4L2_TUNER_SUB_MONO;
-               /* If the hardware itself detected stereo, also return
-                  stereo as an available subchannel */
-               if (V4L2_TUNER_MODE_STEREO == t->audmode)
-                       t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
-       }
-       return;
-}
-
-void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
-{
-       u32 ctl = UNSET;
-       u32 mask = UNSET;
-
-       if (manual) {
-               core->audiomode_manual = mode;
-       } else {
-               if (UNSET != core->audiomode_manual)
-                       return;
-       }
-       core->audiomode_current = mode;
-
-       switch (core->tvaudio) {
-       case WW_BTSC:
-               switch (mode) {
-               case V4L2_TUNER_MODE_MONO:
-                       set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
-                       break;
-               case V4L2_TUNER_MODE_LANG1:
-                       set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
-                       break;
-               case V4L2_TUNER_MODE_LANG2:
-                       set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
-                       break;
-               case V4L2_TUNER_MODE_STEREO:
-               case V4L2_TUNER_MODE_LANG1_LANG2:
-                       set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
-                       break;
-               }
-               break;
-       case WW_BG:
-       case WW_DK:
-       case WW_M:
-       case WW_I:
-       case WW_L:
-               if (1 == core->use_nicam) {
-                       switch (mode) {
-                       case V4L2_TUNER_MODE_MONO:
-                       case V4L2_TUNER_MODE_LANG1:
-                               set_audio_standard_NICAM(core,
-                                                        EN_NICAM_FORCE_MONO1);
-                               break;
-                       case V4L2_TUNER_MODE_LANG2:
-                               set_audio_standard_NICAM(core,
-                                                        EN_NICAM_FORCE_MONO2);
-                               break;
-                       case V4L2_TUNER_MODE_STEREO:
-                       case V4L2_TUNER_MODE_LANG1_LANG2:
-                               set_audio_standard_NICAM(core,
-                                                        EN_NICAM_FORCE_STEREO);
-                               break;
-                       }
-               } else {
-                       if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
-                               /* fall back to fm / am mono */
-                               set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
-                       } else {
-                               /* TODO: Add A2 autodection */
-                               mask = 0x3f;
-                               switch (mode) {
-                               case V4L2_TUNER_MODE_MONO:
-                               case V4L2_TUNER_MODE_LANG1:
-                                       ctl = EN_A2_FORCE_MONO1;
-                                       break;
-                               case V4L2_TUNER_MODE_LANG2:
-                                       ctl = EN_A2_FORCE_MONO2;
-                                       break;
-                               case V4L2_TUNER_MODE_STEREO:
-                               case V4L2_TUNER_MODE_LANG1_LANG2:
-                                       ctl = EN_A2_FORCE_STEREO;
-                                       break;
-                               }
-                       }
-               }
-               break;
-       case WW_FM:
-               switch (mode) {
-               case V4L2_TUNER_MODE_MONO:
-                       ctl = EN_FMRADIO_FORCE_MONO;
-                       mask = 0x3f;
-                       break;
-               case V4L2_TUNER_MODE_STEREO:
-                       ctl = EN_FMRADIO_AUTO_STEREO;
-                       mask = 0x3f;
-                       break;
-               }
-               break;
-       case WW_I2SADC:
-       case WW_NONE:
-       case WW_EIAJ:
-       case WW_I2SPT:
-               /* DO NOTHING */
-               break;
-       }
-
-       if (UNSET != ctl) {
-               dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
-                       "[status=0x%x,ctl=0x%x,vol=0x%x]\n",
-                       mask, ctl, cx_read(AUD_STATUS),
-                       cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
-               cx_andor(AUD_CTL, mask, ctl);
-       }
-       return;
-}
-
-int cx88_audio_thread(void *data)
-{
-       struct cx88_core *core = data;
-       struct v4l2_tuner t;
-       u32 mode = 0;
-
-       dprintk("cx88: tvaudio thread started\n");
-       set_freezable();
-       for (;;) {
-               msleep_interruptible(1000);
-               if (kthread_should_stop())
-                       break;
-               try_to_freeze();
-
-               switch (core->tvaudio) {
-               case WW_BG:
-               case WW_DK:
-               case WW_M:
-               case WW_I:
-               case WW_L:
-                       if (core->use_nicam)
-                               goto hw_autodetect;
-
-                       /* just monitor the audio status for now ... */
-                       memset(&t, 0, sizeof(t));
-                       cx88_get_stereo(core, &t);
-
-                       if (UNSET != core->audiomode_manual)
-                               /* manually set, don't do anything. */
-                               continue;
-
-                       /* monitor signal and set stereo if available */
-                       if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
-                               mode = V4L2_TUNER_MODE_STEREO;
-                       else
-                               mode = V4L2_TUNER_MODE_MONO;
-                       if (mode == core->audiomode_current)
-                               continue;
-                       /* automatically switch to best available mode */
-                       cx88_set_stereo(core, mode, 0);
-                       break;
-               case WW_NONE:
-               case WW_BTSC:
-               case WW_EIAJ:
-               case WW_I2SPT:
-               case WW_FM:
-               case WW_I2SADC:
-hw_autodetect:
-                       /* stereo autodetection is supported by hardware so
-                          we don't need to do it manually. Do nothing. */
-                       break;
-               }
-       }
-
-       dprintk("cx88: tvaudio thread exiting\n");
-       return 0;
-}
-
-/* ----------------------------------------------------------- */
-
-EXPORT_SYMBOL(cx88_set_tvaudio);
-EXPORT_SYMBOL(cx88_newstation);
-EXPORT_SYMBOL(cx88_set_stereo);
-EXPORT_SYMBOL(cx88_get_stereo);
-EXPORT_SYMBOL(cx88_audio_thread);
-
-/*
- * 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
- */
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
deleted file mode 100644 (file)
index f8f8389..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "cx88.h"
-
-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;
-module_param(vbi_debug,int,0644);
-MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
-
-#define dprintk(level,fmt, arg...)     if (vbi_debug >= level) \
-       printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
-
-/* ------------------------------------------------------------------ */
-
-int cx8800_vbi_fmt (struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct cx8800_fh  *fh   = priv;
-       struct cx8800_dev *dev  = fh->dev;
-
-       f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
-       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset = 244;
-       f->fmt.vbi.count[0] = VBI_LINE_COUNT;
-       f->fmt.vbi.count[1] = VBI_LINE_COUNT;
-
-       if (dev->core->tvnorm & V4L2_STD_525_60) {
-               /* ntsc */
-               f->fmt.vbi.sampling_rate = 28636363;
-               f->fmt.vbi.start[0] = 10;
-               f->fmt.vbi.start[1] = 273;
-
-       } else if (dev->core->tvnorm & V4L2_STD_625_50) {
-               /* pal */
-               f->fmt.vbi.sampling_rate = 35468950;
-               f->fmt.vbi.start[0] = 7 -1;
-               f->fmt.vbi.start[1] = 319 -1;
-       }
-       return 0;
-}
-
-static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-                        struct cx88_dmaqueue *q,
-                        struct cx88_buffer   *buf)
-{
-       struct cx88_core *core = dev->core;
-
-       /* setup fifo + format */
-       cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
-                               buf->vb.width, buf->risc.dma);
-
-       cx_write(MO_VBOS_CONTROL, ( (1 << 18) |  // comb filter delay fixup
-                                   (1 << 15) |  // enable vbi capture
-                                   (1 << 11) ));
-
-       /* reset counter */
-       cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
-       q->count = 1;
-
-       /* enable irqs */
-       cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
-       cx_set(MO_VID_INTMSK, 0x0f0088);
-
-       /* enable capture */
-       cx_set(VID_CAPTURE_CONTROL,0x18);
-
-       /* start dma */
-       cx_set(MO_DEV_CNTRL2, (1<<5));
-       cx_set(MO_VID_DMACNTRL, 0x88);
-
-       return 0;
-}
-
-int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-
-       /* stop dma */
-       cx_clear(MO_VID_DMACNTRL, 0x88);
-
-       /* disable capture */
-       cx_clear(VID_CAPTURE_CONTROL,0x18);
-
-       /* disable irqs */
-       cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
-       cx_clear(MO_VID_INTMSK, 0x0f0088);
-       return 0;
-}
-
-int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
-                            struct cx88_dmaqueue *q)
-{
-       struct cx88_buffer *buf;
-
-       if (list_empty(&q->active))
-               return 0;
-
-       buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
-       dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-               buf, buf->vb.i);
-       cx8800_start_vbi_dma(dev, q, buf);
-       list_for_each_entry(buf, &q->active, vb.queue)
-               buf->count = q->count++;
-       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-       return 0;
-}
-
-void cx8800_vbi_timeout(unsigned long data)
-{
-       struct cx8800_dev *dev = (struct cx8800_dev*)data;
-       struct cx88_core *core = dev->core;
-       struct cx88_dmaqueue *q = &dev->vbiq;
-       struct cx88_buffer *buf;
-       unsigned long flags;
-
-       cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
-
-       cx_clear(MO_VID_DMACNTRL, 0x88);
-       cx_clear(VID_CAPTURE_CONTROL, 0x18);
-
-       spin_lock_irqsave(&dev->slock,flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
-                      buf, buf->vb.i, (unsigned long)buf->risc.dma);
-       }
-       cx8800_restart_vbi_queue(dev,q);
-       spin_unlock_irqrestore(&dev->slock,flags);
-}
-
-/* ------------------------------------------------------------------ */
-
-static int
-vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
-       if (0 == *count)
-               *count = vbibufs;
-       if (*count < 2)
-               *count = 2;
-       if (*count > 32)
-               *count = 32;
-       return 0;
-}
-
-static int
-vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-           enum v4l2_field field)
-{
-       struct cx8800_fh   *fh  = q->priv_data;
-       struct cx8800_dev  *dev = fh->dev;
-       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
-       unsigned int size;
-       int rc;
-
-       size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-               buf->vb.width  = VBI_LINE_LENGTH;
-               buf->vb.height = VBI_LINE_COUNT;
-               buf->vb.size   = size;
-               buf->vb.field  = V4L2_FIELD_SEQ_TB;
-
-               if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
-                       goto fail;
-               cx88_risc_buffer(dev->pci, &buf->risc,
-                                dma->sglist,
-                                0, buf->vb.width * buf->vb.height,
-                                buf->vb.width, 0,
-                                buf->vb.height);
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       cx88_free_buffer(q,buf);
-       return rc;
-}
-
-static void
-vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
-       struct cx88_buffer    *prev;
-       struct cx8800_fh      *fh   = vq->priv_data;
-       struct cx8800_dev     *dev  = fh->dev;
-       struct cx88_dmaqueue  *q    = &dev->vbiq;
-
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
-
-       if (list_empty(&q->active)) {
-               list_add_tail(&buf->vb.queue,&q->active);
-               cx8800_start_vbi_dma(dev, q, buf);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = q->count++;
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(2,"[%p/%d] vbi_queue - first active\n",
-                       buf, buf->vb.i);
-
-       } else {
-               prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
-               list_add_tail(&buf->vb.queue,&q->active);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = q->count++;
-               prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-               dprintk(2,"[%p/%d] buffer_queue - append to active\n",
-                       buf, buf->vb.i);
-       }
-}
-
-static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
-
-       cx88_free_buffer(q,buf);
-}
-
-const struct videobuf_queue_ops cx8800_vbi_qops = {
-       .buf_setup    = vbi_setup,
-       .buf_prepare  = vbi_prepare,
-       .buf_queue    = vbi_queue,
-       .buf_release  = vbi_release,
-};
-
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
deleted file mode 100644 (file)
index f6fcc7e..0000000
+++ /dev/null
@@ -1,2075 +0,0 @@
-/*
- *
- * device driver for Conexant 2388x based TV cards
- * video4linux video interface
- *
- * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
- *
- * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
- *     - Multituner support
- *     - video_ioctl2 conversion
- *     - PAL/M fixes
- *
- *  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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <asm/div64.h>
-
-#include "cx88.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-#include <media/wm8775.h>
-
-MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CX88_VERSION);
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[]   = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(vbi_nr,   int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-
-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;
-module_param(video_debug,int,0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
-
-static unsigned int irq_debug;
-module_param(irq_debug,int,0644);
-MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
-
-static unsigned int vid_limit = 16;
-module_param(vid_limit,int,0644);
-MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
-
-#define dprintk(level,fmt, arg...)     if (video_debug >= level) \
-       printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
-
-/* ------------------------------------------------------------------- */
-/* static data                                                         */
-
-static const struct cx8800_fmt formats[] = {
-       {
-               .name     = "8 bpp, gray",
-               .fourcc   = V4L2_PIX_FMT_GREY,
-               .cxformat = ColorFormatY8,
-               .depth    = 8,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "15 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB555,
-               .cxformat = ColorFormatRGB15,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "15 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB555X,
-               .cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "16 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB565,
-               .cxformat = ColorFormatRGB16,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "16 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB565X,
-               .cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "24 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR24,
-               .cxformat = ColorFormatRGB24,
-               .depth    = 24,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "32 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR32,
-               .cxformat = ColorFormatRGB32,
-               .depth    = 32,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "32 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB32,
-               .cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
-               .depth    = 32,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "4:2:2, packed, YUYV",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .cxformat = ColorFormatYUY2,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },{
-               .name     = "4:2:2, packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
-               .depth    = 16,
-               .flags    = FORMAT_FLAGS_PACKED,
-       },
-};
-
-static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(formats); i++)
-               if (formats[i].fourcc == fourcc)
-                       return formats+i;
-       return NULL;
-}
-
-/* ------------------------------------------------------------------- */
-
-struct cx88_ctrl {
-       /* control information */
-       u32 id;
-       s32 minimum;
-       s32 maximum;
-       u32 step;
-       s32 default_value;
-
-       /* control register information */
-       u32 off;
-       u32 reg;
-       u32 sreg;
-       u32 mask;
-       u32 shift;
-};
-
-static const struct cx88_ctrl cx8800_vid_ctls[] = {
-       /* --- video --- */
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .minimum       = 0x00,
-               .maximum       = 0xff,
-               .step          = 1,
-               .default_value = 0x7f,
-               .off           = 128,
-               .reg           = MO_CONTR_BRIGHT,
-               .mask          = 0x00ff,
-               .shift         = 0,
-       },{
-               .id            = V4L2_CID_CONTRAST,
-               .minimum       = 0,
-               .maximum       = 0xff,
-               .step          = 1,
-               .default_value = 0x3f,
-               .off           = 0,
-               .reg           = MO_CONTR_BRIGHT,
-               .mask          = 0xff00,
-               .shift         = 8,
-       },{
-               .id            = V4L2_CID_HUE,
-               .minimum       = 0,
-               .maximum       = 0xff,
-               .step          = 1,
-               .default_value = 0x7f,
-               .off           = 128,
-               .reg           = MO_HUE,
-               .mask          = 0x00ff,
-               .shift         = 0,
-       },{
-               /* strictly, this only describes only U saturation.
-                * V saturation is handled specially through code.
-                */
-               .id            = V4L2_CID_SATURATION,
-               .minimum       = 0,
-               .maximum       = 0xff,
-               .step          = 1,
-               .default_value = 0x7f,
-               .off           = 0,
-               .reg           = MO_UV_SATURATION,
-               .mask          = 0x00ff,
-               .shift         = 0,
-       }, {
-               .id            = V4L2_CID_SHARPNESS,
-               .minimum       = 0,
-               .maximum       = 4,
-               .step          = 1,
-               .default_value = 0x0,
-               .off           = 0,
-               /* NOTE: the value is converted and written to both even
-                  and odd registers in the code */
-               .reg           = MO_FILTER_ODD,
-               .mask          = 7 << 7,
-               .shift         = 7,
-       }, {
-               .id            = V4L2_CID_CHROMA_AGC,
-               .minimum       = 0,
-               .maximum       = 1,
-               .default_value = 0x1,
-               .reg           = MO_INPUT_FORMAT,
-               .mask          = 1 << 10,
-               .shift         = 10,
-       }, {
-               .id            = V4L2_CID_COLOR_KILLER,
-               .minimum       = 0,
-               .maximum       = 1,
-               .default_value = 0x1,
-               .reg           = MO_INPUT_FORMAT,
-               .mask          = 1 << 9,
-               .shift         = 9,
-       }, {
-               .id            = V4L2_CID_BAND_STOP_FILTER,
-               .minimum       = 0,
-               .maximum       = 1,
-               .step          = 1,
-               .default_value = 0x0,
-               .off           = 0,
-               .reg           = MO_HTOTAL,
-               .mask          = 3 << 11,
-               .shift         = 11,
-       }
-};
-
-static const struct cx88_ctrl cx8800_aud_ctls[] = {
-       {
-               /* --- audio --- */
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .minimum       = 0,
-               .maximum       = 1,
-               .default_value = 1,
-               .reg           = AUD_VOL_CTL,
-               .sreg          = SHADOW_AUD_VOL_CTL,
-               .mask          = (1 << 6),
-               .shift         = 6,
-       },{
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .minimum       = 0,
-               .maximum       = 0x3f,
-               .step          = 1,
-               .default_value = 0x3f,
-               .reg           = AUD_VOL_CTL,
-               .sreg          = SHADOW_AUD_VOL_CTL,
-               .mask          = 0x3f,
-               .shift         = 0,
-       },{
-               .id            = V4L2_CID_AUDIO_BALANCE,
-               .minimum       = 0,
-               .maximum       = 0x7f,
-               .step          = 1,
-               .default_value = 0x40,
-               .reg           = AUD_BAL_CTL,
-               .sreg          = SHADOW_AUD_BAL_CTL,
-               .mask          = 0x7f,
-               .shift         = 0,
-       }
-};
-
-enum {
-       CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls),
-       CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
-};
-
-/* ------------------------------------------------------------------- */
-/* resource management                                                 */
-
-static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
-{
-       struct cx88_core *core = dev->core;
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       /* is it free? */
-       mutex_lock(&core->lock);
-       if (dev->resources & bit) {
-               /* no, someone else uses it */
-               mutex_unlock(&core->lock);
-               return 0;
-       }
-       /* it's free, grab it */
-       fh->resources  |= bit;
-       dev->resources |= bit;
-       dprintk(1,"res: get %d\n",bit);
-       mutex_unlock(&core->lock);
-       return 1;
-}
-
-static
-int res_check(struct cx8800_fh *fh, unsigned int bit)
-{
-       return (fh->resources & bit);
-}
-
-static
-int res_locked(struct cx8800_dev *dev, unsigned int bit)
-{
-       return (dev->resources & bit);
-}
-
-static
-void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
-{
-       struct cx88_core *core = dev->core;
-       BUG_ON((fh->resources & bits) != bits);
-
-       mutex_lock(&core->lock);
-       fh->resources  &= ~bits;
-       dev->resources &= ~bits;
-       dprintk(1,"res: put %d\n",bits);
-       mutex_unlock(&core->lock);
-}
-
-/* ------------------------------------------------------------------ */
-
-int cx88_video_mux(struct cx88_core *core, unsigned int input)
-{
-       /* struct cx88_core *core = dev->core; */
-
-       dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
-               input, INPUT(input).vmux,
-               INPUT(input).gpio0,INPUT(input).gpio1,
-               INPUT(input).gpio2,INPUT(input).gpio3);
-       core->input = input;
-       cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
-       cx_write(MO_GP3_IO, INPUT(input).gpio3);
-       cx_write(MO_GP0_IO, INPUT(input).gpio0);
-       cx_write(MO_GP1_IO, INPUT(input).gpio1);
-       cx_write(MO_GP2_IO, INPUT(input).gpio2);
-
-       switch (INPUT(input).type) {
-       case CX88_VMUX_SVIDEO:
-               cx_set(MO_AFECFG_IO,    0x00000001);
-               cx_set(MO_INPUT_FORMAT, 0x00010010);
-               cx_set(MO_FILTER_EVEN,  0x00002020);
-               cx_set(MO_FILTER_ODD,   0x00002020);
-               break;
-       default:
-               cx_clear(MO_AFECFG_IO,    0x00000001);
-               cx_clear(MO_INPUT_FORMAT, 0x00010010);
-               cx_clear(MO_FILTER_EVEN,  0x00002020);
-               cx_clear(MO_FILTER_ODD,   0x00002020);
-               break;
-       }
-
-       /* if there are audioroutes defined, we have an external
-          ADC to deal with audio */
-       if (INPUT(input).audioroute) {
-               /* The wm8775 module has the "2" route hardwired into
-                  the initialization. Some boards may use different
-                  routes for different inputs. HVR-1300 surely does */
-               if (core->board.audio_chip &&
-                   core->board.audio_chip == V4L2_IDENT_WM8775) {
-                       call_all(core, audio, s_routing,
-                                INPUT(input).audioroute, 0, 0);
-               }
-               /* cx2388's C-ADC is connected to the tuner only.
-                  When used with S-Video, that ADC is busy dealing with
-                  chroma, so an external must be used for baseband audio */
-               if (INPUT(input).type != CX88_VMUX_TELEVISION &&
-                   INPUT(input).type != CX88_VMUX_CABLE) {
-                       /* "I2S ADC mode" */
-                       core->tvaudio = WW_I2SADC;
-                       cx88_set_tvaudio(core);
-               } else {
-                       /* Normal mode */
-                       cx_write(AUD_I2SCNTL, 0x0);
-                       cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
-               }
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(cx88_video_mux);
-
-/* ------------------------------------------------------------------ */
-
-static int start_video_dma(struct cx8800_dev    *dev,
-                          struct cx88_dmaqueue *q,
-                          struct cx88_buffer   *buf)
-{
-       struct cx88_core *core = dev->core;
-
-       /* setup fifo + format */
-       cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
-                               buf->bpl, buf->risc.dma);
-       cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
-       cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
-
-       /* reset counter */
-       cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
-       q->count = 1;
-
-       /* enable irqs */
-       cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
-
-       /* Enables corresponding bits at PCI_INT_STAT:
-               bits 0 to 4: video, audio, transport stream, VIP, Host
-               bit 7: timer
-               bits 8 and 9: DMA complete for: SRC, DST
-               bits 10 and 11: BERR signal asserted for RISC: RD, WR
-               bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
-        */
-       cx_set(MO_VID_INTMSK, 0x0f0011);
-
-       /* enable capture */
-       cx_set(VID_CAPTURE_CONTROL,0x06);
-
-       /* start dma */
-       cx_set(MO_DEV_CNTRL2, (1<<5));
-       cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int stop_video_dma(struct cx8800_dev    *dev)
-{
-       struct cx88_core *core = dev->core;
-
-       /* stop dma */
-       cx_clear(MO_VID_DMACNTRL, 0x11);
-
-       /* disable capture */
-       cx_clear(VID_CAPTURE_CONTROL,0x06);
-
-       /* disable irqs */
-       cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
-       cx_clear(MO_VID_INTMSK, 0x0f0011);
-       return 0;
-}
-#endif
-
-static int restart_video_queue(struct cx8800_dev    *dev,
-                              struct cx88_dmaqueue *q)
-{
-       struct cx88_core *core = dev->core;
-       struct cx88_buffer *buf, *prev;
-
-       if (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
-               dprintk(2,"restart_queue [%p/%d]: restart dma\n",
-                       buf, buf->vb.i);
-               start_video_dma(dev, q, buf);
-               list_for_each_entry(buf, &q->active, vb.queue)
-                       buf->count = q->count++;
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-               return 0;
-       }
-
-       prev = NULL;
-       for (;;) {
-               if (list_empty(&q->queued))
-                       return 0;
-               buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
-               if (NULL == prev) {
-                       list_move_tail(&buf->vb.queue, &q->active);
-                       start_video_dma(dev, q, buf);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count    = q->count++;
-                       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-                       dprintk(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_move_tail(&buf->vb.queue, &q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count    = q->count++;
-                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                       dprintk(2,"[%p/%d] restart_queue - move to active\n",
-                               buf,buf->vb.i);
-               } else {
-                       return 0;
-               }
-               prev = buf;
-       }
-}
-
-/* ------------------------------------------------------------------ */
-
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       struct cx8800_fh *fh = q->priv_data;
-       struct cx8800_dev  *dev = fh->dev;
-
-       *size = dev->fmt->depth * dev->width * dev->height >> 3;
-       if (0 == *count)
-               *count = 32;
-       if (*size * *count > vid_limit * 1024 * 1024)
-               *count = (vid_limit * 1024 * 1024) / *size;
-       return 0;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-              enum v4l2_field field)
-{
-       struct cx8800_fh   *fh  = q->priv_data;
-       struct cx8800_dev  *dev = fh->dev;
-       struct cx88_core *core = dev->core;
-       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-       int rc, init_buffer = 0;
-
-       BUG_ON(NULL == dev->fmt);
-       if (dev->width  < 48 || dev->width  > norm_maxw(core->tvnorm) ||
-           dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
-               return -EINVAL;
-       buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       if (buf->fmt       != dev->fmt    ||
-           buf->vb.width  != dev->width  ||
-           buf->vb.height != dev->height ||
-           buf->vb.field  != field) {
-               buf->fmt       = dev->fmt;
-               buf->vb.width  = dev->width;
-               buf->vb.height = dev->height;
-               buf->vb.field  = field;
-               init_buffer = 1;
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               init_buffer = 1;
-               if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
-                       goto fail;
-       }
-
-       if (init_buffer) {
-               buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
-               switch (buf->vb.field) {
-               case V4L2_FIELD_TOP:
-                       cx88_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist, 0, UNSET,
-                                        buf->bpl, 0, buf->vb.height);
-                       break;
-               case V4L2_FIELD_BOTTOM:
-                       cx88_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist, UNSET, 0,
-                                        buf->bpl, 0, buf->vb.height);
-                       break;
-               case V4L2_FIELD_INTERLACED:
-                       cx88_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist, 0, buf->bpl,
-                                        buf->bpl, buf->bpl,
-                                        buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_TB:
-                       cx88_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist,
-                                        0, buf->bpl * (buf->vb.height >> 1),
-                                        buf->bpl, 0,
-                                        buf->vb.height >> 1);
-                       break;
-               case V4L2_FIELD_SEQ_BT:
-                       cx88_risc_buffer(dev->pci, &buf->risc,
-                                        dma->sglist,
-                                        buf->bpl * (buf->vb.height >> 1), 0,
-                                        buf->bpl, 0,
-                                        buf->vb.height >> 1);
-                       break;
-               default:
-                       BUG();
-               }
-       }
-       dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
-               buf, buf->vb.i,
-               dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
-               (unsigned long)buf->risc.dma);
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
- fail:
-       cx88_free_buffer(q,buf);
-       return rc;
-}
-
-static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
-       struct cx88_buffer    *prev;
-       struct cx8800_fh      *fh   = vq->priv_data;
-       struct cx8800_dev     *dev  = fh->dev;
-       struct cx88_core      *core = dev->core;
-       struct cx88_dmaqueue  *q    = &dev->vidq;
-
-       /* add jump to stopper */
-       buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
-       buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
-
-       if (!list_empty(&q->queued)) {
-               list_add_tail(&buf->vb.queue,&q->queued);
-               buf->vb.state = VIDEOBUF_QUEUED;
-               dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
-                       buf, buf->vb.i);
-
-       } else if (list_empty(&q->active)) {
-               list_add_tail(&buf->vb.queue,&q->active);
-               start_video_dma(dev, q, buf);
-               buf->vb.state = VIDEOBUF_ACTIVE;
-               buf->count    = q->count++;
-               mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
-               dprintk(2,"[%p/%d] buffer_queue - first active\n",
-                       buf, buf->vb.i);
-
-       } else {
-               prev = list_entry(q->active.prev, struct cx88_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,&q->active);
-                       buf->vb.state = VIDEOBUF_ACTIVE;
-                       buf->count    = q->count++;
-                       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-                       dprintk(2,"[%p/%d] buffer_queue - append to active\n",
-                               buf, buf->vb.i);
-
-               } else {
-                       list_add_tail(&buf->vb.queue,&q->queued);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-                       dprintk(2,"[%p/%d] buffer_queue - first queued\n",
-                               buf, buf->vb.i);
-               }
-       }
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
-
-       cx88_free_buffer(q,buf);
-}
-
-static const struct videobuf_queue_ops cx8800_video_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-
-/* ------------------------------------------------------------------ */
-
-static struct videobuf_queue *get_queue(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8800_fh *fh = file->private_data;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               return &fh->vidq;
-       case VFL_TYPE_VBI:
-               return &fh->vbiq;
-       default:
-               BUG();
-               return NULL;
-       }
-}
-
-static int get_resource(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               return RESOURCE_VIDEO;
-       case VFL_TYPE_VBI:
-               return RESOURCE_VBI;
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static int video_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8800_dev *dev = video_drvdata(file);
-       struct cx88_core *core = dev->core;
-       struct cx8800_fh *fh;
-       enum v4l2_buf_type type = 0;
-       int radio = 0;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       dprintk(1, "open dev=%s radio=%d type=%s\n",
-               video_device_node_name(vdev), radio, v4l2_type_names[type]);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (unlikely(!fh))
-               return -ENOMEM;
-
-       v4l2_fh_init(&fh->fh, vdev);
-       file->private_data = fh;
-       fh->dev      = dev;
-
-       mutex_lock(&core->lock);
-
-       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, NULL);
-       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),
-                           fh, NULL);
-
-       if (vdev->vfl_type == VFL_TYPE_RADIO) {
-               dprintk(1,"video_open: setting radio device\n");
-               cx_write(MO_GP3_IO, core->board.radio.gpio3);
-               cx_write(MO_GP0_IO, core->board.radio.gpio0);
-               cx_write(MO_GP1_IO, core->board.radio.gpio1);
-               cx_write(MO_GP2_IO, core->board.radio.gpio2);
-               if (core->board.radio.audioroute) {
-                       if(core->board.audio_chip &&
-                               core->board.audio_chip == V4L2_IDENT_WM8775) {
-                               call_all(core, audio, s_routing,
-                                       core->board.radio.audioroute, 0, 0);
-                       }
-                       /* "I2S ADC mode" */
-                       core->tvaudio = WW_I2SADC;
-                       cx88_set_tvaudio(core);
-               } else {
-                       /* FM Mode */
-                       core->tvaudio = WW_FM;
-                       cx88_set_tvaudio(core);
-                       cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
-               }
-               call_all(core, tuner, s_radio);
-       }
-
-       core->users++;
-       mutex_unlock(&core->lock);
-       v4l2_fh_add(&fh->fh);
-
-       return 0;
-}
-
-static ssize_t
-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8800_fh *fh = file->private_data;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               if (res_locked(fh->dev,RESOURCE_VIDEO))
-                       return -EBUSY;
-               return videobuf_read_one(&fh->vidq, data, count, ppos,
-                                        file->f_flags & O_NONBLOCK);
-       case VFL_TYPE_VBI:
-               if (!res_get(fh->dev,fh,RESOURCE_VBI))
-                       return -EBUSY;
-               return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
-                                           file->f_flags & O_NONBLOCK);
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static unsigned int
-video_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8800_fh *fh = file->private_data;
-       struct cx88_buffer *buf;
-       unsigned int rc = v4l2_ctrl_poll(file, wait);
-
-       if (vdev->vfl_type == VFL_TYPE_VBI) {
-               if (!res_get(fh->dev,fh,RESOURCE_VBI))
-                       return rc | POLLERR;
-               return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
-       }
-       mutex_lock(&fh->vidq.vb_lock);
-       if (res_check(fh,RESOURCE_VIDEO)) {
-               /* streaming capture */
-               if (list_empty(&fh->vidq.stream))
-                       goto done;
-               buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
-       } else {
-               /* read() capture */
-               buf = (struct cx88_buffer*)fh->vidq.read_buf;
-               if (NULL == buf)
-                       goto done;
-       }
-       poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == VIDEOBUF_DONE ||
-           buf->vb.state == VIDEOBUF_ERROR)
-               rc |= POLLIN|POLLRDNORM;
-done:
-       mutex_unlock(&fh->vidq.vb_lock);
-       return rc;
-}
-
-static int video_release(struct file *file)
-{
-       struct cx8800_fh  *fh  = file->private_data;
-       struct cx8800_dev *dev = fh->dev;
-
-       /* turn off overlay */
-       if (res_check(fh, RESOURCE_OVERLAY)) {
-               /* FIXME */
-               res_free(dev,fh,RESOURCE_OVERLAY);
-       }
-
-       /* stop video capture */
-       if (res_check(fh, RESOURCE_VIDEO)) {
-               videobuf_queue_cancel(&fh->vidq);
-               res_free(dev,fh,RESOURCE_VIDEO);
-       }
-       if (fh->vidq.read_buf) {
-               buffer_release(&fh->vidq,fh->vidq.read_buf);
-               kfree(fh->vidq.read_buf);
-       }
-
-       /* stop vbi capture */
-       if (res_check(fh, RESOURCE_VBI)) {
-               videobuf_stop(&fh->vbiq);
-               res_free(dev,fh,RESOURCE_VBI);
-       }
-
-       videobuf_mmap_free(&fh->vidq);
-       videobuf_mmap_free(&fh->vbiq);
-
-       mutex_lock(&dev->core->lock);
-       v4l2_fh_del(&fh->fh);
-       v4l2_fh_exit(&fh->fh);
-       file->private_data = NULL;
-       kfree(fh);
-
-       dev->core->users--;
-       if (!dev->core->users)
-               call_all(dev->core, core, s_power, 0);
-       mutex_unlock(&dev->core->lock);
-
-       return 0;
-}
-
-static int
-video_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       return videobuf_mmap_mapper(get_queue(file), vma);
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO CTRL IOCTLS                                                  */
-
-static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct cx88_core *core =
-               container_of(ctrl->handler, struct cx88_core, video_hdl);
-       const struct cx88_ctrl *cc = ctrl->priv;
-       u32 value, mask;
-
-       mask = cc->mask;
-       switch (ctrl->id) {
-       case V4L2_CID_SATURATION:
-               /* special v_sat handling */
-
-               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
-
-               if (core->tvnorm & V4L2_STD_SECAM) {
-                       /* For SECAM, both U and V sat should be equal */
-                       value = value << 8 | value;
-               } else {
-                       /* Keeps U Saturation proportional to V Sat */
-                       value = (value * 0x5a) / 0x7f << 8 | value;
-               }
-               mask = 0xffff;
-               break;
-       case V4L2_CID_SHARPNESS:
-               /* 0b000, 0b100, 0b101, 0b110, or 0b111 */
-               value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
-               /* needs to be set for both fields */
-               cx_andor(MO_FILTER_EVEN, mask, value);
-               break;
-       case V4L2_CID_CHROMA_AGC:
-               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
-               break;
-       default:
-               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
-               break;
-       }
-       dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
-                               ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
-                               mask, cc->sreg ? " [shadowed]" : "");
-       if (cc->sreg)
-               cx_sandor(cc->sreg, cc->reg, mask, value);
-       else
-               cx_andor(cc->reg, mask, value);
-       return 0;
-}
-
-static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct cx88_core *core =
-               container_of(ctrl->handler, struct cx88_core, audio_hdl);
-       const struct cx88_ctrl *cc = ctrl->priv;
-       u32 value,mask;
-
-       /* Pass changes onto any WM8775 */
-       if (core->board.audio_chip == V4L2_IDENT_WM8775) {
-               switch (ctrl->id) {
-               case V4L2_CID_AUDIO_MUTE:
-                       wm8775_s_ctrl(core, ctrl->id, ctrl->val);
-                       break;
-               case V4L2_CID_AUDIO_VOLUME:
-                       wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ?
-                                               (0x90 + ctrl->val) << 8 : 0);
-                       break;
-               case V4L2_CID_AUDIO_BALANCE:
-                       wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       mask = cc->mask;
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_BALANCE:
-               value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40);
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               value = 0x3f - (ctrl->val & 0x3f);
-               break;
-       default:
-               value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
-               break;
-       }
-       dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
-                               ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
-                               mask, cc->sreg ? " [shadowed]" : "");
-       if (cc->sreg)
-               cx_sandor(cc->sreg, cc->reg, mask, value);
-       else
-               cx_andor(cc->reg, mask, value);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-/* VIDEO IOCTLS                                                       */
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct cx8800_fh  *fh   = priv;
-       struct cx8800_dev *dev = fh->dev;
-
-       f->fmt.pix.width        = dev->width;
-       f->fmt.pix.height       = dev->height;
-       f->fmt.pix.field        = fh->vidq.field;
-       f->fmt.pix.pixelformat  = dev->fmt->fourcc;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * dev->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-       const struct cx8800_fmt *fmt;
-       enum v4l2_field   field;
-       unsigned int      maxw, maxh;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-       maxw  = norm_maxw(core->tvnorm);
-       maxh  = norm_maxh(core->tvnorm);
-
-       if (V4L2_FIELD_ANY == field) {
-               field = (f->fmt.pix.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_BOTTOM;
-       }
-
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       f->fmt.pix.field = field;
-       v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
-                             &f->fmt.pix.height, 32, maxh, 0, 0);
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct cx8800_fh  *fh   = priv;
-       struct cx8800_dev *dev = fh->dev;
-       int err = vidioc_try_fmt_vid_cap (file,priv,f);
-
-       if (0 != err)
-               return err;
-       dev->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
-       dev->width      = f->fmt.pix.width;
-       dev->height     = f->fmt.pix.height;
-       fh->vidq.field = f->fmt.pix.field;
-       return 0;
-}
-
-void cx88_querycap(struct file *file, struct cx88_core *core,
-               struct v4l2_capability *cap)
-{
-       struct video_device *vdev = video_devdata(file);
-
-       strlcpy(cap->card, core->board.name, sizeof(cap->card));
-       cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-       if (UNSET != core->board.tuner_type)
-               cap->device_caps |= V4L2_CAP_TUNER;
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_RADIO:
-               cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
-               break;
-       case VFL_TYPE_GRABBER:
-               cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
-               break;
-       }
-       cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;
-       if (core->board.radio.type == CX88_RADIO)
-               cap->capabilities |= V4L2_CAP_RADIO;
-}
-EXPORT_SYMBOL(cx88_querycap);
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
-       struct cx88_core  *core = dev->core;
-
-       strcpy(cap->driver, "cx8800");
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cx88_querycap(file, core, cap);
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(formats)))
-               return -EINVAL;
-
-       strlcpy(f->description,formats[f->index].name,sizeof(f->description));
-       f->pixelformat = formats[f->index].fourcc;
-
-       return 0;
-}
-
-static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
-{
-       return videobuf_reqbufs(get_queue(file), p);
-}
-
-static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       return videobuf_querybuf(get_queue(file), p);
-}
-
-static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       return videobuf_qbuf(get_queue(file), p);
-}
-
-static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       return videobuf_dqbuf(get_queue(file), p,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8800_fh  *fh   = priv;
-       struct cx8800_dev *dev  = fh->dev;
-
-       if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
-           (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       if (unlikely(!res_get(dev, fh, get_resource(file))))
-               return -EBUSY;
-       return videobuf_streamon(get_queue(file));
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct cx8800_fh  *fh   = priv;
-       struct cx8800_dev *dev  = fh->dev;
-       int               err, res;
-
-       if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
-           (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
-               return -EINVAL;
-
-       res = get_resource(file);
-       err = videobuf_streamoff(get_queue(file));
-       if (err < 0)
-               return err;
-       res_free(dev,fh,res);
-       return 0;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
-{
-       struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       *tvnorm = core->tvnorm;
-       return 0;
-}
-
-static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       mutex_lock(&core->lock);
-       cx88_set_tvnorm(core,*tvnorms);
-       mutex_unlock(&core->lock);
-
-       return 0;
-}
-
-/* only one input in this sample driver */
-int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i)
-{
-       static const char * const iname[] = {
-               [ CX88_VMUX_COMPOSITE1 ] = "Composite1",
-               [ CX88_VMUX_COMPOSITE2 ] = "Composite2",
-               [ CX88_VMUX_COMPOSITE3 ] = "Composite3",
-               [ CX88_VMUX_COMPOSITE4 ] = "Composite4",
-               [ CX88_VMUX_SVIDEO     ] = "S-Video",
-               [ CX88_VMUX_TELEVISION ] = "Television",
-               [ CX88_VMUX_CABLE      ] = "Cable TV",
-               [ CX88_VMUX_DVB        ] = "DVB",
-               [ CX88_VMUX_DEBUG      ] = "for debug only",
-       };
-       unsigned int n = i->index;
-
-       if (n >= 4)
-               return -EINVAL;
-       if (0 == INPUT(n).type)
-               return -EINVAL;
-       i->type  = V4L2_INPUT_TYPE_CAMERA;
-       strcpy(i->name,iname[INPUT(n).type]);
-       if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
-           (CX88_VMUX_CABLE      == INPUT(n).type)) {
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       }
-       i->std = CX88_NORMS;
-       return 0;
-}
-EXPORT_SYMBOL(cx88_enum_input);
-
-static int vidioc_enum_input (struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-       return cx88_enum_input (core,i);
-}
-
-static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       *i = core->input;
-       return 0;
-}
-
-static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       if (i >= 4)
-               return -EINVAL;
-       if (0 == INPUT(i).type)
-               return -EINVAL;
-
-       mutex_lock(&core->lock);
-       cx88_newstation(core);
-       cx88_video_mux(core,i);
-       mutex_unlock(&core->lock);
-       return 0;
-}
-
-static int vidioc_g_tuner (struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-       u32 reg;
-
-       if (unlikely(UNSET == core->board.tuner_type))
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Television");
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->rangehigh  = 0xffffffffUL;
-       call_all(core, tuner, g_tuner, t);
-
-       cx88_get_stereo(core ,t);
-       reg = cx_read(MO_DEVICE_STATUS);
-       t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
-       return 0;
-}
-
-static int vidioc_s_tuner (struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       if (UNSET == core->board.tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       cx88_set_stereo(core, t->audmode, 1);
-       return 0;
-}
-
-static int vidioc_g_frequency (struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct cx8800_fh  *fh   = priv;
-       struct cx88_core  *core = fh->dev->core;
-
-       if (unlikely(UNSET == core->board.tuner_type))
-               return -EINVAL;
-       if (f->tuner)
-               return -EINVAL;
-
-       f->frequency = core->freq;
-
-       call_all(core, tuner, g_frequency, f);
-
-       return 0;
-}
-
-int cx88_set_freq (struct cx88_core  *core,
-                               struct v4l2_frequency *f)
-{
-       if (unlikely(UNSET == core->board.tuner_type))
-               return -EINVAL;
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-
-       mutex_lock(&core->lock);
-       cx88_newstation(core);
-       call_all(core, tuner, s_frequency, f);
-       call_all(core, tuner, g_frequency, f);
-       core->freq = f->frequency;
-
-       /* When changing channels it is required to reset TVAUDIO */
-       msleep (10);
-       cx88_set_tvaudio(core);
-
-       mutex_unlock(&core->lock);
-
-       return 0;
-}
-EXPORT_SYMBOL(cx88_set_freq);
-
-static int vidioc_s_frequency (struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct cx8800_fh  *fh   = priv;
-       struct cx88_core  *core = fh->dev->core;
-
-       return cx88_set_freq(core, f);
-}
-
-static int vidioc_g_chip_ident(struct file *file, void *priv,
-                               struct v4l2_dbg_chip_ident *chip)
-{
-       if (!v4l2_chip_match_host(&chip->match))
-               return -EINVAL;
-       chip->revision = 0;
-       chip->ident = V4L2_IDENT_UNKNOWN;
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register (struct file *file, void *fh,
-                               struct v4l2_dbg_register *reg)
-{
-       struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-       /* cx2388x has a 24-bit register space */
-       reg->val = cx_read(reg->reg & 0xffffff);
-       reg->size = 4;
-       return 0;
-}
-
-static int vidioc_s_register (struct file *file, void *fh,
-                               struct v4l2_dbg_register *reg)
-{
-       struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-       cx_write(reg->reg & 0xffffff, reg->val);
-       return 0;
-}
-#endif
-
-/* ----------------------------------------------------------- */
-/* RADIO ESPECIFIC IOCTLS                                      */
-/* ----------------------------------------------------------- */
-
-static int radio_g_tuner (struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       if (unlikely(t->index > 0))
-               return -EINVAL;
-
-       strcpy(t->name, "Radio");
-
-       call_all(core, tuner, g_tuner, t);
-       return 0;
-}
-
-/* FIXME: Should add a standard for radio */
-
-static int radio_s_tuner (struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
-
-       if (0 != t->index)
-               return -EINVAL;
-       if (t->audmode > V4L2_TUNER_MODE_STEREO)
-               t->audmode = V4L2_TUNER_MODE_STEREO;
-
-       call_all(core, tuner, s_tuner, t);
-
-       return 0;
-}
-
-/* ----------------------------------------------------------- */
-
-static void cx8800_vid_timeout(unsigned long data)
-{
-       struct cx8800_dev *dev = (struct cx8800_dev*)data;
-       struct cx88_core *core = dev->core;
-       struct cx88_dmaqueue *q = &dev->vidq;
-       struct cx88_buffer *buf;
-       unsigned long flags;
-
-       cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
-
-       cx_clear(MO_VID_DMACNTRL, 0x11);
-       cx_clear(VID_CAPTURE_CONTROL, 0x06);
-
-       spin_lock_irqsave(&dev->slock,flags);
-       while (!list_empty(&q->active)) {
-               buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
-               list_del(&buf->vb.queue);
-               buf->vb.state = VIDEOBUF_ERROR;
-               wake_up(&buf->vb.done);
-               printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
-                      buf, buf->vb.i, (unsigned long)buf->risc.dma);
-       }
-       restart_video_queue(dev,q);
-       spin_unlock_irqrestore(&dev->slock,flags);
-}
-
-static const char *cx88_vid_irqs[32] = {
-       "y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
-       "y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
-       "y_oflow",  "u_oflow",  "v_oflow",  "vbi_oflow",
-       "y_sync",   "u_sync",   "v_sync",   "vbi_sync",
-       "opc_err",  "par_err",  "rip_err",  "pci_abort",
-};
-
-static void cx8800_vid_irq(struct cx8800_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       u32 status, mask, count;
-
-       status = cx_read(MO_VID_INTSTAT);
-       mask   = cx_read(MO_VID_INTMSK);
-       if (0 == (status & mask))
-               return;
-       cx_write(MO_VID_INTSTAT, status);
-       if (irq_debug  ||  (status & mask & ~0xff))
-               cx88_print_irqbits(core->name, "irq vid",
-                                  cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
-                                  status, mask);
-
-       /* risc op code error */
-       if (status & (1 << 16)) {
-               printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
-               cx_clear(MO_VID_DMACNTRL, 0x11);
-               cx_clear(VID_CAPTURE_CONTROL, 0x06);
-               cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
-       }
-
-       /* risc1 y */
-       if (status & 0x01) {
-               spin_lock(&dev->slock);
-               count = cx_read(MO_VIDY_GPCNT);
-               cx88_wakeup(core, &dev->vidq, count);
-               spin_unlock(&dev->slock);
-       }
-
-       /* risc1 vbi */
-       if (status & 0x08) {
-               spin_lock(&dev->slock);
-               count = cx_read(MO_VBI_GPCNT);
-               cx88_wakeup(core, &dev->vbiq, count);
-               spin_unlock(&dev->slock);
-       }
-
-       /* risc2 y */
-       if (status & 0x10) {
-               dprintk(2,"stopper video\n");
-               spin_lock(&dev->slock);
-               restart_video_queue(dev,&dev->vidq);
-               spin_unlock(&dev->slock);
-       }
-
-       /* risc2 vbi */
-       if (status & 0x80) {
-               dprintk(2,"stopper vbi\n");
-               spin_lock(&dev->slock);
-               cx8800_restart_vbi_queue(dev,&dev->vbiq);
-               spin_unlock(&dev->slock);
-       }
-}
-
-static irqreturn_t cx8800_irq(int irq, void *dev_id)
-{
-       struct cx8800_dev *dev = dev_id;
-       struct cx88_core *core = dev->core;
-       u32 status;
-       int loop, handled = 0;
-
-       for (loop = 0; loop < 10; loop++) {
-               status = cx_read(MO_PCI_INTSTAT) &
-                       (core->pci_irqmask | PCI_INT_VIDINT);
-               if (0 == status)
-                       goto out;
-               cx_write(MO_PCI_INTSTAT, status);
-               handled = 1;
-
-               if (status & core->pci_irqmask)
-                       cx88_core_irq(core,status);
-               if (status & PCI_INT_VIDINT)
-                       cx8800_vid_irq(dev);
-       };
-       if (10 == loop) {
-               printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
-                      core->name);
-               cx_write(MO_PCI_INTMSK,0);
-       }
-
- out:
-       return IRQ_RETVAL(handled);
-}
-
-/* ----------------------------------------------------------- */
-/* exported stuff                                              */
-
-static const struct v4l2_file_operations video_fops =
-{
-       .owner         = THIS_MODULE,
-       .open          = video_open,
-       .release       = video_release,
-       .read          = video_read,
-       .poll          = video_poll,
-       .mmap          = video_mmap,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-       .vidioc_reqbufs       = vidioc_reqbufs,
-       .vidioc_querybuf      = vidioc_querybuf,
-       .vidioc_qbuf          = vidioc_qbuf,
-       .vidioc_dqbuf         = vidioc_dqbuf,
-       .vidioc_g_std         = vidioc_g_std,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_streamon      = vidioc_streamon,
-       .vidioc_streamoff     = vidioc_streamoff,
-       .vidioc_g_tuner       = vidioc_g_tuner,
-       .vidioc_s_tuner       = vidioc_s_tuner,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-       .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
-       .vidioc_g_chip_ident  = vidioc_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = vidioc_g_register,
-       .vidioc_s_register    = vidioc_s_register,
-#endif
-};
-
-static const struct video_device cx8800_video_template = {
-       .name                 = "cx8800-video",
-       .fops                 = &video_fops,
-       .ioctl_ops            = &video_ioctl_ops,
-       .tvnorms              = CX88_NORMS,
-};
-
-static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_g_fmt_vbi_cap     = cx8800_vbi_fmt,
-       .vidioc_try_fmt_vbi_cap   = cx8800_vbi_fmt,
-       .vidioc_s_fmt_vbi_cap     = cx8800_vbi_fmt,
-       .vidioc_reqbufs       = vidioc_reqbufs,
-       .vidioc_querybuf      = vidioc_querybuf,
-       .vidioc_qbuf          = vidioc_qbuf,
-       .vidioc_dqbuf         = vidioc_dqbuf,
-       .vidioc_g_std         = vidioc_g_std,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_streamon      = vidioc_streamon,
-       .vidioc_streamoff     = vidioc_streamoff,
-       .vidioc_g_tuner       = vidioc_g_tuner,
-       .vidioc_s_tuner       = vidioc_s_tuner,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-       .vidioc_g_chip_ident  = vidioc_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = vidioc_g_register,
-       .vidioc_s_register    = vidioc_s_register,
-#endif
-};
-
-static const struct video_device cx8800_vbi_template = {
-       .name                 = "cx8800-vbi",
-       .fops                 = &video_fops,
-       .ioctl_ops            = &vbi_ioctl_ops,
-       .tvnorms              = CX88_NORMS,
-};
-
-static const struct v4l2_file_operations radio_fops =
-{
-       .owner         = THIS_MODULE,
-       .open          = video_open,
-       .poll          = v4l2_ctrl_poll,
-       .release       = video_release,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_g_tuner       = radio_g_tuner,
-       .vidioc_s_tuner       = radio_s_tuner,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-       .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
-       .vidioc_g_chip_ident  = vidioc_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = vidioc_g_register,
-       .vidioc_s_register    = vidioc_s_register,
-#endif
-};
-
-static const struct video_device cx8800_radio_template = {
-       .name                 = "cx8800-radio",
-       .fops                 = &radio_fops,
-       .ioctl_ops            = &radio_ioctl_ops,
-};
-
-static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = {
-       .s_ctrl = cx8800_s_vid_ctrl,
-};
-
-static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = {
-       .s_ctrl = cx8800_s_aud_ctrl,
-};
-
-/* ----------------------------------------------------------- */
-
-static void cx8800_unregister_video(struct cx8800_dev *dev)
-{
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-       if (dev->vbi_dev) {
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
-       }
-       if (dev->video_dev) {
-               if (video_is_registered(dev->video_dev))
-                       video_unregister_device(dev->video_dev);
-               else
-                       video_device_release(dev->video_dev);
-               dev->video_dev = NULL;
-       }
-}
-
-static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
-                                   const struct pci_device_id *pci_id)
-{
-       struct cx8800_dev *dev;
-       struct cx88_core *core;
-       int err;
-       int i;
-
-       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-       if (NULL == dev)
-               return -ENOMEM;
-
-       /* pci init */
-       dev->pci = pci_dev;
-       if (pci_enable_device(pci_dev)) {
-               err = -EIO;
-               goto fail_free;
-       }
-       core = cx88_core_get(dev->pci);
-       if (NULL == core) {
-               err = -EINVAL;
-               goto fail_free;
-       }
-       dev->core = core;
-
-       /* print pci info */
-       dev->pci_rev = pci_dev->revision;
-       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-       printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
-              "latency: %d, mmio: 0x%llx\n", core->name,
-              pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
-              dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
-
-       pci_set_master(pci_dev);
-       if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) {
-               printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
-               err = -EIO;
-               goto fail_core;
-       }
-
-       /* initialize driver struct */
-       spin_lock_init(&dev->slock);
-       core->tvnorm = V4L2_STD_NTSC_M;
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&dev->vidq.active);
-       INIT_LIST_HEAD(&dev->vidq.queued);
-       dev->vidq.timeout.function = cx8800_vid_timeout;
-       dev->vidq.timeout.data     = (unsigned long)dev;
-       init_timer(&dev->vidq.timeout);
-       cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
-                         MO_VID_DMACNTRL,0x11,0x00);
-
-       /* init vbi dma queues */
-       INIT_LIST_HEAD(&dev->vbiq.active);
-       INIT_LIST_HEAD(&dev->vbiq.queued);
-       dev->vbiq.timeout.function = cx8800_vbi_timeout;
-       dev->vbiq.timeout.data     = (unsigned long)dev;
-       init_timer(&dev->vbiq.timeout);
-       cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
-                         MO_VID_DMACNTRL,0x88,0x00);
-
-       /* get irq */
-       err = request_irq(pci_dev->irq, cx8800_irq,
-                         IRQF_SHARED | IRQF_DISABLED, core->name, dev);
-       if (err < 0) {
-               printk(KERN_ERR "%s/0: can't get IRQ %d\n",
-                      core->name,pci_dev->irq);
-               goto fail_core;
-       }
-       cx_set(MO_PCI_INTMSK, core->pci_irqmask);
-
-       for (i = 0; i < CX8800_AUD_CTLS; i++) {
-               const struct cx88_ctrl *cc = &cx8800_aud_ctls[i];
-               struct v4l2_ctrl *vc;
-
-               vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops,
-                       cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
-               if (vc == NULL) {
-                       err = core->audio_hdl.error;
-                       goto fail_core;
-               }
-               vc->priv = (void *)cc;
-       }
-
-       for (i = 0; i < CX8800_VID_CTLS; i++) {
-               const struct cx88_ctrl *cc = &cx8800_vid_ctls[i];
-               struct v4l2_ctrl *vc;
-
-               vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops,
-                       cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
-               if (vc == NULL) {
-                       err = core->video_hdl.error;
-                       goto fail_core;
-               }
-               vc->priv = (void *)cc;
-               if (vc->id == V4L2_CID_CHROMA_AGC)
-                       core->chroma_agc = vc;
-       }
-       v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl);
-
-       /* load and configure helper modules */
-
-       if (core->board.audio_chip == V4L2_IDENT_WM8775) {
-               struct i2c_board_info wm8775_info = {
-                       .type = "wm8775",
-                       .addr = 0x36 >> 1,
-                       .platform_data = &core->wm8775_data,
-               };
-               struct v4l2_subdev *sd;
-
-               if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
-                       core->wm8775_data.is_nova_s = true;
-               else
-                       core->wm8775_data.is_nova_s = false;
-
-               sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
-                               &wm8775_info, NULL);
-               if (sd != NULL) {
-                       core->sd_wm8775 = sd;
-                       sd->grp_id = WM8775_GID;
-               }
-       }
-
-       if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
-               /* This probes for a tda9874 as is used on some
-                  Pixelview Ultra boards. */
-               v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-                               "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
-       }
-
-       switch (core->boardnr) {
-       case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
-       case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
-               static const struct i2c_board_info rtc_info = {
-                       I2C_BOARD_INFO("isl1208", 0x6f)
-               };
-
-               request_module("rtc-isl1208");
-               core->i2c_rtc = i2c_new_device(&core->i2c_adap, &rtc_info);
-       }
-               /* break intentionally omitted */
-       case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
-               request_module("ir-kbd-i2c");
-       }
-
-       /* Sets device info at pci_dev */
-       pci_set_drvdata(pci_dev, dev);
-
-       dev->width   = 320;
-       dev->height  = 240;
-       dev->fmt     = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-
-       /* initial device configuration */
-       mutex_lock(&core->lock);
-       cx88_set_tvnorm(core, core->tvnorm);
-       v4l2_ctrl_handler_setup(&core->video_hdl);
-       v4l2_ctrl_handler_setup(&core->audio_hdl);
-       cx88_video_mux(core, 0);
-
-       /* register v4l devices */
-       dev->video_dev = cx88_vdev_init(core,dev->pci,
-                                       &cx8800_video_template,"video");
-       video_set_drvdata(dev->video_dev, dev);
-       dev->video_dev->ctrl_handler = &core->video_hdl;
-       err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
-                                   video_nr[core->nr]);
-       if (err < 0) {
-               printk(KERN_ERR "%s/0: can't register video device\n",
-                      core->name);
-               goto fail_unreg;
-       }
-       printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
-              core->name, video_device_node_name(dev->video_dev));
-
-       dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
-       video_set_drvdata(dev->vbi_dev, dev);
-       err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
-                                   vbi_nr[core->nr]);
-       if (err < 0) {
-               printk(KERN_ERR "%s/0: can't register vbi device\n",
-                      core->name);
-               goto fail_unreg;
-       }
-       printk(KERN_INFO "%s/0: registered device %s\n",
-              core->name, video_device_node_name(dev->vbi_dev));
-
-       if (core->board.radio.type == CX88_RADIO) {
-               dev->radio_dev = cx88_vdev_init(core,dev->pci,
-                                               &cx8800_radio_template,"radio");
-               video_set_drvdata(dev->radio_dev, dev);
-               dev->radio_dev->ctrl_handler = &core->audio_hdl;
-               err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
-                                           radio_nr[core->nr]);
-               if (err < 0) {
-                       printk(KERN_ERR "%s/0: can't register radio device\n",
-                              core->name);
-                       goto fail_unreg;
-               }
-               printk(KERN_INFO "%s/0: registered device %s\n",
-                      core->name, video_device_node_name(dev->radio_dev));
-       }
-
-       /* start tvaudio thread */
-       if (core->board.tuner_type != TUNER_ABSENT) {
-               core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
-               if (IS_ERR(core->kthread)) {
-                       err = PTR_ERR(core->kthread);
-                       printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n",
-                              core->name, err);
-               }
-       }
-       mutex_unlock(&core->lock);
-
-       return 0;
-
-fail_unreg:
-       cx8800_unregister_video(dev);
-       free_irq(pci_dev->irq, dev);
-       mutex_unlock(&core->lock);
-fail_core:
-       cx88_core_put(core,dev->pci);
-fail_free:
-       kfree(dev);
-       return err;
-}
-
-static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
-{
-       struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
-       struct cx88_core *core = dev->core;
-
-       /* stop thread */
-       if (core->kthread) {
-               kthread_stop(core->kthread);
-               core->kthread = NULL;
-       }
-
-       if (core->ir)
-               cx88_ir_stop(core);
-
-       cx88_shutdown(core); /* FIXME */
-       pci_disable_device(pci_dev);
-
-       /* unregister stuff */
-
-       free_irq(pci_dev->irq, dev);
-       cx8800_unregister_video(dev);
-       pci_set_drvdata(pci_dev, NULL);
-
-       /* free memory */
-       btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
-       cx88_core_put(core,dev->pci);
-       kfree(dev);
-}
-
-#ifdef CONFIG_PM
-static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
-{
-       struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
-       struct cx88_core *core = dev->core;
-
-       /* stop video+vbi capture */
-       spin_lock(&dev->slock);
-       if (!list_empty(&dev->vidq.active)) {
-               printk("%s/0: suspend video\n", core->name);
-               stop_video_dma(dev);
-               del_timer(&dev->vidq.timeout);
-       }
-       if (!list_empty(&dev->vbiq.active)) {
-               printk("%s/0: suspend vbi\n", core->name);
-               cx8800_stop_vbi_dma(dev);
-               del_timer(&dev->vbiq.timeout);
-       }
-       spin_unlock(&dev->slock);
-
-       if (core->ir)
-               cx88_ir_stop(core);
-       /* FIXME -- shutdown device */
-       cx88_shutdown(core);
-
-       pci_save_state(pci_dev);
-       if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
-               pci_disable_device(pci_dev);
-               dev->state.disabled = 1;
-       }
-       return 0;
-}
-
-static int cx8800_resume(struct pci_dev *pci_dev)
-{
-       struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
-       struct cx88_core *core = dev->core;
-       int err;
-
-       if (dev->state.disabled) {
-               err=pci_enable_device(pci_dev);
-               if (err) {
-                       printk(KERN_ERR "%s/0: can't enable device\n",
-                              core->name);
-                       return err;
-               }
-
-               dev->state.disabled = 0;
-       }
-       err= pci_set_power_state(pci_dev, PCI_D0);
-       if (err) {
-               printk(KERN_ERR "%s/0: can't set power state\n", core->name);
-               pci_disable_device(pci_dev);
-               dev->state.disabled = 1;
-
-               return err;
-       }
-       pci_restore_state(pci_dev);
-
-       /* FIXME: re-initialize hardware */
-       cx88_reset(core);
-       if (core->ir)
-               cx88_ir_start(core);
-
-       cx_set(MO_PCI_INTMSK, core->pci_irqmask);
-
-       /* restart video+vbi capture */
-       spin_lock(&dev->slock);
-       if (!list_empty(&dev->vidq.active)) {
-               printk("%s/0: resume video\n", core->name);
-               restart_video_queue(dev,&dev->vidq);
-       }
-       if (!list_empty(&dev->vbiq.active)) {
-               printk("%s/0: resume vbi\n", core->name);
-               cx8800_restart_vbi_queue(dev,&dev->vbiq);
-       }
-       spin_unlock(&dev->slock);
-
-       return 0;
-}
-#endif
-
-/* ----------------------------------------------------------- */
-
-static const struct pci_device_id cx8800_pci_tbl[] = {
-       {
-               .vendor       = 0x14f1,
-               .device       = 0x8800,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       },{
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
-
-static struct pci_driver cx8800_pci_driver = {
-       .name     = "cx8800",
-       .id_table = cx8800_pci_tbl,
-       .probe    = cx8800_initdev,
-       .remove   = __devexit_p(cx8800_finidev),
-#ifdef CONFIG_PM
-       .suspend  = cx8800_suspend,
-       .resume   = cx8800_resume,
-#endif
-};
-
-static int __init cx8800_init(void)
-{
-       printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
-              CX88_VERSION);
-       return pci_register_driver(&cx8800_pci_driver);
-}
-
-static void __exit cx8800_fini(void)
-{
-       pci_unregister_driver(&cx8800_pci_driver);
-}
-
-module_init(cx8800_init);
-module_exit(cx8800_fini);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.c b/drivers/media/video/cx88/cx88-vp3054-i2c.c
deleted file mode 100644 (file)
index d77f8ec..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-
-    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
-                          DNTV Live! DVB-T Pro (VP-3054), wired as:
-                          GPIO[0] -> SCL, GPIO[1] -> SDA
-
-    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
-
-    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/slab.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "cx88.h"
-#include "cx88-vp3054-i2c.h"
-
-MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
-MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
-MODULE_LICENSE("GPL");
-
-/* ----------------------------------------------------------------------- */
-
-static void vp3054_bit_setscl(void *data, int state)
-{
-       struct cx8802_dev *dev = data;
-       struct cx88_core *core = dev->core;
-       struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
-
-       if (state) {
-               vp3054_i2c->state |=  0x0001;   /* SCL high */
-               vp3054_i2c->state &= ~0x0100;   /* external pullup */
-       } else {
-               vp3054_i2c->state &= ~0x0001;   /* SCL low */
-               vp3054_i2c->state |=  0x0100;   /* drive pin */
-       }
-       cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
-       cx_read(MO_GP0_IO);
-}
-
-static void vp3054_bit_setsda(void *data, int state)
-{
-       struct cx8802_dev *dev = data;
-       struct cx88_core *core = dev->core;
-       struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
-
-       if (state) {
-               vp3054_i2c->state |=  0x0002;   /* SDA high */
-               vp3054_i2c->state &= ~0x0200;   /* tristate pin */
-       } else {
-               vp3054_i2c->state &= ~0x0002;   /* SDA low */
-               vp3054_i2c->state |=  0x0200;   /* drive pin */
-       }
-       cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
-       cx_read(MO_GP0_IO);
-}
-
-static int vp3054_bit_getscl(void *data)
-{
-       struct cx8802_dev *dev = data;
-       struct cx88_core *core = dev->core;
-       u32 state;
-
-       state = cx_read(MO_GP0_IO);
-       return (state & 0x01) ? 1 : 0;
-}
-
-static int vp3054_bit_getsda(void *data)
-{
-       struct cx8802_dev *dev = data;
-       struct cx88_core *core = dev->core;
-       u32 state;
-
-       state = cx_read(MO_GP0_IO);
-       return (state & 0x02) ? 1 : 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
-       .setsda  = vp3054_bit_setsda,
-       .setscl  = vp3054_bit_setscl,
-       .getsda  = vp3054_bit_getsda,
-       .getscl  = vp3054_bit_getscl,
-       .udelay  = 16,
-       .timeout = 200,
-};
-
-/* ----------------------------------------------------------------------- */
-
-int vp3054_i2c_probe(struct cx8802_dev *dev)
-{
-       struct cx88_core *core = dev->core;
-       struct vp3054_i2c_state *vp3054_i2c;
-       int rc;
-
-       if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
-               return 0;
-
-       vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
-       if (vp3054_i2c == NULL)
-               return -ENOMEM;
-       dev->vp3054 = vp3054_i2c;
-
-       memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
-              sizeof(vp3054_i2c->algo));
-
-       vp3054_i2c->adap.dev.parent = &dev->pci->dev;
-       strlcpy(vp3054_i2c->adap.name, core->name,
-               sizeof(vp3054_i2c->adap.name));
-       vp3054_i2c->adap.owner = THIS_MODULE;
-       vp3054_i2c->algo.data = dev;
-       i2c_set_adapdata(&vp3054_i2c->adap, dev);
-       vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
-
-       vp3054_bit_setscl(dev,1);
-       vp3054_bit_setsda(dev,1);
-
-       rc = i2c_bit_add_bus(&vp3054_i2c->adap);
-       if (0 != rc) {
-               printk("%s: vp3054_i2c register FAILED\n", core->name);
-
-               kfree(dev->vp3054);
-               dev->vp3054 = NULL;
-       }
-
-       return rc;
-}
-
-void vp3054_i2c_remove(struct cx8802_dev *dev)
-{
-       struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
-
-       if (vp3054_i2c == NULL ||
-           dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
-               return;
-
-       i2c_del_adapter(&vp3054_i2c->adap);
-       kfree(vp3054_i2c);
-}
-
-EXPORT_SYMBOL(vp3054_i2c_probe);
-EXPORT_SYMBOL(vp3054_i2c_remove);
diff --git a/drivers/media/video/cx88/cx88-vp3054-i2c.h b/drivers/media/video/cx88/cx88-vp3054-i2c.h
deleted file mode 100644 (file)
index be99c93..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-
-    cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
-                          DNTV Live! DVB-T Pro (VP-3054), wired as:
-                          GPIO[0] -> SCL, GPIO[1] -> SDA
-
-    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
-
-    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.
-
-*/
-
-/* ----------------------------------------------------------------------- */
-struct vp3054_i2c_state {
-       struct i2c_adapter         adap;
-       struct i2c_algo_bit_data   algo;
-       u32                        state;
-};
-
-/* ----------------------------------------------------------------------- */
-#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
-int  vp3054_i2c_probe(struct cx8802_dev *dev);
-void vp3054_i2c_remove(struct cx8802_dev *dev);
-#else
-static inline int  vp3054_i2c_probe(struct cx8802_dev *dev)
-{ return 0; }
-static inline void vp3054_i2c_remove(struct cx8802_dev *dev)
-{ }
-#endif
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
deleted file mode 100644 (file)
index 44ffc8b..0000000
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- *
- * v4l2 device driver for cx2388x based TV cards
- *
- * (c) 2003,04 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, 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/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev2.h>
-#include <linux/kdev_t.h>
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/tuner.h>
-#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/cx2341x.h>
-#include <media/videobuf-dvb.h>
-#include <media/ir-kbd-i2c.h>
-#include <media/wm8775.h>
-
-#include "btcx-risc.h"
-#include "cx88-reg.h"
-#include "tuner-xc2028.h"
-
-#include <linux/mutex.h>
-
-#define CX88_VERSION "0.0.9"
-
-#define UNSET (-1U)
-
-#define CX88_MAXBOARDS 8
-
-/* Max number of inputs by card */
-#define MAX_CX88_INPUT 8
-
-/* ----------------------------------------------------------- */
-/* defines and enums                                           */
-
-/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
-#define CX88_NORMS (V4L2_STD_ALL               \
-                   & ~V4L2_STD_PAL_H           \
-                   & ~V4L2_STD_NTSC_M_KR       \
-                   & ~V4L2_STD_SECAM_LC)
-
-#define FORMAT_FLAGS_PACKED       0x01
-#define FORMAT_FLAGS_PLANAR       0x02
-
-#define VBI_LINE_COUNT              17
-#define VBI_LINE_LENGTH           2048
-
-#define AUD_RDS_LINES               4
-
-/* need "shadow" registers for some write-only ones ... */
-#define SHADOW_AUD_VOL_CTL           1
-#define SHADOW_AUD_BAL_CTL           2
-#define SHADOW_MAX                   3
-
-/* FM Radio deemphasis type */
-enum cx88_deemph_type {
-       FM_NO_DEEMPH = 0,
-       FM_DEEMPH_50,
-       FM_DEEMPH_75
-};
-
-enum cx88_board_type {
-       CX88_BOARD_NONE = 0,
-       CX88_MPEG_DVB,
-       CX88_MPEG_BLACKBIRD
-};
-
-enum cx8802_board_access {
-       CX8802_DRVCTL_SHARED    = 1,
-       CX8802_DRVCTL_EXCLUSIVE = 2,
-};
-
-/* ----------------------------------------------------------- */
-/* tv norms                                                    */
-
-static unsigned int inline norm_maxw(v4l2_std_id norm)
-{
-       return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
-}
-
-
-static unsigned int inline norm_maxh(v4l2_std_id norm)
-{
-       return (norm & V4L2_STD_625_50) ? 576 : 480;
-}
-
-/* ----------------------------------------------------------- */
-/* static data                                                 */
-
-struct cx8800_fmt {
-       const char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-       int   flags;
-       u32   cxformat;
-};
-
-/* ----------------------------------------------------------- */
-/* SRAM memory management data (see cx88-core.c)               */
-
-#define SRAM_CH21 0   /* video */
-#define SRAM_CH22 1
-#define SRAM_CH23 2
-#define SRAM_CH24 3   /* vbi   */
-#define SRAM_CH25 4   /* audio */
-#define SRAM_CH26 5
-#define SRAM_CH28 6   /* mpeg */
-#define SRAM_CH27 7   /* audio rds */
-/* more */
-
-struct sram_channel {
-       const char *name;
-       u32  cmds_start;
-       u32  ctrl_start;
-       u32  cdt;
-       u32  fifo_start;
-       u32  fifo_size;
-       u32  ptr1_reg;
-       u32  ptr2_reg;
-       u32  cnt1_reg;
-       u32  cnt2_reg;
-};
-extern const struct sram_channel cx88_sram_channels[];
-
-/* ----------------------------------------------------------- */
-/* card configuration                                          */
-
-#define CX88_BOARD_NOAUTO               UNSET
-#define CX88_BOARD_UNKNOWN                  0
-#define CX88_BOARD_HAUPPAUGE                1
-#define CX88_BOARD_GDI                      2
-#define CX88_BOARD_PIXELVIEW                3
-#define CX88_BOARD_ATI_WONDER_PRO           4
-#define CX88_BOARD_WINFAST2000XP_EXPERT     5
-#define CX88_BOARD_AVERTV_STUDIO_303        6
-#define CX88_BOARD_MSI_TVANYWHERE_MASTER    7
-#define CX88_BOARD_WINFAST_DV2000           8
-#define CX88_BOARD_LEADTEK_PVR2000          9
-#define CX88_BOARD_IODATA_GVVCP3PCI        10
-#define CX88_BOARD_PROLINK_PLAYTVPVR       11
-#define CX88_BOARD_ASUS_PVR_416            12
-#define CX88_BOARD_MSI_TVANYWHERE          13
-#define CX88_BOARD_KWORLD_DVB_T            14
-#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
-#define CX88_BOARD_KWORLD_LTV883           16
-#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q  17
-#define CX88_BOARD_HAUPPAUGE_DVB_T1        18
-#define CX88_BOARD_CONEXANT_DVB_T1         19
-#define CX88_BOARD_PROVIDEO_PV259          20
-#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
-#define CX88_BOARD_PCHDTV_HD3000           22
-#define CX88_BOARD_DNTV_LIVE_DVB_T         23
-#define CX88_BOARD_HAUPPAUGE_ROSLYN        24
-#define CX88_BOARD_DIGITALLOGIC_MEC        25
-#define CX88_BOARD_IODATA_GVBCTV7E         26
-#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
-#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T  28
-#define CX88_BOARD_ADSTECH_DVB_T_PCI          29
-#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1  30
-#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
-#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32
-#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33
-#define CX88_BOARD_ATI_HDTVWONDER          34
-#define CX88_BOARD_WINFAST_DTV1000         35
-#define CX88_BOARD_AVERTV_303              36
-#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1  37
-#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1    38
-#define CX88_BOARD_KWORLD_DVBS_100         39
-#define CX88_BOARD_HAUPPAUGE_HVR1100       40
-#define CX88_BOARD_HAUPPAUGE_HVR1100LP     41
-#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO     42
-#define CX88_BOARD_KWORLD_DVB_T_CX22702    43
-#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
-#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
-#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
-#define CX88_BOARD_PCHDTV_HD5500           47
-#define CX88_BOARD_KWORLD_MCE200_DELUXE    48
-#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000  49
-#define CX88_BOARD_NPGTECH_REALTV_TOP10FM  50
-#define CX88_BOARD_WINFAST_DTV2000H        51
-#define CX88_BOARD_GENIATECH_DVBS          52
-#define CX88_BOARD_HAUPPAUGE_HVR3000       53
-#define CX88_BOARD_NORWOOD_MICRO           54
-#define CX88_BOARD_TE_DTV_250_OEM_SWANN    55
-#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
-#define CX88_BOARD_HAUPPAUGE_HVR4000       68
-#define CX88_BOARD_HAUPPAUGE_HVR4000LITE   69
-#define CX88_BOARD_TEVII_S460              70
-#define CX88_BOARD_OMICOM_SS4_PCI          71
-#define CX88_BOARD_TBS_8920                72
-#define CX88_BOARD_TEVII_S420              73
-#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
-#define CX88_BOARD_PROF_7300               75
-#define CX88_BOARD_SATTRADE_ST4200         76
-#define CX88_BOARD_TBS_8910                77
-#define CX88_BOARD_PROF_6200               78
-#define CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII 79
-#define CX88_BOARD_HAUPPAUGE_IRONLY        80
-#define CX88_BOARD_WINFAST_DTV1800H        81
-#define CX88_BOARD_WINFAST_DTV2000H_J      82
-#define CX88_BOARD_PROF_7301               83
-#define CX88_BOARD_SAMSUNG_SMT_7020        84
-#define CX88_BOARD_TWINHAN_VP1027_DVBS     85
-#define CX88_BOARD_TEVII_S464              86
-#define CX88_BOARD_WINFAST_DTV2000H_PLUS   87
-#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
-#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
-#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
-
-enum cx88_itype {
-       CX88_VMUX_COMPOSITE1 = 1,
-       CX88_VMUX_COMPOSITE2,
-       CX88_VMUX_COMPOSITE3,
-       CX88_VMUX_COMPOSITE4,
-       CX88_VMUX_SVIDEO,
-       CX88_VMUX_TELEVISION,
-       CX88_VMUX_CABLE,
-       CX88_VMUX_DVB,
-       CX88_VMUX_DEBUG,
-       CX88_RADIO,
-};
-
-struct cx88_input {
-       enum cx88_itype type;
-       u32             gpio0, gpio1, gpio2, gpio3;
-       unsigned int    vmux:2;
-       unsigned int    audioroute:4;
-};
-
-struct cx88_board {
-       const char              *name;
-       unsigned int            tuner_type;
-       unsigned int            radio_type;
-       unsigned char           tuner_addr;
-       unsigned char           radio_addr;
-       int                     tda9887_conf;
-       struct cx88_input       input[MAX_CX88_INPUT];
-       struct cx88_input       radio;
-       enum cx88_board_type    mpeg;
-       unsigned int            audio_chip;
-       int                     num_frontends;
-
-       /* Used for I2S devices */
-       int                     i2sinputcntl;
-};
-
-struct cx88_subid {
-       u16     subvendor;
-       u16     subdevice;
-       u32     card;
-};
-
-enum cx88_tvaudio {
-       WW_NONE = 1,
-       WW_BTSC,
-       WW_BG,
-       WW_DK,
-       WW_I,
-       WW_L,
-       WW_EIAJ,
-       WW_I2SPT,
-       WW_FM,
-       WW_I2SADC,
-       WW_M
-};
-
-#define INPUT(nr) (core->board.input[nr])
-
-/* ----------------------------------------------------------- */
-/* device / file handle status                                 */
-
-#define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO         2
-#define RESOURCE_VBI           4
-
-#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)
-
-/* buffer for one video frame */
-struct cx88_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       /* cx88 specific */
-       unsigned int           bpl;
-       struct btcx_riscmem    risc;
-       const struct cx8800_fmt *fmt;
-       u32                    count;
-};
-
-struct cx88_dmaqueue {
-       struct list_head       active;
-       struct list_head       queued;
-       struct timer_list      timeout;
-       struct btcx_riscmem    stopper;
-       u32                    count;
-};
-
-struct cx88_core {
-       struct list_head           devlist;
-       atomic_t                   refcount;
-
-       /* board name */
-       int                        nr;
-       char                       name[32];
-
-       /* pci stuff */
-       int                        pci_bus;
-       int                        pci_slot;
-       u32                        __iomem *lmmio;
-       u8                         __iomem *bmmio;
-       u32                        shadow[SHADOW_MAX];
-       int                        pci_irqmask;
-
-       /* i2c i/o */
-       struct i2c_adapter         i2c_adap;
-       struct i2c_algo_bit_data   i2c_algo;
-       struct i2c_client          i2c_client;
-       u32                        i2c_state, i2c_rc;
-
-       /* config info -- analog */
-       struct v4l2_device         v4l2_dev;
-       struct v4l2_ctrl_handler   video_hdl;
-       struct v4l2_ctrl           *chroma_agc;
-       struct v4l2_ctrl_handler   audio_hdl;
-       struct v4l2_subdev         *sd_wm8775;
-       struct i2c_client          *i2c_rtc;
-       unsigned int               boardnr;
-       struct cx88_board          board;
-
-       /* Supported V4L _STD_ tuner formats */
-       unsigned int               tuner_formats;
-
-       /* config info -- dvb */
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
-       int                        (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-#endif
-       void                       (*gate_ctrl)(struct cx88_core  *core, int open);
-
-       /* state info */
-       struct task_struct         *kthread;
-       v4l2_std_id                tvnorm;
-       enum cx88_tvaudio          tvaudio;
-       u32                        audiomode_manual;
-       u32                        audiomode_current;
-       u32                        input;
-       u32                        last_analog_input;
-       u32                        astat;
-       u32                        use_nicam;
-       unsigned long              last_change;
-
-       /* IR remote control state */
-       struct cx88_IR             *ir;
-
-       /* I2C remote data */
-       struct IR_i2c_init_data    init_data;
-       struct wm8775_platform_data wm8775_data;
-
-       struct mutex               lock;
-       /* various v4l controls */
-       u32                        freq;
-       int                        users;
-       int                        mpeg_users;
-
-       /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
-       struct cx8802_dev          *dvbdev;
-       enum cx88_board_type       active_type_id;
-       int                        active_ref;
-       int                        active_fe_id;
-};
-
-static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
-}
-
-#define call_hw(core, grpid, o, f, args...) \
-       do {                                                    \
-               if (!core->i2c_rc) {                            \
-                       if (core->gate_ctrl)                    \
-                               core->gate_ctrl(core, 1);       \
-                       v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
-                       if (core->gate_ctrl)                    \
-                               core->gate_ctrl(core, 0);       \
-               }                                               \
-       } while (0)
-
-#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
-
-#define WM8775_GID      (1 << 0)
-
-#define wm8775_s_ctrl(core, id, val) \
-       do {                                                                    \
-               struct v4l2_ctrl *ctrl_ =                                       \
-                       v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);      \
-               if (ctrl_ && !core->i2c_rc) {                                   \
-                       if (core->gate_ctrl)                                    \
-                               core->gate_ctrl(core, 1);                       \
-                       v4l2_ctrl_s_ctrl(ctrl_, val);                           \
-                       if (core->gate_ctrl)                                    \
-                               core->gate_ctrl(core, 0);                       \
-               }                                                               \
-       } while (0)
-
-#define wm8775_g_ctrl(core, id) \
-       ({                                                                      \
-               struct v4l2_ctrl *ctrl_ =                                       \
-                       v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);      \
-               s32 val = 0;                                                    \
-               if (ctrl_ && !core->i2c_rc) {                                   \
-                       if (core->gate_ctrl)                                    \
-                               core->gate_ctrl(core, 1);                       \
-                       val = v4l2_ctrl_g_ctrl(ctrl_);                          \
-                       if (core->gate_ctrl)                                    \
-                               core->gate_ctrl(core, 0);                       \
-               }                                                               \
-               val;                                                            \
-       })
-
-struct cx8800_dev;
-struct cx8802_dev;
-
-/* ----------------------------------------------------------- */
-/* function 0: video stuff                                     */
-
-struct cx8800_fh {
-       struct v4l2_fh             fh;
-       struct cx8800_dev          *dev;
-       unsigned int               resources;
-
-       /* video capture */
-       struct videobuf_queue      vidq;
-
-       /* vbi capture */
-       struct videobuf_queue      vbiq;
-};
-
-struct cx8800_suspend_state {
-       int                        disabled;
-};
-
-struct cx8800_dev {
-       struct cx88_core           *core;
-       spinlock_t                 slock;
-
-       /* various device info */
-       unsigned int               resources;
-       struct video_device        *video_dev;
-       struct video_device        *vbi_dev;
-       struct video_device        *radio_dev;
-
-       /* pci i/o */
-       struct pci_dev             *pci;
-       unsigned char              pci_rev,pci_lat;
-
-       const struct cx8800_fmt    *fmt;
-       unsigned int               width, height;
-
-       /* capture queues */
-       struct cx88_dmaqueue       vidq;
-       struct cx88_dmaqueue       vbiq;
-
-       /* various v4l controls */
-
-       /* other global state info */
-       struct cx8800_suspend_state state;
-};
-
-/* ----------------------------------------------------------- */
-/* function 1: audio/alsa stuff                                */
-/* =============> moved to cx88-alsa.c <====================== */
-
-
-/* ----------------------------------------------------------- */
-/* function 2: mpeg stuff                                      */
-
-struct cx8802_fh {
-       struct v4l2_fh             fh;
-       struct cx8802_dev          *dev;
-       struct videobuf_queue      mpegq;
-};
-
-struct cx8802_suspend_state {
-       int                        disabled;
-};
-
-struct cx8802_driver {
-       struct cx88_core *core;
-
-       /* List of drivers attached to device */
-       struct list_head drvlist;
-
-       /* Type of driver and access required */
-       enum cx88_board_type type_id;
-       enum cx8802_board_access hw_access;
-
-       /* MPEG 8802 internal only */
-       int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
-       int (*resume)(struct pci_dev *pci_dev);
-
-       /* Callers to the following functions must hold core->lock */
-
-       /* MPEG 8802 -> mini driver - Driver probe and configuration */
-       int (*probe)(struct cx8802_driver *drv);
-       int (*remove)(struct cx8802_driver *drv);
-
-       /* MPEG 8802 -> mini driver - Access for hardware control */
-       int (*advise_acquire)(struct cx8802_driver *drv);
-       int (*advise_release)(struct cx8802_driver *drv);
-
-       /* MPEG 8802 <- mini driver - Access for hardware control */
-       int (*request_acquire)(struct cx8802_driver *drv);
-       int (*request_release)(struct cx8802_driver *drv);
-};
-
-struct cx8802_dev {
-       struct cx88_core           *core;
-       spinlock_t                 slock;
-
-       /* pci i/o */
-       struct pci_dev             *pci;
-       unsigned char              pci_rev,pci_lat;
-
-       /* dma queues */
-       struct cx88_dmaqueue       mpegq;
-       u32                        ts_packet_size;
-       u32                        ts_packet_count;
-
-       /* other global state info */
-       struct cx8802_suspend_state state;
-
-       /* for blackbird only */
-       struct list_head           devlist;
-#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
-    defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
-       struct video_device        *mpeg_dev;
-       u32                        mailbox;
-       int                        width;
-       int                        height;
-       unsigned char              mpeg_active; /* nonzero if mpeg encoder is active */
-
-       /* mpeg params */
-       struct cx2341x_handler     cxhdl;
-#endif
-
-#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
-       /* for dvb only */
-       struct videobuf_dvb_frontends frontends;
-#endif
-
-#if defined(CONFIG_VIDEO_CX88_VP3054) || \
-    defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
-       /* For VP3045 secondary I2C bus support */
-       struct vp3054_i2c_state    *vp3054;
-#endif
-       /* for switching modulation types */
-       unsigned char              ts_gen_cntrl;
-
-       /* List of attached drivers; must hold core->lock to access */
-       struct list_head           drvlist;
-
-       struct work_struct         request_module_wk;
-};
-
-/* ----------------------------------------------------------- */
-
-#define cx_read(reg)             readl(core->lmmio + ((reg)>>2))
-#define cx_write(reg,value)      writel((value), core->lmmio + ((reg)>>2))
-#define cx_writeb(reg,value)     writeb((value), core->bmmio + (reg))
-
-#define cx_andor(reg,mask,value) \
-  writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
-  ((value) & (mask)), core->lmmio+((reg)>>2))
-#define cx_set(reg,bit)          cx_andor((reg),(bit),(bit))
-#define cx_clear(reg,bit)        cx_andor((reg),(bit),0)
-
-#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
-
-/* shadow registers */
-#define cx_sread(sreg)             (core->shadow[sreg])
-#define cx_swrite(sreg,reg,value) \
-  (core->shadow[sreg] = value, \
-   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
-#define cx_sandor(sreg,reg,mask,value) \
-  (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
-   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
-
-/* ----------------------------------------------------------- */
-/* cx88-core.c                                                 */
-
-extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
-                              int len, u32 bits, u32 mask);
-
-extern int cx88_core_irq(struct cx88_core *core, u32 status);
-extern void cx88_wakeup(struct cx88_core *core,
-                       struct cx88_dmaqueue *q, u32 count);
-extern void cx88_shutdown(struct cx88_core *core);
-extern int cx88_reset(struct cx88_core *core);
-
-extern int
-cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                struct scatterlist *sglist,
-                unsigned int top_offset, unsigned int bottom_offset,
-                unsigned int bpl, unsigned int padding, unsigned int lines);
-extern int
-cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
-                    struct scatterlist *sglist, unsigned int bpl,
-                    unsigned int lines, unsigned int lpi);
-extern int
-cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
-                 u32 reg, u32 mask, u32 value);
-extern void
-cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
-
-extern void cx88_risc_disasm(struct cx88_core *core,
-                            struct btcx_riscmem *risc);
-extern int cx88_sram_channel_setup(struct cx88_core *core,
-                                  const struct sram_channel *ch,
-                                  unsigned int bpl, u32 risc);
-extern void cx88_sram_channel_dump(struct cx88_core *core,
-                                  const struct sram_channel *ch);
-
-extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
-                         unsigned int height, enum v4l2_field field);
-extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
-
-extern struct video_device *cx88_vdev_init(struct cx88_core *core,
-                                          struct pci_dev *pci,
-                                          const struct video_device *template_,
-                                          const char *type);
-extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
-extern void cx88_core_put(struct cx88_core *core,
-                         struct pci_dev *pci);
-
-extern int cx88_start_audio_dma(struct cx88_core *core);
-extern int cx88_stop_audio_dma(struct cx88_core *core);
-
-
-/* ----------------------------------------------------------- */
-/* cx88-vbi.c                                                  */
-
-/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
-int cx8800_vbi_fmt (struct file *file, void *priv,
-                                       struct v4l2_format *f);
-
-/*
-int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-                        struct cx88_dmaqueue *q,
-                        struct cx88_buffer   *buf);
-*/
-int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
-int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
-                            struct cx88_dmaqueue *q);
-void cx8800_vbi_timeout(unsigned long data);
-
-extern const struct videobuf_queue_ops cx8800_vbi_qops;
-
-/* ----------------------------------------------------------- */
-/* cx88-i2c.c                                                  */
-
-extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
-
-
-/* ----------------------------------------------------------- */
-/* cx88-cards.c                                                */
-
-extern int cx88_tuner_callback(void *dev, int component, 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                                              */
-
-void cx88_set_tvaudio(struct cx88_core *core);
-void cx88_newstation(struct cx88_core *core);
-void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
-void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
-int cx88_audio_thread(void *data);
-
-int cx8802_register_driver(struct cx8802_driver *drv);
-int cx8802_unregister_driver(struct cx8802_driver *drv);
-
-/* Caller must hold core->lock */
-struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
-
-/* ----------------------------------------------------------- */
-/* cx88-dsp.c                                                  */
-
-s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
-
-/* ----------------------------------------------------------- */
-/* cx88-input.c                                                */
-
-int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
-int cx88_ir_fini(struct cx88_core *core);
-void cx88_ir_irq(struct cx88_core *core);
-int cx88_ir_start(struct cx88_core *core);
-void cx88_ir_stop(struct cx88_core *core);
-extern void cx88_i2c_init_ir(struct cx88_core *core);
-
-/* ----------------------------------------------------------- */
-/* cx88-mpeg.c                                                 */
-
-int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
-                       struct cx88_buffer *buf, enum v4l2_field field);
-void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
-void cx8802_cancel_buffers(struct cx8802_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* cx88-video.c*/
-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_video_mux(struct cx88_core *core, unsigned int input);
-void cx88_querycap(struct file *file, struct cx88_core *core,
-               struct v4l2_capability *cap);
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig
deleted file mode 100644 (file)
index 89f6591..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-config VIDEO_IVTV
-       tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
-       depends on VIDEO_V4L2 && PCI && I2C
-       select I2C_ALGOBIT
-       depends on RC_CORE
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEO_CX2341X
-       select VIDEO_CX25840
-       select VIDEO_MSP3400
-       select VIDEO_SAA711X
-       select VIDEO_SAA717X
-       select VIDEO_SAA7127
-       select VIDEO_CS53L32A
-       select VIDEO_M52790
-       select VIDEO_WM8775
-       select VIDEO_WM8739
-       select VIDEO_VP27SMPX
-       select VIDEO_UPD64031A
-       select VIDEO_UPD64083
-       ---help---
-         This is a video4linux driver for Conexant cx23416 or cx23415 based
-         PCI personal video recorder devices.
-
-         This is used in devices such as the Hauppauge PVR-150/250/350/500
-         cards. There is a driver homepage at <http://www.ivtvdriver.org>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ivtv.
-
-config VIDEO_FB_IVTV
-       tristate "Conexant cx23415 framebuffer support"
-       depends on VIDEO_IVTV && FB
-       select FB_CFB_FILLRECT
-       select FB_CFB_COPYAREA
-       select FB_CFB_IMAGEBLIT
-       ---help---
-         This is a framebuffer driver for the Conexant cx23415 MPEG
-         encoder/decoder.
-
-         This is used in the Hauppauge PVR-350 card. There is a driver
-         homepage at <http://www.ivtvdriver.org>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ivtvfb.
diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile
deleted file mode 100644 (file)
index 80b4ec1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-ivtv-objs      := ivtv-routing.o ivtv-cards.o ivtv-controls.o \
-                  ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \
-                  ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \
-                  ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \
-                  ivtv-vbi.o ivtv-yuv.o
-
-obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
-obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
-
-ccflags-y += -I$(srctree)/drivers/media/video
-ccflags-y += -I$(srctree)/drivers/media/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
-
diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c
deleted file mode 100644 (file)
index 145e474..0000000
+++ /dev/null
@@ -1,1370 +0,0 @@
-/*
-    Functions to query card hardware
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-cards.h"
-#include "ivtv-i2c.h"
-
-#include <media/msp3400.h>
-#include <media/m52790.h>
-#include <media/wm8775.h>
-#include <media/cs53l32a.h>
-#include <media/cx25840.h>
-#include <media/upd64031a.h>
-
-#define MSP_TUNER  MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
-                               MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER)
-#define MSP_SCART1 MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
-                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
-#define MSP_SCART2 MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, \
-                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
-#define MSP_SCART3 MSP_INPUT(MSP_IN_SCART3, MSP_IN_TUNER1, \
-                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
-#define MSP_MONO   MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
-                               MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
-
-#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
-
-/* usual i2c tuner addresses to probe */
-static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
-       .radio = { I2C_CLIENT_END },
-       .demod = { 0x43, I2C_CLIENT_END },
-       .tv    = { 0x61, 0x60, I2C_CLIENT_END },
-};
-
-/* as above, but with possible radio tuner */
-static struct ivtv_card_tuner_i2c ivtv_i2c_radio = {
-       .radio = { 0x60, I2C_CLIENT_END },
-       .demod = { 0x43, I2C_CLIENT_END },
-       .tv    = { 0x61, I2C_CLIENT_END },
-};
-
-/* using the tda8290+75a combo */
-static struct ivtv_card_tuner_i2c ivtv_i2c_tda8290 = {
-       .radio = { I2C_CLIENT_END },
-       .demod = { I2C_CLIENT_END },
-       .tv    = { 0x4b, I2C_CLIENT_END },
-};
-
-/********************** card configuration *******************************/
-
-/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ 
-   This keeps the PCI ID database up to date. Note that the entries
-   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
-   New vendor IDs should still be added to the vendor ID list. */
-
-/* Hauppauge PVR-250 cards */
-
-/* Note: for Hauppauge cards the tveeprom information is used instead of PCI IDs */
-static const struct ivtv_card ivtv_card_pvr250 = {
-       .type = IVTV_CARD_PVR_250,
-       .name = "Hauppauge WinTV PVR-250",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_MSP34XX,
-       .hw_audio_ctrl = IVTV_HW_MSP34XX,
-       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
-                 IVTV_HW_TVEEPROM | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
-               { IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
-               { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
-               { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  MSP_TUNER  },
-               { IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
-               { IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Hauppauge PVR-350 cards */
-
-/* Outputs for Hauppauge PVR350 cards */
-static struct ivtv_card_output ivtv_pvr350_outputs[] = {
-       {
-               .name = "S-Video + Composite",
-               .video_output = 0,
-       }, {
-               .name = "Composite",
-               .video_output = 1,
-       }, {
-               .name = "S-Video",
-               .video_output = 2,
-       }, {
-               .name = "RGB",
-               .video_output = 3,
-       }, {
-               .name = "YUV C",
-               .video_output = 4,
-       }, {
-               .name = "YUV V",
-               .video_output = 5,
-       }
-};
-
-static const struct ivtv_card ivtv_card_pvr350 = {
-       .type = IVTV_CARD_PVR_350,
-       .name = "Hauppauge WinTV PVR-350",
-       .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER,
-       .video_outputs = ivtv_pvr350_outputs,
-       .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs),
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_MSP34XX,
-       .hw_audio_ctrl = IVTV_HW_MSP34XX,
-       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
-                 IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER |
-                 IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
-               { IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
-               { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
-               { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  MSP_TUNER  },
-               { IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
-               { IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
-       .i2c = &ivtv_i2c_std,
-};
-
-/* PVR-350 V1 boards have a different audio tuner input and use a
-   saa7114 instead of a saa7115.
-   Note that the info below comes from a pre-production model so it may
-   not be correct. Especially the audio behaves strangely (mono only it seems) */
-static const struct ivtv_card ivtv_card_pvr350_v1 = {
-       .type = IVTV_CARD_PVR_350_V1,
-       .name = "Hauppauge WinTV PVR-350 (V1)",
-       .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER,
-       .video_outputs = ivtv_pvr350_outputs,
-       .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs),
-       .hw_video = IVTV_HW_SAA7114,
-       .hw_audio = IVTV_HW_MSP34XX,
-       .hw_audio_ctrl = IVTV_HW_MSP34XX,
-       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7114 |
-                 IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
-               { IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
-               { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
-               { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  MSP_MONO   },
-               { IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
-               { IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Hauppauge PVR-150/PVR-500 cards */
-
-static const struct ivtv_card ivtv_card_pvr150 = {
-       .type = IVTV_CARD_PVR_150,
-       .name = "Hauppauge WinTV PVR-150",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_muxer = IVTV_HW_WM8775,
-       .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 |
-                 IVTV_HW_TVEEPROM | IVTV_HW_TUNER |
-                 IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT |
-                 IVTV_HW_Z8F0811_IR_HAUP,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE7 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO1    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 },
-               { IVTV_CARD_INPUT_SVIDEO2,    2, CX25840_SVIDEO2    },
-               { IVTV_CARD_INPUT_COMPOSITE2, 2, CX25840_COMPOSITE4 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,
-                 CX25840_AUDIO8, WM8775_AIN2 },
-               { IVTV_CARD_INPUT_LINE_IN1,
-                 CX25840_AUDIO_SERIAL, WM8775_AIN2 },
-               { IVTV_CARD_INPUT_LINE_IN2,
-                 CX25840_AUDIO_SERIAL, WM8775_AIN3 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER,
-                        CX25840_AUDIO_SERIAL, WM8775_AIN4 },
-       /* apparently needed for the IR blaster */
-       .gpio_init = { .direction = 0x1f01, .initial_value = 0x26f3 },
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AVerMedia M179 cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_m179[] = {
-       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3cf },
-       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3ce },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_m179 = {
-       .type = IVTV_CARD_M179,
-       .name = "AVerMedia M179",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7114,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0xe380, .initial_value = 0x8290 },
-       .gpio_audio_input  = { .mask = 0x8040, .tuner  = 0x8000, .linein = 0x0000 },
-       .gpio_audio_mute   = { .mask = 0x2000, .mute   = 0x2000 },
-       .gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
-                             .lang1 = 0x0200, .lang2  = 0x0100, .both   = 0x0000 },
-       .gpio_audio_freq   = { .mask = 0x0018, .f32000 = 0x0000,
-                            .f44100 = 0x0008, .f48000 = 0x0010 },
-       .gpio_audio_detect = { .mask = 0x4000, .stereo = 0x0000 },
-       .tuners = {
-               /* As far as we know all M179 cards use this tuner */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_NTSC },
-       },
-       .pci_list = ivtv_pci_m179,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan MPG600/Kuroutoshikou ITVC16-STVLP cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_mpg600[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xfff3 },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xffff },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_mpg600 = {
-       .type = IVTV_CARD_MPG600,
-       .name = "Yuan MPG600, Kuroutoshikou ITVC16-STVLP",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0x3080, .initial_value = 0x0004 },
-       .gpio_audio_input  = { .mask = 0x3000, .tuner  = 0x0000, .linein = 0x2000 },
-       .gpio_audio_mute   = { .mask = 0x0001, .mute   = 0x0001 },
-       .gpio_audio_mode   = { .mask = 0x000e, .mono   = 0x0006, .stereo = 0x0004,
-                             .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
-       .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
-       .tuners = {
-               /* The PAL tuner is confirmed */
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
-       },
-       .pci_list = ivtv_pci_mpg600,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan MPG160/Kuroutoshikou ITVC15-STVLP cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_mpg160[] = {
-       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_YUAN1, 0 },
-       { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_IODATA, 0x40a0 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_mpg160 = {
-       .type = IVTV_CARD_MPG160,
-       .name = "YUAN MPG160, Kuroutoshikou ITVC15-STVLP, I/O Data GV-M2TV/PCI",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7114,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0x7080, .initial_value = 0x400c },
-       .gpio_audio_input  = { .mask = 0x3000, .tuner  = 0x0000, .linein = 0x2000 },
-       .gpio_audio_mute   = { .mask = 0x0001, .mute   = 0x0001 },
-       .gpio_audio_mode   = { .mask = 0x000e, .mono   = 0x0006, .stereo = 0x0004,
-                             .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
-       .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
-       },
-       .pci_list = ivtv_pci_mpg160,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan PG600/Diamond PVR-550 cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_pg600[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_DIAMONDMM, 0x0070 },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_pg600 = {
-       .type = IVTV_CARD_PG600,
-       .name = "Yuan PG600, Diamond PVR-550",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1,
-                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
-       },
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
-       },
-       .pci_list = ivtv_pci_pg600,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Adaptec VideOh! AVC-2410 card */
-
-static const struct ivtv_card_pci_info ivtv_pci_avc2410[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0093 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_avc2410 = {
-       .type = IVTV_CARD_AVC2410,
-       .name = "Adaptec VideOh! AVC-2410",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_MSP34XX,
-       .hw_audio_ctrl = IVTV_HW_MSP34XX,
-       .hw_muxer = IVTV_HW_CS53L32A,
-       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A |
-                 IVTV_HW_SAA7115 | IVTV_HW_TUNER |
-                 IVTV_HW_I2C_IR_RX_ADAPTEC,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,
-                 MSP_TUNER, CS53L32A_IN0 },
-               { IVTV_CARD_INPUT_LINE_IN1,
-                 MSP_SCART1, CS53L32A_IN2 },
-       },
-       /* This card has no eeprom and in fact the Windows driver relies
-          on the country/region setting of the user to decide which tuner
-          is available. */
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_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,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Adaptec VideOh! AVC-2010 card */
-
-static const struct ivtv_card_pci_info ivtv_pci_avc2010[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0092 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_avc2010 = {
-       .type = IVTV_CARD_AVC2010,
-       .name = "Adaptec VideOh! AVC-2010",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_CS53L32A,
-       .hw_audio_ctrl = IVTV_HW_CS53L32A,
-       .hw_all = IVTV_HW_CS53L32A | IVTV_HW_SAA7115,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_SVIDEO1,    0, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 0, IVTV_SAA71XX_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_LINE_IN1,   CS53L32A_IN2 },
-       },
-       /* Does not have a tuner */
-       .pci_list = ivtv_pci_avc2010,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Nagase Transgear 5000TV card */
-
-static const struct ivtv_card_pci_info ivtv_pci_tg5000tv[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_tg5000tv = {
-       .type = IVTV_CARD_TG5000TV,
-       .name = "Nagase Transgear 5000TV",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7114 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X |
-       IVTV_HW_GPIO,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER |
-                 IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO2 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gr_config = UPD64031A_VERTICAL_EXTERNAL,
-       .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 },
-       .gpio_audio_input  = { .mask = 0x8080, .tuner  = 0x8000, .linein = 0x0080 },
-       .gpio_audio_mute   = { .mask = 0x6000, .mute   = 0x6000 },
-       .gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
-                             .lang1 = 0x0300, .lang2  = 0x0000, .both   = 0x0200 },
-       .gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
-                         .composite = 0x0010, .svideo = 0x0020 },
-       .tuners = {
-               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
-       },
-       .pci_list = ivtv_pci_tg5000tv,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AOpen VA2000MAX-SNT6 card */
-
-static const struct ivtv_card_pci_info ivtv_pci_va2000[] = {
-       { PCI_DEVICE_ID_IVTV16, 0, 0xff5f },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_va2000 = {
-       .type = IVTV_CARD_VA2000MAX_SNT6,
-       .name = "AOpen VA2000MAX-SNT6",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD6408X,
-       .hw_audio = IVTV_HW_MSP34XX,
-       .hw_audio_ctrl = IVTV_HW_MSP34XX,
-       .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
-                 IVTV_HW_UPD6408X | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
-       },
-       .tuners = {
-               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
-       },
-       .pci_list = ivtv_pci_va2000,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan MPG600GR/Kuroutoshikou CX23416GYC-STVLP cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_cx23416gyc[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN4, 0x0600 },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x0523 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_cx23416gyc = {
-       .type = IVTV_CARD_CX23416GYC,
-       .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO |
-               IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
-       .hw_audio = IVTV_HW_SAA717X,
-       .hw_audio_ctrl = IVTV_HW_SAA717X,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER |
-                 IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO3 |
-                                                IVTV_SAA717X_TUNER_FLAG },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
-       },
-       .gr_config = UPD64031A_VERTICAL_EXTERNAL,
-       .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
-       .gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
-                              .composite = 0x0020, .svideo = 0x0020 },
-       .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
-                            .f44100 = 0x4000, .f48000 = 0x8000 },
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
-       },
-       .pci_list = ivtv_pci_cx23416gyc,
-       .i2c = &ivtv_i2c_std,
-};
-
-static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
-       .type = IVTV_CARD_CX23416GYC_NOGR,
-       .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR)",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | IVTV_HW_UPD6408X,
-       .hw_audio = IVTV_HW_SAA717X,
-       .hw_audio_ctrl = IVTV_HW_SAA717X,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER |
-                 IVTV_HW_UPD6408X,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 |
-                                                IVTV_SAA717X_TUNER_FLAG },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
-       },
-       .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
-       .gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
-                              .composite = 0x0020, .svideo = 0x0020 },
-       .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
-                            .f44100 = 0x4000, .f48000 = 0x8000 },
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
-       },
-       .i2c = &ivtv_i2c_std,
-};
-
-static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
-       .type = IVTV_CARD_CX23416GYC_NOGRYCS,
-       .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR/YCS)",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO,
-       .hw_audio = IVTV_HW_SAA717X,
-       .hw_audio_ctrl = IVTV_HW_SAA717X,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 |
-                                                IVTV_SAA717X_TUNER_FLAG },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
-       },
-       .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
-       .gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
-                              .composite = 0x0020, .svideo = 0x0020 },
-       .gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
-                            .f44100 = 0x4000, .f48000 = 0x8000 },
-       .tuners = {
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
-       },
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* I/O Data GV-MVP/RX & GV-MVP/RX2W (dual tuner) cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd01e },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd038 }, /* 2W unit #1 */
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd039 }, /* 2W unit #2 */
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_gv_mvprx = {
-       .type = IVTV_CARD_GV_MVPRX,
-       .name = "I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_WM8739,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_VP27SMPX |
-                 IVTV_HW_TUNER | IVTV_HW_WM8739 |
-                 IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO1    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2    },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 },
-       .gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
-       .tuners = {
-               /* This card has the Panasonic VP27 tuner */
-               { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
-       },
-       .pci_list = ivtv_pci_gv_mvprx,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* I/O Data GV-MVP/RX2E card */
-
-static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx2e[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd025 },
-       {0, 0, 0}
-};
-
-static const struct ivtv_card ivtv_card_gv_mvprx2e = {
-       .type = IVTV_CARD_GV_MVPRX2E,
-       .name = "I/O Data GV-MVP/RX2E",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_WM8739,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
-                 IVTV_HW_VP27SMPX | IVTV_HW_WM8739,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 },
-       .gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
-       .tuners = {
-               /* This card has the Panasonic VP27 tuner */
-               { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
-       },
-       .pci_list = ivtv_pci_gv_mvprx2e,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* GotVIEW PCI DVD card */
-
-static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
-       .type = IVTV_CARD_GOTVIEW_PCI_DVD,
-       .name = "GotView PCI DVD",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA717X,
-       .hw_audio = IVTV_HW_SAA717X,
-       .hw_audio_ctrl = IVTV_HW_SAA717X,
-       .hw_all = IVTV_HW_SAA717X | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE1 },  /* pin 116 */
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0 },     /* pin 114/109 */
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },  /* pin 118 */
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN0 },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN2 },
-       },
-       .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
-       .tuners = {
-               /* This card has a Philips FQ1216ME MK3 tuner */
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-       },
-       .pci_list = ivtv_pci_gotview_pci_dvd,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* GotVIEW PCI DVD2 Deluxe card */
-
-static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd2[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW1, 0x0600 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
-       .type = IVTV_CARD_GOTVIEW_PCI_DVD2,
-       .name = "GotView PCI DVD2 Deluxe",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_muxer = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1,
-                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
-       .gpio_init = { .direction = 0x0800, .initial_value = 0 },
-       .gpio_audio_input  = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
-       .tuners = {
-               /* This card has a Philips FQ1216ME MK5 tuner */
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
-       },
-       .pci_list = ivtv_pci_gotview_pci_dvd2,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan MPC622 miniPCI card */
-
-static const struct ivtv_card_pci_info ivtv_pci_yuan_mpc622[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN2, 0xd998 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_yuan_mpc622 = {
-       .type = IVTV_CARD_YUAN_MPC622,
-       .name = "Yuan MPC622",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1,
-                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
-       },
-       .gpio_init = { .direction = 0x00ff, .initial_value = 0x0002 },
-       .tuners = {
-               /* This card has the TDA8290/TDA8275 tuner chips */
-               { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_TDA8290 },
-       },
-       .pci_list = ivtv_pci_yuan_mpc622,
-       .i2c = &ivtv_i2c_tda8290,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* DIGITAL COWBOY DCT-MTVP1 card */
-
-static const struct ivtv_card_pci_info ivtv_pci_dctmvtvp1[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_dctmvtvp1 = {
-       .type = IVTV_CARD_DCTMTVP1,
-       .name = "Digital Cowboy DCT-MTVP1",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X |
-               IVTV_HW_GPIO,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
-               IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0    },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO2    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
-               { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 },
-       .gpio_audio_input  = { .mask = 0x8080, .tuner  = 0x8000, .linein = 0x0080 },
-       .gpio_audio_mute   = { .mask = 0x6000, .mute   = 0x6000 },
-       .gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
-                             .lang1 = 0x0300, .lang2  = 0x0000, .both   = 0x0200 },
-       .gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
-                              .composite = 0x0010, .svideo = 0x0020},
-       .tuners = {
-               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
-       },
-       .pci_list = ivtv_pci_dctmvtvp1,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Yuan PG600-2/GotView PCI DVD Lite cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW2,  0x0600 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_pg600v2 = {
-       .type = IVTV_CARD_PG600V2,
-       .name = "Yuan PG600-2, GotView PCI DVD Lite",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
-       /* XC2028 support apparently works for the Yuan, it's still
-          uncertain whether it also works with the GotView. */
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1,
-                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
-       .xceive_pin = 12,
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .pci_list = ivtv_pci_pg600v2,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Club3D ZAP-TV1x01 cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_club3d[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_club3d = {
-       .type = IVTV_CARD_CLUB3D,
-       .name = "Club3D ZAP-TV1x01",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1,
-                 CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
-       .xceive_pin = 12,
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .pci_list = ivtv_pci_club3d,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AVerTV MCE 116 Plus (M116) card */
-
-static const struct ivtv_card_pci_info ivtv_pci_avertv_mce116[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc439 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_avertv_mce116 = {
-       .type = IVTV_CARD_AVERTV_MCE116,
-       .name = "AVerTV MCE 116 Plus",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739 |
-                 IVTV_HW_I2C_IR_RX_AVER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5 },
-       /* enable line-in */
-       .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
-       .xceive_pin = 10,
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .pci_list = ivtv_pci_avertv_mce116,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AVerMedia PVR-150 Plus / AVerTV M113 cards with a Daewoo/Partsnic Tuner */
-
-static const struct ivtv_card_pci_info ivtv_pci_aver_pvr150[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc034 }, /* NTSC */
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc035 }, /* NTSC FM */
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_aver_pvr150 = {
-       .type = IVTV_CARD_AVER_PVR150PLUS,
-       .name = "AVerMedia PVR-150 Plus / AVerTV M113 Partsnic (Daewoo) Tuner",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_muxer = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER |
-                 IVTV_HW_WM8739 | IVTV_HW_GPIO,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
-       /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */
-       .gpio_init = { .direction = 0xc000, .initial_value = 0 },
-       .gpio_audio_input  = { .mask   = 0xc000,
-                              .tuner  = 0x0000,
-                              .linein = 0x4000,
-                              .radio  = 0x8000 },
-       .tuners = {
-               /* Subsystem ID's 0xc03[45] have a Partsnic PTI-5NF05 tuner */
-               { .std = V4L2_STD_MN, .tuner = TUNER_PARTSNIC_PTI_5NF05 },
-       },
-       .pci_list = ivtv_pci_aver_pvr150,
-       /* Subsystem ID 0xc035 has a TEA5767(?) FM tuner, 0xc034 does not */
-       .i2c = &ivtv_i2c_radio,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */
-
-static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, /* NTSC */
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc01b }, /* PAL/SECAM */
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_aver_ultra1500mce = {
-       .type = IVTV_CARD_AVER_ULTRA1500MCE,
-       .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner",
-       .comment = "For non-NTSC tuners, use the pal= or secam= module options",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_muxer = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER |
-                 IVTV_HW_WM8739 | IVTV_HW_GPIO,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
-       /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */
-       .gpio_init = { .direction = 0xc000, .initial_value = 0 },
-       .gpio_audio_input  = { .mask   = 0xc000,
-                              .tuner  = 0x0000,
-                              .linein = 0x4000,
-                              .radio  = 0x8000 },
-       .tuners = {
-               /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */
-               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
-               { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216MK5 },
-       },
-       .pci_list = ivtv_pci_aver_ultra1500mce,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AVerMedia EZMaker PCI Deluxe card */
-
-static const struct ivtv_card_pci_info ivtv_pci_aver_ezmaker[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc03f },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_aver_ezmaker = {
-       .type = IVTV_CARD_AVER_EZMAKER,
-       .name = "AVerMedia EZMaker PCI Deluxe",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 0 },
-       },
-       .gpio_init = { .direction = 0x4000, .initial_value = 0x4000 },
-       /* Does not have a tuner */
-       .pci_list = ivtv_pci_aver_ezmaker,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* ASUS Falcon2 */
-
-static const struct ivtv_card_pci_info ivtv_pci_asus_falcon2[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b66 },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x462e },
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b2e },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_asus_falcon2 = {
-       .type = IVTV_CARD_ASUS_FALCON2,
-       .name = "ASUS Falcon2",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_muxer = IVTV_HW_M52790,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_M52790 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 2, CX25840_COMPOSITE2 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, M52790_IN_TUNER },
-               { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL,
-                       M52790_IN_V2 | M52790_SW1_YCMIX | M52790_SW2_YCMIX },
-               { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, M52790_IN_V2 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
-       .tuners = {
-               { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
-       },
-       .pci_list = ivtv_pci_asus_falcon2,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* AVerMedia M104 miniPCI card */
-
-static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_aver_m104 = {
-       .type = IVTV_CARD_AVER_M104,
-       .name = "AVerMedia M104",
-       .comment = "Not yet supported!\n",
-       .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3    },
-               { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
-       },
-       .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
-       /* enable line-in + reset tuner */
-       .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
-       .xceive_pin = 10,
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .pci_list = ivtv_pci_aver_m104,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* Buffalo PC-MV5L/PCI cards */
-
-static const struct ivtv_card_pci_info ivtv_pci_buffalo[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x052b },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_buffalo = {
-       .type = IVTV_CARD_BUFFALO_MV5L,
-       .name = "Buffalo PC-MV5L/PCI",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_CX25840,
-       .hw_audio = IVTV_HW_CX25840,
-       .hw_audio_ctrl = IVTV_HW_CX25840,
-       .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
-       .video_inputs = {
-               { IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
-               { IVTV_CARD_INPUT_SVIDEO1,    1,
-                       CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
-               { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
-       },
-       .audio_inputs = {
-               { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
-               { IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
-       },
-       .xceive_pin = 12,
-       .tuners = {
-               { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
-       },
-       .pci_list = ivtv_pci_buffalo,
-       .i2c = &ivtv_i2c_std,
-};
-
-/* ------------------------------------------------------------------------- */
-/* Sony Kikyou */
-
-static const struct ivtv_card_pci_info ivtv_pci_kikyou[] = {
-       { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_SONY, 0x813d },
-       { 0, 0, 0 }
-};
-
-static const struct ivtv_card ivtv_card_kikyou = {
-       .type = IVTV_CARD_KIKYOU,
-       .name = "Sony VAIO Giga Pocket (ENX Kikyou)",
-       .v4l2_capabilities = IVTV_CAP_ENCODER,
-       .hw_video = IVTV_HW_SAA7115,
-       .hw_audio = IVTV_HW_GPIO,
-       .hw_audio_ctrl = IVTV_HW_GPIO,
-       .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER,
-       .video_inputs = {
-       { IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE1 },
-       { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE1 },
-       { IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO1 },
-       },
-       .audio_inputs = {
-            { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER },
-            { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
-            { IVTV_CARD_INPUT_LINE_IN2,   IVTV_GPIO_LINE_IN },
-       },
-       .gpio_init = { .direction = 0x03e1, .initial_value = 0x0320 },
-       .gpio_audio_input = { .mask   = 0x0060,
-                             .tuner  = 0x0020,
-                             .linein = 0x0000,
-                             .radio  = 0x0060 },
-       .gpio_audio_mute  = { .mask = 0x0000,
-                             .mute = 0x0000 }, /* 0x200? Disable for now. */
-       .gpio_audio_mode  = { .mask   = 0x0080,
-                             .mono   = 0x0000,
-                             .stereo = 0x0000, /* SAP */
-                             .lang1  = 0x0080,
-                             .lang2  = 0x0000,
-                             .both   = 0x0080 },
-       .tuners = {
-            { .std = V4L2_STD_ALL, .tuner = TUNER_SONY_BTF_PXN01Z },
-       },
-       .pci_list = ivtv_pci_kikyou,
-       .i2c = &ivtv_i2c_std,
-};
-
-
-static const struct ivtv_card *ivtv_card_list[] = {
-       &ivtv_card_pvr250,
-       &ivtv_card_pvr350,
-       &ivtv_card_pvr150,
-       &ivtv_card_m179,
-       &ivtv_card_mpg600,
-       &ivtv_card_mpg160,
-       &ivtv_card_pg600,
-       &ivtv_card_avc2410,
-       &ivtv_card_avc2010,
-       &ivtv_card_tg5000tv,
-       &ivtv_card_va2000,
-       &ivtv_card_cx23416gyc,
-       &ivtv_card_gv_mvprx,
-       &ivtv_card_gv_mvprx2e,
-       &ivtv_card_gotview_pci_dvd,
-       &ivtv_card_gotview_pci_dvd2,
-       &ivtv_card_yuan_mpc622,
-       &ivtv_card_dctmvtvp1,
-       &ivtv_card_pg600v2,
-       &ivtv_card_club3d,
-       &ivtv_card_avertv_mce116,
-       &ivtv_card_asus_falcon2,
-       &ivtv_card_aver_pvr150,
-       &ivtv_card_aver_ezmaker,
-       &ivtv_card_aver_m104,
-       &ivtv_card_buffalo,
-       &ivtv_card_aver_ultra1500mce,
-       &ivtv_card_kikyou,
-
-       /* Variations of standard cards but with the same PCI IDs.
-          These cards must come last in this list. */
-       &ivtv_card_pvr350_v1,
-       &ivtv_card_cx23416gyc_nogr,
-       &ivtv_card_cx23416gyc_nogrycs,
-};
-
-const struct ivtv_card *ivtv_get_card(u16 index)
-{
-       if (index >= ARRAY_SIZE(ivtv_card_list))
-               return NULL;
-       return ivtv_card_list[index];
-}
-
-int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
-{
-       const struct ivtv_card_video_input *card_input = itv->card->video_inputs + index;
-       static const char * const input_strs[] = {
-               "Tuner 1",
-               "S-Video 1",
-               "S-Video 2",
-               "Composite 1",
-               "Composite 2",
-               "Composite 3"
-       };
-
-       if (index >= itv->nof_inputs)
-               return -EINVAL;
-       input->index = index;
-       strlcpy(input->name, input_strs[card_input->video_type - 1],
-                       sizeof(input->name));
-       input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
-                       V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
-       input->audioset = (1 << itv->nof_audio_inputs) - 1;
-       input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
-                               itv->tuner_std : V4L2_STD_ALL;
-       return 0;
-}
-
-int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
-{
-       const struct ivtv_card_output *card_output = itv->card->video_outputs + index;
-
-       if (index >= itv->card->nof_outputs)
-               return -EINVAL;
-       output->index = index;
-       strlcpy(output->name, card_output->name, sizeof(output->name));
-       output->type = V4L2_OUTPUT_TYPE_ANALOG;
-       output->audioset = 1;
-       output->std = V4L2_STD_ALL;
-       return 0;
-}
-
-int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
-{
-       const struct ivtv_card_audio_input *aud_input = itv->card->audio_inputs + index;
-       static const char * const input_strs[] = {
-               "Tuner 1",
-               "Line In 1",
-               "Line In 2"
-       };
-
-       memset(audio, 0, sizeof(*audio));
-       if (index >= itv->nof_audio_inputs)
-               return -EINVAL;
-       strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
-                       sizeof(audio->name));
-       audio->index = index;
-       audio->capability = V4L2_AUDCAP_STEREO;
-       return 0;
-}
-
-int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud_output)
-{
-       memset(aud_output, 0, sizeof(*aud_output));
-       if (itv->card->video_outputs == NULL || index != 0)
-               return -EINVAL;
-       strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
-       return 0;
-}
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
deleted file mode 100644 (file)
index e6f5c02..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-    Functions to query card hardware
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_CARDS_H
-#define IVTV_CARDS_H
-
-/* Supported cards */
-#define IVTV_CARD_PVR_250            0 /* WinTV PVR 250 */
-#define IVTV_CARD_PVR_350            1 /* encoder, decoder, tv-out */
-#define IVTV_CARD_PVR_150            2 /* WinTV PVR 150 and PVR 500 (really just two
-                                          PVR150s on one PCI board) */
-#define IVTV_CARD_M179               3 /* AVerMedia M179 (encoder only) */
-#define IVTV_CARD_MPG600             4 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */
-#define IVTV_CARD_MPG160             5 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160
-                                          cx23415 based, but does not have tv-out */
-#define IVTV_CARD_PG600              6 /* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */
-#define IVTV_CARD_AVC2410            7 /* Adaptec AVC-2410 */
-#define IVTV_CARD_AVC2010            8 /* Adaptec AVD-2010 (No Tuner) */
-#define IVTV_CARD_TG5000TV           9 /* NAGASE TRANSGEAR 5000TV, encoder only */
-#define IVTV_CARD_VA2000MAX_SNT6     10 /* VA2000MAX-STN6 */
-#define IVTV_CARD_CX23416GYC        11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */
-#define IVTV_CARD_GV_MVPRX          12 /* I/O Data GV-MVP/RX, RX2, RX2W */
-#define IVTV_CARD_GV_MVPRX2E        13 /* I/O Data GV-MVP/RX2E */
-#define IVTV_CARD_GOTVIEW_PCI_DVD    14        /* GotView PCI DVD */
-#define IVTV_CARD_GOTVIEW_PCI_DVD2   15        /* GotView PCI DVD2 */
-#define IVTV_CARD_YUAN_MPC622        16        /* Yuan MPC622 miniPCI */
-#define IVTV_CARD_DCTMTVP1          17 /* DIGITAL COWBOY DCT-MTVP1 */
-#define IVTV_CARD_PG600V2           18 /* Yuan PG600V2/GotView PCI DVD Lite */
-#define IVTV_CARD_CLUB3D            19 /* Club3D ZAP-TV1x01 */
-#define IVTV_CARD_AVERTV_MCE116             20 /* AVerTV MCE 116 Plus */
-#define IVTV_CARD_ASUS_FALCON2      21 /* ASUS Falcon2 */
-#define IVTV_CARD_AVER_PVR150PLUS    22 /* AVerMedia PVR-150 Plus */
-#define IVTV_CARD_AVER_EZMAKER       23 /* AVerMedia EZMaker PCI Deluxe */
-#define IVTV_CARD_AVER_M104          24 /* AverMedia M104 miniPCI card */
-#define IVTV_CARD_BUFFALO_MV5L       25 /* Buffalo PC-MV5L/PCI card */
-#define IVTV_CARD_AVER_ULTRA1500MCE  26 /* AVerMedia UltraTV 1500 MCE */
-#define IVTV_CARD_KIKYOU             27 /* Sony VAIO Giga Pocket (ENX Kikyou) */
-#define IVTV_CARD_LAST                      27
-
-/* Variants of existing cards but with the same PCI IDs. The driver
-   detects these based on other device information.
-   These cards must always come last.
-   New cards must be inserted above, and the indices of the cards below
-   must be adjusted accordingly. */
-
-/* PVR-350 V1 (uses saa7114) */
-#define IVTV_CARD_PVR_350_V1        (IVTV_CARD_LAST+1)
-/* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */
-#define IVTV_CARD_CX23416GYC_NOGR    (IVTV_CARD_LAST+2)
-#define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3)
-
-/* system vendor and device IDs */
-#define PCI_VENDOR_ID_ICOMP  0x4444
-#define PCI_DEVICE_ID_IVTV15 0x0803
-#define PCI_DEVICE_ID_IVTV16 0x0016
-
-/* subsystem vendor ID */
-#define IVTV_PCI_ID_HAUPPAUGE          0x0070
-#define IVTV_PCI_ID_HAUPPAUGE_ALT1     0x0270
-#define IVTV_PCI_ID_HAUPPAUGE_ALT2     0x4070
-#define IVTV_PCI_ID_ADAPTEC            0x9005
-#define IVTV_PCI_ID_ASUSTEK            0x1043
-#define IVTV_PCI_ID_AVERMEDIA          0x1461
-#define IVTV_PCI_ID_YUAN1              0x12ab
-#define IVTV_PCI_ID_YUAN2              0xff01
-#define IVTV_PCI_ID_YUAN3              0xffab
-#define IVTV_PCI_ID_YUAN4              0xfbab
-#define IVTV_PCI_ID_DIAMONDMM          0xff92
-#define IVTV_PCI_ID_IODATA             0x10fc
-#define IVTV_PCI_ID_MELCO              0x1154
-#define IVTV_PCI_ID_GOTVIEW1           0xffac
-#define IVTV_PCI_ID_GOTVIEW2           0xffad
-#define IVTV_PCI_ID_SONY               0x104d
-
-/* hardware flags, no gaps allowed */
-#define IVTV_HW_CX25840                        (1 << 0)
-#define IVTV_HW_SAA7115                        (1 << 1)
-#define IVTV_HW_SAA7127                        (1 << 2)
-#define IVTV_HW_MSP34XX                        (1 << 3)
-#define IVTV_HW_TUNER                  (1 << 4)
-#define IVTV_HW_WM8775                 (1 << 5)
-#define IVTV_HW_CS53L32A               (1 << 6)
-#define IVTV_HW_TVEEPROM               (1 << 7)
-#define IVTV_HW_SAA7114                        (1 << 8)
-#define IVTV_HW_UPD64031A              (1 << 9)
-#define IVTV_HW_UPD6408X               (1 << 10)
-#define IVTV_HW_SAA717X                        (1 << 11)
-#define IVTV_HW_WM8739                 (1 << 12)
-#define IVTV_HW_VP27SMPX               (1 << 13)
-#define IVTV_HW_M52790                 (1 << 14)
-#define IVTV_HW_GPIO                   (1 << 15)
-#define IVTV_HW_I2C_IR_RX_AVER         (1 << 16)
-#define IVTV_HW_I2C_IR_RX_HAUP_EXT     (1 << 17) /* External before internal */
-#define IVTV_HW_I2C_IR_RX_HAUP_INT     (1 << 18)
-#define IVTV_HW_Z8F0811_IR_TX_HAUP     (1 << 19)
-#define IVTV_HW_Z8F0811_IR_RX_HAUP     (1 << 20)
-#define IVTV_HW_I2C_IR_RX_ADAPTEC      (1 << 21)
-
-#define IVTV_HW_Z8F0811_IR_HAUP        (IVTV_HW_Z8F0811_IR_RX_HAUP | \
-                                IVTV_HW_Z8F0811_IR_TX_HAUP)
-
-#define IVTV_HW_SAA711X   (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)
-
-#define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \
-                          IVTV_HW_I2C_IR_RX_HAUP_EXT | \
-                          IVTV_HW_I2C_IR_RX_HAUP_INT | \
-                          IVTV_HW_Z8F0811_IR_RX_HAUP | \
-                          IVTV_HW_I2C_IR_RX_ADAPTEC)
-
-#define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP)
-
-#define IVTV_HW_IR_ANY   (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY)
-
-/* video inputs */
-#define        IVTV_CARD_INPUT_VID_TUNER       1
-#define        IVTV_CARD_INPUT_SVIDEO1         2
-#define        IVTV_CARD_INPUT_SVIDEO2         3
-#define        IVTV_CARD_INPUT_COMPOSITE1      4
-#define        IVTV_CARD_INPUT_COMPOSITE2      5
-#define        IVTV_CARD_INPUT_COMPOSITE3      6
-
-/* audio inputs */
-#define        IVTV_CARD_INPUT_AUD_TUNER       1
-#define        IVTV_CARD_INPUT_LINE_IN1        2
-#define        IVTV_CARD_INPUT_LINE_IN2        3
-
-#define IVTV_CARD_MAX_VIDEO_INPUTS 6
-#define IVTV_CARD_MAX_AUDIO_INPUTS 3
-#define IVTV_CARD_MAX_TUNERS      3
-
-/* SAA71XX HW inputs */
-#define IVTV_SAA71XX_COMPOSITE0 0
-#define IVTV_SAA71XX_COMPOSITE1 1
-#define IVTV_SAA71XX_COMPOSITE2 2
-#define IVTV_SAA71XX_COMPOSITE3 3
-#define IVTV_SAA71XX_COMPOSITE4 4
-#define IVTV_SAA71XX_COMPOSITE5 5
-#define IVTV_SAA71XX_SVIDEO0    6
-#define IVTV_SAA71XX_SVIDEO1    7
-#define IVTV_SAA71XX_SVIDEO2    8
-#define IVTV_SAA71XX_SVIDEO3    9
-
-/* SAA717X needs to mark the tuner input by ORing with this flag */
-#define IVTV_SAA717X_TUNER_FLAG 0x80
-
-/* Dummy HW input */
-#define IVTV_DUMMY_AUDIO        0
-
-/* GPIO HW inputs */
-#define IVTV_GPIO_TUNER   0
-#define IVTV_GPIO_LINE_IN 1
-
-/* SAA717X HW inputs */
-#define IVTV_SAA717X_IN0 0
-#define IVTV_SAA717X_IN1 1
-#define IVTV_SAA717X_IN2 2
-
-/* V4L2 capability aliases */
-#define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
-                         V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
-                         V4L2_CAP_SLICED_VBI_CAPTURE)
-#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \
-                         V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
-
-struct ivtv_card_video_input {
-       u8  video_type;         /* video input type */
-       u8  audio_index;        /* index in ivtv_card_audio_input array */
-       u16 video_input;        /* hardware video input */
-};
-
-struct ivtv_card_audio_input {
-       u8  audio_type;         /* audio input type */
-       u32 audio_input;        /* hardware audio input */
-       u16 muxer_input;        /* hardware muxer input for boards with a
-                                  multiplexer chip */
-};
-
-struct ivtv_card_output {
-       u8  name[32];
-       u16 video_output;  /* hardware video output */
-};
-
-struct ivtv_card_pci_info {
-       u16 device;
-       u16 subsystem_vendor;
-       u16 subsystem_device;
-};
-
-/* GPIO definitions */
-
-/* The mask is the set of bits used by the operation */
-
-struct ivtv_gpio_init {        /* set initial GPIO DIR and OUT values */
-       u16 direction;          /* DIR setting. Leave to 0 if no init is needed */
-       u16 initial_value;
-};
-
-struct ivtv_gpio_video_input {         /* select tuner/line in input */
-       u16 mask;               /* leave to 0 if not supported */
-       u16 tuner;
-       u16 composite;
-       u16 svideo;
-};
-
-struct ivtv_gpio_audio_input {         /* select tuner/line in input */
-       u16 mask;               /* leave to 0 if not supported */
-       u16 tuner;
-       u16 linein;
-       u16 radio;
-};
-
-struct ivtv_gpio_audio_mute {
-       u16 mask;               /* leave to 0 if not supported */
-       u16 mute;               /* set this value to mute, 0 to unmute */
-};
-
-struct ivtv_gpio_audio_mode {
-       u16 mask;               /* leave to 0 if not supported */
-       u16 mono;               /* set audio to mono */
-       u16 stereo;             /* set audio to stereo */
-       u16 lang1;              /* set audio to the first language */
-       u16 lang2;              /* set audio to the second language */
-       u16 both;               /* both languages are output */
-};
-
-struct ivtv_gpio_audio_freq {
-       u16 mask;               /* leave to 0 if not supported */
-       u16 f32000;
-       u16 f44100;
-       u16 f48000;
-};
-
-struct ivtv_gpio_audio_detect {
-       u16 mask;               /* leave to 0 if not supported */
-       u16 stereo;             /* if the input matches this value then
-                                  stereo is detected */
-};
-
-struct ivtv_card_tuner {
-       v4l2_std_id std;        /* standard for which the tuner is suitable */
-       int         tuner;      /* tuner ID (from tuner.h) */
-};
-
-struct ivtv_card_tuner_i2c {
-       unsigned short radio[2];/* radio tuner i2c address to probe */
-       unsigned short demod[2];/* demodulator i2c address to probe */
-       unsigned short tv[4];   /* tv tuner i2c addresses to probe */
-};
-
-/* for card information/parameters */
-struct ivtv_card {
-       int type;
-       char *name;
-       char *comment;
-       u32 v4l2_capabilities;
-       u32 hw_video;           /* hardware used to process video */
-       u32 hw_audio;           /* hardware used to process audio */
-       u32 hw_audio_ctrl;      /* hardware used for the V4L2 controls (only 1 dev allowed) */
-       u32 hw_muxer;           /* hardware used to multiplex audio input */
-       u32 hw_all;             /* all hardware used by the board */
-       struct ivtv_card_video_input video_inputs[IVTV_CARD_MAX_VIDEO_INPUTS];
-       struct ivtv_card_audio_input audio_inputs[IVTV_CARD_MAX_AUDIO_INPUTS];
-       struct ivtv_card_audio_input radio_input;
-       int nof_outputs;
-       const struct ivtv_card_output *video_outputs;
-       u8 gr_config;           /* config byte for the ghost reduction device */
-       u8 xceive_pin;          /* XCeive tuner GPIO reset pin */
-
-       /* GPIO card-specific settings */
-       struct ivtv_gpio_init           gpio_init;
-       struct ivtv_gpio_video_input    gpio_video_input;
-       struct ivtv_gpio_audio_input    gpio_audio_input;
-       struct ivtv_gpio_audio_mute     gpio_audio_mute;
-       struct ivtv_gpio_audio_mode     gpio_audio_mode;
-       struct ivtv_gpio_audio_freq     gpio_audio_freq;
-       struct ivtv_gpio_audio_detect   gpio_audio_detect;
-
-       struct ivtv_card_tuner tuners[IVTV_CARD_MAX_TUNERS];
-       struct ivtv_card_tuner_i2c *i2c;
-
-       /* list of device and subsystem vendor/devices that
-          correspond to this card type. */
-       const struct ivtv_card_pci_info *pci_list;
-};
-
-int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input);
-int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output);
-int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input);
-int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output);
-const struct ivtv_card *ivtv_get_card(u16 index);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c
deleted file mode 100644 (file)
index c604246..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-    ioctl control functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-controls.h"
-#include "ivtv-mailbox.h"
-
-static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
-{
-       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
-
-       /* First try to allocate sliced VBI buffers if needed. */
-       if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) {
-               int i;
-
-               for (i = 0; i < IVTV_VBI_FRAMES; i++) {
-                       /* Yuck, hardcoded. Needs to be a define */
-                       itv->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
-                       if (itv->vbi.sliced_mpeg_data[i] == NULL) {
-                               while (--i >= 0) {
-                                       kfree(itv->vbi.sliced_mpeg_data[i]);
-                                       itv->vbi.sliced_mpeg_data[i] = NULL;
-                               }
-                               return -ENOMEM;
-                       }
-               }
-       }
-
-       itv->vbi.insert_mpeg = fmt;
-
-       if (itv->vbi.insert_mpeg == 0) {
-               return 0;
-       }
-       /* Need sliced data for mpeg insertion */
-       if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) {
-               if (itv->is_60hz)
-                       itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
-               else
-                       itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
-               ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz);
-       }
-       return 0;
-}
-
-static int ivtv_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
-{
-       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
-       int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-       struct v4l2_mbus_framefmt fmt;
-
-       /* fix videodecoder resolution */
-       fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
-       fmt.height = cxhdl->height;
-       fmt.code = V4L2_MBUS_FMT_FIXED;
-       v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
-       return 0;
-}
-
-static int ivtv_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
-{
-       static const u32 freqs[3] = { 44100, 48000, 32000 };
-       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
-
-       /* The audio clock of the digitizer must match the codec sample
-          rate otherwise you get some very strange effects. */
-       if (idx < ARRAY_SIZE(freqs))
-               ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
-       return 0;
-}
-
-static int ivtv_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
-{
-       struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
-
-       itv->dualwatch_stereo_mode = val;
-       return 0;
-}
-
-struct cx2341x_handler_ops ivtv_cxhdl_ops = {
-       .s_audio_mode = ivtv_s_audio_mode,
-       .s_audio_sampling_freq = ivtv_s_audio_sampling_freq,
-       .s_video_encoding = ivtv_s_video_encoding,
-       .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt,
-};
-
-int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-
-       if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
-               *pts = (s64)((u64)itv->last_dec_timing[2] << 32) |
-                       (u64)itv->last_dec_timing[1];
-               *frame = itv->last_dec_timing[0];
-               return 0;
-       }
-       *pts = 0;
-       *frame = 0;
-       if (atomic_read(&itv->decoding)) {
-               if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
-                       IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
-                       return -EIO;
-               }
-               memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
-               set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
-               *pts = (s64)((u64) data[2] << 32) | (u64) data[1];
-               *frame = data[0];
-               /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
-       }
-       return 0;
-}
-
-static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl);
-
-       switch (ctrl->id) {
-       /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
-          control cluster */
-       case V4L2_CID_MPEG_VIDEO_DEC_PTS:
-               return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
-                                            &itv->ctrl_frame->val64);
-       }
-       return 0;
-}
-
-static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl);
-
-       switch (ctrl->id) {
-       /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK
-          control cluster */
-       case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
-               itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1;
-               itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1;
-               ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
-               break;
-       }
-       return 0;
-}
-
-const struct v4l2_ctrl_ops ivtv_hdl_out_ops = {
-       .s_ctrl = ivtv_s_ctrl,
-       .g_volatile_ctrl = ivtv_g_volatile_ctrl,
-};
diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h
deleted file mode 100644 (file)
index 3999e63..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-    ioctl control functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_CONTROLS_H
-#define IVTV_CONTROLS_H
-
-extern struct cx2341x_handler_ops ivtv_cxhdl_ops;
-extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops;
-int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
deleted file mode 100644 (file)
index 5462ce2..0000000
+++ /dev/null
@@ -1,1498 +0,0 @@
-/*
-    ivtv driver initialization and card probing
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    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
- */
-
-/* Main Driver file for the ivtv project:
- * Driver for the Conexant CX23415/CX23416 chip.
- * Author: Kevin Thayer (nufan_wfk at yahoo.com)
- * License: GPL
- * http://www.ivtvdriver.org
- *
- * -----
- * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
- *                      and Takeru KOMORIYA<komoriya@paken.org>
- *
- * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
- *                using information provided by Jiun-Kuei Jung @ AVerMedia.
- *
- * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp>
- *                using information from T.Adachi,Takeru KOMORIYA and others :-)
- *
- * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX
- *                version by T.Adachi. Special thanks  Mr.Suzuki
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-version.h"
-#include "ivtv-fileops.h"
-#include "ivtv-i2c.h"
-#include "ivtv-firmware.h"
-#include "ivtv-queue.h"
-#include "ivtv-udma.h"
-#include "ivtv-irq.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-streams.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-cards.h"
-#include "ivtv-vbi.h"
-#include "ivtv-routing.h"
-#include "ivtv-controls.h"
-#include "ivtv-gpio.h"
-#include <linux/dma-mapping.h>
-#include <media/tveeprom.h>
-#include <media/saa7115.h>
-#include <media/v4l2-chip-ident.h>
-#include "tuner-xc2028.h"
-
-/* If you have already X v4l cards, then set this to X. This way
-   the device numbers stay matched. Example: you have a WinTV card
-   without radio and a PVR-350 with. Normally this would give a
-   video1 device together with a radio0 device for the PVR. By
-   setting this to 1 you ensure that radio0 is now also radio1. */
-int ivtv_first_minor;
-
-/* add your revision and whatnot here */
-static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
-       {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {0,}
-};
-
-MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
-
-/* ivtv instance counter */
-static atomic_t ivtv_instance = ATOMIC_INIT(0);
-
-/* Parameter declarations */
-static int cardtype[IVTV_MAX_CARDS];
-static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1 };
-static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1,
-                                    -1, -1, -1, -1, -1, -1, -1, -1 };
-static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
-                                              -1, -1, -1, -1, -1, -1, -1, -1,
-                                              -1, -1, -1, -1, -1, -1, -1, -1,
-                                              -1, -1, -1, -1, -1, -1, -1, -1 };
-
-static unsigned int cardtype_c = 1;
-static unsigned int tuner_c = 1;
-static int radio_c = 1;
-static unsigned int i2c_clock_period_c = 1;
-static char pal[] = "---";
-static char secam[] = "--";
-static char ntsc[] = "-";
-
-/* Buffers */
-
-/* DMA Buffers, Default size in MB allocated */
-#define IVTV_DEFAULT_ENC_MPG_BUFFERS 4
-#define IVTV_DEFAULT_ENC_YUV_BUFFERS 2
-#define IVTV_DEFAULT_ENC_VBI_BUFFERS 1
-/* Exception: size in kB for this stream (MB is overkill) */
-#define IVTV_DEFAULT_ENC_PCM_BUFFERS 320
-#define IVTV_DEFAULT_DEC_MPG_BUFFERS 1
-#define IVTV_DEFAULT_DEC_YUV_BUFFERS 1
-/* Exception: size in kB for this stream (MB is way overkill) */
-#define IVTV_DEFAULT_DEC_VBI_BUFFERS 64
-
-static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS;
-static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS;
-static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS;
-static int enc_pcm_buffers = IVTV_DEFAULT_ENC_PCM_BUFFERS;
-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;
-static int ivtv_yuv_threshold = -1;
-static int ivtv_pci_latency = 1;
-
-int ivtv_debug;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-int ivtv_fw_debug;
-#endif
-
-static int tunertype = -1;
-static int newi2c = -1;
-
-module_param_array(tuner, int, &tuner_c, 0644);
-module_param_array(radio, int, &radio_c, 0644);
-module_param_array(cardtype, int, &cardtype_c, 0644);
-module_param_string(pal, pal, sizeof(pal), 0644);
-module_param_string(secam, secam, sizeof(secam), 0644);
-module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
-module_param_named(debug,ivtv_debug, int, 0644);
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-module_param_named(fw_debug, ivtv_fw_debug, int, 0644);
-#endif
-module_param(ivtv_pci_latency, int, 0644);
-module_param(ivtv_yuv_mode, int, 0644);
-module_param(ivtv_yuv_threshold, int, 0644);
-module_param(ivtv_first_minor, int, 0644);
-
-module_param(enc_mpg_buffers, int, 0644);
-module_param(enc_yuv_buffers, int, 0644);
-module_param(enc_vbi_buffers, int, 0644);
-module_param(enc_pcm_buffers, int, 0644);
-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_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644);
-
-MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
-                       "\t\t\tsee tuner.h for values");
-MODULE_PARM_DESC(radio,
-                "Enable or disable the radio. Use only if autodetection\n"
-                "\t\t\tfails. 0 = disable, 1 = enable");
-MODULE_PARM_DESC(cardtype,
-                "Only use this option if your card is not detected properly.\n"
-                "\t\tSpecify card type:\n"
-                "\t\t\t 1 = WinTV PVR 250\n"
-                "\t\t\t 2 = WinTV PVR 350\n"
-                "\t\t\t 3 = WinTV PVR-150 or PVR-500\n"
-                "\t\t\t 4 = AVerMedia M179\n"
-                "\t\t\t 5 = YUAN MPG600/Kuroutoshikou iTVC16-STVLP\n"
-                "\t\t\t 6 = YUAN MPG160/Kuroutoshikou iTVC15-STVLP\n"
-                "\t\t\t 7 = YUAN PG600/DIAMONDMM PVR-550 (CX Falcon 2)\n"
-                "\t\t\t 8 = Adaptec AVC-2410\n"
-                "\t\t\t 9 = Adaptec AVC-2010\n"
-                "\t\t\t10 = NAGASE TRANSGEAR 5000TV\n"
-                "\t\t\t11 = AOpen VA2000MAX-STN6\n"
-                "\t\t\t12 = YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP\n"
-                "\t\t\t13 = I/O Data GV-MVP/RX\n"
-                "\t\t\t14 = I/O Data GV-MVP/RX2E\n"
-                "\t\t\t15 = GOTVIEW PCI DVD\n"
-                "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n"
-                "\t\t\t17 = Yuan MPC622\n"
-                "\t\t\t18 = Digital Cowboy DCT-MTVP1\n"
-                "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite\n"
-                "\t\t\t20 = Club3D ZAP-TV1x01\n"
-                "\t\t\t21 = AverTV MCE 116 Plus\n"
-                "\t\t\t22 = ASUS Falcon2\n"
-                "\t\t\t23 = AverMedia PVR-150 Plus\n"
-                "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
-                "\t\t\t25 = AverMedia M104 (not yet working)\n"
-                "\t\t\t26 = Buffalo PC-MV5L/PCI\n"
-                "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n"
-                "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\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: 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"
-                "\t\t\t   2/0x0002: info\n"
-                "\t\t\t   4/0x0004: mailbox\n"
-                "\t\t\t   8/0x0008: ioctl\n"
-                "\t\t\t  16/0x0010: file\n"
-                "\t\t\t  32/0x0020: dma\n"
-                "\t\t\t  64/0x0040: irq\n"
-                "\t\t\t 128/0x0080: decoder\n"
-                "\t\t\t 256/0x0100: yuv\n"
-                "\t\t\t 512/0x0200: i2c\n"
-                "\t\t\t1024/0x0400: high volume\n");
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-MODULE_PARM_DESC(fw_debug,
-                "Enable code for debugging firmware problems.  Default: 0\n");
-#endif
-MODULE_PARM_DESC(ivtv_pci_latency,
-                "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
-                "\t\t\tDefault: Yes");
-MODULE_PARM_DESC(ivtv_yuv_mode,
-                "Specify the yuv playback mode:\n"
-                "\t\t\t0 = interlaced\n\t\t\t1 = progressive\n\t\t\t2 = auto\n"
-                "\t\t\tDefault: 0 (interlaced)");
-MODULE_PARM_DESC(ivtv_yuv_threshold,
-                "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n"
-                "\t\t\tDefault: 480");
-MODULE_PARM_DESC(enc_mpg_buffers,
-                "Encoder MPG Buffers (in MB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS));
-MODULE_PARM_DESC(enc_yuv_buffers,
-                "Encoder YUV Buffers (in MB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_YUV_BUFFERS));
-MODULE_PARM_DESC(enc_vbi_buffers,
-                "Encoder VBI Buffers (in MB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS));
-MODULE_PARM_DESC(enc_pcm_buffers,
-                "Encoder PCM buffers (in kB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS));
-MODULE_PARM_DESC(dec_mpg_buffers,
-                "Decoder MPG buffers (in MB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_MPG_BUFFERS));
-MODULE_PARM_DESC(dec_yuv_buffers,
-                "Decoder YUV buffers (in MB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS));
-MODULE_PARM_DESC(dec_vbi_buffers,
-                "Decoder VBI buffers (in kB)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS));
-MODULE_PARM_DESC(newi2c,
-                "Use new I2C implementation\n"
-                "\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
-                "\t\t\tDefault is autodetect");
-MODULE_PARM_DESC(i2c_clock_period,
-                "Period of SCL for the I2C bus controlled by the CX23415/6\n"
-                "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n"
-                "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD));
-
-MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card");
-
-MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
-MODULE_DESCRIPTION("CX23415/CX23416 driver");
-MODULE_SUPPORTED_DEVICE
-    ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n"
-               "\t\t\tYuan MPG series and similar)");
-MODULE_LICENSE("GPL");
-
-MODULE_VERSION(IVTV_VERSION);
-
-void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask)
-{
-       itv->irqmask &= ~mask;
-       write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK);
-}
-
-void ivtv_set_irq_mask(struct ivtv *itv, u32 mask)
-{
-       itv->irqmask |= mask;
-       write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK);
-}
-
-int ivtv_set_output_mode(struct ivtv *itv, int mode)
-{
-    int old_mode;
-
-    spin_lock(&itv->lock);
-    old_mode = itv->output_mode;
-    if (old_mode == 0)
-       itv->output_mode = old_mode = mode;
-    spin_unlock(&itv->lock);
-    return old_mode;
-}
-
-struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv)
-{
-       switch (itv->output_mode) {
-       case OUT_MPG:
-               return &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
-       case OUT_YUV:
-               return &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
-       default:
-               return NULL;
-       }
-}
-
-int ivtv_waitq(wait_queue_head_t *waitq)
-{
-       DEFINE_WAIT(wait);
-
-       prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE);
-       schedule();
-       finish_wait(waitq, &wait);
-       return signal_pending(current) ? -EINTR : 0;
-}
-
-/* Generic utility functions */
-int ivtv_msleep_timeout(unsigned int msecs, int intr)
-{
-       int timeout = msecs_to_jiffies(msecs);
-
-       do {
-               set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-               if (intr) {
-                       int ret = signal_pending(current);
-
-                       if (ret)
-                               return ret;
-               }
-       } while (timeout);
-       return 0;
-}
-
-/* Release ioremapped memory */
-static void ivtv_iounmap(struct ivtv *itv)
-{
-       if (itv == NULL)
-               return;
-
-       /* Release registers memory */
-       if (itv->reg_mem != NULL) {
-               IVTV_DEBUG_INFO("releasing reg_mem\n");
-               iounmap(itv->reg_mem);
-               itv->reg_mem = NULL;
-       }
-       /* Release io memory */
-       if (itv->has_cx23415 && itv->dec_mem != NULL) {
-               IVTV_DEBUG_INFO("releasing dec_mem\n");
-               iounmap(itv->dec_mem);
-       }
-       itv->dec_mem = NULL;
-
-       /* Release io memory */
-       if (itv->enc_mem != NULL) {
-               IVTV_DEBUG_INFO("releasing enc_mem\n");
-               iounmap(itv->enc_mem);
-               itv->enc_mem = NULL;
-       }
-}
-
-/* Hauppauge card? get values from tveeprom */
-void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
-{
-       u8 eedata[256];
-
-       itv->i2c_client.addr = 0xA0 >> 1;
-       tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata));
-       tveeprom_hauppauge_analog(&itv->i2c_client, tv, eedata);
-}
-
-static void ivtv_process_eeprom(struct ivtv *itv)
-{
-       struct tveeprom tv;
-       int pci_slot = PCI_SLOT(itv->pdev->devfn);
-
-       ivtv_read_eeprom(itv, &tv);
-
-       /* Many thanks to Steven Toth from Hauppauge for providing the
-          model numbers */
-       switch (tv.model) {
-               /* In a few cases the PCI subsystem IDs do not correctly
-                  identify the card. A better method is to check the
-                  model number from the eeprom instead. */
-               case 30012 ... 30039:  /* Low profile PVR250 */
-               case 32000 ... 32999:
-               case 48000 ... 48099:  /* 48??? range are PVR250s with a cx23415 */
-               case 48400 ... 48599:
-                       itv->card = ivtv_get_card(IVTV_CARD_PVR_250);
-                       break;
-               case 48100 ... 48399:
-               case 48600 ... 48999:
-                       itv->card = ivtv_get_card(IVTV_CARD_PVR_350);
-                       break;
-               case 23000 ... 23999:  /* PVR500 */
-               case 25000 ... 25999:  /* Low profile PVR150 */
-               case 26000 ... 26999:  /* Regular PVR150 */
-                       itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
-                       break;
-               case 0:
-                       IVTV_ERR("Invalid EEPROM\n");
-                       return;
-               default:
-                       IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model);
-                       itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
-                       break;
-       }
-
-       switch (tv.model) {
-               /* Old style PVR350 (with an saa7114) uses this input for
-                  the tuner. */
-               case 48254:
-                       itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1);
-                       break;
-               default:
-                       break;
-       }
-
-       itv->v4l2_cap = itv->card->v4l2_capabilities;
-       itv->card_name = itv->card->name;
-       itv->card_i2c = itv->card->i2c;
-
-       /* If this is a PVR500 then it should be possible to detect whether it is the
-          first or second unit by looking at the subsystem device ID: is bit 4 is
-          set, then it is the second unit (according to info from Hauppauge).
-
-          However, while this works for most cards, I have seen a few PVR500 cards
-          where both units have the same subsystem ID.
-
-          So instead I look at the reported 'PCI slot' (which is the slot on the PVR500
-          PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise
-          it is the second unit. It is possible that it is a different slot when ivtv is
-          used in Xen, in that case I ignore this card here. The worst that can happen
-          is that the card presents itself with a non-working radio device.
-
-          This detection is needed since the eeprom reports incorrectly that a radio is
-          present on the second unit. */
-       if (tv.model / 1000 == 23) {
-               static const struct ivtv_card_tuner_i2c ivtv_i2c_radio = {
-                       .radio = { 0x60, I2C_CLIENT_END },
-                       .demod = { 0x43, I2C_CLIENT_END },
-                       .tv = { 0x61, I2C_CLIENT_END },
-               };
-
-               itv->card_name = "WinTV PVR 500";
-               itv->card_i2c = &ivtv_i2c_radio;
-               if (pci_slot == 8 || pci_slot == 9) {
-                       int is_first = (pci_slot & 1) == 0;
-
-                       itv->card_name = is_first ? "WinTV PVR 500 (unit #1)" :
-                                                   "WinTV PVR 500 (unit #2)";
-                       if (!is_first) {
-                               IVTV_INFO("Correcting tveeprom data: no radio present on second unit\n");
-                               tv.has_radio = 0;
-                       }
-               }
-       }
-       IVTV_INFO("Autodetected %s\n", itv->card_name);
-
-       switch (tv.tuner_hauppauge_model) {
-               case 85:
-               case 99:
-               case 112:
-                       itv->pvr150_workaround = 1;
-                       break;
-               default:
-                       break;
-       }
-       if (tv.tuner_type == TUNER_ABSENT)
-               IVTV_ERR("tveeprom cannot autodetect tuner!\n");
-
-       if (itv->options.tuner == -1)
-               itv->options.tuner = tv.tuner_type;
-       if (itv->options.radio == -1)
-               itv->options.radio = (tv.has_radio != 0);
-       /* only enable newi2c if an IR blaster is present */
-       if (itv->options.newi2c == -1 && tv.has_ir) {
-               itv->options.newi2c = (tv.has_ir & 4) ? 1 : 0;
-               if (itv->options.newi2c) {
-                   IVTV_INFO("Reopen i2c bus for IR-blaster support\n");
-                   exit_ivtv_i2c(itv);
-                   init_ivtv_i2c(itv);
-               }
-       }
-
-       if (itv->std != 0)
-               /* user specified tuner standard */
-               return;
-
-       /* autodetect tuner standard */
-       if (tv.tuner_formats & V4L2_STD_PAL) {
-               IVTV_DEBUG_INFO("PAL tuner detected\n");
-               itv->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
-       } else if (tv.tuner_formats & V4L2_STD_NTSC) {
-               IVTV_DEBUG_INFO("NTSC tuner detected\n");
-               itv->std |= V4L2_STD_NTSC_M;
-       } else if (tv.tuner_formats & V4L2_STD_SECAM) {
-               IVTV_DEBUG_INFO("SECAM tuner detected\n");
-               itv->std |= V4L2_STD_SECAM_L;
-       } else {
-               IVTV_INFO("No tuner detected, default to NTSC-M\n");
-               itv->std |= V4L2_STD_NTSC_M;
-       }
-}
-
-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':
-               case 'h':
-               case '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;
-               default:
-                       IVTV_WARN("pal= argument not recognised\n");
-                       return 0;
-       }
-
-       switch (secam[0]) {
-               case 'b':
-               case 'B':
-               case 'g':
-               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;
-               case '-':
-                       break;
-               default:
-                       IVTV_WARN("secam= argument not recognised\n");
-                       return 0;
-       }
-
-       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;
-               default:
-                       IVTV_WARN("ntsc= argument not recognised\n");
-                       return 0;
-       }
-
-       /* no match found */
-       return 0;
-}
-
-static void ivtv_process_options(struct ivtv *itv)
-{
-       const char *chipname;
-       int i, j;
-
-       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers * 1024;
-       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers * 1024;
-       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers * 1024;
-       itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
-       itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024;
-       itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024;
-       itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers;
-       itv->options.cardtype = cardtype[itv->instance];
-       itv->options.tuner = tuner[itv->instance];
-       itv->options.radio = radio[itv->instance];
-
-       itv->options.i2c_clock_period = i2c_clock_period[itv->instance];
-       if (itv->options.i2c_clock_period == -1)
-               itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD;
-       else if (itv->options.i2c_clock_period < 10)
-               itv->options.i2c_clock_period = 10;
-       else if (itv->options.i2c_clock_period > 4500)
-               itv->options.i2c_clock_period = 4500;
-
-       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->pdev->device == PCI_DEVICE_ID_IVTV15);
-       chipname = itv->has_cx23415 ? "cx23415" : "cx23416";
-       if (itv->options.cardtype == -1) {
-               IVTV_INFO("Ignore card (detected %s based chip)\n", chipname);
-               return;
-       }
-       if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) {
-               IVTV_INFO("User specified %s card (detected %s based chip)\n",
-                               itv->card->name, chipname);
-       } else if (itv->options.cardtype != 0) {
-               IVTV_ERR("Unknown user specified type, trying to autodetect card\n");
-       }
-       if (itv->card == NULL) {
-               if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE ||
-                   itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 ||
-                   itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) {
-                       itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150);
-                       IVTV_INFO("Autodetected Hauppauge card (%s based)\n",
-                                       chipname);
-               }
-       }
-       if (itv->card == NULL) {
-               for (i = 0; (itv->card = ivtv_get_card(i)); i++) {
-                       if (itv->card->pci_list == NULL)
-                               continue;
-                       for (j = 0; itv->card->pci_list[j].device; j++) {
-                               if (itv->pdev->device !=
-                                   itv->card->pci_list[j].device)
-                                       continue;
-                               if (itv->pdev->subsystem_vendor !=
-                                   itv->card->pci_list[j].subsystem_vendor)
-                                       continue;
-                               if (itv->pdev->subsystem_device !=
-                                   itv->card->pci_list[j].subsystem_device)
-                                       continue;
-                               IVTV_INFO("Autodetected %s card (%s based)\n",
-                                               itv->card->name, chipname);
-                               goto done;
-                       }
-               }
-       }
-done:
-
-       if (itv->card == NULL) {
-               itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
-               IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
-                    itv->pdev->vendor, itv->pdev->device);
-               IVTV_ERR("              subsystem vendor/device: [%04x:%04x]\n",
-                    itv->pdev->subsystem_vendor, itv->pdev->subsystem_device);
-               IVTV_ERR("              %s based\n", chipname);
-               IVTV_ERR("Defaulting to %s card\n", itv->card->name);
-               IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
-               IVTV_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
-               IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n");
-       }
-       itv->v4l2_cap = itv->card->v4l2_capabilities;
-       itv->card_name = itv->card->name;
-       itv->card_i2c = itv->card->i2c;
-}
-
-/* Precondition: the ivtv structure has been memset to 0. Only
-   the dev and num fields have been filled in.
-   No assumptions on the card type may be made here (see ivtv_init_struct2
-   for that).
- */
-static int __devinit ivtv_init_struct1(struct ivtv *itv)
-{
-       struct sched_param param = { .sched_priority = 99 };
-
-       itv->base_addr = pci_resource_start(itv->pdev, 0);
-       itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
-       itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */
-
-       mutex_init(&itv->serialize_lock);
-       mutex_init(&itv->i2c_bus_lock);
-       mutex_init(&itv->udma.lock);
-
-       spin_lock_init(&itv->lock);
-       spin_lock_init(&itv->dma_reg_lock);
-
-       init_kthread_worker(&itv->irq_worker);
-       itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker,
-                                          itv->v4l2_dev.name);
-       if (IS_ERR(itv->irq_worker_task)) {
-               IVTV_ERR("Could not create ivtv task\n");
-               return -1;
-       }
-       /* must use the FIFO scheduler as it is realtime sensitive */
-       sched_setscheduler(itv->irq_worker_task, SCHED_FIFO, &param);
-
-       init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
-
-       /* Initial settings */
-       itv->cxhdl.port = CX2341X_PORT_MEMORY;
-       itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
-       init_waitqueue_head(&itv->eos_waitq);
-       init_waitqueue_head(&itv->event_waitq);
-       init_waitqueue_head(&itv->vsync_waitq);
-       init_waitqueue_head(&itv->dma_waitq);
-       init_timer(&itv->dma_timer);
-       itv->dma_timer.function = ivtv_unfinished_dma;
-       itv->dma_timer.data = (unsigned long)itv;
-
-       itv->cur_dma_stream = -1;
-       itv->cur_pio_stream = -1;
-
-       /* Ctrls */
-       itv->speed = 1000;
-
-       /* VBI */
-       itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
-
-       /* Init the sg table for osd/yuv output */
-       sg_init_table(itv->udma.SGlist, IVTV_DMA_SG_OSD_ENT);
-
-       /* OSD */
-       itv->osd_global_alpha_state = 1;
-       itv->osd_global_alpha = 255;
-
-       /* YUV */
-       atomic_set(&itv->yuv_info.next_dma_frame, -1);
-       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;
-}
-
-/* Second initialization part. Here the card type has been
-   autodetected. */
-static void __devinit ivtv_init_struct2(struct ivtv *itv)
-{
-       int i;
-
-       for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
-               if (itv->card->video_inputs[i].video_type == 0)
-                       break;
-       itv->nof_inputs = i;
-       for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
-               if (itv->card->audio_inputs[i].audio_type == 0)
-                       break;
-       itv->nof_audio_inputs = i;
-
-       if (itv->card->hw_all & IVTV_HW_CX25840) {
-               itv->vbi.sliced_size = 288;  /* multiple of 16, real size = 284 */
-       } else {
-               itv->vbi.sliced_size = 64;   /* multiple of 16, real size = 52 */
-       }
-
-       /* Find tuner input */
-       for (i = 0; i < itv->nof_inputs; i++) {
-               if (itv->card->video_inputs[i].video_type ==
-                               IVTV_CARD_INPUT_VID_TUNER)
-                       break;
-       }
-       if (i == itv->nof_inputs)
-               i = 0;
-       itv->active_input = i;
-       itv->audio_input = itv->card->video_inputs[i].audio_index;
-}
-
-static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
-                         const struct pci_device_id *pci_id)
-{
-       u16 cmd;
-       unsigned char pci_latency;
-
-       IVTV_DEBUG_INFO("Enabling pci device\n");
-
-       if (pci_enable_device(pdev)) {
-               IVTV_ERR("Can't enable device!\n");
-               return -EIO;
-       }
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-               IVTV_ERR("No suitable DMA available.\n");
-               return -EIO;
-       }
-       if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) {
-               IVTV_ERR("Cannot request encoder memory region.\n");
-               return -EIO;
-       }
-
-       if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,
-                               IVTV_REG_SIZE, "ivtv registers")) {
-               IVTV_ERR("Cannot request register memory region.\n");
-               release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
-               return -EIO;
-       }
-
-       if (itv->has_cx23415 &&
-           !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
-                               IVTV_DECODER_SIZE, "ivtv decoder")) {
-               IVTV_ERR("Cannot request decoder memory region.\n");
-               release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
-               release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
-               return -EIO;
-       }
-
-       /* Check for bus mastering */
-       pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-       if (!(cmd & PCI_COMMAND_MASTER)) {
-               IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n");
-               pci_set_master(pdev);
-               pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-               if (!(cmd & PCI_COMMAND_MASTER)) {
-                       IVTV_ERR("Bus Mastering is not enabled\n");
-                       return -ENXIO;
-               }
-       }
-       IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
-
-       pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
-
-       if (pci_latency < 64 && ivtv_pci_latency) {
-               IVTV_INFO("Unreasonably low latency timer, "
-                              "setting to 64 (was %d)\n", pci_latency);
-               pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-               pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
-       }
-       /* This config space value relates to DMA latencies. The
-          default value 0x8080 is too low however and will lead
-          to DMA errors. 0xffff is the max value which solves
-          these problems. */
-       pci_write_config_dword(pdev, 0x40, 0xffff);
-
-       IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
-                  "irq: %d, latency: %d, memory: 0x%llx\n",
-                  pdev->device, pdev->revision, pdev->bus->number,
-                  PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-                  pdev->irq, pci_latency, (u64)itv->base_addr);
-
-       return 0;
-}
-
-static void ivtv_load_and_init_modules(struct ivtv *itv)
-{
-       u32 hw = itv->card->hw_all;
-       unsigned i;
-
-       /* check which i2c devices are actually found */
-       for (i = 0; i < 32; i++) {
-               u32 device = 1 << i;
-
-               if (!(device & hw))
-                       continue;
-               if (device == IVTV_HW_GPIO || device == IVTV_HW_TVEEPROM) {
-                       /* GPIO and TVEEPROM do not use i2c probing */
-                       itv->hw_flags |= device;
-                       continue;
-               }
-               if (ivtv_i2c_register(itv, i) == 0)
-                       itv->hw_flags |= device;
-       }
-
-       /* probe for legacy IR controllers that aren't in card definitions */
-       if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0)
-               ivtv_i2c_new_ir_legacy(itv);
-
-       if (itv->card->hw_all & IVTV_HW_CX25840)
-               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840);
-       else if (itv->card->hw_all & IVTV_HW_SAA717X)
-               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X);
-       else if (itv->card->hw_all & IVTV_HW_SAA7114)
-               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114);
-       else
-               itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115);
-       itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl);
-       itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer);
-
-       hw = itv->hw_flags;
-
-       if (itv->card->type == IVTV_CARD_CX23416GYC) {
-               /* Several variations of this card exist, detect which card
-                  type should be used. */
-               if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0)
-                       itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS);
-               else if ((hw & IVTV_HW_UPD64031A) == 0)
-                       itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR);
-       }
-       else if (itv->card->type == IVTV_CARD_GV_MVPRX ||
-                itv->card->type == IVTV_CARD_GV_MVPRX2E) {
-               /* The crystal frequency of GVMVPRX is 24.576MHz */
-               v4l2_subdev_call(itv->sd_video, video, s_crystal_freq,
-                       SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC);
-       }
-
-       if (hw & IVTV_HW_CX25840) {
-               itv->vbi.raw_decoder_line_size = 1444;
-               itv->vbi.raw_decoder_sav_odd_field = 0x20;
-               itv->vbi.raw_decoder_sav_even_field = 0x60;
-               itv->vbi.sliced_decoder_line_size = 272;
-               itv->vbi.sliced_decoder_sav_odd_field = 0xB0;
-               itv->vbi.sliced_decoder_sav_even_field = 0xF0;
-       }
-
-       if (hw & IVTV_HW_SAA711X) {
-               struct v4l2_dbg_chip_ident v;
-
-               /* determine the exact saa711x model */
-               itv->hw_flags &= ~IVTV_HW_SAA711X;
-
-               v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
-               strlcpy(v.match.name, "saa7115", sizeof(v.match.name));
-               ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v);
-               if (v.ident == V4L2_IDENT_SAA7114) {
-                       itv->hw_flags |= IVTV_HW_SAA7114;
-                       /* VBI is not yet supported by the saa7114 driver. */
-                       itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE);
-               } else {
-                       itv->hw_flags |= IVTV_HW_SAA7115;
-               }
-               itv->vbi.raw_decoder_line_size = 1443;
-               itv->vbi.raw_decoder_sav_odd_field = 0x25;
-               itv->vbi.raw_decoder_sav_even_field = 0x62;
-               itv->vbi.sliced_decoder_line_size = 51;
-               itv->vbi.sliced_decoder_sav_odd_field = 0xAB;
-               itv->vbi.sliced_decoder_sav_even_field = 0xEC;
-       }
-
-       if (hw & IVTV_HW_SAA717X) {
-               itv->vbi.raw_decoder_line_size = 1443;
-               itv->vbi.raw_decoder_sav_odd_field = 0x25;
-               itv->vbi.raw_decoder_sav_even_field = 0x62;
-               itv->vbi.sliced_decoder_line_size = 51;
-               itv->vbi.sliced_decoder_sav_odd_field = 0xAB;
-               itv->vbi.sliced_decoder_sav_even_field = 0xEC;
-       }
-}
-
-static int __devinit ivtv_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *pci_id)
-{
-       int retval = 0;
-       int vbi_buf_size;
-       struct ivtv *itv;
-
-       itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC);
-       if (itv == NULL)
-               return -ENOMEM;
-       itv->pdev = pdev;
-       itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv",
-                                               &ivtv_instance);
-
-       retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev);
-       if (retval) {
-               kfree(itv);
-               return retval;
-       }
-       IVTV_INFO("Initializing card %d\n", itv->instance);
-
-       ivtv_process_options(itv);
-       if (itv->options.cardtype == -1) {
-               retval = -ENODEV;
-               goto err;
-       }
-       if (ivtv_init_struct1(itv)) {
-               retval = -ENOMEM;
-               goto err;
-       }
-       retval = cx2341x_handler_init(&itv->cxhdl, 50);
-       if (retval)
-               goto err;
-       itv->v4l2_dev.ctrl_handler = &itv->cxhdl.hdl;
-       itv->cxhdl.ops = &ivtv_cxhdl_ops;
-       itv->cxhdl.priv = itv;
-       itv->cxhdl.func = ivtv_api_func;
-
-       IVTV_DEBUG_INFO("base addr: 0x%llx\n", (u64)itv->base_addr);
-
-       /* PCI Device Setup */
-       retval = ivtv_setup_pci(itv, pdev, pci_id);
-       if (retval == -EIO)
-               goto free_worker;
-       if (retval == -ENXIO)
-               goto free_mem;
-
-       /* map io memory */
-       IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
-                  (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
-       itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET,
-                                      IVTV_ENCODER_SIZE);
-       if (!itv->enc_mem) {
-               IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
-                        "encoder memory\n");
-               IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of "
-                        "vmalloc address space for this window\n");
-               IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
-               IVTV_ERR("Use the vmalloc= kernel command line option to set "
-                        "VmallocTotal to a larger value\n");
-               retval = -ENOMEM;
-               goto free_mem;
-       }
-
-       if (itv->has_cx23415) {
-               IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
-                               (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
-               itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET,
-                               IVTV_DECODER_SIZE);
-               if (!itv->dec_mem) {
-                       IVTV_ERR("ioremap failed. Can't get a window into "
-                                "CX23415 decoder memory\n");
-                       IVTV_ERR("Each capture card with a CX23415 needs 8 MB "
-                                "of vmalloc address space for this window\n");
-                       IVTV_ERR("Check the output of 'grep Vmalloc "
-                                "/proc/meminfo'\n");
-                       IVTV_ERR("Use the vmalloc= kernel command line option "
-                                "to set VmallocTotal to a larger value\n");
-                       retval = -ENOMEM;
-                       goto free_mem;
-               }
-       }
-       else {
-               itv->dec_mem = itv->enc_mem;
-       }
-
-       /* map registers memory */
-       IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
-                  (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
-       itv->reg_mem =
-           ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
-       if (!itv->reg_mem) {
-               IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
-                        "register space\n");
-               IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of "
-                        "vmalloc address space for this window\n");
-               IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
-               IVTV_ERR("Use the vmalloc= kernel command line option to set "
-                        "VmallocTotal to a larger value\n");
-               retval = -ENOMEM;
-               goto free_io;
-       }
-
-       retval = ivtv_gpio_init(itv);
-       if (retval)
-               goto free_io;
-
-       /* active i2c  */
-       IVTV_DEBUG_INFO("activating i2c...\n");
-       if (init_ivtv_i2c(itv)) {
-               IVTV_ERR("Could not initialize i2c\n");
-               goto free_io;
-       }
-
-       if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
-               /* Based on the model number the cardtype may be changed.
-                  The PCI IDs are not always reliable. */
-               ivtv_process_eeprom(itv);
-       }
-       if (itv->card->comment)
-               IVTV_INFO("%s", itv->card->comment);
-       if (itv->card->v4l2_capabilities == 0) {
-               /* card was detected but is not supported */
-               retval = -ENODEV;
-               goto free_i2c;
-       }
-
-       if (itv->std == 0) {
-               itv->std = V4L2_STD_NTSC_M;
-       }
-
-       if (itv->options.tuner == -1) {
-               int i;
-
-               for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) {
-                       if ((itv->std & itv->card->tuners[i].std) == 0)
-                               continue;
-                       itv->options.tuner = itv->card->tuners[i].tuner;
-                       break;
-               }
-       }
-       /* if no tuner was found, then pick the first tuner in the card list */
-       if (itv->options.tuner == -1 && itv->card->tuners[0].std) {
-               itv->std = itv->card->tuners[0].std;
-               if (itv->std & V4L2_STD_PAL)
-                       itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
-               else if (itv->std & V4L2_STD_NTSC)
-                       itv->std = V4L2_STD_NTSC_M;
-               else if (itv->std & V4L2_STD_SECAM)
-                       itv->std = V4L2_STD_SECAM_L;
-               itv->options.tuner = itv->card->tuners[0].tuner;
-       }
-       if (itv->options.radio == -1)
-               itv->options.radio = (itv->card->radio_input.audio_type != 0);
-
-       /* The card is now fully identified, continue with card-specific
-          initialization. */
-       ivtv_init_struct2(itv);
-
-       ivtv_load_and_init_modules(itv);
-
-       if (itv->std & V4L2_STD_525_60) {
-               itv->is_60hz = 1;
-               itv->is_out_60hz = 1;
-       } else {
-               itv->is_50hz = 1;
-               itv->is_out_50hz = 1;
-       }
-
-       itv->yuv_info.osd_full_w = 720;
-       itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480;
-       itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w;
-       itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h;
-
-       cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
-
-       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
-       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200;
-       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000;
-       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000;
-       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000;
-
-       /* Setup VBI Raw Size. Should be big enough to hold PAL.
-          It is possible to switch between PAL and NTSC, so we need to
-          take the largest size here. */
-       /* 1456 is multiple of 16, real size = 1444 */
-       itv->vbi.raw_size = 1456;
-       /* We use a buffer size of 1/2 of the total size needed for a
-          frame. This is actually very useful, since we now receive
-          a field at a time and that makes 'compressing' the raw data
-          down to size by stripping off the SAV codes a lot easier.
-          Note: having two different buffer sizes prevents standard
-          switching on the fly. We need to find a better solution... */
-       vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2;
-       itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
-       itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36;
-
-       if (itv->options.radio > 0)
-               itv->v4l2_cap |= V4L2_CAP_RADIO;
-
-       if (itv->options.tuner > -1) {
-               struct tuner_setup setup;
-
-               setup.addr = ADDR_UNSET;
-               setup.type = itv->options.tuner;
-               setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
-               if (itv->options.radio > 0)
-                       setup.mode_mask |= T_RADIO;
-               setup.tuner_callback = (setup.type == TUNER_XC2028) ?
-                       ivtv_reset_tuner_gpio : NULL;
-               ivtv_call_all(itv, tuner, s_type_addr, &setup);
-               if (setup.type == TUNER_XC2028) {
-                       static struct xc2028_ctrl ctrl = {
-                               .fname = XC2028_DEFAULT_FIRMWARE,
-                               .max_len = 64,
-                       };
-                       struct v4l2_priv_tun_config cfg = {
-                               .tuner = itv->options.tuner,
-                               .priv = &ctrl,
-                       };
-                       ivtv_call_all(itv, tuner, s_config, &cfg);
-               }
-       }
-
-       /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
-          are not. */
-       itv->tuner_std = itv->std;
-
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler;
-
-               itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
-                               V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 0, 0);
-               itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
-                               V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0, 0, 0);
-               /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported,
-                  mask that menu item. */
-               itv->ctrl_audio_playback =
-                       v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
-                               V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK,
-                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
-                               1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
-                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO);
-               itv->ctrl_audio_multilingual_playback =
-                       v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
-                               V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK,
-                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
-                               1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
-                               V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT);
-               if (hdl->error) {
-                       retval = hdl->error;
-                       goto free_i2c;
-               }
-               v4l2_ctrl_cluster(2, &itv->ctrl_pts);
-               v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback);
-               ivtv_call_all(itv, video, s_std_output, itv->std);
-               /* Turn off the output signal. The mpeg decoder is not yet
-                  active so without this you would get a green image until the
-                  mpeg decoder becomes active. */
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
-       }
-
-       /* clear interrupt mask, effectively disabling interrupts */
-       ivtv_set_irq_mask(itv, 0xffffffff);
-
-       /* Register IRQ */
-       retval = request_irq(itv->pdev->irq, ivtv_irq_handler,
-            IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv);
-       if (retval) {
-               IVTV_ERR("Failed to register irq %d\n", retval);
-               goto free_i2c;
-       }
-
-       retval = ivtv_streams_setup(itv);
-       if (retval) {
-               IVTV_ERR("Error %d setting up streams\n", retval);
-               goto free_irq;
-       }
-       retval = ivtv_streams_register(itv);
-       if (retval) {
-               IVTV_ERR("Error %d registering devices\n", retval);
-               goto free_streams;
-       }
-       IVTV_INFO("Initialized card: %s\n", itv->card_name);
-       return 0;
-
-free_streams:
-       ivtv_streams_cleanup(itv, 1);
-free_irq:
-       free_irq(itv->pdev->irq, (void *)itv);
-free_i2c:
-       v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
-       exit_ivtv_i2c(itv);
-free_io:
-       ivtv_iounmap(itv);
-free_mem:
-       release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
-       release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
-       if (itv->has_cx23415)
-               release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
-free_worker:
-       kthread_stop(itv->irq_worker_task);
-err:
-       if (retval == 0)
-               retval = -ENODEV;
-       IVTV_ERR("Error %d on initialization\n", retval);
-
-       v4l2_device_unregister(&itv->v4l2_dev);
-       kfree(itv);
-       return retval;
-}
-
-int ivtv_init_on_first_open(struct ivtv *itv)
-{
-       struct v4l2_frequency vf;
-       /* Needed to call ioctls later */
-       struct ivtv_open_id fh;
-       int fw_retry_count = 3;
-       int video_input;
-
-       fh.itv = itv;
-
-       if (test_bit(IVTV_F_I_FAILED, &itv->i_flags))
-               return -ENXIO;
-
-       if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags))
-               return 0;
-
-       while (--fw_retry_count > 0) {
-               /* load firmware */
-               if (ivtv_firmware_init(itv) == 0)
-                       break;
-               if (fw_retry_count > 1)
-                       IVTV_WARN("Retry loading firmware\n");
-       }
-
-       if (fw_retry_count == 0) {
-               set_bit(IVTV_F_I_FAILED, &itv->i_flags);
-               return -ENXIO;
-       }
-
-       /* Try and get firmware versions */
-       IVTV_DEBUG_INFO("Getting firmware version..\n");
-       ivtv_firmware_versions(itv);
-
-       if (itv->card->hw_all & IVTV_HW_CX25840)
-               v4l2_subdev_call(itv->sd_video, core, load_fw);
-
-       vf.tuner = 0;
-       vf.type = V4L2_TUNER_ANALOG_TV;
-       vf.frequency = 6400; /* the tuner 'baseline' frequency */
-
-       /* Set initial frequency. For PAL/SECAM broadcasts no
-          'default' channel exists AFAIK. */
-       if (itv->std == V4L2_STD_NTSC_M_JP) {
-               vf.frequency = 1460;    /* ch. 1 91250*16/1000 */
-       }
-       else if (itv->std & V4L2_STD_NTSC_M) {
-               vf.frequency = 1076;    /* ch. 4 67250*16/1000 */
-       }
-
-       video_input = itv->active_input;
-       itv->active_input++;    /* Force update of input */
-       ivtv_s_input(NULL, &fh, video_input);
-
-       /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
-          in one place. */
-       itv->std++;             /* Force full standard initialization */
-       itv->std_out = itv->std;
-       ivtv_s_frequency(NULL, &fh, &vf);
-
-       if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
-               /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes
-                  the mpeg decoder so now the saa7127 receives a proper
-                  signal. */
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
-               ivtv_init_mpeg_decoder(itv);
-       }
-
-       /* On a cx23416 this seems to be able to enable DMA to the chip? */
-       if (!itv->has_cx23415)
-               write_reg_sync(0x03, IVTV_REG_DMACONTROL);
-
-       ivtv_s_std_enc(itv, &itv->tuner_std);
-
-       /* Default interrupts enabled. For the PVR350 this includes the
-          decoder VSYNC interrupt, which is always on. It is not only used
-          during decoding but also by the OSD.
-          Some old PVR250 cards had a cx23415, so testing for that is too
-          general. Instead test if the card has video output capability. */
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
-               ivtv_set_osd_alpha(itv);
-               ivtv_s_std_dec(itv, &itv->tuner_std);
-       } else {
-               ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
-       }
-
-       /* Setup initial controls */
-       cx2341x_handler_setup(&itv->cxhdl);
-       return 0;
-}
-
-static void ivtv_remove(struct pci_dev *pdev)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-       struct ivtv *itv = to_ivtv(v4l2_dev);
-       int i;
-
-       IVTV_DEBUG_INFO("Removing card\n");
-
-       if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
-               /* Stop all captures */
-               IVTV_DEBUG_INFO("Stopping all streams\n");
-               if (atomic_read(&itv->capturing) > 0)
-                       ivtv_stop_all_captures(itv);
-
-               /* Stop all decoding */
-               IVTV_DEBUG_INFO("Stopping decoding\n");
-
-               /* Turn off the TV-out */
-               if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
-                       ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
-               if (atomic_read(&itv->decoding) > 0) {
-                       int type;
-
-                       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
-                               type = IVTV_DEC_STREAM_TYPE_YUV;
-                       else
-                               type = IVTV_DEC_STREAM_TYPE_MPG;
-                       ivtv_stop_v4l2_decode_stream(&itv->streams[type],
-                               V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
-               }
-               ivtv_halt_firmware(itv);
-       }
-
-       /* Interrupts */
-       ivtv_set_irq_mask(itv, 0xffffffff);
-       del_timer_sync(&itv->dma_timer);
-
-       /* Kill irq worker */
-       flush_kthread_worker(&itv->irq_worker);
-       kthread_stop(itv->irq_worker_task);
-
-       ivtv_streams_cleanup(itv, 1);
-       ivtv_udma_free(itv);
-
-       v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
-
-       exit_ivtv_i2c(itv);
-
-       free_irq(itv->pdev->irq, (void *)itv);
-       ivtv_iounmap(itv);
-
-       release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
-       release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
-       if (itv->has_cx23415)
-               release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
-
-       pci_disable_device(itv->pdev);
-       for (i = 0; i < IVTV_VBI_FRAMES; i++)
-               kfree(itv->vbi.sliced_mpeg_data[i]);
-
-       printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name);
-
-       v4l2_device_unregister(&itv->v4l2_dev);
-       kfree(itv);
-}
-
-/* define a pci_driver for card detection */
-static struct pci_driver ivtv_pci_driver = {
-      .name =     "ivtv",
-      .id_table = ivtv_pci_tbl,
-      .probe =    ivtv_probe,
-      .remove =   ivtv_remove,
-};
-
-static int __init module_start(void)
-{
-       printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION);
-
-       /* Validate parameters */
-       if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) {
-               printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n",
-                    IVTV_MAX_CARDS - 1);
-               return -1;
-       }
-
-       if (ivtv_debug < 0 || ivtv_debug > 2047) {
-               ivtv_debug = 0;
-               printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n");
-       }
-
-       if (pci_register_driver(&ivtv_pci_driver)) {
-               printk(KERN_ERR "ivtv: Error detecting PCI card\n");
-               return -ENODEV;
-       }
-       printk(KERN_INFO "ivtv: End initialization\n");
-       return 0;
-}
-
-static void __exit module_cleanup(void)
-{
-       pci_unregister_driver(&ivtv_pci_driver);
-}
-
-/* Note: These symbols are exported because they are used by the ivtvfb
-   framebuffer module and an infrared module for the IR-blaster. */
-EXPORT_SYMBOL(ivtv_set_irq_mask);
-EXPORT_SYMBOL(ivtv_api);
-EXPORT_SYMBOL(ivtv_vapi);
-EXPORT_SYMBOL(ivtv_vapi_result);
-EXPORT_SYMBOL(ivtv_clear_irq_mask);
-EXPORT_SYMBOL(ivtv_debug);
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-EXPORT_SYMBOL(ivtv_fw_debug);
-#endif
-EXPORT_SYMBOL(ivtv_reset_ir_gpio);
-EXPORT_SYMBOL(ivtv_udma_setup);
-EXPORT_SYMBOL(ivtv_udma_unmap);
-EXPORT_SYMBOL(ivtv_udma_alloc);
-EXPORT_SYMBOL(ivtv_udma_prepare);
-EXPORT_SYMBOL(ivtv_init_on_first_open);
-EXPORT_SYMBOL(ivtv_firmware_check);
-
-module_init(module_start);
-module_exit(module_cleanup);
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
deleted file mode 100644 (file)
index a7e00f8..0000000
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
-    ivtv driver internal defines and structures
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_DRIVER_H
-#define IVTV_DRIVER_H
-
-/* Internal header for ivtv project:
- * Driver for the cx23415/6 chip.
- * Author: Kevin Thayer (nufan_wfk at yahoo.com)
- * License: GPL
- * http://www.ivtvdriver.org
- *
- * -----
- * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
- *                      and Takeru KOMORIYA<komoriya@paken.org>
- *
- * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
- *                using information provided by Jiun-Kuei Jung @ AVerMedia.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/list.h>
-#include <linux/unistd.h>
-#include <linux/pagemap.h>
-#include <linux/scatterlist.h>
-#include <linux/kthread.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-#include <asm/byteorder.h>
-
-#include <linux/dvb/video.h>
-#include <linux/dvb/audio.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/tuner.h>
-#include <media/cx2341x.h>
-#include <media/ir-kbd-i2c.h>
-
-#include <linux/ivtv.h>
-
-/* Memory layout */
-#define IVTV_ENCODER_OFFSET    0x00000000
-#define IVTV_ENCODER_SIZE      0x00800000      /* Total size is 0x01000000, but only first half is used */
-#define IVTV_DECODER_OFFSET    0x01000000
-#define IVTV_DECODER_SIZE      0x00800000      /* Total size is 0x01000000, but only first half is used */
-#define IVTV_REG_OFFSET        0x02000000
-#define IVTV_REG_SIZE          0x00010000
-
-/* Maximum ivtv driver instances. Some people have a huge number of
-   capture cards, so set this to a high value. */
-#define IVTV_MAX_CARDS 32
-
-#define IVTV_ENC_STREAM_TYPE_MPG  0
-#define IVTV_ENC_STREAM_TYPE_YUV  1
-#define IVTV_ENC_STREAM_TYPE_VBI  2
-#define IVTV_ENC_STREAM_TYPE_PCM  3
-#define IVTV_ENC_STREAM_TYPE_RAD  4
-#define IVTV_DEC_STREAM_TYPE_MPG  5
-#define IVTV_DEC_STREAM_TYPE_VBI  6
-#define IVTV_DEC_STREAM_TYPE_VOUT 7
-#define IVTV_DEC_STREAM_TYPE_YUV  8
-#define IVTV_MAX_STREAMS         9
-
-#define IVTV_DMA_SG_OSD_ENT    (2883584/PAGE_SIZE)     /* sg entities */
-
-/* DMA Registers */
-#define IVTV_REG_DMAXFER       (0x0000)
-#define IVTV_REG_DMASTATUS     (0x0004)
-#define IVTV_REG_DECDMAADDR    (0x0008)
-#define IVTV_REG_ENCDMAADDR    (0x000c)
-#define IVTV_REG_DMACONTROL    (0x0010)
-#define IVTV_REG_IRQSTATUS     (0x0040)
-#define IVTV_REG_IRQMASK       (0x0048)
-
-/* Setup Registers */
-#define IVTV_REG_ENC_SDRAM_REFRESH     (0x07F8)
-#define IVTV_REG_ENC_SDRAM_PRECHARGE   (0x07FC)
-#define IVTV_REG_DEC_SDRAM_REFRESH     (0x08F8)
-#define IVTV_REG_DEC_SDRAM_PRECHARGE   (0x08FC)
-#define IVTV_REG_VDM                   (0x2800)
-#define IVTV_REG_AO                    (0x2D00)
-#define IVTV_REG_BYTEFLUSH             (0x2D24)
-#define IVTV_REG_SPU                   (0x9050)
-#define IVTV_REG_HW_BLOCKS             (0x9054)
-#define IVTV_REG_VPU                   (0x9058)
-#define IVTV_REG_APU                   (0xA064)
-
-/* Other registers */
-#define IVTV_REG_DEC_LINE_FIELD                (0x28C0)
-
-/* debugging */
-extern int ivtv_debug;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-extern int ivtv_fw_debug;
-#endif
-
-#define IVTV_DBGFLG_WARN    (1 << 0)
-#define IVTV_DBGFLG_INFO    (1 << 1)
-#define IVTV_DBGFLG_MB      (1 << 2)
-#define IVTV_DBGFLG_IOCTL   (1 << 3)
-#define IVTV_DBGFLG_FILE    (1 << 4)
-#define IVTV_DBGFLG_DMA     (1 << 5)
-#define IVTV_DBGFLG_IRQ     (1 << 6)
-#define IVTV_DBGFLG_DEC     (1 << 7)
-#define IVTV_DBGFLG_YUV     (1 << 8)
-#define IVTV_DBGFLG_I2C     (1 << 9)
-/* Flag to turn on high volume debugging */
-#define IVTV_DBGFLG_HIGHVOL (1 << 10)
-
-#define IVTV_DEBUG(x, type, fmt, args...) \
-       do { \
-               if ((x) & ivtv_debug) \
-                       v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args);  \
-       } while (0)
-#define IVTV_DEBUG_WARN(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_WARN,  "warn",  fmt , ## args)
-#define IVTV_DEBUG_INFO(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_INFO,  "info",  fmt , ## args)
-#define IVTV_DEBUG_MB(fmt, args...)    IVTV_DEBUG(IVTV_DBGFLG_MB,    "mb",    fmt , ## args)
-#define IVTV_DEBUG_DMA(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_DMA,   "dma",   fmt , ## args)
-#define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
-#define IVTV_DEBUG_FILE(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_FILE,  "file",  fmt , ## args)
-#define IVTV_DEBUG_I2C(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_I2C,   "i2c",   fmt , ## args)
-#define IVTV_DEBUG_IRQ(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_IRQ,   "irq",   fmt , ## args)
-#define IVTV_DEBUG_DEC(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_DEC,   "dec",   fmt , ## args)
-#define IVTV_DEBUG_YUV(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_YUV,   "yuv",   fmt , ## args)
-
-#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \
-       do { \
-               if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL))   \
-                       v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args);  \
-       } while (0)
-#define IVTV_DEBUG_HI_WARN(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN,  "warn",  fmt , ## args)
-#define IVTV_DEBUG_HI_INFO(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO,  "info",  fmt , ## args)
-#define IVTV_DEBUG_HI_MB(fmt, args...)    IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_MB,    "mb",    fmt , ## args)
-#define IVTV_DEBUG_HI_DMA(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA,   "dma",   fmt , ## args)
-#define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
-#define IVTV_DEBUG_HI_FILE(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_FILE,  "file",  fmt , ## args)
-#define IVTV_DEBUG_HI_I2C(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C,   "i2c",   fmt , ## args)
-#define IVTV_DEBUG_HI_IRQ(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ,   "irq",   fmt , ## args)
-#define IVTV_DEBUG_HI_DEC(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC,   "dec",   fmt , ## args)
-#define IVTV_DEBUG_HI_YUV(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV,   "yuv",   fmt , ## args)
-
-/* Standard kernel messages */
-#define IVTV_ERR(fmt, args...)      v4l2_err(&itv->v4l2_dev, fmt , ## args)
-#define IVTV_WARN(fmt, args...)     v4l2_warn(&itv->v4l2_dev, fmt , ## args)
-#define IVTV_INFO(fmt, args...)     v4l2_info(&itv->v4l2_dev, fmt , ## args)
-
-/* output modes (cx23415 only) */
-#define OUT_NONE        0
-#define OUT_MPG         1
-#define OUT_YUV         2
-#define OUT_UDMA_YUV    3
-#define OUT_PASSTHROUGH 4
-
-#define IVTV_MAX_PGM_INDEX (400)
-
-/* Default I2C SCL period in microseconds */
-#define IVTV_DEFAULT_I2C_CLOCK_PERIOD  20
-
-struct ivtv_options {
-       int kilobytes[IVTV_MAX_STREAMS];        /* size in kilobytes of each stream */
-       int cardtype;                           /* force card type on load */
-       int tuner;                              /* set tuner on load */
-       int radio;                              /* enable/disable radio */
-       int newi2c;                             /* new I2C algorithm */
-       int i2c_clock_period;                   /* period of SCL for I2C bus */
-};
-
-/* ivtv-specific mailbox template */
-struct ivtv_mailbox {
-       u32 flags;
-       u32 cmd;
-       u32 retval;
-       u32 timeout;
-       u32 data[CX2341X_MBOX_MAX_DATA];
-};
-
-struct ivtv_api_cache {
-       unsigned long last_jiffies;             /* when last command was issued */
-       u32 data[CX2341X_MBOX_MAX_DATA];        /* last sent api data */
-};
-
-struct ivtv_mailbox_data {
-       volatile struct ivtv_mailbox __iomem *mbox;
-       /* Bits 0-2 are for the encoder mailboxes, 0-1 are for the decoder mailboxes.
-          If the bit is set, then the corresponding mailbox is in use by the driver. */
-       unsigned long busy;
-       u8 max_mbox;
-};
-
-/* per-buffer bit flags */
-#define IVTV_F_B_NEED_BUF_SWAP  (1 << 0)       /* this buffer should be byte swapped */
-
-/* per-stream, s_flags */
-#define IVTV_F_S_DMA_PENDING   0       /* this stream has pending DMA */
-#define IVTV_F_S_DMA_HAS_VBI   1       /* the current DMA request also requests VBI data */
-#define IVTV_F_S_NEEDS_DATA    2       /* this decoding stream needs more data */
-
-#define IVTV_F_S_CLAIMED       3       /* this stream is claimed */
-#define IVTV_F_S_STREAMING      4      /* the fw is decoding/encoding this stream */
-#define IVTV_F_S_INTERNAL_USE  5       /* this stream is used internally (sliced VBI processing) */
-#define IVTV_F_S_PASSTHROUGH   6       /* this stream is in passthrough mode */
-#define IVTV_F_S_STREAMOFF     7       /* signal end of stream EOS */
-#define IVTV_F_S_APPL_IO        8      /* this stream is used read/written by an application */
-
-#define IVTV_F_S_PIO_PENDING   9       /* this stream has pending PIO */
-#define IVTV_F_S_PIO_HAS_VBI   1       /* the current PIO request also requests VBI data */
-
-/* per-ivtv, i_flags */
-#define IVTV_F_I_DMA              0    /* DMA in progress */
-#define IVTV_F_I_UDMA             1    /* UDMA in progress */
-#define IVTV_F_I_UDMA_PENDING     2    /* UDMA pending */
-#define IVTV_F_I_SPEED_CHANGE     3    /* a speed change is in progress */
-#define IVTV_F_I_EOS              4    /* end of encoder stream reached */
-#define IVTV_F_I_RADIO_USER       5    /* the radio tuner is selected */
-#define IVTV_F_I_DIG_RST          6    /* reset digitizer */
-#define IVTV_F_I_DEC_YUV          7    /* YUV instead of MPG is being decoded */
-#define IVTV_F_I_UPDATE_CC        9    /* CC should be updated */
-#define IVTV_F_I_UPDATE_WSS       10   /* WSS should be updated */
-#define IVTV_F_I_UPDATE_VPS       11   /* VPS should be updated */
-#define IVTV_F_I_DECODING_YUV     12   /* this stream is YUV frame decoding */
-#define IVTV_F_I_ENC_PAUSED       13   /* the encoder is paused */
-#define IVTV_F_I_VALID_DEC_TIMINGS 14  /* last_dec_timing is valid */
-#define IVTV_F_I_HAVE_WORK        15   /* used in the interrupt handler: there is work to be done */
-#define IVTV_F_I_WORK_HANDLER_VBI  16  /* there is work to be done for VBI */
-#define IVTV_F_I_WORK_HANDLER_YUV  17  /* there is work to be done for YUV */
-#define IVTV_F_I_WORK_HANDLER_PIO  18  /* there is work to be done for PIO */
-#define IVTV_F_I_PIO              19   /* PIO in progress */
-#define IVTV_F_I_DEC_PAUSED       20   /* the decoder is paused */
-#define IVTV_F_I_INITED                   21   /* set after first open */
-#define IVTV_F_I_FAILED                   22   /* set if first open failed */
-
-/* Event notifications */
-#define IVTV_F_I_EV_DEC_STOPPED           28   /* decoder stopped event */
-#define IVTV_F_I_EV_VSYNC         29   /* VSYNC event */
-#define IVTV_F_I_EV_VSYNC_FIELD    30  /* VSYNC event field (0 = first, 1 = second field) */
-#define IVTV_F_I_EV_VSYNC_ENABLED  31  /* VSYNC event enabled */
-
-/* Scatter-Gather array element, used in DMA transfers */
-struct ivtv_sg_element {
-       __le32 src;
-       __le32 dst;
-       __le32 size;
-};
-
-struct ivtv_sg_host_element {
-       u32 src;
-       u32 dst;
-       u32 size;
-};
-
-struct ivtv_user_dma {
-       struct mutex lock;
-       int page_count;
-       struct page *map[IVTV_DMA_SG_OSD_ENT];
-       /* Needed when dealing with highmem userspace buffers */
-       struct page *bouncemap[IVTV_DMA_SG_OSD_ENT];
-
-       /* Base Dev SG Array for cx23415/6 */
-       struct ivtv_sg_element SGarray[IVTV_DMA_SG_OSD_ENT];
-       dma_addr_t SG_handle;
-       int SG_length;
-
-       /* SG List of Buffers */
-       struct scatterlist SGlist[IVTV_DMA_SG_OSD_ENT];
-};
-
-struct ivtv_dma_page_info {
-       unsigned long uaddr;
-       unsigned long first;
-       unsigned long last;
-       unsigned int offset;
-       unsigned int tail;
-       int page_count;
-};
-
-struct ivtv_buffer {
-       struct list_head list;
-       dma_addr_t dma_handle;
-       unsigned short b_flags;
-       unsigned short dma_xfer_cnt;
-       char *buf;
-       u32 bytesused;
-       u32 readpos;
-};
-
-struct ivtv_queue {
-       struct list_head list;          /* the list of buffers in this queue */
-       u32 buffers;                    /* number of buffers in this queue */
-       u32 length;                     /* total number of bytes of available buffer space */
-       u32 bytesused;                  /* total number of bytes used in this queue */
-};
-
-struct ivtv;                           /* forward reference */
-
-struct ivtv_stream {
-       /* These first four fields are always set, even if the stream
-          is not actually created. */
-       struct video_device *vdev;      /* NULL when stream not created */
-       struct ivtv *itv;               /* for ease of use */
-       const char *name;               /* name of the stream */
-       int type;                       /* stream type */
-       u32 caps;                       /* V4L2 capabilities */
-
-       struct v4l2_fh *fh;             /* pointer to the streaming filehandle */
-       spinlock_t qlock;               /* locks access to the queues */
-       unsigned long s_flags;          /* status flags, see above */
-       int dma;                        /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
-       u32 pending_offset;
-       u32 pending_backup;
-       u64 pending_pts;
-
-       u32 dma_offset;
-       u32 dma_backup;
-       u64 dma_pts;
-
-       int subtype;
-       wait_queue_head_t waitq;
-       u32 dma_last_offset;
-
-       /* Buffer Stats */
-       u32 buffers;
-       u32 buf_size;
-       u32 buffers_stolen;
-
-       /* Buffer Queues */
-       struct ivtv_queue q_free;       /* free buffers */
-       struct ivtv_queue q_full;       /* full buffers */
-       struct ivtv_queue q_io;         /* waiting for I/O */
-       struct ivtv_queue q_dma;        /* waiting for DMA */
-       struct ivtv_queue q_predma;     /* waiting for DMA */
-
-       /* DMA xfer counter, buffers belonging to the same DMA
-          xfer will have the same dma_xfer_cnt. */
-       u16 dma_xfer_cnt;
-
-       /* Base Dev SG Array for cx23415/6 */
-       struct ivtv_sg_host_element *sg_pending;
-       struct ivtv_sg_host_element *sg_processing;
-       struct ivtv_sg_element *sg_dma;
-       dma_addr_t sg_handle;
-       int sg_pending_size;
-       int sg_processing_size;
-       int sg_processed;
-
-       /* SG List of Buffers */
-       struct scatterlist *SGlist;
-};
-
-struct ivtv_open_id {
-       struct v4l2_fh fh;
-       int type;                       /* stream type */
-       int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode */
-       struct ivtv *itv;
-};
-
-static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh)
-{
-       return container_of(fh, struct ivtv_open_id, fh);
-}
-
-struct yuv_frame_info
-{
-       u32 update;
-       s32 src_x;
-       s32 src_y;
-       u32 src_w;
-       u32 src_h;
-       s32 dst_x;
-       s32 dst_y;
-       u32 dst_w;
-       u32 dst_h;
-       s32 pan_x;
-       s32 pan_y;
-       u32 vis_w;
-       u32 vis_h;
-       u32 interlaced_y;
-       u32 interlaced_uv;
-       s32 tru_x;
-       u32 tru_w;
-       u32 tru_h;
-       u32 offset_y;
-       s32 lace_mode;
-       u32 sync_field;
-       u32 delay;
-       u32 interlaced;
-};
-
-#define IVTV_YUV_MODE_INTERLACED       0x00
-#define IVTV_YUV_MODE_PROGRESSIVE      0x01
-#define IVTV_YUV_MODE_AUTO             0x02
-#define IVTV_YUV_MODE_MASK             0x03
-
-#define IVTV_YUV_SYNC_EVEN             0x00
-#define IVTV_YUV_SYNC_ODD              0x04
-#define IVTV_YUV_SYNC_MASK             0x04
-
-#define IVTV_YUV_BUFFERS 8
-
-struct yuv_playback_info
-{
-       u32 reg_2834;
-       u32 reg_2838;
-       u32 reg_283c;
-       u32 reg_2840;
-       u32 reg_2844;
-       u32 reg_2848;
-       u32 reg_2854;
-       u32 reg_285c;
-       u32 reg_2864;
-
-       u32 reg_2870;
-       u32 reg_2874;
-       u32 reg_2890;
-       u32 reg_2898;
-       u32 reg_289c;
-
-       u32 reg_2918;
-       u32 reg_291c;
-       u32 reg_2920;
-       u32 reg_2924;
-       u32 reg_2928;
-       u32 reg_292c;
-       u32 reg_2930;
-
-       u32 reg_2934;
-
-       u32 reg_2938;
-       u32 reg_293c;
-       u32 reg_2940;
-       u32 reg_2944;
-       u32 reg_2948;
-       u32 reg_294c;
-       u32 reg_2950;
-       u32 reg_2954;
-       u32 reg_2958;
-       u32 reg_295c;
-       u32 reg_2960;
-       u32 reg_2964;
-       u32 reg_2968;
-       u32 reg_296c;
-
-       u32 reg_2970;
-
-       int v_filter_1;
-       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;
-
-       u32 osd_x_pan;
-       u32 osd_y_pan;
-
-       u32 osd_vis_w;
-       u32 osd_vis_h;
-
-       u32 osd_full_w;
-       u32 osd_full_h;
-
-       int decode_height;
-
-       int lace_mode;
-       int lace_threshold;
-       int lace_sync_field;
-
-       atomic_t next_dma_frame;
-       atomic_t next_fill_frame;
-
-       u32 yuv_forced_update;
-       int update_frame;
-
-       u8 fields_lapsed;   /* Counter used when delaying a frame */
-
-       struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS];
-       struct yuv_frame_info old_frame_info;
-       struct yuv_frame_info old_frame_info_args;
-
-       void *blanking_ptr;
-       dma_addr_t blanking_dmaptr;
-
-       int stream_size;
-
-       u8 draw_frame; /* PVR350 buffer to draw into */
-       u8 max_frames_buffered; /* Maximum number of frames to buffer */
-
-       struct v4l2_rect main_rect;
-       u32 v4l2_src_w;
-       u32 v4l2_src_h;
-
-       u8 running; /* Have any frames been displayed */
-};
-
-#define IVTV_VBI_FRAMES 32
-
-/* VBI data */
-struct vbi_cc {
-       u8 odd[2];      /* two-byte payload of odd field */
-       u8 even[2];     /* two-byte payload of even field */;
-};
-
-struct vbi_vps {
-       u8 data[5];     /* five-byte VPS payload */
-};
-
-struct vbi_info {
-       /* VBI general data, does not change during streaming */
-
-       u32 raw_decoder_line_size;              /* raw VBI line size from digitizer */
-       u8 raw_decoder_sav_odd_field;           /* raw VBI Start Active Video digitizer code of odd field */
-       u8 raw_decoder_sav_even_field;          /* raw VBI Start Active Video digitizer code of even field */
-       u32 sliced_decoder_line_size;           /* sliced VBI line size from digitizer */
-       u8 sliced_decoder_sav_odd_field;        /* sliced VBI Start Active Video digitizer code of odd field */
-       u8 sliced_decoder_sav_even_field;       /* sliced VBI Start Active Video digitizer code of even field */
-
-       u32 start[2];                           /* start of first VBI line in the odd/even fields */
-       u32 count;                              /* number of VBI lines per field */
-       u32 raw_size;                           /* size of raw VBI line from the digitizer */
-       u32 sliced_size;                        /* size of sliced VBI line from the digitizer */
-
-       u32 dec_start;                          /* start in decoder memory of VBI re-insertion buffers */
-       u32 enc_start;                          /* start in encoder memory of VBI capture buffers */
-       u32 enc_size;                           /* size of VBI capture area */
-       int fpi;                                /* number of VBI frames per interrupt */
-
-       struct v4l2_format in;                  /* current VBI capture format */
-       struct v4l2_sliced_vbi_format *sliced_in; /* convenience pointer to sliced struct in vbi.in union */
-       int insert_mpeg;                        /* if non-zero, then embed VBI data in MPEG stream */
-
-       /* Raw VBI compatibility hack */
-
-       u32 frame;                              /* frame counter hack needed for backwards compatibility
-                                                  of old VBI software */
-
-       /* Sliced VBI output data */
-
-       struct vbi_cc cc_payload[256];          /* sliced VBI CC payload array: it is an array to
-                                                  prevent dropping CC data if they couldn't be
-                                                  processed fast enough */
-       int cc_payload_idx;                     /* index in cc_payload */
-       u8 cc_missing_cnt;                      /* counts number of frames without CC for passthrough mode */
-       int wss_payload;                        /* sliced VBI WSS payload */
-       u8 wss_missing_cnt;                     /* counts number of frames without WSS for passthrough mode */
-       struct vbi_vps vps_payload;             /* sliced VBI VPS payload */
-
-       /* Sliced VBI capture data */
-
-       struct v4l2_sliced_vbi_data sliced_data[36];    /* sliced VBI storage for VBI encoder stream */
-       struct v4l2_sliced_vbi_data sliced_dec_data[36];/* sliced VBI storage for VBI decoder stream */
-
-       /* VBI Embedding data */
-
-       /* Buffer for VBI data inserted into MPEG stream.
-          The first byte is a dummy byte that's never used.
-          The next 16 bytes contain the MPEG header for the VBI data,
-          the remainder is the actual VBI data.
-          The max size accepted by the MPEG VBI reinsertion turns out
-          to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes,
-          where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is
-          a single line header byte and 2 * 18 is the number of VBI lines per frame.
-
-          However, it seems that the data must be 1K aligned, so we have to
-          pad the data until the 1 or 2 K boundary.
-
-          This pointer array will allocate 2049 bytes to store each VBI frame. */
-       u8 *sliced_mpeg_data[IVTV_VBI_FRAMES];
-       u32 sliced_mpeg_size[IVTV_VBI_FRAMES];
-       struct ivtv_buffer sliced_mpeg_buf;     /* temporary buffer holding data from sliced_mpeg_data */
-       u32 inserted_frame;                     /* index in sliced_mpeg_size of next sliced data
-                                                  to be inserted in the MPEG stream */
-};
-
-/* forward declaration of struct defined in ivtv-cards.h */
-struct ivtv_card;
-
-/* Struct to hold info about ivtv cards */
-struct ivtv {
-       /* General fixed card data */
-       struct pci_dev *pdev;           /* PCI device */
-       const struct ivtv_card *card;   /* card information */
-       const char *card_name;          /* full name of the card */
-       const struct ivtv_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
-       u8 has_cx23415;                 /* 1 if it is a cx23415 based card, 0 for cx23416 */
-       u8 pvr150_workaround;           /* 1 if the cx25840 needs to workaround a PVR150 bug */
-       u8 nof_inputs;                  /* number of video inputs */
-       u8 nof_audio_inputs;            /* number of audio inputs */
-       u32 v4l2_cap;                   /* V4L2 capabilities of card */
-       u32 hw_flags;                   /* hardware description of the board */
-       v4l2_std_id tuner_std;          /* the norm of the card's tuner (fixed) */
-       struct v4l2_subdev *sd_video;   /* controlling video decoder subdev */
-       struct v4l2_subdev *sd_audio;   /* controlling audio subdev */
-       struct v4l2_subdev *sd_muxer;   /* controlling audio muxer subdev */
-       resource_size_t base_addr;      /* PCI resource base address */
-       volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */
-       volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */
-       volatile void __iomem *reg_mem; /* pointer to mapped registers */
-       struct ivtv_options options;    /* user options */
-
-       struct v4l2_device v4l2_dev;
-       struct cx2341x_handler cxhdl;
-       struct {
-               /* PTS/Frame count control cluster */
-               struct v4l2_ctrl *ctrl_pts;
-               struct v4l2_ctrl *ctrl_frame;
-       };
-       struct {
-               /* Audio Playback control cluster */
-               struct v4l2_ctrl *ctrl_audio_playback;
-               struct v4l2_ctrl *ctrl_audio_multilingual_playback;
-       };
-       struct v4l2_ctrl_handler hdl_gpio;
-       struct v4l2_subdev sd_gpio;     /* GPIO sub-device */
-       u16 instance;
-
-       /* High-level state info */
-       unsigned long i_flags;          /* global ivtv flags */
-       u8 is_50hz;                     /* 1 if the current capture standard is 50 Hz */
-       u8 is_60hz                      /* 1 if the current capture standard is 60 Hz */;
-       u8 is_out_50hz                  /* 1 if the current TV output standard is 50 Hz */;
-       u8 is_out_60hz                  /* 1 if the current TV output standard is 60 Hz */;
-       int output_mode;                /* decoder output mode: NONE, MPG, YUV, UDMA YUV, passthrough */
-       u32 audio_input;                /* current audio input */
-       u32 active_input;               /* current video input */
-       u32 active_output;              /* current video output */
-       v4l2_std_id std;                /* current capture TV standard */
-       v4l2_std_id std_out;            /* current TV output standard */
-       u8 audio_stereo_mode;           /* decoder setting how to handle stereo MPEG audio */
-       u8 audio_bilingual_mode;        /* decoder setting how to handle bilingual MPEG audio */
-
-       /* Locking */
-       spinlock_t lock;                /* lock access to this struct */
-       struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
-
-       /* Streams */
-       int stream_buf_size[IVTV_MAX_STREAMS];          /* stream buffer size */
-       struct ivtv_stream streams[IVTV_MAX_STREAMS];   /* stream data */
-       atomic_t capturing;             /* count number of active capture streams */
-       atomic_t decoding;              /* count number of active decoding streams */
-
-
-       /* Interrupts & DMA */
-       u32 irqmask;                    /* active interrupts */
-       u32 irq_rr_idx;                 /* round-robin stream index */
-       struct kthread_worker irq_worker;               /* kthread worker for PIO/YUV/VBI actions */
-       struct task_struct *irq_worker_task;            /* task for irq_worker */
-       struct kthread_work irq_work;   /* kthread work entry */
-       spinlock_t dma_reg_lock;        /* lock access to DMA engine registers */
-       int cur_dma_stream;             /* index of current stream doing DMA (-1 if none) */
-       int cur_pio_stream;             /* index of current stream doing PIO (-1 if none) */
-       u32 dma_data_req_offset;        /* store offset in decoder memory of current DMA request */
-       u32 dma_data_req_size;          /* store size of current DMA request */
-       int dma_retries;                /* current DMA retry attempt */
-       struct ivtv_user_dma udma;      /* user based DMA for OSD */
-       struct timer_list dma_timer;    /* timer used to catch unfinished DMAs */
-       u32 last_vsync_field;           /* last seen vsync field */
-       wait_queue_head_t dma_waitq;    /* wake up when the current DMA is finished */
-       wait_queue_head_t eos_waitq;    /* wake up when EOS arrives */
-       wait_queue_head_t event_waitq;  /* wake up when the next decoder event arrives */
-       wait_queue_head_t vsync_waitq;  /* wake up when the next decoder vsync arrives */
-
-
-       /* Mailbox */
-       struct ivtv_mailbox_data enc_mbox;              /* encoder mailboxes */
-       struct ivtv_mailbox_data dec_mbox;              /* decoder mailboxes */
-       struct ivtv_api_cache api_cache[256];           /* cached API commands */
-
-
-       /* I2C */
-       struct i2c_adapter i2c_adap;
-       struct i2c_algo_bit_data i2c_algo;
-       struct i2c_client i2c_client;
-       int i2c_state;                  /* i2c bit state */
-       struct mutex i2c_bus_lock;      /* lock i2c bus */
-
-       struct IR_i2c_init_data ir_i2c_init_data;
-
-       /* Program Index information */
-       u32 pgm_info_offset;            /* start of pgm info in encoder memory */
-       u32 pgm_info_num;               /* number of elements in the pgm cyclic buffer in encoder memory */
-       u32 pgm_info_write_idx;         /* last index written by the card that was transferred to pgm_info[] */
-       u32 pgm_info_read_idx;          /* last index in pgm_info read by the application */
-       struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; /* filled from the pgm cyclic buffer on the card */
-
-
-       /* Miscellaneous */
-       u32 open_id;                    /* incremented each time an open occurs, is >= 1 */
-       int search_pack_header;         /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */
-       int speed;                      /* current playback speed setting */
-       u8 speed_mute_audio;            /* 1 if audio should be muted when fast forward */
-       u64 mpg_data_received;          /* number of bytes received from the MPEG stream */
-       u64 vbi_data_inserted;          /* number of VBI bytes inserted into the MPEG stream */
-       u32 last_dec_timing[3];         /* cache last retrieved pts/scr/frame values */
-       unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */
-       u32 dualwatch_stereo_mode;      /* current detected dualwatch stereo mode */
-
-
-       /* VBI state info */
-       struct vbi_info vbi;            /* VBI-specific data */
-
-
-       /* YUV playback */
-       struct yuv_playback_info yuv_info;              /* YUV playback data */
-
-
-       /* OSD support */
-       unsigned long osd_video_pbase;
-       int osd_global_alpha_state;     /* 1 = global alpha is on */
-       int osd_local_alpha_state;      /* 1 = local alpha is on */
-       int osd_chroma_key_state;       /* 1 = chroma-keying is on */
-       u8  osd_global_alpha;           /* current global alpha */
-       u32 osd_chroma_key;             /* current chroma key */
-       struct v4l2_rect osd_rect;      /* current OSD position and size */
-       struct v4l2_rect main_rect;     /* current Main window position and size */
-       struct osd_info *osd_info;      /* ivtvfb private OSD info */
-       void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */
-};
-
-static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct ivtv, v4l2_dev);
-}
-
-/* Globals */
-extern int ivtv_first_minor;
-
-/*==============Prototypes==================*/
-
-/* Hardware/IRQ */
-void ivtv_set_irq_mask(struct ivtv *itv, u32 mask);
-void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask);
-
-/* try to set output mode, return current mode. */
-int ivtv_set_output_mode(struct ivtv *itv, int mode);
-
-/* return current output stream based on current mode */
-struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv);
-
-/* Return non-zero if a signal is pending */
-int ivtv_msleep_timeout(unsigned int msecs, int intr);
-
-/* Wait on queue, returns -EINTR if interrupted */
-int ivtv_waitq(wait_queue_head_t *waitq);
-
-/* Read Hauppauge eeprom */
-struct tveeprom; /* forward reference */
-void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
-
-/* First-open initialization: load firmware, init cx25840, etc. */
-int ivtv_init_on_first_open(struct ivtv *itv);
-
-/* Test if the current VBI mode is raw (1) or sliced (0) */
-static inline int ivtv_raw_vbi(const struct ivtv *itv)
-{
-       return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
-}
-
-/* This is a PCI post thing, where if the pci register is not read, then
-   the write doesn't always take effect right away. By reading back the
-   register any pending PCI writes will be performed (in order), and so
-   you can be sure that the writes are guaranteed to be done.
-
-   Rarely needed, only in some timing sensitive cases.
-   Apparently if this is not done some motherboards seem
-   to kill the firmware and get into the broken state until computer is
-   rebooted. */
-#define write_sync(val, reg) \
-       do { writel(val, reg); readl(reg); } while (0)
-
-#define read_reg(reg) readl(itv->reg_mem + (reg))
-#define write_reg(val, reg) writel(val, itv->reg_mem + (reg))
-#define write_reg_sync(val, reg) \
-       do { write_reg(val, reg); read_reg(reg); } while (0)
-
-#define read_enc(addr) readl(itv->enc_mem + (u32)(addr))
-#define write_enc(val, addr) writel(val, itv->enc_mem + (u32)(addr))
-#define write_enc_sync(val, addr) \
-       do { write_enc(val, addr); read_enc(addr); } while (0)
-
-#define read_dec(addr) readl(itv->dec_mem + (u32)(addr))
-#define write_dec(val, addr) writel(val, itv->dec_mem + (u32)(addr))
-#define write_dec_sync(val, addr) \
-       do { write_dec(val, addr); read_dec(addr); } while (0)
-
-/* Call the specified callback for all subdevs matching hw (if 0, then
-   match them all). Ignore any errors. */
-#define ivtv_call_hw(itv, hw, o, f, args...)                           \
-       do {                                                            \
-               struct v4l2_subdev *__sd;                               \
-               __v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd,    \
-                       !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \
-       } while (0)
-
-#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
-
-/* Call the specified callback for all subdevs matching hw (if 0, then
-   match them all). If the callback returns an error other than 0 or
-   -ENOIOCTLCMD, then return with that error code. */
-#define ivtv_call_hw_err(itv, hw, o, f, args...)                       \
-({                                                                     \
-       struct v4l2_subdev *__sd;                                       \
-       __v4l2_device_call_subdevs_until_err_p(&(itv)->v4l2_dev, __sd,  \
-               !(hw) || (__sd->grp_id & (hw)), o, f , ##args);         \
-})
-
-#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args)
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
deleted file mode 100644 (file)
index 88bce90..0000000
+++ /dev/null
@@ -1,1070 +0,0 @@
-/*
-    file operation functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-fileops.h"
-#include "ivtv-i2c.h"
-#include "ivtv-queue.h"
-#include "ivtv-udma.h"
-#include "ivtv-irq.h"
-#include "ivtv-vbi.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-routing.h"
-#include "ivtv-streams.h"
-#include "ivtv-yuv.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-cards.h"
-#include "ivtv-firmware.h"
-#include <media/v4l2-event.h>
-#include <media/saa7115.h>
-
-/* This function tries to claim the stream for a specific file descriptor.
-   If no one else is using this stream then the stream is claimed and
-   associated VBI streams are also automatically claimed.
-   Possible error returns: -EBUSY if someone else has claimed
-   the stream or 0 on success. */
-static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
-{
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[type];
-       struct ivtv_stream *s_vbi;
-       int vbi_type;
-
-       if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
-               /* someone already claimed this stream */
-               if (s->fh == &id->fh) {
-                       /* yes, this file descriptor did. So that's OK. */
-                       return 0;
-               }
-               if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
-                                        type == IVTV_ENC_STREAM_TYPE_VBI)) {
-                       /* VBI is handled already internally, now also assign
-                          the file descriptor to this stream for external
-                          reading of the stream. */
-                       s->fh = &id->fh;
-                       IVTV_DEBUG_INFO("Start Read VBI\n");
-                       return 0;
-               }
-               /* someone else is using this stream already */
-               IVTV_DEBUG_INFO("Stream %d is busy\n", type);
-               return -EBUSY;
-       }
-       s->fh = &id->fh;
-       if (type == IVTV_DEC_STREAM_TYPE_VBI) {
-               /* Enable reinsertion interrupt */
-               ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
-       }
-
-       /* IVTV_DEC_STREAM_TYPE_MPG needs to claim IVTV_DEC_STREAM_TYPE_VBI,
-          IVTV_ENC_STREAM_TYPE_MPG needs to claim IVTV_ENC_STREAM_TYPE_VBI
-          (provided VBI insertion is on and sliced VBI is selected), for all
-          other streams we're done */
-       if (type == IVTV_DEC_STREAM_TYPE_MPG) {
-               vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
-       } else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
-                  itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) {
-               vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
-       } else {
-               return 0;
-       }
-       s_vbi = &itv->streams[vbi_type];
-
-       if (!test_and_set_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags)) {
-               /* Enable reinsertion interrupt */
-               if (vbi_type == IVTV_DEC_STREAM_TYPE_VBI)
-                       ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
-       }
-       /* mark that it is used internally */
-       set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags);
-       return 0;
-}
-
-/* This function releases a previously claimed stream. It will take into
-   account associated VBI streams. */
-void ivtv_release_stream(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-       struct ivtv_stream *s_vbi;
-
-       s->fh = NULL;
-       if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
-               test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
-               /* this stream is still in use internally */
-               return;
-       }
-       if (!test_and_clear_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
-               IVTV_DEBUG_WARN("Release stream %s not in use!\n", s->name);
-               return;
-       }
-
-       ivtv_flush_queues(s);
-
-       /* disable reinsertion interrupt */
-       if (s->type == IVTV_DEC_STREAM_TYPE_VBI)
-               ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
-
-       /* IVTV_DEC_STREAM_TYPE_MPG needs to release IVTV_DEC_STREAM_TYPE_VBI,
-          IVTV_ENC_STREAM_TYPE_MPG needs to release IVTV_ENC_STREAM_TYPE_VBI,
-          for all other streams we're done */
-       if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
-               s_vbi = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
-       else if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
-               s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-       else
-               return;
-
-       /* clear internal use flag */
-       if (!test_and_clear_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
-               /* was already cleared */
-               return;
-       }
-       if (s_vbi->fh) {
-               /* VBI stream still claimed by a file descriptor */
-               return;
-       }
-       /* disable reinsertion interrupt */
-       if (s_vbi->type == IVTV_DEC_STREAM_TYPE_VBI)
-               ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
-       clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags);
-       ivtv_flush_queues(s_vbi);
-}
-
-static void ivtv_dualwatch(struct ivtv *itv)
-{
-       struct v4l2_tuner vt;
-       u32 new_stereo_mode;
-       const u32 dual = 0x02;
-
-       new_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
-       memset(&vt, 0, sizeof(vt));
-       ivtv_call_all(itv, tuner, g_tuner, &vt);
-       if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
-               new_stereo_mode = dual;
-
-       if (new_stereo_mode == itv->dualwatch_stereo_mode)
-               return;
-
-       IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
-                          itv->dualwatch_stereo_mode, new_stereo_mode);
-       if (v4l2_ctrl_s_ctrl(itv->cxhdl.audio_mode, new_stereo_mode))
-               IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
-}
-
-static void ivtv_update_pgm_info(struct ivtv *itv)
-{
-       u32 wr_idx = (read_enc(itv->pgm_info_offset) - itv->pgm_info_offset - 4) / 24;
-       int cnt;
-       int i = 0;
-
-       if (wr_idx >= itv->pgm_info_num) {
-               IVTV_DEBUG_WARN("Invalid PGM index %d (>= %d)\n", wr_idx, itv->pgm_info_num);
-               return;
-       }
-       cnt = (wr_idx + itv->pgm_info_num - itv->pgm_info_write_idx) % itv->pgm_info_num;
-       while (i < cnt) {
-               int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
-               struct v4l2_enc_idx_entry *e = itv->pgm_info + idx;
-               u32 addr = itv->pgm_info_offset + 4 + idx * 24;
-               const int mapping[8] = { -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, -1,
-                       V4L2_ENC_IDX_FRAME_B, -1, -1, -1 };
-                                       // 1=I, 2=P, 4=B
-
-               e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32);
-               if (e->offset > itv->mpg_data_received) {
-                       break;
-               }
-               e->offset += itv->vbi_data_inserted;
-               e->length = read_enc(addr);
-               e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32);
-               e->flags = mapping[read_enc(addr + 12) & 7];
-               i++;
-       }
-       itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
-}
-
-static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)
-{
-       struct ivtv *itv = s->itv;
-       struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-       struct ivtv_buffer *buf;
-       DEFINE_WAIT(wait);
-
-       *err = 0;
-       while (1) {
-               if (s->type == IVTV_ENC_STREAM_TYPE_MPG) {
-                       /* Process pending program info updates and pending VBI data */
-                       ivtv_update_pgm_info(itv);
-
-                       if (time_after(jiffies,
-                                      itv->dualwatch_jiffies +
-                                      msecs_to_jiffies(1000))) {
-                               itv->dualwatch_jiffies = jiffies;
-                               ivtv_dualwatch(itv);
-                       }
-
-                       if (test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
-                           !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) {
-                               while ((buf = ivtv_dequeue(s_vbi, &s_vbi->q_full))) {
-                                       /* byteswap and process VBI data */
-                                       ivtv_process_vbi_data(itv, buf, s_vbi->dma_pts, s_vbi->type);
-                                       ivtv_enqueue(s_vbi, buf, &s_vbi->q_free);
-                               }
-                       }
-                       buf = &itv->vbi.sliced_mpeg_buf;
-                       if (buf->readpos != buf->bytesused) {
-                               return buf;
-                       }
-               }
-
-               /* do we have leftover data? */
-               buf = ivtv_dequeue(s, &s->q_io);
-               if (buf)
-                       return buf;
-
-               /* do we have new data? */
-               buf = ivtv_dequeue(s, &s->q_full);
-               if (buf) {
-                       if ((buf->b_flags & IVTV_F_B_NEED_BUF_SWAP) == 0)
-                               return buf;
-                       buf->b_flags &= ~IVTV_F_B_NEED_BUF_SWAP;
-                       if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
-                               /* byteswap MPG data */
-                               ivtv_buf_swap(buf);
-                       else if (s->type != IVTV_DEC_STREAM_TYPE_VBI) {
-                               /* byteswap and process VBI data */
-                               ivtv_process_vbi_data(itv, buf, s->dma_pts, s->type);
-                       }
-                       return buf;
-               }
-
-               /* return if end of stream */
-               if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
-                       IVTV_DEBUG_INFO("EOS %s\n", s->name);
-                       return NULL;
-               }
-
-               /* return if file was opened with O_NONBLOCK */
-               if (non_block) {
-                       *err = -EAGAIN;
-                       return NULL;
-               }
-
-               /* wait for more data to arrive */
-               mutex_unlock(&itv->serialize_lock);
-               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
-               /* New buffers might have become available before we were added to the waitqueue */
-               if (!s->q_full.buffers)
-                       schedule();
-               finish_wait(&s->waitq, &wait);
-               mutex_lock(&itv->serialize_lock);
-               if (signal_pending(current)) {
-                       /* return if a signal was received */
-                       IVTV_DEBUG_INFO("User stopped %s\n", s->name);
-                       *err = -EINTR;
-                       return NULL;
-               }
-       }
-}
-
-static void ivtv_setup_sliced_vbi_buf(struct ivtv *itv)
-{
-       int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES;
-
-       itv->vbi.sliced_mpeg_buf.buf = itv->vbi.sliced_mpeg_data[idx];
-       itv->vbi.sliced_mpeg_buf.bytesused = itv->vbi.sliced_mpeg_size[idx];
-       itv->vbi.sliced_mpeg_buf.readpos = 0;
-}
-
-static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *buf,
-               char __user *ubuf, size_t ucount)
-{
-       struct ivtv *itv = s->itv;
-       size_t len = buf->bytesused - buf->readpos;
-
-       if (len > ucount) len = ucount;
-       if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
-           !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) {
-               const char *start = buf->buf + buf->readpos;
-               const char *p = start + 1;
-               const u8 *q;
-               u8 ch = itv->search_pack_header ? 0xba : 0xe0;
-               int stuffing, i;
-
-               while (start + len > p && (q = memchr(p, 0, start + len - p))) {
-                       p = q + 1;
-                       if ((char *)q + 15 >= buf->buf + buf->bytesused ||
-                           q[1] != 0 || q[2] != 1 || q[3] != ch) {
-                               continue;
-                       }
-                       if (!itv->search_pack_header) {
-                               if ((q[6] & 0xc0) != 0x80)
-                                       continue;
-                               if (((q[7] & 0xc0) == 0x80 && (q[9] & 0xf0) == 0x20) ||
-                                   ((q[7] & 0xc0) == 0xc0 && (q[9] & 0xf0) == 0x30)) {
-                                       ch = 0xba;
-                                       itv->search_pack_header = 1;
-                                       p = q + 9;
-                               }
-                               continue;
-                       }
-                       stuffing = q[13] & 7;
-                       /* all stuffing bytes must be 0xff */
-                       for (i = 0; i < stuffing; i++)
-                               if (q[14 + i] != 0xff)
-                                       break;
-                       if (i == stuffing && (q[4] & 0xc4) == 0x44 && (q[12] & 3) == 3 &&
-                                       q[14 + stuffing] == 0 && q[15 + stuffing] == 0 &&
-                                       q[16 + stuffing] == 1) {
-                               itv->search_pack_header = 0;
-                               len = (char *)q - start;
-                               ivtv_setup_sliced_vbi_buf(itv);
-                               break;
-                       }
-               }
-       }
-       if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
-               IVTV_DEBUG_WARN("copy %zd bytes to user failed for %s\n", len, s->name);
-               return -EFAULT;
-       }
-       /*IVTV_INFO("copied %lld %d %d %d %d %d vbi %d\n", itv->mpg_data_received, len, ucount,
-                       buf->readpos, buf->bytesused, buf->bytesused - buf->readpos - len,
-                       buf == &itv->vbi.sliced_mpeg_buf); */
-       buf->readpos += len;
-       if (s->type == IVTV_ENC_STREAM_TYPE_MPG && buf != &itv->vbi.sliced_mpeg_buf)
-               itv->mpg_data_received += len;
-       return len;
-}
-
-static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_count, int non_block)
-{
-       struct ivtv *itv = s->itv;
-       size_t tot_written = 0;
-       int single_frame = 0;
-
-       if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
-               /* shouldn't happen */
-               IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
-               return -EIO;
-       }
-
-       /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
-          arrive one-by-one, so make sure we never output more than one VBI frame at a time */
-       if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
-           (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv)))
-               single_frame = 1;
-
-       for (;;) {
-               struct ivtv_buffer *buf;
-               int rc;
-
-               buf = ivtv_get_buffer(s, non_block, &rc);
-               /* if there is no data available... */
-               if (buf == NULL) {
-                       /* if we got data, then return that regardless */
-                       if (tot_written)
-                               break;
-                       /* EOS condition */
-                       if (rc == 0) {
-                               clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-                               clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-                               ivtv_release_stream(s);
-                       }
-                       /* set errno */
-                       return rc;
-               }
-               rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written);
-               if (buf != &itv->vbi.sliced_mpeg_buf) {
-                       ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io);
-               }
-               else if (buf->readpos == buf->bytesused) {
-                       int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES;
-                       itv->vbi.sliced_mpeg_size[idx] = 0;
-                       itv->vbi.inserted_frame++;
-                       itv->vbi_data_inserted += buf->bytesused;
-               }
-               if (rc < 0)
-                       return rc;
-               tot_written += rc;
-
-               if (tot_written == tot_count || single_frame)
-                       break;
-       }
-       return tot_written;
-}
-
-static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t count,
-                       loff_t *pos, int non_block)
-{
-       ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0;
-       struct ivtv *itv = s->itv;
-
-       IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
-       if (rc > 0)
-               pos += rc;
-       return rc;
-}
-
-int ivtv_start_capture(struct ivtv_open_id *id)
-{
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       struct ivtv_stream *s_vbi;
-
-       if (s->type == IVTV_ENC_STREAM_TYPE_RAD ||
-           s->type == IVTV_DEC_STREAM_TYPE_MPG ||
-           s->type == IVTV_DEC_STREAM_TYPE_YUV ||
-           s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
-               /* you cannot read from these stream types. */
-               return -EPERM;
-       }
-
-       /* Try to claim this stream. */
-       if (ivtv_claim_stream(id, s->type))
-               return -EBUSY;
-
-       /* This stream does not need to start capturing */
-       if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
-               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               return 0;
-       }
-
-       /* If capture is already in progress, then we also have to
-          do nothing extra. */
-       if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
-               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               return 0;
-       }
-
-       /* Start VBI capture if required */
-       s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-       if (s->type == IVTV_ENC_STREAM_TYPE_MPG &&
-           test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
-           !test_and_set_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) {
-               /* Note: the IVTV_ENC_STREAM_TYPE_VBI is claimed
-                  automatically when the MPG stream is claimed.
-                  We only need to start the VBI capturing. */
-               if (ivtv_start_v4l2_encode_stream(s_vbi)) {
-                       IVTV_DEBUG_WARN("VBI capture start failed\n");
-
-                       /* Failure, clean up and return an error */
-                       clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags);
-                       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
-                       /* also releases the associated VBI stream */
-                       ivtv_release_stream(s);
-                       return -EIO;
-               }
-               IVTV_DEBUG_INFO("VBI insertion started\n");
-       }
-
-       /* Tell the card to start capturing */
-       if (!ivtv_start_v4l2_encode_stream(s)) {
-               /* We're done */
-               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               /* Resume a possibly paused encoder */
-               if (test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
-                       ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
-               return 0;
-       }
-
-       /* failure, clean up */
-       IVTV_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
-
-       /* Note: the IVTV_ENC_STREAM_TYPE_VBI is released
-          automatically when the MPG stream is released.
-          We only need to stop the VBI capturing. */
-       if (s->type == IVTV_ENC_STREAM_TYPE_MPG &&
-           test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) {
-               ivtv_stop_v4l2_encode_stream(s_vbi, 0);
-               clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags);
-       }
-       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
-       ivtv_release_stream(s);
-       return -EIO;
-}
-
-ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       ssize_t rc;
-
-       IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
-
-       if (mutex_lock_interruptible(&itv->serialize_lock))
-               return -ERESTARTSYS;
-       rc = ivtv_start_capture(id);
-       if (!rc)
-               rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
-       mutex_unlock(&itv->serialize_lock);
-       return rc;
-}
-
-int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
-{
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       int rc;
-
-       if (atomic_read(&itv->decoding) == 0) {
-               if (ivtv_claim_stream(id, s->type)) {
-                       /* someone else is using this stream already */
-                       IVTV_DEBUG_WARN("start decode, stream already claimed\n");
-                       return -EBUSY;
-               }
-               rc = ivtv_start_v4l2_decode_stream(s, 0);
-               if (rc < 0) {
-                       if (rc == -EAGAIN)
-                               rc = ivtv_start_v4l2_decode_stream(s, 0);
-                       if (rc < 0)
-                               return rc;
-               }
-       }
-       if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
-               return ivtv_set_speed(itv, speed);
-       return 0;
-}
-
-static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       struct ivtv_buffer *buf;
-       struct ivtv_queue q;
-       int bytes_written = 0;
-       int mode;
-       int rc;
-       DEFINE_WAIT(wait);
-
-       IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);
-
-       if (s->type != IVTV_DEC_STREAM_TYPE_MPG &&
-           s->type != IVTV_DEC_STREAM_TYPE_YUV &&
-           s->type != IVTV_DEC_STREAM_TYPE_VOUT)
-               /* not decoder streams */
-               return -EPERM;
-
-       /* Try to claim this stream */
-       if (ivtv_claim_stream(id, s->type))
-               return -EBUSY;
-
-       /* This stream does not need to start any decoding */
-       if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
-               int elems = count / sizeof(struct v4l2_sliced_vbi_data);
-
-               set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               return ivtv_write_vbi_from_user(itv,
-                  (const struct v4l2_sliced_vbi_data __user *)user_buf, elems);
-       }
-
-       mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
-
-       if (ivtv_set_output_mode(itv, mode) != mode) {
-           ivtv_release_stream(s);
-           return -EBUSY;
-       }
-       ivtv_queue_init(&q);
-       set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-
-       /* Start decoder (returns 0 if already started) */
-       rc = ivtv_start_decoding(id, itv->speed);
-       if (rc) {
-               IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
-
-               /* failure, clean up */
-               clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
-               clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               return rc;
-       }
-
-retry:
-       /* If possible, just DMA the entire frame - Check the data transfer size
-       since we may get here before the stream has been fully set-up */
-       if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
-               while (count >= itv->dma_data_req_size) {
-                       rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf);
-
-                       if (rc < 0)
-                               return rc;
-
-                       bytes_written += itv->dma_data_req_size;
-                       user_buf += itv->dma_data_req_size;
-                       count -= itv->dma_data_req_size;
-               }
-               if (count == 0) {
-                       IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
-                       return bytes_written;
-               }
-       }
-
-       for (;;) {
-               /* Gather buffers */
-               while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io)))
-                       ivtv_enqueue(s, buf, &q);
-               while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_free))) {
-                       ivtv_enqueue(s, buf, &q);
-               }
-               if (q.buffers)
-                       break;
-               if (filp->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               mutex_unlock(&itv->serialize_lock);
-               prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
-               /* New buffers might have become free before we were added to the waitqueue */
-               if (!s->q_free.buffers)
-                       schedule();
-               finish_wait(&s->waitq, &wait);
-               mutex_lock(&itv->serialize_lock);
-               if (signal_pending(current)) {
-                       IVTV_DEBUG_INFO("User stopped %s\n", s->name);
-                       return -EINTR;
-               }
-       }
-
-       /* copy user data into buffers */
-       while ((buf = ivtv_dequeue(s, &q))) {
-               /* yuv is a pain. Don't copy more data than needed for a single
-                  frame, otherwise we lose sync with the incoming stream */
-               if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
-                   yi->stream_size + count > itv->dma_data_req_size)
-                       rc  = ivtv_buf_copy_from_user(s, buf, user_buf,
-                               itv->dma_data_req_size - yi->stream_size);
-               else
-                       rc = ivtv_buf_copy_from_user(s, buf, user_buf, count);
-
-               /* Make sure we really got all the user data */
-               if (rc < 0) {
-                       ivtv_queue_move(s, &q, NULL, &s->q_free, 0);
-                       return rc;
-               }
-               user_buf += rc;
-               count -= rc;
-               bytes_written += rc;
-
-               if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
-                       yi->stream_size += rc;
-                       /* If we have a complete yuv frame, break loop now */
-                       if (yi->stream_size == itv->dma_data_req_size) {
-                               ivtv_enqueue(s, buf, &s->q_full);
-                               yi->stream_size = 0;
-                               break;
-                       }
-               }
-
-               if (buf->bytesused != s->buf_size) {
-                       /* incomplete, leave in q_io for next time */
-                       ivtv_enqueue(s, buf, &s->q_io);
-                       break;
-               }
-               /* Byteswap MPEG buffer */
-               if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
-                       ivtv_buf_swap(buf);
-               ivtv_enqueue(s, buf, &s->q_full);
-       }
-
-       if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
-               if (s->q_full.length >= itv->dma_data_req_size) {
-                       int got_sig;
-
-                       if (mode == OUT_YUV)
-                               ivtv_yuv_setup_stream_frame(itv);
-
-                       mutex_unlock(&itv->serialize_lock);
-                       prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
-                       while (!(got_sig = signal_pending(current)) &&
-                                       test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
-                               schedule();
-                       }
-                       finish_wait(&itv->dma_waitq, &wait);
-                       mutex_lock(&itv->serialize_lock);
-                       if (got_sig) {
-                               IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
-                               return -EINTR;
-                       }
-
-                       clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
-                       ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
-                       ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 1);
-               }
-       }
-       /* more user data is available, wait until buffers become free
-          to transfer the rest. */
-       if (count && !(filp->f_flags & O_NONBLOCK))
-               goto retry;
-       IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
-       return bytes_written;
-}
-
-ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       ssize_t res;
-
-       if (mutex_lock_interruptible(&itv->serialize_lock))
-               return -ERESTARTSYS;
-       res = ivtv_write(filp, user_buf, count, pos);
-       mutex_unlock(&itv->serialize_lock);
-       return res;
-}
-
-unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       int res = 0;
-
-       /* add stream's waitq to the poll list */
-       IVTV_DEBUG_HI_FILE("Decoder poll\n");
-
-       /* If there are subscribed events, then only use the new event
-          API instead of the old video.h based API. */
-       if (!list_empty(&id->fh.subscribed)) {
-               poll_wait(filp, &id->fh.wait, wait);
-               /* Turn off the old-style vsync events */
-               clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
-               if (v4l2_event_pending(&id->fh))
-                       res = POLLPRI;
-       } else {
-               /* This is the old-style API which is here only for backwards
-                  compatibility. */
-               poll_wait(filp, &s->waitq, wait);
-               set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
-               if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) ||
-                   test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
-                       res = POLLPRI;
-       }
-
-       /* Allow write if buffers are available for writing */
-       if (s->q_free.buffers)
-               res |= POLLOUT | POLLWRNORM;
-       return res;
-}
-
-unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait)
-{
-       unsigned long req_events = poll_requested_events(wait);
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-       unsigned res = 0;
-
-       /* Start a capture if there is none */
-       if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) &&
-                       (req_events & (POLLIN | POLLRDNORM))) {
-               int rc;
-
-               mutex_lock(&itv->serialize_lock);
-               rc = ivtv_start_capture(id);
-               mutex_unlock(&itv->serialize_lock);
-               if (rc) {
-                       IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
-                                       s->name, rc);
-                       return POLLERR;
-               }
-               IVTV_DEBUG_FILE("Encoder poll started capture\n");
-       }
-
-       /* add stream's waitq to the poll list */
-       IVTV_DEBUG_HI_FILE("Encoder poll\n");
-       poll_wait(filp, &s->waitq, wait);
-       if (v4l2_event_pending(&id->fh))
-               res |= POLLPRI;
-       else
-               poll_wait(filp, &id->fh.wait, wait);
-
-       if (s->q_full.length || s->q_io.length)
-               return res | POLLIN | POLLRDNORM;
-       if (eof)
-               return res | POLLHUP;
-       return res;
-}
-
-void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
-{
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-
-       IVTV_DEBUG_FILE("close() of %s\n", s->name);
-
-       /* 'Unclaim' this stream */
-
-       /* Stop capturing */
-       if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
-               struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-
-               IVTV_DEBUG_INFO("close stopping capture\n");
-               /* Special case: a running VBI capture for VBI insertion
-                  in the mpeg stream. Need to stop that too. */
-               if (id->type == IVTV_ENC_STREAM_TYPE_MPG &&
-                   test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags) &&
-                   !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) {
-                       IVTV_DEBUG_INFO("close stopping embedded VBI capture\n");
-                       ivtv_stop_v4l2_encode_stream(s_vbi, 0);
-               }
-               if ((id->type == IVTV_DEC_STREAM_TYPE_VBI ||
-                    id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
-                   test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
-                       /* Also used internally, don't stop capturing */
-                       s->fh = NULL;
-               }
-               else {
-                       ivtv_stop_v4l2_encode_stream(s, gop_end);
-               }
-       }
-       if (!gop_end) {
-               clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-               clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-               ivtv_release_stream(s);
-       }
-}
-
-static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
-{
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-
-       IVTV_DEBUG_FILE("close() of %s\n", s->name);
-
-       if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
-               test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
-               /* Restore registers we've changed & clean up any mess */
-               ivtv_yuv_close(itv);
-       }
-
-       /* Stop decoding */
-       if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
-               IVTV_DEBUG_INFO("close stopping decode\n");
-
-               ivtv_stop_v4l2_decode_stream(s, flags, pts);
-               itv->output_mode = OUT_NONE;
-       }
-       clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
-       clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-
-       if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
-               itv->output_mode = OUT_NONE;
-
-       itv->speed = 0;
-       clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
-       ivtv_release_stream(s);
-}
-
-int ivtv_v4l2_close(struct file *filp)
-{
-       struct v4l2_fh *fh = filp->private_data;
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-
-       IVTV_DEBUG_FILE("close %s\n", s->name);
-
-       mutex_lock(&itv->serialize_lock);
-
-       /* Stop radio */
-       if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
-                       v4l2_fh_is_singular_file(filp)) {
-               /* Closing radio device, return to TV mode */
-               ivtv_mute(itv);
-               /* Mark that the radio is no longer in use */
-               clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
-               /* Switch tuner to TV */
-               ivtv_call_all(itv, core, s_std, itv->std);
-               /* Select correct audio input (i.e. TV tuner or Line in) */
-               ivtv_audio_set_io(itv);
-               if (itv->hw_flags & IVTV_HW_SAA711X) {
-                       ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
-                                       SAA7115_FREQ_32_11_MHZ, 0);
-               }
-               if (atomic_read(&itv->capturing) > 0) {
-                       /* Undo video mute */
-                       ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
-                                       v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
-                                       (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
-               }
-               /* Done! Unmute and continue. */
-               ivtv_unmute(itv);
-       }
-
-       v4l2_fh_del(fh);
-       v4l2_fh_exit(fh);
-
-       /* Easy case first: this stream was never claimed by us */
-       if (s->fh != &id->fh)
-               goto close_done;
-
-       /* 'Unclaim' this stream */
-
-       if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
-               struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
-
-               ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
-
-               /* If all output streams are closed, and if the user doesn't have
-                  IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */
-               if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) {
-                       /* disable CC on TV-out */
-                       ivtv_disable_cc(itv);
-               }
-       } else {
-               ivtv_stop_capture(id, 0);
-       }
-close_done:
-       kfree(id);
-       mutex_unlock(&itv->serialize_lock);
-       return 0;
-}
-
-static int ivtv_open(struct file *filp)
-{
-       struct video_device *vdev = video_devdata(filp);
-       struct ivtv_stream *s = video_get_drvdata(vdev);
-       struct ivtv *itv = s->itv;
-       struct ivtv_open_id *item;
-       int res = 0;
-
-       IVTV_DEBUG_FILE("open %s\n", s->name);
-
-       if (ivtv_init_on_first_open(itv)) {
-               IVTV_ERR("Failed to initialize on device %s\n",
-                        video_device_node_name(vdev));
-               return -ENXIO;
-       }
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       /* Unless ivtv_fw_debug is set, error out if firmware dead. */
-       if (ivtv_fw_debug) {
-               IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
-                         video_device_node_name(vdev));
-               IVTV_WARN("Selected firmware errors will be ignored\n");
-       } else {
-#else
-       if (1) {
-#endif
-               res = ivtv_firmware_check(itv, "ivtv_serialized_open");
-               if (res == -EAGAIN)
-                       res = ivtv_firmware_check(itv, "ivtv_serialized_open");
-               if (res < 0)
-                       return -EIO;
-       }
-
-       if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
-               test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
-               return -EBUSY;
-
-       if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
-               test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags))
-               return -EBUSY;
-
-       if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
-               if (read_reg(0x82c) == 0) {
-                       IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n");
-                       /* return -ENODEV; */
-               }
-               ivtv_udma_alloc(itv);
-       }
-
-       /* Allocate memory */
-       item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
-       if (NULL == item) {
-               IVTV_DEBUG_WARN("nomem on v4l2 open\n");
-               return -ENOMEM;
-       }
-       v4l2_fh_init(&item->fh, s->vdev);
-       item->itv = itv;
-       item->type = s->type;
-
-       filp->private_data = &item->fh;
-       v4l2_fh_add(&item->fh);
-
-       if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
-                       v4l2_fh_is_singular_file(filp)) {
-               if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
-                       if (atomic_read(&itv->capturing) > 0) {
-                               /* switching to radio while capture is
-                                  in progress is not polite */
-                               v4l2_fh_del(&item->fh);
-                               v4l2_fh_exit(&item->fh);
-                               kfree(item);
-                               return -EBUSY;
-                       }
-               }
-               /* Mark that the radio is being used. */
-               set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
-               /* We have the radio */
-               ivtv_mute(itv);
-               /* Switch tuner to radio */
-               ivtv_call_all(itv, tuner, s_radio);
-               /* Select the correct audio input (i.e. radio tuner) */
-               ivtv_audio_set_io(itv);
-               if (itv->hw_flags & IVTV_HW_SAA711X) {
-                       ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
-                               SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL);
-               }
-               /* Done! Unmute and continue. */
-               ivtv_unmute(itv);
-       }
-
-       /* YUV or MPG Decoding Mode? */
-       if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
-               clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
-       } else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
-               set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
-               /* For yuv, we need to know the dma size before we start */
-               itv->dma_data_req_size =
-                               1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
-               itv->yuv_info.stream_size = 0;
-       }
-       return 0;
-}
-
-int ivtv_v4l2_open(struct file *filp)
-{
-       struct video_device *vdev = video_devdata(filp);
-       int res;
-
-       if (mutex_lock_interruptible(vdev->lock))
-               return -ERESTARTSYS;
-       res = ivtv_open(filp);
-       mutex_unlock(vdev->lock);
-       return res;
-}
-
-void ivtv_mute(struct ivtv *itv)
-{
-       if (atomic_read(&itv->capturing))
-               ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1);
-       IVTV_DEBUG_INFO("Mute\n");
-}
-
-void ivtv_unmute(struct ivtv *itv)
-{
-       if (atomic_read(&itv->capturing)) {
-               ivtv_msleep_timeout(100, 0);
-               ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
-               ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
-       }
-       IVTV_DEBUG_INFO("Unmute\n");
-}
diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h
deleted file mode 100644 (file)
index 049a292..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-    file operation functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_FILEOPS_H
-#define IVTV_FILEOPS_H
-
-/* Testing/Debugging */
-int ivtv_v4l2_open(struct file *filp);
-ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count,
-                     loff_t * pos);
-ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count,
-                      loff_t * pos);
-int ivtv_v4l2_close(struct file *filp);
-unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait);
-unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait);
-int ivtv_start_capture(struct ivtv_open_id *id);
-void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end);
-int ivtv_start_decoding(struct ivtv_open_id *id, int speed);
-void ivtv_mute(struct ivtv *itv);
-void ivtv_unmute(struct ivtv *itv);
-
-/* Utilities */
-
-/* Release a previously claimed stream. */
-void ivtv_release_stream(struct ivtv_stream *s);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c
deleted file mode 100644 (file)
index 6ec7705..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
-    ivtv firmware functions.
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-firmware.h"
-#include "ivtv-yuv.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-cards.h"
-#include <linux/firmware.h>
-#include <media/saa7127.h>
-
-#define IVTV_MASK_SPU_ENABLE           0xFFFFFFFE
-#define IVTV_MASK_VPU_ENABLE15                 0xFFFFFFF6
-#define IVTV_MASK_VPU_ENABLE16                 0xFFFFFFFB
-#define IVTV_CMD_VDM_STOP              0x00000000
-#define IVTV_CMD_AO_STOP               0x00000005
-#define IVTV_CMD_APU_PING              0x00000000
-#define IVTV_CMD_VPU_STOP15            0xFFFFFFFE
-#define IVTV_CMD_VPU_STOP16            0xFFFFFFEE
-#define IVTV_CMD_HW_BLOCKS_RST                 0xFFFFFFFF
-#define IVTV_CMD_SPU_STOP              0x00000001
-#define IVTV_CMD_SDRAM_PRECHARGE_INIT  0x0000001A
-#define IVTV_CMD_SDRAM_REFRESH_INIT    0x80000640
-#define IVTV_SDRAM_SLEEPTIME           600
-
-#define IVTV_DECODE_INIT_MPEG_FILENAME         "v4l-cx2341x-init.mpg"
-#define IVTV_DECODE_INIT_MPEG_SIZE     (152*1024)
-
-/* Encoder/decoder firmware sizes */
-#define IVTV_FW_ENC_SIZE               (376836)
-#define IVTV_FW_DEC_SIZE               (256*1024)
-
-static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size)
-{
-       const struct firmware *fw = NULL;
-       int retries = 3;
-
-retry:
-       if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) {
-               int i;
-               volatile u32 __iomem *dst = (volatile u32 __iomem *)mem;
-               const u32 *src = (const u32 *)fw->data;
-
-               if (fw->size != size) {
-                       /* Due to race conditions in firmware loading (esp. with udev <0.95)
-                          the wrong file was sometimes loaded. So we check filesizes to
-                          see if at least the right-sized file was loaded. If not, then we
-                          retry. */
-                       IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size);
-                       release_firmware(fw);
-                       retries--;
-                       goto retry;
-               }
-               for (i = 0; i < fw->size; i += 4) {
-                       /* no need for endianness conversion on the ppc */
-                       __raw_writel(*src, dst);
-                       dst++;
-                       src++;
-               }
-               IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size);
-               release_firmware(fw);
-               return size;
-       }
-       IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size);
-       IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n");
-       return -ENOMEM;
-}
-
-void ivtv_halt_firmware(struct ivtv *itv)
-{
-       IVTV_DEBUG_INFO("Preparing for firmware halt.\n");
-       if (itv->has_cx23415 && itv->dec_mbox.mbox)
-               ivtv_vapi(itv, CX2341X_DEC_HALT_FW, 0);
-       if (itv->enc_mbox.mbox)
-               ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0);
-
-       ivtv_msleep_timeout(10, 0);
-       itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL;
-
-       IVTV_DEBUG_INFO("Stopping VDM\n");
-       write_reg(IVTV_CMD_VDM_STOP, IVTV_REG_VDM);
-
-       IVTV_DEBUG_INFO("Stopping AO\n");
-       write_reg(IVTV_CMD_AO_STOP, IVTV_REG_AO);
-
-       IVTV_DEBUG_INFO("pinging (?) APU\n");
-       write_reg(IVTV_CMD_APU_PING, IVTV_REG_APU);
-
-       IVTV_DEBUG_INFO("Stopping VPU\n");
-       if (!itv->has_cx23415)
-               write_reg(IVTV_CMD_VPU_STOP16, IVTV_REG_VPU);
-       else
-               write_reg(IVTV_CMD_VPU_STOP15, IVTV_REG_VPU);
-
-       IVTV_DEBUG_INFO("Resetting Hw Blocks\n");
-       write_reg(IVTV_CMD_HW_BLOCKS_RST, IVTV_REG_HW_BLOCKS);
-
-       IVTV_DEBUG_INFO("Stopping SPU\n");
-       write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU);
-
-       ivtv_msleep_timeout(10, 0);
-
-       IVTV_DEBUG_INFO("init Encoder SDRAM pre-charge\n");
-       write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_ENC_SDRAM_PRECHARGE);
-
-       IVTV_DEBUG_INFO("init Encoder SDRAM refresh to 1us\n");
-       write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_ENC_SDRAM_REFRESH);
-
-       if (itv->has_cx23415) {
-               IVTV_DEBUG_INFO("init Decoder SDRAM pre-charge\n");
-               write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_DEC_SDRAM_PRECHARGE);
-
-               IVTV_DEBUG_INFO("init Decoder SDRAM refresh to 1us\n");
-               write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH);
-       }
-
-       IVTV_DEBUG_INFO("Sleeping for %dms\n", IVTV_SDRAM_SLEEPTIME);
-       ivtv_msleep_timeout(IVTV_SDRAM_SLEEPTIME, 0);
-}
-
-void ivtv_firmware_versions(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-
-       /* Encoder */
-       ivtv_vapi_result(itv, data, CX2341X_ENC_GET_VERSION, 0);
-       IVTV_INFO("Encoder revision: 0x%08x\n", data[0]);
-
-       if (data[0] != 0x02060039)
-               IVTV_WARN("Recommended firmware version is 0x02060039.\n");
-
-       if (itv->has_cx23415) {
-               /* Decoder */
-               ivtv_vapi_result(itv, data, CX2341X_DEC_GET_VERSION, 0);
-               IVTV_INFO("Decoder revision: 0x%08x\n", data[0]);
-       }
-}
-
-static int ivtv_firmware_copy(struct ivtv *itv)
-{
-       IVTV_DEBUG_INFO("Loading encoder image\n");
-       if (load_fw_direct(CX2341X_FIRM_ENC_FILENAME,
-                  itv->enc_mem, itv, IVTV_FW_ENC_SIZE) != IVTV_FW_ENC_SIZE) {
-               IVTV_DEBUG_WARN("failed loading encoder firmware\n");
-               return -3;
-       }
-       if (!itv->has_cx23415)
-               return 0;
-
-       IVTV_DEBUG_INFO("Loading decoder image\n");
-       if (load_fw_direct(CX2341X_FIRM_DEC_FILENAME,
-                  itv->dec_mem, itv, IVTV_FW_DEC_SIZE) != IVTV_FW_DEC_SIZE) {
-               IVTV_DEBUG_WARN("failed loading decoder firmware\n");
-               return -1;
-       }
-       return 0;
-}
-
-static volatile struct ivtv_mailbox __iomem *ivtv_search_mailbox(const volatile u8 __iomem *mem, u32 size)
-{
-       int i;
-
-       /* mailbox is preceded by a 16 byte 'magic cookie' starting at a 256-byte
-          address boundary */
-       for (i = 0; i < size; i += 0x100) {
-               if (readl(mem + i)      == 0x12345678 &&
-                   readl(mem + i + 4)  == 0x34567812 &&
-                   readl(mem + i + 8)  == 0x56781234 &&
-                   readl(mem + i + 12) == 0x78123456) {
-                       return (volatile struct ivtv_mailbox __iomem *)(mem + i + 16);
-               }
-       }
-       return NULL;
-}
-
-int ivtv_firmware_init(struct ivtv *itv)
-{
-       int err;
-
-       ivtv_halt_firmware(itv);
-
-       /* load firmware */
-       err = ivtv_firmware_copy(itv);
-       if (err) {
-               IVTV_DEBUG_WARN("Error %d loading firmware\n", err);
-               return err;
-       }
-
-       /* start firmware */
-       write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU);
-       ivtv_msleep_timeout(100, 0);
-       if (itv->has_cx23415)
-               write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE15, IVTV_REG_VPU);
-       else
-               write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE16, IVTV_REG_VPU);
-       ivtv_msleep_timeout(100, 0);
-
-       /* find mailboxes and ping firmware */
-       itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE);
-       if (itv->enc_mbox.mbox == NULL)
-               IVTV_ERR("Encoder mailbox not found\n");
-       else if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0)) {
-               IVTV_ERR("Encoder firmware dead!\n");
-               itv->enc_mbox.mbox = NULL;
-       }
-       if (itv->enc_mbox.mbox == NULL)
-               return -ENODEV;
-
-       if (!itv->has_cx23415)
-               return 0;
-
-       itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE);
-       if (itv->dec_mbox.mbox == NULL) {
-               IVTV_ERR("Decoder mailbox not found\n");
-       } else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) {
-               IVTV_ERR("Decoder firmware dead!\n");
-               itv->dec_mbox.mbox = NULL;
-       } else {
-               /* Firmware okay, so check yuv output filter table */
-               ivtv_yuv_filter_check(itv);
-       }
-       return itv->dec_mbox.mbox ? 0 : -ENODEV;
-}
-
-void ivtv_init_mpeg_decoder(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       long readbytes;
-       volatile u8 __iomem *mem_offset;
-
-       data[0] = 0;
-       data[1] = itv->cxhdl.width;     /* YUV source width */
-       data[2] = itv->cxhdl.height;
-       data[3] = itv->cxhdl.audio_properties;  /* Audio settings to use,
-                                                          bitmap. see docs. */
-       if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) {
-               IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n");
-               return;
-       }
-
-       if (ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1) != 0) {
-               IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n");
-               return;
-       }
-       ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
-       mem_offset = itv->dec_mem + data[1];
-
-       if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME,
-               mem_offset, itv, IVTV_DECODE_INIT_MPEG_SIZE)) <= 0) {
-               IVTV_DEBUG_WARN("failed to read mpeg decoder initialisation file %s\n",
-                               IVTV_DECODE_INIT_MPEG_FILENAME);
-       } else {
-               ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0);
-               ivtv_msleep_timeout(100, 0);
-       }
-       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1);
-}
-
-/* Try to restart the card & restore previous settings */
-int ivtv_firmware_restart(struct ivtv *itv)
-{
-       int rc = 0;
-       v4l2_std_id std;
-
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
-               /* Display test image during restart */
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
-                   SAA7127_INPUT_TYPE_TEST_IMAGE,
-                   itv->card->video_outputs[itv->active_output].video_output,
-                   0);
-
-       mutex_lock(&itv->udma.lock);
-
-       rc = ivtv_firmware_init(itv);
-       if (rc) {
-               mutex_unlock(&itv->udma.lock);
-               return rc;
-       }
-
-       /* Allow settings to reload */
-       ivtv_mailbox_cache_invalidate(itv);
-
-       /* Restore encoder video standard */
-       std = itv->std;
-       itv->std = 0;
-       ivtv_s_std_enc(itv, &std);
-
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               ivtv_init_mpeg_decoder(itv);
-
-               /* Restore decoder video standard */
-               std = itv->std_out;
-               itv->std_out = 0;
-               ivtv_s_std_dec(itv, &std);
-
-               /* Restore framebuffer if active */
-               if (itv->ivtvfb_restore)
-                       itv->ivtvfb_restore(itv);
-
-               /* Restore alpha settings */
-               ivtv_set_osd_alpha(itv);
-
-               /* Restore normal output */
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
-                   SAA7127_INPUT_TYPE_NORMAL,
-                   itv->card->video_outputs[itv->active_output].video_output,
-                   0);
-       }
-
-       mutex_unlock(&itv->udma.lock);
-       return rc;
-}
-
-/* Check firmware running state. The checks fall through
-   allowing multiple failures to be logged. */
-int ivtv_firmware_check(struct ivtv *itv, char *where)
-{
-       int res = 0;
-
-       /* Check encoder is still running */
-       if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) {
-               IVTV_WARN("Encoder has died : %s\n", where);
-               res = -1;
-       }
-
-       /* Also check audio. Only check if not in use & encoder is okay */
-       if (!res && !atomic_read(&itv->capturing) &&
-           (!atomic_read(&itv->decoding) ||
-            (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV,
-                                                            &itv->i_flags)))) {
-
-               if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) {
-                       IVTV_WARN("Audio has died (Encoder OK) : %s\n", where);
-                       res = -2;
-               }
-       }
-
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               /* Second audio check. Skip if audio already failed */
-               if (res != -2 && read_dec(0x100) != read_dec(0x104)) {
-                       /* Wait & try again to be certain. */
-                       ivtv_msleep_timeout(14, 0);
-                       if (read_dec(0x100) != read_dec(0x104)) {
-                               IVTV_WARN("Audio has died (Decoder) : %s\n",
-                                         where);
-                               res = -1;
-                       }
-               }
-
-               /* Check decoder is still running */
-               if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) {
-                       IVTV_WARN("Decoder has died : %s\n", where);
-                       res = -1;
-               }
-       }
-
-       /* If something failed & currently idle, try to reload */
-       if (res && !atomic_read(&itv->capturing) &&
-                                               !atomic_read(&itv->decoding)) {
-               IVTV_INFO("Detected in %s that firmware had failed - "
-                         "Reloading\n", where);
-               res = ivtv_firmware_restart(itv);
-               /*
-                * Even if restarted ok, still signal a problem had occurred.
-                * The caller can come through this function again to check
-                * if things are really ok after the restart.
-                */
-               if (!res) {
-                       IVTV_INFO("Firmware restart okay\n");
-                       res = -EAGAIN;
-               } else {
-                       IVTV_INFO("Firmware restart failed\n");
-               }
-       } else if (res) {
-               res = -EIO;
-       }
-
-       return res;
-}
-
-MODULE_FIRMWARE(CX2341X_FIRM_ENC_FILENAME);
-MODULE_FIRMWARE(CX2341X_FIRM_DEC_FILENAME);
-MODULE_FIRMWARE(IVTV_DECODE_INIT_MPEG_FILENAME);
diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/video/ivtv/ivtv-firmware.h
deleted file mode 100644 (file)
index 52bb4e5..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-    ivtv firmware functions.
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_FIRMWARE_H
-#define IVTV_FIRMWARE_H
-
-int ivtv_firmware_init(struct ivtv *itv);
-void ivtv_firmware_versions(struct ivtv *itv);
-void ivtv_halt_firmware(struct ivtv *itv);
-void ivtv_init_mpeg_decoder(struct ivtv *itv);
-int ivtv_firmware_check(struct ivtv *itv, char *where);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c
deleted file mode 100644 (file)
index 8f0d077..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
-    gpio functions.
-    Merging GPIO support into driver:
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-cards.h"
-#include "ivtv-gpio.h"
-#include "tuner-xc2028.h"
-#include <media/tuner.h>
-#include <media/v4l2-ctrls.h>
-
-/*
- * GPIO assignment of Yuan MPG600/MPG160
- *
- *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
- * OUTPUT         IN1 IN0                                       AM3 AM2 AM1 AM0
- *  INPUT                   DM1         DM0
- *
- *   IN* : Input selection
- *          IN1 IN0
- *           1   1  N/A
- *           1   0  Line
- *           0   1  N/A
- *           0   0  Tuner
- *
- *   AM* : Audio Mode
- *          AM3  0: Normal        1: Mixed(Sub+Main channel)
- *          AM2  0: Subchannel    1: Main channel
- *          AM1  0: Stereo        1: Mono
- *          AM0  0: Normal        1: Mute
- *
- *   DM* : Detected tuner audio Mode
- *          DM1  0: Stereo        1: Mono
- *          DM0  0: Multiplex     1: Normal
- *
- * GPIO Initial Settings
- *           MPG600   MPG160
- *     DIR   0x3080   0x7080
- *  OUTPUT   0x000C   0x400C
- *
- *  Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous
- *  for analyzing GPIO of MPG160.
- *
- *****************************************************************************
- *
- * GPIO assignment of Avermedia M179 (per information direct from AVerMedia)
- *
- *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
- * OUTPUT IN0 AM0 IN1               AM1 AM2       IN2     BR0   BR1
- *  INPUT
- *
- *   IN* : Input selection
- *          IN0 IN1 IN2
- *           *   1   *  Mute
- *           0   0   0  Line-In
- *           1   0   0  TV Tuner Audio
- *           0   0   1  FM Audio
- *           1   0   1  Mute
- *
- *   AM* : Audio Mode
- *          AM0 AM1 AM2
- *           0   0   0  TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP
- *           0   0   1  TV Tuner Audio: L_OUT=R_OUT=SAP   (SAP)
- *           0   1   0  TV Tuner Audio: L_OUT=L, R_OUT=R   (stereo)
- *           0   1   1  TV Tuner Audio: mute
- *           1   *   *  TV Tuner Audio: L_OUT=R_OUT=(L+R)/2   (mono)
- *
- *   BR* : Audio Sample Rate (BR stands for bitrate for some reason)
- *          BR0 BR1
- *           0   0   32 kHz
- *           0   1   44.1 kHz
- *           1   0   48 kHz
- *
- *   DM* : Detected tuner audio Mode
- *         Unknown currently
- *
- * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at
- * AVerMedia for providing the GPIO information used to add support
- * for the M179 cards.
- */
-
-/********************* GPIO stuffs *********************/
-
-/* GPIO registers */
-#define IVTV_REG_GPIO_IN    0x9008
-#define IVTV_REG_GPIO_OUT   0x900c
-#define IVTV_REG_GPIO_DIR   0x9020
-
-void ivtv_reset_ir_gpio(struct ivtv *itv)
-{
-       int curdir, curout;
-
-       if (itv->card->type != IVTV_CARD_PVR_150)
-               return;
-       IVTV_DEBUG_INFO("Resetting PVR150 IR\n");
-       curout = read_reg(IVTV_REG_GPIO_OUT);
-       curdir = read_reg(IVTV_REG_GPIO_DIR);
-       curdir |= 0x80;
-       write_reg(curdir, IVTV_REG_GPIO_DIR);
-       curout = (curout & ~0xF) | 1;
-       write_reg(curout, IVTV_REG_GPIO_OUT);
-       /* We could use something else for smaller time */
-       schedule_timeout_interruptible(msecs_to_jiffies(1));
-       curout |= 2;
-       write_reg(curout, IVTV_REG_GPIO_OUT);
-       curdir &= ~0x80;
-       write_reg(curdir, IVTV_REG_GPIO_DIR);
-}
-
-/* Xceive tuner reset function */
-int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
-{
-       struct i2c_algo_bit_data *algo = dev;
-       struct ivtv *itv = algo->data;
-       u32 curout;
-
-       if (cmd != XC2028_TUNER_RESET)
-               return 0;
-       IVTV_DEBUG_INFO("Resetting tuner\n");
-       curout = read_reg(IVTV_REG_GPIO_OUT);
-       curout &= ~(1 << itv->card->xceive_pin);
-       write_reg(curout, IVTV_REG_GPIO_OUT);
-       schedule_timeout_interruptible(msecs_to_jiffies(1));
-
-       curout |= 1 << itv->card->xceive_pin;
-       write_reg(curout, IVTV_REG_GPIO_OUT);
-       schedule_timeout_interruptible(msecs_to_jiffies(1));
-       return 0;
-}
-
-static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct ivtv, sd_gpio);
-}
-
-static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
-{
-       return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio;
-}
-
-static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask, data;
-
-       mask = itv->card->gpio_audio_freq.mask;
-       switch (freq) {
-       case 32000:
-               data = itv->card->gpio_audio_freq.f32000;
-               break;
-       case 44100:
-               data = itv->card->gpio_audio_freq.f44100;
-               break;
-       case 48000:
-       default:
-               data = itv->card->gpio_audio_freq.f48000;
-               break;
-       }
-       if (mask)
-               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
-       return 0;
-}
-
-static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask;
-
-       mask = itv->card->gpio_audio_detect.mask;
-       if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
-               vt->rxsubchans = V4L2_TUNER_SUB_STEREO |
-                       V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-       else
-               vt->rxsubchans = V4L2_TUNER_SUB_MONO;
-       return 0;
-}
-
-static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask, data;
-
-       mask = itv->card->gpio_audio_mode.mask;
-       switch (vt->audmode) {
-       case V4L2_TUNER_MODE_LANG1:
-               data = itv->card->gpio_audio_mode.lang1;
-               break;
-       case V4L2_TUNER_MODE_LANG2:
-               data = itv->card->gpio_audio_mode.lang2;
-               break;
-       case V4L2_TUNER_MODE_MONO:
-               data = itv->card->gpio_audio_mode.mono;
-               break;
-       case V4L2_TUNER_MODE_STEREO:
-       case V4L2_TUNER_MODE_LANG1_LANG2:
-       default:
-               data = itv->card->gpio_audio_mode.stereo;
-               break;
-       }
-       if (mask)
-               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
-       return 0;
-}
-
-static int subdev_s_radio(struct v4l2_subdev *sd)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask, data;
-
-       mask = itv->card->gpio_audio_input.mask;
-       data = itv->card->gpio_audio_input.radio;
-       if (mask)
-               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
-       return 0;
-}
-
-static int subdev_s_audio_routing(struct v4l2_subdev *sd,
-                                 u32 input, u32 output, u32 config)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask, data;
-
-       if (input > 2)
-               return -EINVAL;
-       mask = itv->card->gpio_audio_input.mask;
-       switch (input) {
-       case 0:
-               data = itv->card->gpio_audio_input.tuner;
-               break;
-       case 1:
-               data = itv->card->gpio_audio_input.linein;
-               break;
-       case 2:
-       default:
-               data = itv->card->gpio_audio_input.radio;
-               break;
-       }
-       if (mask)
-               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
-       return 0;
-}
-
-static int subdev_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct v4l2_subdev *sd = to_sd(ctrl);
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask, data;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               mask = itv->card->gpio_audio_mute.mask;
-               data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0;
-               if (mask)
-                       write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) |
-                                       (data & mask), IVTV_REG_GPIO_OUT);
-               return 0;
-       }
-       return -EINVAL;
-}
-
-
-static int subdev_log_status(struct v4l2_subdev *sd)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-
-       IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
-                       read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
-                       read_reg(IVTV_REG_GPIO_IN));
-       v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name);
-       return 0;
-}
-
-static int subdev_s_video_routing(struct v4l2_subdev *sd,
-                                 u32 input, u32 output, u32 config)
-{
-       struct ivtv *itv = sd_to_ivtv(sd);
-       u16 mask, data;
-
-       if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */
-               return -EINVAL;
-       mask = itv->card->gpio_video_input.mask;
-       if (input == 0)
-               data = itv->card->gpio_video_input.tuner;
-       else if (input == 1)
-               data = itv->card->gpio_video_input.composite;
-       else
-               data = itv->card->gpio_video_input.svideo;
-       if (mask)
-               write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
-       return 0;
-}
-
-static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
-       .s_ctrl = subdev_s_ctrl,
-};
-
-static const struct v4l2_subdev_core_ops subdev_core_ops = {
-       .log_status = subdev_log_status,
-       .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
-       .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
-       .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
-       .g_ctrl = v4l2_subdev_g_ctrl,
-       .s_ctrl = v4l2_subdev_s_ctrl,
-       .queryctrl = v4l2_subdev_queryctrl,
-       .querymenu = v4l2_subdev_querymenu,
-};
-
-static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
-       .s_radio = subdev_s_radio,
-       .g_tuner = subdev_g_tuner,
-       .s_tuner = subdev_s_tuner,
-};
-
-static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
-       .s_clock_freq = subdev_s_clock_freq,
-       .s_routing = subdev_s_audio_routing,
-};
-
-static const struct v4l2_subdev_video_ops subdev_video_ops = {
-       .s_routing = subdev_s_video_routing,
-};
-
-static const struct v4l2_subdev_ops subdev_ops = {
-       .core = &subdev_core_ops,
-       .tuner = &subdev_tuner_ops,
-       .audio = &subdev_audio_ops,
-       .video = &subdev_video_ops,
-};
-
-int ivtv_gpio_init(struct ivtv *itv)
-{
-       u16 pin = 0;
-
-       if (itv->card->xceive_pin)
-               pin = 1 << itv->card->xceive_pin;
-
-       if ((itv->card->gpio_init.direction | pin) == 0)
-               return 0;
-
-       IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
-                  read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
-
-       /* init output data then direction */
-       write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
-       write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
-       v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
-       snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name);
-       itv->sd_gpio.grp_id = IVTV_HW_GPIO;
-       v4l2_ctrl_handler_init(&itv->hdl_gpio, 1);
-       v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops,
-                       V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
-       if (itv->hdl_gpio.error)
-               return itv->hdl_gpio.error;
-       itv->sd_gpio.ctrl_handler = &itv->hdl_gpio;
-       v4l2_ctrl_handler_setup(&itv->hdl_gpio);
-       return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
-}
diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h
deleted file mode 100644 (file)
index 0b5d19c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-    gpio functions.
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_GPIO_H
-#define IVTV_GPIO_H
-
-/* GPIO stuff */
-int ivtv_gpio_init(struct ivtv *itv);
-void ivtv_reset_ir_gpio(struct ivtv *itv);
-int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
deleted file mode 100644 (file)
index d47f41a..0000000
+++ /dev/null
@@ -1,760 +0,0 @@
-/*
-    I2C functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
-    This file includes an i2c implementation that was reverse engineered
-    from the Hauppauge windows driver.  Older ivtv versions used i2c-algo-bit,
-    which whilst fine under most circumstances, had trouble with the Zilog
-    CPU on the PVR-150 which handles IR functions (occasional inability to
-    communicate with the chip until it was reset) and also with the i2c
-    bus being completely unreachable when multiple PVR cards were present.
-
-    The implementation is very similar to i2c-algo-bit, but there are enough
-    subtle differences that the two are hard to merge.  The general strategy
-    employed by i2c-algo-bit is to use udelay() to implement the timing
-    when putting out bits on the scl/sda lines.  The general strategy taken
-    here is to poll the lines for state changes (see ivtv_waitscl and
-    ivtv_waitsda).  In addition there are small delays at various locations
-    which poll the SCL line 5 times (ivtv_scldelay).  I would guess that
-    since this is memory mapped I/O that the length of those delays is tied
-    to the PCI bus clock.  There is some extra code to do with recovery
-    and retries.  Since it is not known what causes the actual i2c problems
-    in the first place, the only goal if one was to attempt to use
-    i2c-algo-bit would be to try to make it follow the same code path.
-    This would be a lot of work, and I'm also not convinced that it would
-    provide a generic benefit to i2c-algo-bit.  Therefore consider this
-    an engineering solution -- not pretty, but it works.
-
-    Some more general comments about what we are doing:
-
-    The i2c bus is a 2 wire serial bus, with clock (SCL) and data (SDA)
-    lines.  To communicate on the bus (as a master, we don't act as a slave),
-    we first initiate a start condition (ivtv_start).  We then write the
-    address of the device that we want to communicate with, along with a flag
-    that indicates whether this is a read or a write.  The slave then issues
-    an ACK signal (ivtv_ack), which tells us that it is ready for reading /
-    writing.  We then proceed with reading or writing (ivtv_read/ivtv_write),
-    and finally issue a stop condition (ivtv_stop) to make the bus available
-    to other masters.
-
-    There is an additional form of transaction where a write may be
-    immediately followed by a read.  In this case, there is no intervening
-    stop condition.  (Only the msp3400 chip uses this method of data transfer).
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-cards.h"
-#include "ivtv-gpio.h"
-#include "ivtv-i2c.h"
-#include <media/cx25840.h>
-
-/* i2c implementation for cx23415/6 chip, ivtv project.
- * Author: Kevin Thayer (nufan_wfk at yahoo.com)
- */
-/* i2c stuff */
-#define IVTV_REG_I2C_SETSCL_OFFSET 0x7000
-#define IVTV_REG_I2C_SETSDA_OFFSET 0x7004
-#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008
-#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c
-
-#define IVTV_CS53L32A_I2C_ADDR         0x11
-#define IVTV_M52790_I2C_ADDR           0x48
-#define IVTV_CX25840_I2C_ADDR          0x44
-#define IVTV_SAA7115_I2C_ADDR          0x21
-#define IVTV_SAA7127_I2C_ADDR          0x44
-#define IVTV_SAA717x_I2C_ADDR          0x21
-#define IVTV_MSP3400_I2C_ADDR          0x40
-#define IVTV_HAUPPAUGE_I2C_ADDR        0x50
-#define IVTV_WM8739_I2C_ADDR           0x1a
-#define IVTV_WM8775_I2C_ADDR           0x1b
-#define IVTV_TEA5767_I2C_ADDR          0x60
-#define IVTV_UPD64031A_I2C_ADDR        0x12
-#define IVTV_UPD64083_I2C_ADDR                 0x5c
-#define IVTV_VP27SMPX_I2C_ADDR         0x5b
-#define IVTV_M52790_I2C_ADDR           0x48
-#define IVTV_AVERMEDIA_IR_RX_I2C_ADDR  0x40
-#define IVTV_HAUP_EXT_IR_RX_I2C_ADDR   0x1a
-#define IVTV_HAUP_INT_IR_RX_I2C_ADDR   0x18
-#define IVTV_Z8F0811_IR_TX_I2C_ADDR    0x70
-#define IVTV_Z8F0811_IR_RX_I2C_ADDR    0x71
-#define IVTV_ADAPTEC_IR_ADDR           0x6b
-
-/* This array should match the IVTV_HW_ defines */
-static const u8 hw_addrs[] = {
-       IVTV_CX25840_I2C_ADDR,
-       IVTV_SAA7115_I2C_ADDR,
-       IVTV_SAA7127_I2C_ADDR,
-       IVTV_MSP3400_I2C_ADDR,
-       0,
-       IVTV_WM8775_I2C_ADDR,
-       IVTV_CS53L32A_I2C_ADDR,
-       0,
-       IVTV_SAA7115_I2C_ADDR,
-       IVTV_UPD64031A_I2C_ADDR,
-       IVTV_UPD64083_I2C_ADDR,
-       IVTV_SAA717x_I2C_ADDR,
-       IVTV_WM8739_I2C_ADDR,
-       IVTV_VP27SMPX_I2C_ADDR,
-       IVTV_M52790_I2C_ADDR,
-       0,                              /* IVTV_HW_GPIO dummy driver ID */
-       IVTV_AVERMEDIA_IR_RX_I2C_ADDR,  /* IVTV_HW_I2C_IR_RX_AVER */
-       IVTV_HAUP_EXT_IR_RX_I2C_ADDR,   /* IVTV_HW_I2C_IR_RX_HAUP_EXT */
-       IVTV_HAUP_INT_IR_RX_I2C_ADDR,   /* IVTV_HW_I2C_IR_RX_HAUP_INT */
-       IVTV_Z8F0811_IR_TX_I2C_ADDR,    /* IVTV_HW_Z8F0811_IR_TX_HAUP */
-       IVTV_Z8F0811_IR_RX_I2C_ADDR,    /* IVTV_HW_Z8F0811_IR_RX_HAUP */
-       IVTV_ADAPTEC_IR_ADDR,           /* IVTV_HW_I2C_IR_RX_ADAPTEC */
-};
-
-/* This array should match the IVTV_HW_ defines */
-static const char * const hw_devicenames[] = {
-       "cx25840",
-       "saa7115",
-       "saa7127_auto", /* saa7127 or saa7129 */
-       "msp3400",
-       "tuner",
-       "wm8775",
-       "cs53l32a",
-       "tveeprom",
-       "saa7114",
-       "upd64031a",
-       "upd64083",
-       "saa717x",
-       "wm8739",
-       "vp27smpx",
-       "m52790",
-       "gpio",
-       "ir_video",             /* IVTV_HW_I2C_IR_RX_AVER */
-       "ir_video",             /* IVTV_HW_I2C_IR_RX_HAUP_EXT */
-       "ir_video",             /* IVTV_HW_I2C_IR_RX_HAUP_INT */
-       "ir_tx_z8f0811_haup",   /* IVTV_HW_Z8F0811_IR_TX_HAUP */
-       "ir_rx_z8f0811_haup",   /* IVTV_HW_Z8F0811_IR_RX_HAUP */
-       "ir_video",             /* IVTV_HW_I2C_IR_RX_ADAPTEC */
-};
-
-static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       unsigned char keybuf[4];
-
-       keybuf[0] = 0x00;
-       i2c_master_send(ir->c, keybuf, 1);
-       /* poll IR chip */
-       if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) {
-               return 0;
-       }
-
-       /* key pressed ? */
-       if (keybuf[2] == 0xff)
-               return 0;
-
-       /* remove repeat bit */
-       keybuf[2] &= 0x7f;
-       keybuf[3] |= 0x80;
-
-       *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
-       *ir_raw = *ir_key;
-
-       return 1;
-}
-
-static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
-{
-       struct i2c_board_info info;
-       struct i2c_adapter *adap = &itv->i2c_adap;
-       struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data;
-       unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
-
-       /* Only allow one IR transmitter to be registered per board */
-       if (hw & IVTV_HW_IR_TX_ANY) {
-               if (itv->hw_flags & IVTV_HW_IR_TX_ANY)
-                       return -1;
-               memset(&info, 0, sizeof(struct i2c_board_info));
-               strlcpy(info.type, type, I2C_NAME_SIZE);
-               return i2c_new_probed_device(adap, &info, addr_list, NULL)
-                                                          == NULL ? -1 : 0;
-       }
-
-       /* Only allow one IR receiver to be registered per board */
-       if (itv->hw_flags & IVTV_HW_IR_RX_ANY)
-               return -1;
-
-       /* Our default information for ir-kbd-i2c.c to use */
-       switch (hw) {
-       case IVTV_HW_I2C_IR_RX_AVER:
-               init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
-               init_data->internal_get_key_func =
-                                       IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
-               init_data->type = RC_TYPE_OTHER;
-               init_data->name = "AVerMedia AVerTV card";
-               break;
-       case IVTV_HW_I2C_IR_RX_HAUP_EXT:
-       case IVTV_HW_I2C_IR_RX_HAUP_INT:
-               init_data->ir_codes = RC_MAP_HAUPPAUGE;
-               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-               init_data->type = RC_TYPE_RC5;
-               init_data->name = itv->card_name;
-               break;
-       case IVTV_HW_Z8F0811_IR_RX_HAUP:
-               /* Default to grey remote */
-               init_data->ir_codes = RC_MAP_HAUPPAUGE;
-               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-               init_data->type = RC_TYPE_RC5;
-               init_data->name = itv->card_name;
-               break;
-       case IVTV_HW_I2C_IR_RX_ADAPTEC:
-               init_data->get_key = get_key_adaptec;
-               init_data->name = itv->card_name;
-               /* FIXME: The protocol and RC_MAP needs to be corrected */
-               init_data->ir_codes = RC_MAP_EMPTY;
-               init_data->type = RC_TYPE_UNKNOWN;
-               break;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.platform_data = init_data;
-       strlcpy(info.type, type, I2C_NAME_SIZE);
-
-       return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
-              -1 : 0;
-}
-
-/* Instantiate the IR receiver device using probing -- undesirable */
-struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv)
-{
-       struct i2c_board_info info;
-       /*
-        * The external IR receiver is at i2c address 0x34.
-        * The internal IR receiver is at i2c address 0x30.
-        *
-        * In theory, both can be fitted, and Hauppauge suggests an external
-        * overrides an internal.  That's why we probe 0x1a (~0x34) first. CB
-        *
-        * Some of these addresses we probe may collide with other i2c address
-        * allocations, so this function must be called after all other i2c
-        * devices we care about are registered.
-        */
-       const unsigned short addr_list[] = {
-               0x1a,   /* Hauppauge IR external - collides with WM8739 */
-               0x18,   /* Hauppauge IR internal */
-               I2C_CLIENT_END
-       };
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-       return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL);
-}
-
-int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
-{
-       struct v4l2_subdev *sd;
-       struct i2c_adapter *adap = &itv->i2c_adap;
-       const char *type = hw_devicenames[idx];
-       u32 hw = 1 << idx;
-
-       if (idx >= ARRAY_SIZE(hw_addrs))
-               return -1;
-       if (hw == IVTV_HW_TUNER) {
-               /* special tuner handling */
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
-                               itv->card_i2c->radio);
-               if (sd)
-                       sd->grp_id = 1 << idx;
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
-                               itv->card_i2c->demod);
-               if (sd)
-                       sd->grp_id = 1 << idx;
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
-                               itv->card_i2c->tv);
-               if (sd)
-                       sd->grp_id = 1 << idx;
-               return sd ? 0 : -1;
-       }
-
-       if (hw & IVTV_HW_IR_ANY)
-               return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]);
-
-       /* Is it not an I2C device or one we do not wish to register? */
-       if (!hw_addrs[idx])
-               return -1;
-
-       /* It's an I2C device other than an analog tuner or IR chip */
-       if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
-       } else if (hw == IVTV_HW_CX25840) {
-               struct cx25840_platform_data pdata;
-               struct i2c_board_info cx25840_info = {
-                       .type = "cx25840",
-                       .addr = hw_addrs[idx],
-                       .platform_data = &pdata,
-               };
-
-               pdata.pvr150_workaround = itv->pvr150_workaround;
-               sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap,
-                               &cx25840_info, NULL);
-       } else {
-               sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
-                               adap, type, hw_addrs[idx], NULL);
-       }
-       if (sd)
-               sd->grp_id = 1 << idx;
-       return sd ? 0 : -1;
-}
-
-struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw)
-{
-       struct v4l2_subdev *result = NULL;
-       struct v4l2_subdev *sd;
-
-       spin_lock(&itv->v4l2_dev.lock);
-       v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) {
-               if (sd->grp_id == hw) {
-                       result = sd;
-                       break;
-               }
-       }
-       spin_unlock(&itv->v4l2_dev.lock);
-       return result;
-}
-
-/* Set the serial clock line to the desired state */
-static void ivtv_setscl(struct ivtv *itv, int state)
-{
-       /* write them out */
-       /* write bits are inverted */
-       write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET);
-}
-
-/* Set the serial data line to the desired state */
-static void ivtv_setsda(struct ivtv *itv, int state)
-{
-       /* write them out */
-       /* write bits are inverted */
-       write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET);
-}
-
-/* Read the serial clock line */
-static int ivtv_getscl(struct ivtv *itv)
-{
-       return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
-}
-
-/* Read the serial data line */
-static int ivtv_getsda(struct ivtv *itv)
-{
-       return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
-}
-
-/* Implement a short delay by polling the serial clock line */
-static void ivtv_scldelay(struct ivtv *itv)
-{
-       int i;
-
-       for (i = 0; i < 5; ++i)
-               ivtv_getscl(itv);
-}
-
-/* Wait for the serial clock line to become set to a specific value */
-static int ivtv_waitscl(struct ivtv *itv, int val)
-{
-       int i;
-
-       ivtv_scldelay(itv);
-       for (i = 0; i < 1000; ++i) {
-               if (ivtv_getscl(itv) == val)
-                       return 1;
-       }
-       return 0;
-}
-
-/* Wait for the serial data line to become set to a specific value */
-static int ivtv_waitsda(struct ivtv *itv, int val)
-{
-       int i;
-
-       ivtv_scldelay(itv);
-       for (i = 0; i < 1000; ++i) {
-               if (ivtv_getsda(itv) == val)
-                       return 1;
-       }
-       return 0;
-}
-
-/* Wait for the slave to issue an ACK */
-static int ivtv_ack(struct ivtv *itv)
-{
-       int ret = 0;
-
-       if (ivtv_getscl(itv) == 1) {
-               IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n");
-               ivtv_setscl(itv, 0);
-               if (!ivtv_waitscl(itv, 0)) {
-                       IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n");
-                       return -EREMOTEIO;
-               }
-       }
-       ivtv_setsda(itv, 1);
-       ivtv_scldelay(itv);
-       ivtv_setscl(itv, 1);
-       if (!ivtv_waitsda(itv, 0)) {
-               IVTV_DEBUG_I2C("Slave did not ack\n");
-               ret = -EREMOTEIO;
-       }
-       ivtv_setscl(itv, 0);
-       if (!ivtv_waitscl(itv, 0)) {
-               IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n");
-               ret = -EREMOTEIO;
-       }
-       return ret;
-}
-
-/* Write a single byte to the i2c bus and wait for the slave to ACK */
-static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte)
-{
-       int i, bit;
-
-       IVTV_DEBUG_HI_I2C("write %x\n",byte);
-       for (i = 0; i < 8; ++i, byte<<=1) {
-               ivtv_setscl(itv, 0);
-               if (!ivtv_waitscl(itv, 0)) {
-                       IVTV_DEBUG_I2C("Error setting SCL low\n");
-                       return -EREMOTEIO;
-               }
-               bit = (byte>>7)&1;
-               ivtv_setsda(itv, bit);
-               if (!ivtv_waitsda(itv, bit)) {
-                       IVTV_DEBUG_I2C("Error setting SDA\n");
-                       return -EREMOTEIO;
-               }
-               ivtv_setscl(itv, 1);
-               if (!ivtv_waitscl(itv, 1)) {
-                       IVTV_DEBUG_I2C("Slave not ready for bit\n");
-                       return -EREMOTEIO;
-               }
-       }
-       ivtv_setscl(itv, 0);
-       if (!ivtv_waitscl(itv, 0)) {
-               IVTV_DEBUG_I2C("Error setting SCL low\n");
-               return -EREMOTEIO;
-       }
-       return ivtv_ack(itv);
-}
-
-/* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the
-   final byte) */
-static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack)
-{
-       int i;
-
-       *byte = 0;
-
-       ivtv_setsda(itv, 1);
-       ivtv_scldelay(itv);
-       for (i = 0; i < 8; ++i) {
-               ivtv_setscl(itv, 0);
-               ivtv_scldelay(itv);
-               ivtv_setscl(itv, 1);
-               if (!ivtv_waitscl(itv, 1)) {
-                       IVTV_DEBUG_I2C("Error setting SCL high\n");
-                       return -EREMOTEIO;
-               }
-               *byte = ((*byte)<<1)|ivtv_getsda(itv);
-       }
-       ivtv_setscl(itv, 0);
-       ivtv_scldelay(itv);
-       ivtv_setsda(itv, nack);
-       ivtv_scldelay(itv);
-       ivtv_setscl(itv, 1);
-       ivtv_scldelay(itv);
-       ivtv_setscl(itv, 0);
-       ivtv_scldelay(itv);
-       IVTV_DEBUG_HI_I2C("read %x\n",*byte);
-       return 0;
-}
-
-/* Issue a start condition on the i2c bus to alert slaves to prepare for
-   an address write */
-static int ivtv_start(struct ivtv *itv)
-{
-       int sda;
-
-       sda = ivtv_getsda(itv);
-       if (sda != 1) {
-               IVTV_DEBUG_HI_I2C("SDA was low at start\n");
-               ivtv_setsda(itv, 1);
-               if (!ivtv_waitsda(itv, 1)) {
-                       IVTV_DEBUG_I2C("SDA stuck low\n");
-                       return -EREMOTEIO;
-               }
-       }
-       if (ivtv_getscl(itv) != 1) {
-               ivtv_setscl(itv, 1);
-               if (!ivtv_waitscl(itv, 1)) {
-                       IVTV_DEBUG_I2C("SCL stuck low at start\n");
-                       return -EREMOTEIO;
-               }
-       }
-       ivtv_setsda(itv, 0);
-       ivtv_scldelay(itv);
-       return 0;
-}
-
-/* Issue a stop condition on the i2c bus to release it */
-static int ivtv_stop(struct ivtv *itv)
-{
-       int i;
-
-       if (ivtv_getscl(itv) != 0) {
-               IVTV_DEBUG_HI_I2C("SCL not low when stopping\n");
-               ivtv_setscl(itv, 0);
-               if (!ivtv_waitscl(itv, 0)) {
-                       IVTV_DEBUG_I2C("SCL could not be set low\n");
-               }
-       }
-       ivtv_setsda(itv, 0);
-       ivtv_scldelay(itv);
-       ivtv_setscl(itv, 1);
-       if (!ivtv_waitscl(itv, 1)) {
-               IVTV_DEBUG_I2C("SCL could not be set high\n");
-               return -EREMOTEIO;
-       }
-       ivtv_scldelay(itv);
-       ivtv_setsda(itv, 1);
-       if (!ivtv_waitsda(itv, 1)) {
-               IVTV_DEBUG_I2C("resetting I2C\n");
-               for (i = 0; i < 16; ++i) {
-                       ivtv_setscl(itv, 0);
-                       ivtv_scldelay(itv);
-                       ivtv_setscl(itv, 1);
-                       ivtv_scldelay(itv);
-                       ivtv_setsda(itv, 1);
-               }
-               ivtv_waitsda(itv, 1);
-               return -EREMOTEIO;
-       }
-       return 0;
-}
-
-/* Write a message to the given i2c slave.  do_stop may be 0 to prevent
-   issuing the i2c stop condition (when following with a read) */
-static int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop)
-{
-       int retry, ret = -EREMOTEIO;
-       u32 i;
-
-       for (retry = 0; ret != 0 && retry < 8; ++retry) {
-               ret = ivtv_start(itv);
-
-               if (ret == 0) {
-                       ret = ivtv_sendbyte(itv, addr<<1);
-                       for (i = 0; ret == 0 && i < len; ++i)
-                               ret = ivtv_sendbyte(itv, data[i]);
-               }
-               if (ret != 0 || do_stop) {
-                       ivtv_stop(itv);
-               }
-       }
-       if (ret)
-               IVTV_DEBUG_I2C("i2c write to %x failed\n", addr);
-       return ret;
-}
-
-/* Read data from the given i2c slave.  A stop condition is always issued. */
-static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len)
-{
-       int retry, ret = -EREMOTEIO;
-       u32 i;
-
-       for (retry = 0; ret != 0 && retry < 8; ++retry) {
-               ret = ivtv_start(itv);
-               if (ret == 0)
-                       ret = ivtv_sendbyte(itv, (addr << 1) | 1);
-               for (i = 0; ret == 0 && i < len; ++i) {
-                       ret = ivtv_readbyte(itv, &data[i], i == len - 1);
-               }
-               ivtv_stop(itv);
-       }
-       if (ret)
-               IVTV_DEBUG_I2C("i2c read from %x failed\n", addr);
-       return ret;
-}
-
-/* Kernel i2c transfer implementation.  Takes a number of messages to be read
-   or written.  If a read follows a write, this will occur without an
-   intervening stop condition */
-static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
-       struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
-       struct ivtv *itv = to_ivtv(v4l2_dev);
-       int retval;
-       int i;
-
-       mutex_lock(&itv->i2c_bus_lock);
-       for (i = retval = 0; retval == 0 && i < num; i++) {
-               if (msgs[i].flags & I2C_M_RD)
-                       retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len);
-               else {
-                       /* if followed by a read, don't stop */
-                       int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD);
-
-                       retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop);
-               }
-       }
-       mutex_unlock(&itv->i2c_bus_lock);
-       return retval ? retval : num;
-}
-
-/* Kernel i2c capabilities */
-static u32 ivtv_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm ivtv_algo = {
-       .master_xfer   = ivtv_xfer,
-       .functionality = ivtv_functionality,
-};
-
-/* template for our-bit banger */
-static struct i2c_adapter ivtv_i2c_adap_hw_template = {
-       .name = "ivtv i2c driver",
-       .algo = &ivtv_algo,
-       .algo_data = NULL,                      /* filled from template */
-       .owner = THIS_MODULE,
-};
-
-static void ivtv_setscl_old(void *data, int state)
-{
-       struct ivtv *itv = (struct ivtv *)data;
-
-       if (state)
-               itv->i2c_state |= 0x01;
-       else
-               itv->i2c_state &= ~0x01;
-
-       /* write them out */
-       /* write bits are inverted */
-       write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET);
-}
-
-static void ivtv_setsda_old(void *data, int state)
-{
-       struct ivtv *itv = (struct ivtv *)data;
-
-       if (state)
-               itv->i2c_state |= 0x01;
-       else
-               itv->i2c_state &= ~0x01;
-
-       /* write them out */
-       /* write bits are inverted */
-       write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET);
-}
-
-static int ivtv_getscl_old(void *data)
-{
-       struct ivtv *itv = (struct ivtv *)data;
-
-       return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
-}
-
-static int ivtv_getsda_old(void *data)
-{
-       struct ivtv *itv = (struct ivtv *)data;
-
-       return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
-}
-
-/* template for i2c-bit-algo */
-static struct i2c_adapter ivtv_i2c_adap_template = {
-       .name = "ivtv i2c driver",
-       .algo = NULL,                   /* set by i2c-algo-bit */
-       .algo_data = NULL,              /* filled from template */
-       .owner = THIS_MODULE,
-};
-
-#define IVTV_ALGO_BIT_TIMEOUT  (2)     /* seconds */
-
-static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
-       .setsda         = ivtv_setsda_old,
-       .setscl         = ivtv_setscl_old,
-       .getsda         = ivtv_getsda_old,
-       .getscl         = ivtv_getscl_old,
-       .udelay         = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2,  /* microseconds */
-       .timeout        = IVTV_ALGO_BIT_TIMEOUT * HZ,         /* jiffies */
-};
-
-static struct i2c_client ivtv_i2c_client_template = {
-       .name = "ivtv internal",
-};
-
-/* init + register i2c adapter */
-int init_ivtv_i2c(struct ivtv *itv)
-{
-       int retval;
-
-       IVTV_DEBUG_I2C("i2c init\n");
-
-       /* Sanity checks for the I2C hardware arrays. They must be the
-        * same size.
-        */
-       if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs)) {
-               IVTV_ERR("Mismatched I2C hardware arrays\n");
-               return -ENODEV;
-       }
-       if (itv->options.newi2c > 0) {
-               memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template,
-                      sizeof(struct i2c_adapter));
-       } else {
-               memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template,
-                      sizeof(struct i2c_adapter));
-               memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,
-                      sizeof(struct i2c_algo_bit_data));
-       }
-       itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2;
-       itv->i2c_algo.data = itv;
-       itv->i2c_adap.algo_data = &itv->i2c_algo;
-
-       sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
-               itv->instance);
-       i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev);
-
-       memcpy(&itv->i2c_client, &ivtv_i2c_client_template,
-              sizeof(struct i2c_client));
-       itv->i2c_client.adapter = &itv->i2c_adap;
-       itv->i2c_adap.dev.parent = &itv->pdev->dev;
-
-       IVTV_DEBUG_I2C("setting scl and sda to 1\n");
-       ivtv_setscl(itv, 1);
-       ivtv_setsda(itv, 1);
-
-       if (itv->options.newi2c > 0)
-               retval = i2c_add_adapter(&itv->i2c_adap);
-       else
-               retval = i2c_bit_add_bus(&itv->i2c_adap);
-
-       return retval;
-}
-
-void exit_ivtv_i2c(struct ivtv *itv)
-{
-       IVTV_DEBUG_I2C("i2c exit\n");
-
-       i2c_del_adapter(&itv->i2c_adap);
-}
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h
deleted file mode 100644 (file)
index 7b9ec1c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-    I2C functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_I2C_H
-#define IVTV_I2C_H
-
-struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv);
-int ivtv_i2c_register(struct ivtv *itv, unsigned idx);
-struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw);
-
-/* init + register i2c adapter */
-int init_ivtv_i2c(struct ivtv *itv);
-void exit_ivtv_i2c(struct ivtv *itv);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
deleted file mode 100644 (file)
index 32a5910..0000000
+++ /dev/null
@@ -1,1899 +0,0 @@
-/*
-    ioctl system call
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-version.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-i2c.h"
-#include "ivtv-queue.h"
-#include "ivtv-fileops.h"
-#include "ivtv-vbi.h"
-#include "ivtv-routing.h"
-#include "ivtv-streams.h"
-#include "ivtv-yuv.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-gpio.h"
-#include "ivtv-controls.h"
-#include "ivtv-cards.h"
-#include <media/saa7127.h>
-#include <media/tveeprom.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/v4l2-event.h>
-#include <linux/dvb/audio.h>
-
-u16 ivtv_service2vbi(int type)
-{
-       switch (type) {
-               case V4L2_SLICED_TELETEXT_B:
-                       return IVTV_SLICED_TYPE_TELETEXT_B;
-               case V4L2_SLICED_CAPTION_525:
-                       return IVTV_SLICED_TYPE_CAPTION_525;
-               case V4L2_SLICED_WSS_625:
-                       return IVTV_SLICED_TYPE_WSS_625;
-               case V4L2_SLICED_VPS:
-                       return IVTV_SLICED_TYPE_VPS;
-               default:
-                       return 0;
-       }
-}
-
-static int valid_service_line(int field, int line, int is_pal)
-{
-       return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
-              (!is_pal && line >= 10 && line < 22);
-}
-
-static u16 select_service_from_set(int field, int line, u16 set, int is_pal)
-{
-       u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525);
-       int i;
-
-       set = set & valid_set;
-       if (set == 0 || !valid_service_line(field, line, is_pal)) {
-               return 0;
-       }
-       if (!is_pal) {
-               if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
-                       return V4L2_SLICED_CAPTION_525;
-       }
-       else {
-               if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
-                       return V4L2_SLICED_VPS;
-               if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
-                       return V4L2_SLICED_WSS_625;
-               if (line == 23)
-                       return 0;
-       }
-       for (i = 0; i < 32; i++) {
-               if ((1 << i) & set)
-                       return 1 << i;
-       }
-       return 0;
-}
-
-void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
-{
-       u16 set = fmt->service_set;
-       int f, l;
-
-       fmt->service_set = 0;
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++) {
-                       fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal);
-               }
-       }
-}
-
-static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
-{
-       int f, l;
-
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++) {
-                       fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal);
-               }
-       }
-}
-
-u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
-{
-       int f, l;
-       u16 set = 0;
-
-       for (f = 0; f < 2; f++) {
-               for (l = 0; l < 24; l++) {
-                       set |= fmt->service_lines[f][l];
-               }
-       }
-       return set;
-}
-
-void ivtv_set_osd_alpha(struct ivtv *itv)
-{
-       ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
-               itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
-       ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);
-}
-
-int ivtv_set_speed(struct ivtv *itv, int speed)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       int single_step = (speed == 1 || speed == -1);
-       DEFINE_WAIT(wait);
-
-       if (speed == 0) speed = 1000;
-
-       /* No change? */
-       if (speed == itv->speed && !single_step)
-               return 0;
-
-       if (single_step && (speed < 0) == (itv->speed < 0)) {
-               /* Single step video and no need to change direction */
-               ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
-               itv->speed = speed;
-               return 0;
-       }
-       if (single_step)
-               /* Need to change direction */
-               speed = speed < 0 ? -1000 : 1000;
-
-       data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
-       data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
-       data[1] = (speed < 0);
-       data[2] = speed < 0 ? 3 : 7;
-       data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);
-       data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
-       data[5] = 0;
-       data[6] = 0;
-
-       if (speed == 1500 || speed == -1500) data[0] |= 1;
-       else if (speed == 2000 || speed == -2000) data[0] |= 2;
-       else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
-       else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
-
-       /* If not decoding, just change speed setting */
-       if (atomic_read(&itv->decoding) > 0) {
-               int got_sig = 0;
-
-               /* Stop all DMA and decoding activity */
-               ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
-
-               /* Wait for any DMA to finish */
-               mutex_unlock(&itv->serialize_lock);
-               prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
-               while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
-                       got_sig = signal_pending(current);
-                       if (got_sig)
-                               break;
-                       got_sig = 0;
-                       schedule();
-               }
-               finish_wait(&itv->dma_waitq, &wait);
-               mutex_lock(&itv->serialize_lock);
-               if (got_sig)
-                       return -EINTR;
-
-               /* Change Speed safely */
-               ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
-               IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
-                               data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
-       }
-       if (single_step) {
-               speed = (speed < 0) ? -1 : 1;
-               ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
-       }
-       itv->speed = speed;
-       return 0;
-}
-
-static int ivtv_validate_speed(int cur_speed, int new_speed)
-{
-       int fact = new_speed < 0 ? -1 : 1;
-       int s;
-
-       if (cur_speed == 0)
-               cur_speed = 1000;
-       if (new_speed < 0)
-               new_speed = -new_speed;
-       if (cur_speed < 0)
-               cur_speed = -cur_speed;
-
-       if (cur_speed <= new_speed) {
-               if (new_speed > 1500)
-                       return fact * 2000;
-               if (new_speed > 1000)
-                       return fact * 1500;
-       }
-       else {
-               if (new_speed >= 2000)
-                       return fact * 2000;
-               if (new_speed >= 1500)
-                       return fact * 1500;
-               if (new_speed >= 1000)
-                       return fact * 1000;
-       }
-       if (new_speed == 0)
-               return 1000;
-       if (new_speed == 1 || new_speed == 1000)
-               return fact * new_speed;
-
-       s = new_speed;
-       new_speed = 1000 / new_speed;
-       if (1000 / cur_speed == new_speed)
-               new_speed += (cur_speed < s) ? -1 : 1;
-       if (new_speed > 60) return 1000 / (fact * 60);
-       return 1000 / (fact * new_speed);
-}
-
-static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
-               struct v4l2_decoder_cmd *dc, int try)
-{
-       struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return -EINVAL;
-
-       switch (dc->cmd) {
-       case V4L2_DEC_CMD_START: {
-               dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
-               dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
-               if (dc->start.speed < 0)
-                       dc->start.format = V4L2_DEC_START_FMT_GOP;
-               else
-                       dc->start.format = V4L2_DEC_START_FMT_NONE;
-               if (dc->start.speed != 500 && dc->start.speed != 1500)
-                       dc->flags = dc->start.speed == 1000 ? 0 :
-                                       V4L2_DEC_CMD_START_MUTE_AUDIO;
-               if (try) break;
-
-               itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
-               if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
-                       return -EBUSY;
-               if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
-                       /* forces ivtv_set_speed to be called */
-                       itv->speed = 0;
-               }
-               return ivtv_start_decoding(id, dc->start.speed);
-       }
-
-       case V4L2_DEC_CMD_STOP:
-               dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
-               if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
-                       dc->stop.pts = 0;
-               if (try) break;
-               if (atomic_read(&itv->decoding) == 0)
-                       return 0;
-               if (itv->output_mode != OUT_MPG)
-                       return -EBUSY;
-
-               itv->output_mode = OUT_NONE;
-               return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
-
-       case V4L2_DEC_CMD_PAUSE:
-               dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
-               if (try) break;
-               if (itv->output_mode != OUT_MPG)
-                       return -EBUSY;
-               if (atomic_read(&itv->decoding) > 0) {
-                       ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
-                               (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
-                       set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
-               }
-               break;
-
-       case V4L2_DEC_CMD_RESUME:
-               dc->flags = 0;
-               if (try) break;
-               if (itv->output_mode != OUT_MPG)
-                       return -EBUSY;
-               if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
-                       int speed = itv->speed;
-                       itv->speed = 0;
-                       return ivtv_start_decoding(id, speed);
-               }
-               break;
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
-               return -EINVAL;
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
-       if (itv->is_60hz) {
-               vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
-               vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
-       } else {
-               vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
-               vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
-       }
-       vbifmt->service_set = ivtv_get_service_set(vbifmt);
-       return 0;
-}
-
-static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
-
-       pixfmt->width = itv->cxhdl.width;
-       pixfmt->height = itv->cxhdl.height;
-       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
-       if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
-               pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
-               /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
-               pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
-               pixfmt->bytesperline = 720;
-       } else {
-               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
-               pixfmt->sizeimage = 128 * 1024;
-               pixfmt->bytesperline = 0;
-       }
-       return 0;
-}
-
-static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
-
-       vbifmt->sampling_rate = 27000000;
-       vbifmt->offset = 248;
-       vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
-       vbifmt->sample_format = V4L2_PIX_FMT_GREY;
-       vbifmt->start[0] = itv->vbi.start[0];
-       vbifmt->start[1] = itv->vbi.start[1];
-       vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
-       vbifmt->flags = 0;
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       return 0;
-}
-
-static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
-
-       if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
-               vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
-                       V4L2_SLICED_VBI_525;
-               ivtv_expand_service_set(vbifmt, itv->is_50hz);
-               return 0;
-       }
-
-       v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);
-       vbifmt->service_set = ivtv_get_service_set(vbifmt);
-       return 0;
-}
-
-static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return -EINVAL;
-       pixfmt->width = itv->main_rect.width;
-       pixfmt->height = itv->main_rect.height;
-       pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       pixfmt->field = V4L2_FIELD_INTERLACED;
-       pixfmt->priv = 0;
-       if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
-               switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
-               case IVTV_YUV_MODE_INTERLACED:
-                       pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
-                               V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
-                       break;
-               case IVTV_YUV_MODE_PROGRESSIVE:
-                       pixfmt->field = V4L2_FIELD_NONE;
-                       break;
-               default:
-                       pixfmt->field = V4L2_FIELD_ANY;
-                       break;
-               }
-               pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
-               pixfmt->bytesperline = 720;
-               pixfmt->width = itv->yuv_info.v4l2_src_w;
-               pixfmt->height = itv->yuv_info.v4l2_src_h;
-               /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
-               pixfmt->sizeimage =
-                       1080 * ((pixfmt->height + 31) & ~31);
-       } else {
-               pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
-               pixfmt->sizeimage = 128 * 1024;
-               pixfmt->bytesperline = 0;
-       }
-       return 0;
-}
-
-static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       struct v4l2_window *winfmt = &fmt->fmt.win;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return -EINVAL;
-       winfmt->chromakey = itv->osd_chroma_key;
-       winfmt->global_alpha = itv->osd_global_alpha;
-       winfmt->field = V4L2_FIELD_INTERLACED;
-       winfmt->clips = NULL;
-       winfmt->clipcount = 0;
-       winfmt->bitmap = NULL;
-       winfmt->w.top = winfmt->w.left = 0;
-       winfmt->w.width = itv->osd_rect.width;
-       winfmt->w.height = itv->osd_rect.height;
-       return 0;
-}
-
-static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
-}
-
-static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       int w = fmt->fmt.pix.width;
-       int h = fmt->fmt.pix.height;
-       int min_h = 2;
-
-       w = min(w, 720);
-       w = max(w, 2);
-       if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
-               /* YUV height must be a multiple of 32 */
-               h &= ~0x1f;
-               min_h = 32;
-       }
-       h = min(h, itv->is_50hz ? 576 : 480);
-       h = max(h, min_h);
-       ivtv_g_fmt_vid_cap(file, fh, fmt);
-       fmt->fmt.pix.width = w;
-       fmt->fmt.pix.height = h;
-       return 0;
-}
-
-static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       return ivtv_g_fmt_vbi_cap(file, fh, fmt);
-}
-
-static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-
-       if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
-               return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
-
-       /* set sliced VBI capture format */
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-
-       if (vbifmt->service_set)
-               ivtv_expand_service_set(vbifmt, itv->is_50hz);
-       check_service_set(vbifmt, itv->is_50hz);
-       vbifmt->service_set = ivtv_get_service_set(vbifmt);
-       return 0;
-}
-
-static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       s32 w = fmt->fmt.pix.width;
-       s32 h = fmt->fmt.pix.height;
-       int field = fmt->fmt.pix.field;
-       int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
-
-       w = min(w, 720);
-       w = max(w, 2);
-       /* Why can the height be 576 even when the output is NTSC?
-
-          Internally the buffers of the PVR350 are always set to 720x576. The
-          decoded video frame will always be placed in the top left corner of
-          this buffer. For any video which is not 720x576, the buffer will
-          then be cropped to remove the unused right and lower areas, with
-          the remaining image being scaled by the hardware to fit the display
-          area. The video can be scaled both up and down, so a 720x480 video
-          can be displayed full-screen on PAL and a 720x576 video can be
-          displayed without cropping on NTSC.
-
-          Note that the scaling only occurs on the video stream, the osd
-          resolution is locked to the broadcast standard and not scaled.
-
-          Thanks to Ian Armstrong for this explanation. */
-       h = min(h, 576);
-       h = max(h, 2);
-       if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
-               fmt->fmt.pix.field = field;
-       fmt->fmt.pix.width = w;
-       fmt->fmt.pix.height = h;
-       return ret;
-}
-
-static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       u32 chromakey = fmt->fmt.win.chromakey;
-       u8 global_alpha = fmt->fmt.win.global_alpha;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return -EINVAL;
-       ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
-       fmt->fmt.win.chromakey = chromakey;
-       fmt->fmt.win.global_alpha = global_alpha;
-       return 0;
-}
-
-static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
-}
-
-static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
-       int w = fmt->fmt.pix.width;
-       int h = fmt->fmt.pix.height;
-
-       if (ret)
-               return ret;
-
-       if (itv->cxhdl.width == w && itv->cxhdl.height == h)
-               return 0;
-
-       if (atomic_read(&itv->capturing) > 0)
-               return -EBUSY;
-
-       itv->cxhdl.width = w;
-       itv->cxhdl.height = h;
-       if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
-               fmt->fmt.pix.width /= 2;
-       mbus_fmt.width = fmt->fmt.pix.width;
-       mbus_fmt.height = h;
-       mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
-       v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
-       return ivtv_g_fmt_vid_cap(file, fh, fmt);
-}
-
-static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
-               return -EBUSY;
-       itv->vbi.sliced_in->service_set = 0;
-       itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);
-       return ivtv_g_fmt_vbi_cap(file, fh, fmt);
-}
-
-static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
-
-       if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
-               return ret;
-
-       check_service_set(vbifmt, itv->is_50hz);
-       if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
-               return -EBUSY;
-       itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
-       v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);
-       memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
-       return 0;
-}
-
-static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
-
-       if (ret)
-               return ret;
-
-       if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
-               return 0;
-
-       /* Return now if we already have some frame data */
-       if (yi->stream_size)
-               return -EBUSY;
-
-       yi->v4l2_src_w = fmt->fmt.pix.width;
-       yi->v4l2_src_h = fmt->fmt.pix.height;
-
-       switch (fmt->fmt.pix.field) {
-       case V4L2_FIELD_NONE:
-               yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
-               break;
-       case V4L2_FIELD_ANY:
-               yi->lace_mode = IVTV_YUV_MODE_AUTO;
-               break;
-       case V4L2_FIELD_INTERLACED_BT:
-               yi->lace_mode =
-                       IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
-               break;
-       case V4L2_FIELD_INTERLACED_TB:
-       default:
-               yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
-               break;
-       }
-       yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
-
-       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
-               itv->dma_data_req_size =
-                       1080 * ((yi->v4l2_src_h + 31) & ~31);
-
-       return 0;
-}
-
-static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
-
-       if (ret == 0) {
-               itv->osd_chroma_key = fmt->fmt.win.chromakey;
-               itv->osd_global_alpha = fmt->fmt.win.global_alpha;
-               ivtv_set_osd_alpha(itv);
-       }
-       return ret;
-}
-
-static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-       if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
-               if (v4l2_chip_match_host(&chip->match))
-                       chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
-               return 0;
-       }
-       if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
-           chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
-               return -EINVAL;
-       /* TODO: is this correct? */
-       return ivtv_call_all_err(itv, core, g_chip_ident, chip);
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
-{
-       struct v4l2_dbg_register *regs = arg;
-       volatile u8 __iomem *reg_start;
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-       if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
-               reg_start = itv->reg_mem - IVTV_REG_OFFSET;
-       else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
-                       regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
-               reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
-       else if (regs->reg < IVTV_ENCODER_SIZE)
-               reg_start = itv->enc_mem;
-       else
-               return -EINVAL;
-
-       regs->size = 4;
-       if (cmd == VIDIOC_DBG_G_REGISTER)
-               regs->val = readl(regs->reg + reg_start);
-       else
-               writel(regs->val, regs->reg + reg_start);
-       return 0;
-}
-
-static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (v4l2_chip_match_host(&reg->match))
-               return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
-       /* TODO: subdev errors should not be ignored, this should become a
-          subdev helper function. */
-       ivtv_call_all(itv, core, g_register, reg);
-       return 0;
-}
-
-static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (v4l2_chip_match_host(&reg->match))
-               return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
-       /* TODO: subdev errors should not be ignored, this should become a
-          subdev helper function. */
-       ivtv_call_all(itv, core, s_register, reg);
-       return 0;
-}
-#endif
-
-static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
-{
-       struct ivtv_open_id *id = fh2id(file->private_data);
-       struct ivtv *itv = id->itv;
-       struct ivtv_stream *s = &itv->streams[id->type];
-
-       strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
-       strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
-       snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev));
-       vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
-       vcap->device_caps = s->caps;
-       return 0;
-}
-
-static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       return ivtv_get_audio_input(itv, vin->index, vin);
-}
-
-static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       vin->index = itv->audio_input;
-       return ivtv_get_audio_input(itv, vin->index, vin);
-}
-
-static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (vout->index >= itv->nof_audio_inputs)
-               return -EINVAL;
-
-       itv->audio_input = vout->index;
-       ivtv_audio_set_io(itv);
-
-       return 0;
-}
-
-static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       /* set it to defaults from our table */
-       return ivtv_get_audio_output(itv, vin->index, vin);
-}
-
-static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       vin->index = 0;
-       return ivtv_get_audio_output(itv, vin->index, vin);
-}
-
-static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       return ivtv_get_audio_output(itv, vout->index, vout);
-}
-
-static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       /* set it to defaults from our table */
-       return ivtv_get_input(itv, vin->index, vin);
-}
-
-static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       return ivtv_get_output(itv, vout->index, vout);
-}
-
-static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int streamtype;
-
-       streamtype = id->type;
-
-       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return -EINVAL;
-       cropcap->bounds.top = cropcap->bounds.left = 0;
-       cropcap->bounds.width = 720;
-       if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               cropcap->bounds.height = itv->is_50hz ? 576 : 480;
-               cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
-               cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
-       } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-               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 {
-               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;
-       }
-       cropcap->defrect = cropcap->bounds;
-       return 0;
-}
-
-static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int streamtype;
-
-       streamtype = id->type;
-
-       if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
-               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
-                       yi->main_rect = crop->c;
-                       return 0;
-               } else {
-                       if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
-                               crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
-                               itv->main_rect = crop->c;
-                               return 0;
-                       }
-               }
-               return -EINVAL;
-       }
-       return -EINVAL;
-}
-
-static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int streamtype;
-
-       streamtype = id->type;
-
-       if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
-               if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
-                       crop->c = yi->main_rect;
-               else
-                       crop->c = itv->main_rect;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
-{
-       static struct v4l2_fmtdesc formats[] = {
-               { 0, 0, 0,
-                 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
-                 { 0, 0, 0, 0 }
-               },
-               { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
-                 "MPEG", V4L2_PIX_FMT_MPEG,
-                 { 0, 0, 0, 0 }
-               }
-       };
-       enum v4l2_buf_type type = fmt->type;
-
-       if (fmt->index > 1)
-               return -EINVAL;
-
-       *fmt = formats[fmt->index];
-       fmt->type = type;
-       return 0;
-}
-
-static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       static struct v4l2_fmtdesc formats[] = {
-               { 0, 0, 0,
-                 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
-                 { 0, 0, 0, 0 }
-               },
-               { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
-                 "MPEG", V4L2_PIX_FMT_MPEG,
-                 { 0, 0, 0, 0 }
-               }
-       };
-       enum v4l2_buf_type type = fmt->type;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return -EINVAL;
-
-       if (fmt->index > 1)
-               return -EINVAL;
-
-       *fmt = formats[fmt->index];
-       fmt->type = type;
-
-       return 0;
-}
-
-static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       *i = itv->active_input;
-
-       return 0;
-}
-
-int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (inp < 0 || inp >= itv->nof_inputs)
-               return -EINVAL;
-
-       if (inp == itv->active_input) {
-               IVTV_DEBUG_INFO("Input unchanged\n");
-               return 0;
-       }
-
-       if (atomic_read(&itv->capturing) > 0) {
-               return -EBUSY;
-       }
-
-       IVTV_DEBUG_INFO("Changing input from %d to %d\n",
-                       itv->active_input, inp);
-
-       itv->active_input = inp;
-       /* Set the audio input to whatever is appropriate for the
-          input type. */
-       itv->audio_input = itv->card->video_inputs[inp].audio_index;
-
-       /* prevent others from messing with the streams until
-          we're finished changing inputs. */
-       ivtv_mute(itv);
-       ivtv_video_set_io(itv);
-       ivtv_audio_set_io(itv);
-       ivtv_unmute(itv);
-
-       return 0;
-}
-
-static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return -EINVAL;
-
-       *i = itv->active_output;
-
-       return 0;
-}
-
-static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (outp >= itv->card->nof_outputs)
-               return -EINVAL;
-
-       if (outp == itv->active_output) {
-               IVTV_DEBUG_INFO("Output unchanged\n");
-               return 0;
-       }
-       IVTV_DEBUG_INFO("Changing output from %d to %d\n",
-                  itv->active_output, outp);
-
-       itv->active_output = outp;
-       ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
-                       SAA7127_INPUT_TYPE_NORMAL,
-                       itv->card->video_outputs[outp].video_output, 0);
-
-       return 0;
-}
-
-static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (vf->tuner != 0)
-               return -EINVAL;
-
-       ivtv_call_all(itv, tuner, g_frequency, vf);
-       return 0;
-}
-
-int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (vf->tuner != 0)
-               return -EINVAL;
-
-       ivtv_mute(itv);
-       IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
-       ivtv_call_all(itv, tuner, s_frequency, vf);
-       ivtv_unmute(itv);
-       return 0;
-}
-
-static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       *std = itv->std;
-       return 0;
-}
-
-void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
-{
-       itv->std = *std;
-       itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
-       itv->is_50hz = !itv->is_60hz;
-       cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
-       itv->cxhdl.width = 720;
-       itv->cxhdl.height = itv->is_50hz ? 576 : 480;
-       itv->vbi.count = itv->is_50hz ? 18 : 12;
-       itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
-       itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
-
-       if (itv->hw_flags & IVTV_HW_CX25840)
-               itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
-
-       /* Tuner */
-       ivtv_call_all(itv, core, s_std, itv->std);
-}
-
-void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       DEFINE_WAIT(wait);
-       int f;
-
-       /* set display standard */
-       itv->std_out = *std;
-       itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
-       itv->is_out_50hz = !itv->is_out_60hz;
-       ivtv_call_all(itv, video, s_std_output, itv->std_out);
-
-       /*
-        * The next firmware call is time sensitive. Time it to
-        * avoid risk of a hard lock, by trying to ensure the call
-        * happens within the first 100 lines of the top field.
-        * Make 4 attempts to sync to the decoder before giving up.
-        */
-       mutex_unlock(&itv->serialize_lock);
-       for (f = 0; f < 4; f++) {
-               prepare_to_wait(&itv->vsync_waitq, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
-                       break;
-               schedule_timeout(msecs_to_jiffies(25));
-       }
-       finish_wait(&itv->vsync_waitq, &wait);
-       mutex_lock(&itv->serialize_lock);
-
-       if (f == 4)
-               IVTV_WARN("Mode change failed to sync to decoder\n");
-
-       ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
-       itv->main_rect.left = 0;
-       itv->main_rect.top = 0;
-       itv->main_rect.width = 720;
-       itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
-       ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
-               720, itv->main_rect.height, 0, 0);
-       yi->main_rect = itv->main_rect;
-       if (!itv->osd_info) {
-               yi->osd_full_w = 720;
-               yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
-       }
-}
-
-int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if ((*std & V4L2_STD_ALL) == 0)
-               return -EINVAL;
-
-       if (*std == itv->std)
-               return 0;
-
-       if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
-           atomic_read(&itv->capturing) > 0 ||
-           atomic_read(&itv->decoding) > 0) {
-               /* Switching standard would mess with already running
-                  streams, prevent that by returning EBUSY. */
-               return -EBUSY;
-       }
-
-       IVTV_DEBUG_INFO("Switching standard to %llx.\n",
-               (unsigned long long)itv->std);
-
-       ivtv_s_std_enc(itv, std);
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
-               ivtv_s_std_dec(itv, std);
-
-       return 0;
-}
-
-static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-
-       if (vt->index != 0)
-               return -EINVAL;
-
-       ivtv_call_all(itv, tuner, s_tuner, vt);
-
-       return 0;
-}
-
-static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (vt->index != 0)
-               return -EINVAL;
-
-       ivtv_call_all(itv, tuner, g_tuner, vt);
-
-       if (vt->type == V4L2_TUNER_RADIO)
-               strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
-       else
-               strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
-       return 0;
-}
-
-static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
-       int f, l;
-
-       if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
-               for (f = 0; f < 2; f++) {
-                       for (l = 0; l < 24; l++) {
-                               if (valid_service_line(f, l, itv->is_50hz))
-                                       cap->service_lines[f][l] = set;
-                       }
-               }
-       } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
-               if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
-                       return -EINVAL;
-               if (itv->is_60hz) {
-                       cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
-                       cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
-               } else {
-                       cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
-                       cap->service_lines[0][16] = V4L2_SLICED_VPS;
-               }
-       } else {
-               return -EINVAL;
-       }
-
-       set = 0;
-       for (f = 0; f < 2; f++)
-               for (l = 0; l < 24; l++)
-                       set |= cap->service_lines[f][l];
-       cap->service_set = set;
-       return 0;
-}
-
-static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       struct v4l2_enc_idx_entry *e = idx->entry;
-       int entries;
-       int i;
-
-       entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
-                               IVTV_MAX_PGM_INDEX;
-       if (entries > V4L2_ENC_IDX_ENTRIES)
-               entries = V4L2_ENC_IDX_ENTRIES;
-       idx->entries = 0;
-       for (i = 0; i < entries; i++) {
-               *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
-               if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
-                       idx->entries++;
-                       e++;
-               }
-       }
-       itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
-       return 0;
-}
-
-static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-
-
-       switch (enc->cmd) {
-       case V4L2_ENC_CMD_START:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
-               enc->flags = 0;
-               return ivtv_start_capture(id);
-
-       case V4L2_ENC_CMD_STOP:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
-               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
-               ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
-               return 0;
-
-       case V4L2_ENC_CMD_PAUSE:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
-               enc->flags = 0;
-
-               if (!atomic_read(&itv->capturing))
-                       return -EPERM;
-               if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
-                       return 0;
-
-               ivtv_mute(itv);
-               ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
-               break;
-
-       case V4L2_ENC_CMD_RESUME:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
-               enc->flags = 0;
-
-               if (!atomic_read(&itv->capturing))
-                       return -EPERM;
-
-               if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
-                       return 0;
-
-               ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
-               ivtv_unmute(itv);
-               break;
-       default:
-               IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       switch (enc->cmd) {
-       case V4L2_ENC_CMD_START:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
-               enc->flags = 0;
-               return 0;
-
-       case V4L2_ENC_CMD_STOP:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
-               enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
-               return 0;
-
-       case V4L2_ENC_CMD_PAUSE:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
-               enc->flags = 0;
-               return 0;
-
-       case V4L2_ENC_CMD_RESUME:
-               IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
-               enc->flags = 0;
-               return 0;
-       default:
-               IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
-               return -EINVAL;
-       }
-}
-
-static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct yuv_playback_info *yi = &itv->yuv_info;
-
-       int pixfmt;
-       static u32 pixel_format[16] = {
-               V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
-               V4L2_PIX_FMT_RGB565,
-               V4L2_PIX_FMT_RGB555,
-               V4L2_PIX_FMT_RGB444,
-               V4L2_PIX_FMT_RGB32,
-               0,
-               0,
-               0,
-               V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
-               V4L2_PIX_FMT_YUV565,
-               V4L2_PIX_FMT_YUV555,
-               V4L2_PIX_FMT_YUV444,
-               V4L2_PIX_FMT_YUV32,
-               0,
-               0,
-               0,
-       };
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
-               return -EINVAL;
-       if (!itv->osd_video_pbase)
-               return -EINVAL;
-
-       fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
-               V4L2_FBUF_CAP_GLOBAL_ALPHA;
-
-       ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
-       data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
-       pixfmt = (data[0] >> 3) & 0xf;
-
-       fb->fmt.pixelformat = pixel_format[pixfmt];
-       fb->fmt.width = itv->osd_rect.width;
-       fb->fmt.height = itv->osd_rect.height;
-       fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->fmt.bytesperline = fb->fmt.width;
-       fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->fmt.priv = 0;
-       if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
-               fb->fmt.bytesperline *= 2;
-       if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
-           fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
-               fb->fmt.bytesperline *= 2;
-       fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
-       fb->base = (void *)itv->osd_video_pbase;
-       fb->flags = 0;
-
-       if (itv->osd_chroma_key_state)
-               fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
-
-       if (itv->osd_global_alpha_state)
-               fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
-
-       if (yi->track_osd)
-               fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
-
-       pixfmt &= 7;
-
-       /* no local alpha for RGB565 or unknown formats */
-       if (pixfmt == 1 || pixfmt > 4)
-               return 0;
-
-       /* 16-bit formats have inverted local alpha */
-       if (pixfmt == 2 || pixfmt == 3)
-               fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
-       else
-               fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
-
-       if (itv->osd_local_alpha_state) {
-               /* 16-bit formats have inverted local alpha */
-               if (pixfmt == 2 || pixfmt == 3)
-                       fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
-               else
-                       fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
-       }
-
-       return 0;
-}
-
-static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
-               return -EINVAL;
-       if (!itv->osd_video_pbase)
-               return -EINVAL;
-
-       itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
-       itv->osd_local_alpha_state =
-               (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;
-       return ivtv_g_fbuf(file, fh, fb);
-}
-
-static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
-{
-       struct ivtv_open_id *id = fh2id(fh);
-       struct ivtv *itv = id->itv;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
-               return -EINVAL;
-
-       ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
-
-       return 0;
-}
-
-static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub)
-{
-       switch (sub->type) {
-       case V4L2_EVENT_VSYNC:
-       case V4L2_EVENT_EOS:
-               return v4l2_event_subscribe(fh, sub, 0, NULL);
-       case V4L2_EVENT_CTRL:
-               return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int ivtv_log_status(struct file *file, void *fh)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-       u32 data[CX2341X_MBOX_MAX_DATA];
-
-       int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
-       struct v4l2_input vidin;
-       struct v4l2_audio audin;
-       int i;
-
-       IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
-       if (itv->hw_flags & IVTV_HW_TVEEPROM) {
-               struct tveeprom tv;
-
-               ivtv_read_eeprom(itv, &tv);
-       }
-       ivtv_call_all(itv, core, log_status);
-       ivtv_get_input(itv, itv->active_input, &vidin);
-       ivtv_get_audio_input(itv, itv->audio_input, &audin);
-       IVTV_INFO("Video Input:  %s\n", vidin.name);
-       IVTV_INFO("Audio Input:  %s%s\n", audin.name,
-               (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
-       if (has_output) {
-               struct v4l2_output vidout;
-               struct v4l2_audioout audout;
-               int mode = itv->output_mode;
-               static const char * const output_modes[5] = {
-                       "None",
-                       "MPEG Streaming",
-                       "YUV Streaming",
-                       "YUV Frames",
-                       "Passthrough",
-               };
-               static const char * const alpha_mode[4] = {
-                       "None",
-                       "Global",
-                       "Local",
-                       "Global and Local"
-               };
-               static const char * const pixel_format[16] = {
-                       "ARGB Indexed",
-                       "RGB 5:6:5",
-                       "ARGB 1:5:5:5",
-                       "ARGB 1:4:4:4",
-                       "ARGB 8:8:8:8",
-                       "5",
-                       "6",
-                       "7",
-                       "AYUV Indexed",
-                       "YUV 5:6:5",
-                       "AYUV 1:5:5:5",
-                       "AYUV 1:4:4:4",
-                       "AYUV 8:8:8:8",
-                       "13",
-                       "14",
-                       "15",
-               };
-
-               ivtv_get_output(itv, itv->active_output, &vidout);
-               ivtv_get_audio_output(itv, 0, &audout);
-               IVTV_INFO("Video Output: %s\n", vidout.name);
-               if (mode < 0 || mode > OUT_PASSTHROUGH)
-                       mode = OUT_NONE;
-               IVTV_INFO("Output Mode:  %s\n", output_modes[mode]);
-               ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
-               data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
-               IVTV_INFO("Overlay:      %s, Alpha: %s, Pixel Format: %s\n",
-                       data[0] & 1 ? "On" : "Off",
-                       alpha_mode[(data[0] >> 1) & 0x3],
-                       pixel_format[(data[0] >> 3) & 0xf]);
-       }
-       IVTV_INFO("Tuner:  %s\n",
-               test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
-       v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name);
-       IVTV_INFO("Status flags:    0x%08lx\n", itv->i_flags);
-       for (i = 0; i < IVTV_MAX_STREAMS; i++) {
-               struct ivtv_stream *s = &itv->streams[i];
-
-               if (s->vdev == NULL || s->buffers == 0)
-                       continue;
-               IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags,
-                               (s->buffers - s->q_free.buffers) * 100 / s->buffers,
-                               (s->buffers * s->buf_size) / 1024, s->buffers);
-       }
-
-       IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
-                       (long long)itv->mpg_data_received,
-                       (long long)itv->vbi_data_inserted);
-       return 0;
-}
-
-static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
-{
-       struct ivtv_open_id *id = fh2id(file->private_data);
-       struct ivtv *itv = id->itv;
-
-       IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
-       return ivtv_video_command(itv, id, dec, false);
-}
-
-static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
-{
-       struct ivtv_open_id *id = fh2id(file->private_data);
-       struct ivtv *itv = id->itv;
-
-       IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
-       return ivtv_video_command(itv, id, dec, true);
-}
-
-static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
-{
-       struct ivtv_open_id *id = fh2id(filp->private_data);
-       struct ivtv *itv = id->itv;
-       int nonblocking = filp->f_flags & O_NONBLOCK;
-       struct ivtv_stream *s = &itv->streams[id->type];
-       unsigned long iarg = (unsigned long)arg;
-
-       switch (cmd) {
-       case IVTV_IOC_DMA_FRAME: {
-               struct ivtv_dma_frame *args = arg;
-
-               IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
-               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-                       return -EINVAL;
-               if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-                       return -EINVAL;
-               if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
-                       return 0;
-               if (ivtv_start_decoding(id, id->type)) {
-                       return -EBUSY;
-               }
-               if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
-                       ivtv_release_stream(s);
-                       return -EBUSY;
-               }
-               /* Mark that this file handle started the UDMA_YUV mode */
-               id->yuv_frames = 1;
-               if (args->y_source == NULL)
-                       return 0;
-               return ivtv_yuv_prep_frame(itv, args);
-       }
-
-       case IVTV_IOC_PASSTHROUGH_MODE:
-               IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
-               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-                       return -EINVAL;
-               return ivtv_passthrough_mode(itv, *(int *)arg != 0);
-
-       case VIDEO_GET_PTS: {
-               s64 *pts = arg;
-               s64 frame;
-
-               IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
-               if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
-                       *pts = s->dma_pts;
-                       break;
-               }
-               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-                       return -EINVAL;
-               return ivtv_g_pts_frame(itv, pts, &frame);
-       }
-
-       case VIDEO_GET_FRAME_COUNT: {
-               s64 *frame = arg;
-               s64 pts;
-
-               IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
-               if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
-                       *frame = 0;
-                       break;
-               }
-               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-                       return -EINVAL;
-               return ivtv_g_pts_frame(itv, &pts, frame);
-       }
-
-       case VIDEO_PLAY: {
-               struct v4l2_decoder_cmd dc;
-
-               IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
-               memset(&dc, 0, sizeof(dc));
-               dc.cmd = V4L2_DEC_CMD_START;
-               return ivtv_video_command(itv, id, &dc, 0);
-       }
-
-       case VIDEO_STOP: {
-               struct v4l2_decoder_cmd dc;
-
-               IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
-               memset(&dc, 0, sizeof(dc));
-               dc.cmd = V4L2_DEC_CMD_STOP;
-               dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
-               return ivtv_video_command(itv, id, &dc, 0);
-       }
-
-       case VIDEO_FREEZE: {
-               struct v4l2_decoder_cmd dc;
-
-               IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
-               memset(&dc, 0, sizeof(dc));
-               dc.cmd = V4L2_DEC_CMD_PAUSE;
-               return ivtv_video_command(itv, id, &dc, 0);
-       }
-
-       case VIDEO_CONTINUE: {
-               struct v4l2_decoder_cmd dc;
-
-               IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
-               memset(&dc, 0, sizeof(dc));
-               dc.cmd = V4L2_DEC_CMD_RESUME;
-               return ivtv_video_command(itv, id, &dc, 0);
-       }
-
-       case VIDEO_COMMAND:
-       case VIDEO_TRY_COMMAND: {
-               /* Note: struct v4l2_decoder_cmd has the same layout as
-                  struct video_command */
-               struct v4l2_decoder_cmd *dc = arg;
-               int try = (cmd == VIDEO_TRY_COMMAND);
-
-               if (try)
-                       IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
-               else
-                       IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
-               return ivtv_video_command(itv, id, dc, try);
-       }
-
-       case VIDEO_GET_EVENT: {
-               struct video_event *ev = arg;
-               DEFINE_WAIT(wait);
-
-               IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
-               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-                       return -EINVAL;
-               memset(ev, 0, sizeof(*ev));
-               set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
-
-               while (1) {
-                       if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
-                               ev->type = VIDEO_EVENT_DECODER_STOPPED;
-                       else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
-                               ev->type = VIDEO_EVENT_VSYNC;
-                               ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
-                                       VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
-                               if (itv->output_mode == OUT_UDMA_YUV &&
-                                       (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
-                                                               IVTV_YUV_MODE_PROGRESSIVE) {
-                                       ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
-                               }
-                       }
-                       if (ev->type)
-                               return 0;
-                       if (nonblocking)
-                               return -EAGAIN;
-                       /* Wait for event. Note that serialize_lock is locked,
-                          so to allow other processes to access the driver while
-                          we are waiting unlock first and later lock again. */
-                       mutex_unlock(&itv->serialize_lock);
-                       prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
-                       if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
-                           !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
-                               schedule();
-                       finish_wait(&itv->event_waitq, &wait);
-                       mutex_lock(&itv->serialize_lock);
-                       if (signal_pending(current)) {
-                               /* return if a signal was received */
-                               IVTV_DEBUG_INFO("User stopped wait for event\n");
-                               return -EINTR;
-                       }
-               }
-               break;
-       }
-
-       case VIDEO_SELECT_SOURCE:
-               IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
-               if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-                       return -EINVAL;
-               return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
-
-       case AUDIO_SET_MUTE:
-               IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
-               itv->speed_mute_audio = iarg;
-               return 0;
-
-       case AUDIO_CHANNEL_SELECT:
-               IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
-               if (iarg > AUDIO_STEREO_SWAPPED)
-                       return -EINVAL;
-               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
-
-       case AUDIO_BILINGUAL_CHANNEL_SELECT:
-               IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
-               if (iarg > AUDIO_STEREO_SWAPPED)
-                       return -EINVAL;
-               return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static long ivtv_default(struct file *file, void *fh, bool valid_prio,
-                        int cmd, void *arg)
-{
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       if (!valid_prio) {
-               switch (cmd) {
-               case IVTV_IOC_PASSTHROUGH_MODE:
-               case VIDEO_PLAY:
-               case VIDEO_STOP:
-               case VIDEO_FREEZE:
-               case VIDEO_CONTINUE:
-               case VIDEO_COMMAND:
-               case VIDEO_SELECT_SOURCE:
-               case AUDIO_SET_MUTE:
-               case AUDIO_CHANNEL_SELECT:
-               case AUDIO_BILINGUAL_CHANNEL_SELECT:
-                       return -EBUSY;
-               }
-       }
-
-       switch (cmd) {
-       case VIDIOC_INT_RESET: {
-               u32 val = *(u32 *)arg;
-
-               if ((val == 0 && itv->options.newi2c) || (val & 0x01))
-                       ivtv_reset_ir_gpio(itv);
-               if (val & 0x02)
-                       v4l2_subdev_call(itv->sd_video, core, reset, 0);
-               break;
-       }
-
-       case IVTV_IOC_DMA_FRAME:
-       case IVTV_IOC_PASSTHROUGH_MODE:
-       case VIDEO_GET_PTS:
-       case VIDEO_GET_FRAME_COUNT:
-       case VIDEO_GET_EVENT:
-       case VIDEO_PLAY:
-       case VIDEO_STOP:
-       case VIDEO_FREEZE:
-       case VIDEO_CONTINUE:
-       case VIDEO_COMMAND:
-       case VIDEO_TRY_COMMAND:
-       case VIDEO_SELECT_SOURCE:
-       case AUDIO_SET_MUTE:
-       case AUDIO_CHANNEL_SELECT:
-       case AUDIO_BILINGUAL_CHANNEL_SELECT:
-               return ivtv_decoder_ioctls(file, cmd, (void *)arg);
-
-       default:
-               return -ENOTTY;
-       }
-       return 0;
-}
-
-static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
-       .vidioc_querycap                    = ivtv_querycap,
-       .vidioc_s_audio                     = ivtv_s_audio,
-       .vidioc_g_audio                     = ivtv_g_audio,
-       .vidioc_enumaudio                   = ivtv_enumaudio,
-       .vidioc_s_audout                    = ivtv_s_audout,
-       .vidioc_g_audout                    = ivtv_g_audout,
-       .vidioc_enum_input                  = ivtv_enum_input,
-       .vidioc_enum_output                 = ivtv_enum_output,
-       .vidioc_enumaudout                  = ivtv_enumaudout,
-       .vidioc_cropcap                     = ivtv_cropcap,
-       .vidioc_s_crop                      = ivtv_s_crop,
-       .vidioc_g_crop                      = ivtv_g_crop,
-       .vidioc_g_input                     = ivtv_g_input,
-       .vidioc_s_input                     = ivtv_s_input,
-       .vidioc_g_output                    = ivtv_g_output,
-       .vidioc_s_output                    = ivtv_s_output,
-       .vidioc_g_frequency                 = ivtv_g_frequency,
-       .vidioc_s_frequency                 = ivtv_s_frequency,
-       .vidioc_s_tuner                     = ivtv_s_tuner,
-       .vidioc_g_tuner                     = ivtv_g_tuner,
-       .vidioc_g_enc_index                 = ivtv_g_enc_index,
-       .vidioc_g_fbuf                      = ivtv_g_fbuf,
-       .vidioc_s_fbuf                      = ivtv_s_fbuf,
-       .vidioc_g_std                       = ivtv_g_std,
-       .vidioc_s_std                       = ivtv_s_std,
-       .vidioc_overlay                     = ivtv_overlay,
-       .vidioc_log_status                  = ivtv_log_status,
-       .vidioc_enum_fmt_vid_cap            = ivtv_enum_fmt_vid_cap,
-       .vidioc_encoder_cmd                 = ivtv_encoder_cmd,
-       .vidioc_try_encoder_cmd             = ivtv_try_encoder_cmd,
-       .vidioc_decoder_cmd                 = ivtv_decoder_cmd,
-       .vidioc_try_decoder_cmd             = ivtv_try_decoder_cmd,
-       .vidioc_enum_fmt_vid_out            = ivtv_enum_fmt_vid_out,
-       .vidioc_g_fmt_vid_cap               = ivtv_g_fmt_vid_cap,
-       .vidioc_g_fmt_vbi_cap               = ivtv_g_fmt_vbi_cap,
-       .vidioc_g_fmt_sliced_vbi_cap        = ivtv_g_fmt_sliced_vbi_cap,
-       .vidioc_g_fmt_vid_out               = ivtv_g_fmt_vid_out,
-       .vidioc_g_fmt_vid_out_overlay       = ivtv_g_fmt_vid_out_overlay,
-       .vidioc_g_fmt_sliced_vbi_out        = ivtv_g_fmt_sliced_vbi_out,
-       .vidioc_s_fmt_vid_cap               = ivtv_s_fmt_vid_cap,
-       .vidioc_s_fmt_vbi_cap               = ivtv_s_fmt_vbi_cap,
-       .vidioc_s_fmt_sliced_vbi_cap        = ivtv_s_fmt_sliced_vbi_cap,
-       .vidioc_s_fmt_vid_out               = ivtv_s_fmt_vid_out,
-       .vidioc_s_fmt_vid_out_overlay       = ivtv_s_fmt_vid_out_overlay,
-       .vidioc_s_fmt_sliced_vbi_out        = ivtv_s_fmt_sliced_vbi_out,
-       .vidioc_try_fmt_vid_cap             = ivtv_try_fmt_vid_cap,
-       .vidioc_try_fmt_vbi_cap             = ivtv_try_fmt_vbi_cap,
-       .vidioc_try_fmt_sliced_vbi_cap      = ivtv_try_fmt_sliced_vbi_cap,
-       .vidioc_try_fmt_vid_out             = ivtv_try_fmt_vid_out,
-       .vidioc_try_fmt_vid_out_overlay     = ivtv_try_fmt_vid_out_overlay,
-       .vidioc_try_fmt_sliced_vbi_out      = ivtv_try_fmt_sliced_vbi_out,
-       .vidioc_g_sliced_vbi_cap            = ivtv_g_sliced_vbi_cap,
-       .vidioc_g_chip_ident                = ivtv_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register                  = ivtv_g_register,
-       .vidioc_s_register                  = ivtv_s_register,
-#endif
-       .vidioc_default                     = ivtv_default,
-       .vidioc_subscribe_event             = ivtv_subscribe_event,
-       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
-};
-
-void ivtv_set_funcs(struct video_device *vdev)
-{
-       vdev->ioctl_ops = &ivtv_ioctl_ops;
-}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h
deleted file mode 100644 (file)
index 7c553d1..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-    ioctl system call
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_IOCTL_H
-#define IVTV_IOCTL_H
-
-u16 ivtv_service2vbi(int type);
-void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
-u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
-void ivtv_set_osd_alpha(struct ivtv *itv);
-int ivtv_set_speed(struct ivtv *itv, int speed);
-void ivtv_set_funcs(struct video_device *vdev);
-void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
-void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
-int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
-int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
deleted file mode 100644 (file)
index 1b3b957..0000000
+++ /dev/null
@@ -1,1038 +0,0 @@
-/* interrupt handling
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-queue.h"
-#include "ivtv-udma.h"
-#include "ivtv-irq.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-vbi.h"
-#include "ivtv-yuv.h"
-#include <media/v4l2-event.h>
-
-#define DMA_MAGIC_COOKIE 0x000001fe
-
-static void ivtv_dma_dec_start(struct ivtv_stream *s);
-
-static const int ivtv_stream_map[] = {
-       IVTV_ENC_STREAM_TYPE_MPG,
-       IVTV_ENC_STREAM_TYPE_YUV,
-       IVTV_ENC_STREAM_TYPE_PCM,
-       IVTV_ENC_STREAM_TYPE_VBI,
-};
-
-
-static void ivtv_pio_work_handler(struct ivtv *itv)
-{
-       struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
-       struct ivtv_buffer *buf;
-       int i = 0;
-
-       IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
-       if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
-                       s->vdev == NULL || !ivtv_use_pio(s)) {
-               itv->cur_pio_stream = -1;
-               /* trigger PIO complete user interrupt */
-               write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
-               return;
-       }
-       IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name);
-       list_for_each_entry(buf, &s->q_dma.list, list) {
-               u32 size = s->sg_processing[i].size & 0x3ffff;
-
-               /* Copy the data from the card to the buffer */
-               if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
-                       memcpy_fromio(buf->buf, itv->dec_mem + s->sg_processing[i].src - IVTV_DECODER_OFFSET, size);
-               }
-               else {
-                       memcpy_fromio(buf->buf, itv->enc_mem + s->sg_processing[i].src, size);
-               }
-               i++;
-               if (i == s->sg_processing_size)
-                       break;
-       }
-       write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
-}
-
-void ivtv_irq_work_handler(struct kthread_work *work)
-{
-       struct ivtv *itv = container_of(work, struct ivtv, irq_work);
-
-       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
-               ivtv_pio_work_handler(itv);
-
-       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
-               ivtv_vbi_work_handler(itv);
-
-       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
-               ivtv_yuv_work_handler(itv);
-}
-
-/* Determine the required DMA size, setup enough buffers in the predma queue and
-   actually copy the data from the card to the buffers in case a PIO transfer is
-   required for this stream.
- */
-static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MAX_DATA])
-{
-       struct ivtv *itv = s->itv;
-       struct ivtv_buffer *buf;
-       u32 bytes_needed = 0;
-       u32 offset, size;
-       u32 UVoffset = 0, UVsize = 0;
-       int skip_bufs = s->q_predma.buffers;
-       int idx = s->sg_pending_size;
-       int rc;
-
-       /* sanity checks */
-       if (s->vdev == NULL) {
-               IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
-               return -1;
-       }
-       if (!test_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
-               IVTV_DEBUG_WARN("Stream %s not open\n", s->name);
-               return -1;
-       }
-
-       /* determine offset, size and PTS for the various streams */
-       switch (s->type) {
-               case IVTV_ENC_STREAM_TYPE_MPG:
-                       offset = data[1];
-                       size = data[2];
-                       s->pending_pts = 0;
-                       break;
-
-               case IVTV_ENC_STREAM_TYPE_YUV:
-                       offset = data[1];
-                       size = data[2];
-                       UVoffset = data[3];
-                       UVsize = data[4];
-                       s->pending_pts = ((u64) data[5] << 32) | data[6];
-                       break;
-
-               case IVTV_ENC_STREAM_TYPE_PCM:
-                       offset = data[1] + 12;
-                       size = data[2] - 12;
-                       s->pending_pts = read_dec(offset - 8) |
-                               ((u64)(read_dec(offset - 12)) << 32);
-                       if (itv->has_cx23415)
-                               offset += IVTV_DECODER_OFFSET;
-                       break;
-
-               case IVTV_ENC_STREAM_TYPE_VBI:
-                       size = itv->vbi.enc_size * itv->vbi.fpi;
-                       offset = read_enc(itv->vbi.enc_start - 4) + 12;
-                       if (offset == 12) {
-                               IVTV_DEBUG_INFO("VBI offset == 0\n");
-                               return -1;
-                       }
-                       s->pending_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32);
-                       break;
-
-               case IVTV_DEC_STREAM_TYPE_VBI:
-                       size = read_dec(itv->vbi.dec_start + 4) + 8;
-                       offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start;
-                       s->pending_pts = 0;
-                       offset += IVTV_DECODER_OFFSET;
-                       break;
-               default:
-                       /* shouldn't happen */
-                       return -1;
-       }
-
-       /* if this is the start of the DMA then fill in the magic cookie */
-       if (s->sg_pending_size == 0 && ivtv_use_dma(s)) {
-               if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
-                   s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
-                       s->pending_backup = read_dec(offset - IVTV_DECODER_OFFSET);
-                       write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET);
-               }
-               else {
-                       s->pending_backup = read_enc(offset);
-                       write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset);
-               }
-               s->pending_offset = offset;
-       }
-
-       bytes_needed = size;
-       if (s->type == IVTV_ENC_STREAM_TYPE_YUV) {
-               /* The size for the Y samples needs to be rounded upwards to a
-                  multiple of the buf_size. The UV samples then start in the
-                  next buffer. */
-               bytes_needed = s->buf_size * ((bytes_needed + s->buf_size - 1) / s->buf_size);
-               bytes_needed += UVsize;
-       }
-
-       IVTV_DEBUG_HI_DMA("%s %s: 0x%08x bytes at 0x%08x\n",
-               ivtv_use_pio(s) ? "PIO" : "DMA", s->name, bytes_needed, offset);
-
-       rc = ivtv_queue_move(s, &s->q_free, &s->q_full, &s->q_predma, bytes_needed);
-       if (rc < 0) { /* Insufficient buffers */
-               IVTV_DEBUG_WARN("Cannot obtain %d bytes for %s data transfer\n",
-                               bytes_needed, s->name);
-               return -1;
-       }
-       if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) {
-               IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name);
-               IVTV_WARN("Cause: the application is not reading fast enough.\n");
-       }
-       s->buffers_stolen = rc;
-
-       /* got the buffers, now fill in sg_pending */
-       buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
-       memset(buf->buf, 0, 128);
-       list_for_each_entry(buf, &s->q_predma.list, list) {
-               if (skip_bufs-- > 0)
-                       continue;
-               s->sg_pending[idx].dst = buf->dma_handle;
-               s->sg_pending[idx].src = offset;
-               s->sg_pending[idx].size = s->buf_size;
-               buf->bytesused = min(size, s->buf_size);
-               buf->dma_xfer_cnt = s->dma_xfer_cnt;
-
-               s->q_predma.bytesused += buf->bytesused;
-               size -= buf->bytesused;
-               offset += s->buf_size;
-
-               /* Sync SG buffers */
-               ivtv_buf_sync_for_device(s, buf);
-
-               if (size == 0) {        /* YUV */
-                       /* process the UV section */
-                       offset = UVoffset;
-                       size = UVsize;
-               }
-               idx++;
-       }
-       s->sg_pending_size = idx;
-       return 0;
-}
-
-static void dma_post(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-       struct ivtv_buffer *buf = NULL;
-       struct list_head *p;
-       u32 offset;
-       __le32 *u32buf;
-       int x = 0;
-
-       IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
-                       s->name, s->dma_offset);
-       list_for_each(p, &s->q_dma.list) {
-               buf = list_entry(p, struct ivtv_buffer, list);
-               u32buf = (__le32 *)buf->buf;
-
-               /* Sync Buffer */
-               ivtv_buf_sync_for_cpu(s, buf);
-
-               if (x == 0 && ivtv_use_dma(s)) {
-                       offset = s->dma_last_offset;
-                       if (u32buf[offset / 4] != DMA_MAGIC_COOKIE)
-                       {
-                               for (offset = 0; offset < 64; offset++) {
-                                       if (u32buf[offset] == DMA_MAGIC_COOKIE) {
-                                               break;
-                                       }
-                               }
-                               offset *= 4;
-                               if (offset == 256) {
-                                       IVTV_DEBUG_WARN("%s: Couldn't find start of buffer within the first 256 bytes\n", s->name);
-                                       offset = s->dma_last_offset;
-                               }
-                               if (s->dma_last_offset != offset)
-                                       IVTV_DEBUG_WARN("%s: offset %d -> %d\n", s->name, s->dma_last_offset, offset);
-                               s->dma_last_offset = offset;
-                       }
-                       if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
-                                               s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
-                               write_dec_sync(0, s->dma_offset - IVTV_DECODER_OFFSET);
-                       }
-                       else {
-                               write_enc_sync(0, s->dma_offset);
-                       }
-                       if (offset) {
-                               buf->bytesused -= offset;
-                               memcpy(buf->buf, buf->buf + offset, buf->bytesused + offset);
-                       }
-                       *u32buf = cpu_to_le32(s->dma_backup);
-               }
-               x++;
-               /* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */
-               if (s->type == IVTV_ENC_STREAM_TYPE_MPG ||
-                   s->type == IVTV_ENC_STREAM_TYPE_VBI)
-                       buf->b_flags |= IVTV_F_B_NEED_BUF_SWAP;
-       }
-       if (buf)
-               buf->bytesused += s->dma_last_offset;
-       if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
-               list_for_each_entry(buf, &s->q_dma.list, list) {
-                       /* Parse and Groom VBI Data */
-                       s->q_dma.bytesused -= buf->bytesused;
-                       ivtv_process_vbi_data(itv, buf, 0, s->type);
-                       s->q_dma.bytesused += buf->bytesused;
-               }
-               if (s->fh == NULL) {
-                       ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
-                       return;
-               }
-       }
-       ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
-       if (s->fh)
-               wake_up(&s->waitq);
-}
-
-void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
-{
-       struct ivtv *itv = s->itv;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       u8 frame = yi->draw_frame;
-       struct yuv_frame_info *f = &yi->new_frame_info[frame];
-       struct ivtv_buffer *buf;
-       u32 y_size = 720 * ((f->src_h + 31) & ~31);
-       u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
-       int y_done = 0;
-       int bytes_written = 0;
-       unsigned long flags = 0;
-       int idx = 0;
-
-       IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
-
-       /* Insert buffer block for YUV if needed */
-       if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) {
-               if (yi->blanking_dmaptr) {
-                       s->sg_pending[idx].src = yi->blanking_dmaptr;
-                       s->sg_pending[idx].dst = offset;
-                       s->sg_pending[idx].size = 720 * 16;
-               }
-               offset += 720 * 16;
-               idx++;
-       }
-
-       list_for_each_entry(buf, &s->q_predma.list, list) {
-               /* YUV UV Offset from Y Buffer */
-               if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
-                               (bytes_written + buf->bytesused) >= y_size) {
-                       s->sg_pending[idx].src = buf->dma_handle;
-                       s->sg_pending[idx].dst = offset;
-                       s->sg_pending[idx].size = y_size - bytes_written;
-                       offset = uv_offset;
-                       if (s->sg_pending[idx].size != buf->bytesused) {
-                               idx++;
-                               s->sg_pending[idx].src =
-                                 buf->dma_handle + s->sg_pending[idx - 1].size;
-                               s->sg_pending[idx].dst = offset;
-                               s->sg_pending[idx].size =
-                                  buf->bytesused - s->sg_pending[idx - 1].size;
-                               offset += s->sg_pending[idx].size;
-                       }
-                       y_done = 1;
-               } else {
-                       s->sg_pending[idx].src = buf->dma_handle;
-                       s->sg_pending[idx].dst = offset;
-                       s->sg_pending[idx].size = buf->bytesused;
-                       offset += buf->bytesused;
-               }
-               bytes_written += buf->bytesused;
-
-               /* Sync SG buffers */
-               ivtv_buf_sync_for_device(s, buf);
-               idx++;
-       }
-       s->sg_pending_size = idx;
-
-       /* Sync Hardware SG List of buffers */
-       ivtv_stream_sync_for_device(s);
-       if (lock)
-               spin_lock_irqsave(&itv->dma_reg_lock, flags);
-       if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
-               ivtv_dma_dec_start(s);
-       }
-       else {
-               set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
-       }
-       if (lock)
-               spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
-}
-
-static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-
-       s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src);
-       s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst);
-       s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000);
-       s->sg_processed++;
-       /* Sync Hardware SG List of buffers */
-       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(300);
-       add_timer(&itv->dma_timer);
-}
-
-static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-
-       s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src);
-       s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst);
-       s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000);
-       s->sg_processed++;
-       /* Sync Hardware SG List of buffers */
-       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(300);
-       add_timer(&itv->dma_timer);
-}
-
-/* start the encoder DMA */
-static void ivtv_dma_enc_start(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-       struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-       int i;
-
-       IVTV_DEBUG_HI_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
-
-       if (s->q_predma.bytesused)
-               ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
-
-       if (ivtv_use_dma(s))
-               s->sg_pending[s->sg_pending_size - 1].size += 256;
-
-       /* If this is an MPEG stream, and VBI data is also pending, then append the
-          VBI DMA to the MPEG DMA and transfer both sets of data at once.
-
-          VBI DMA is a second class citizen compared to MPEG and mixing them together
-          will confuse the firmware (the end of a VBI DMA is seen as the end of a
-          MPEG DMA, thus effectively dropping an MPEG frame). So instead we make
-          sure we only use the MPEG DMA to transfer the VBI DMA if both are in
-          use. This way no conflicts occur. */
-       clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
-       if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->sg_pending_size &&
-                       s->sg_pending_size + s_vbi->sg_pending_size <= s->buffers) {
-               ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
-               if (ivtv_use_dma(s_vbi))
-                       s_vbi->sg_pending[s_vbi->sg_pending_size - 1].size += 256;
-               for (i = 0; i < s_vbi->sg_pending_size; i++) {
-                       s->sg_pending[s->sg_pending_size++] = s_vbi->sg_pending[i];
-               }
-               s_vbi->dma_offset = s_vbi->pending_offset;
-               s_vbi->sg_pending_size = 0;
-               s_vbi->dma_xfer_cnt++;
-               set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
-               IVTV_DEBUG_HI_DMA("include DMA for %s\n", s_vbi->name);
-       }
-
-       s->dma_xfer_cnt++;
-       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
-       s->sg_processing_size = s->sg_pending_size;
-       s->sg_pending_size = 0;
-       s->sg_processed = 0;
-       s->dma_offset = s->pending_offset;
-       s->dma_backup = s->pending_backup;
-       s->dma_pts = s->pending_pts;
-
-       if (ivtv_use_pio(s)) {
-               set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
-               set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
-               set_bit(IVTV_F_I_PIO, &itv->i_flags);
-               itv->cur_pio_stream = s->type;
-       }
-       else {
-               itv->dma_retries = 0;
-               ivtv_dma_enc_start_xfer(s);
-               set_bit(IVTV_F_I_DMA, &itv->i_flags);
-               itv->cur_dma_stream = s->type;
-       }
-}
-
-static void ivtv_dma_dec_start(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-
-       if (s->q_predma.bytesused)
-               ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
-       s->dma_xfer_cnt++;
-       memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
-       s->sg_processing_size = s->sg_pending_size;
-       s->sg_pending_size = 0;
-       s->sg_processed = 0;
-
-       IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name);
-       itv->dma_retries = 0;
-       ivtv_dma_dec_start_xfer(s);
-       set_bit(IVTV_F_I_DMA, &itv->i_flags);
-       itv->cur_dma_stream = s->type;
-}
-
-static void ivtv_irq_dma_read(struct ivtv *itv)
-{
-       struct ivtv_stream *s = NULL;
-       struct ivtv_buffer *buf;
-       int hw_stream_type = 0;
-
-       IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
-
-       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];
-               ivtv_stream_sync_for_cpu(s);
-
-               if (read_reg(IVTV_REG_DMASTATUS) & 0x14) {
-                       IVTV_DEBUG_WARN("DEC DMA ERROR %x (xfer %d of %d, retry %d)\n",
-                                       read_reg(IVTV_REG_DMASTATUS),
-                                       s->sg_processed, s->sg_processing_size, itv->dma_retries);
-                       write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
-                       if (itv->dma_retries == 3) {
-                               /* Too many retries, give up on this frame */
-                               itv->dma_retries = 0;
-                               s->sg_processed = s->sg_processing_size;
-                       }
-                       else {
-                               /* Retry, starting with the first xfer segment.
-                                  Just retrying the current segment is not sufficient. */
-                               s->sg_processed = 0;
-                               itv->dma_retries++;
-                       }
-               }
-               if (s->sg_processed < s->sg_processing_size) {
-                       /* DMA next buffer */
-                       ivtv_dma_dec_start_xfer(s);
-                       return;
-               }
-               if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
-                       hw_stream_type = 2;
-               IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused);
-
-               /* For some reason must kick the firmware, like PIO mode,
-                  I think this tells the firmware we are done and the size
-                  of the xfer so it can calculate what we need next.
-                  I think we can do this part ourselves but would have to
-                  fully calculate xfer info ourselves and not use interrupts
-                */
-               ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, s->q_dma.bytesused,
-                               hw_stream_type);
-
-               /* Free last DMA call */
-               while ((buf = ivtv_dequeue(s, &s->q_dma)) != NULL) {
-                       ivtv_buf_sync_for_cpu(s, buf);
-                       ivtv_enqueue(s, buf, &s->q_free);
-               }
-               wake_up(&s->waitq);
-       }
-       clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
-       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
-       itv->cur_dma_stream = -1;
-       wake_up(&itv->dma_waitq);
-}
-
-static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv_stream *s;
-
-       ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
-       IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
-
-       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);
-
-       if (data[0] & 0x18) {
-               IVTV_DEBUG_WARN("ENC DMA ERROR %x (offset %08x, xfer %d of %d, retry %d)\n", data[0],
-                       s->dma_offset, s->sg_processed, s->sg_processing_size, itv->dma_retries);
-               write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
-               if (itv->dma_retries == 3) {
-                       /* Too many retries, give up on this frame */
-                       itv->dma_retries = 0;
-                       s->sg_processed = s->sg_processing_size;
-               }
-               else {
-                       /* Retry, starting with the first xfer segment.
-                          Just retrying the current segment is not sufficient. */
-                       s->sg_processed = 0;
-                       itv->dma_retries++;
-               }
-       }
-       if (s->sg_processed < s->sg_processing_size) {
-               /* DMA next buffer */
-               ivtv_dma_enc_start_xfer(s);
-               return;
-       }
-       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
-       itv->cur_dma_stream = -1;
-       dma_post(s);
-       if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
-               s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-               dma_post(s);
-       }
-       s->sg_processing_size = 0;
-       s->sg_processed = 0;
-       wake_up(&itv->dma_waitq);
-}
-
-static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
-{
-       struct ivtv_stream *s;
-
-       if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
-               itv->cur_pio_stream = -1;
-               return;
-       }
-       s = &itv->streams[itv->cur_pio_stream];
-       IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name);
-       clear_bit(IVTV_F_I_PIO, &itv->i_flags);
-       itv->cur_pio_stream = -1;
-       dma_post(s);
-       if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
-               ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
-       else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
-               ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
-       else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
-               ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
-       clear_bit(IVTV_F_I_PIO, &itv->i_flags);
-       if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
-               s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-               dma_post(s);
-       }
-       wake_up(&itv->dma_waitq);
-}
-
-static void ivtv_irq_dma_err(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       u32 status;
-
-       del_timer(&itv->dma_timer);
-
-       ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
-       status = read_reg(IVTV_REG_DMASTATUS);
-       IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
-                               status, itv->cur_dma_stream);
-       /*
-        * We do *not* write back to the IVTV_REG_DMASTATUS register to
-        * clear the error status, if either the encoder write (0x02) or
-        * decoder read (0x01) bus master DMA operation do not indicate
-        * completed.  We can race with the DMA engine, which may have
-        * transitioned to completed status *after* we read the register.
-        * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the
-        * DMA engine has completed, will cause the DMA engine to stop working.
-        */
-       status &= 0x3;
-       if (status == 0x3)
-               write_reg(status, IVTV_REG_DMASTATUS);
-
-       if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) &&
-           itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) {
-               struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream];
-
-               if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
-                       /* retry */
-                       /*
-                        * FIXME - handle cases of DMA error similar to
-                        * encoder below, except conditioned on status & 0x1
-                        */
-                       ivtv_dma_dec_start(s);
-                       return;
-               } else {
-                       if ((status & 0x2) == 0) {
-                               /*
-                                * CX2341x Bus Master DMA write is ongoing.
-                                * Reset the timer and let it complete.
-                                */
-                               itv->dma_timer.expires =
-                                               jiffies + msecs_to_jiffies(600);
-                               add_timer(&itv->dma_timer);
-                               return;
-                       }
-
-                       if (itv->dma_retries < 3) {
-                               /*
-                                * CX2341x Bus Master DMA write has ended.
-                                * Retry the write, starting with the first
-                                * xfer segment. Just retrying the current
-                                * segment is not sufficient.
-                                */
-                               s->sg_processed = 0;
-                               itv->dma_retries++;
-                               ivtv_dma_enc_start_xfer(s);
-                               return;
-                       }
-                       /* Too many retries, give up on this one */
-               }
-
-       }
-       if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
-               ivtv_udma_start(itv);
-               return;
-       }
-       clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
-       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
-       itv->cur_dma_stream = -1;
-       wake_up(&itv->dma_waitq);
-}
-
-static void ivtv_irq_enc_start_cap(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv_stream *s;
-
-       /* Get DMA destination and size arguments from card */
-       ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data);
-       IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]);
-
-       if (data[0] > 2 || data[1] == 0 || data[2] == 0) {
-               IVTV_DEBUG_WARN("Unknown input: %08x %08x %08x\n",
-                               data[0], data[1], data[2]);
-               return;
-       }
-       s = &itv->streams[ivtv_stream_map[data[0]]];
-       if (!stream_enc_dma_append(s, data)) {
-               set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
-       }
-}
-
-static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv_stream *s;
-
-       IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n");
-       s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
-
-       if (!stream_enc_dma_append(s, data))
-               set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
-}
-
-static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
-
-       IVTV_DEBUG_HI_IRQ("DEC VBI REINSERT\n");
-       if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
-                       !stream_enc_dma_append(s, data)) {
-               set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
-       }
-}
-
-static void ivtv_irq_dec_data_req(struct ivtv *itv)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv_stream *s;
-
-       /* YUV or MPG */
-
-       if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
-               ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
-               itv->dma_data_req_size =
-                                1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
-               itv->dma_data_req_offset = data[1];
-               if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0)
-                       ivtv_yuv_frame_complete(itv);
-               s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
-       }
-       else {
-               ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data);
-               itv->dma_data_req_size = min_t(u32, data[2], 0x10000);
-               itv->dma_data_req_offset = data[1];
-               s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
-       }
-       IVTV_DEBUG_HI_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused,
-                      itv->dma_data_req_offset, itv->dma_data_req_size);
-       if (itv->dma_data_req_size == 0 || s->q_full.bytesused < itv->dma_data_req_size) {
-               set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
-       }
-       else {
-               if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
-                       ivtv_yuv_setup_stream_frame(itv);
-               clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
-               ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
-               ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0);
-       }
-}
-
-static void ivtv_irq_vsync(struct ivtv *itv)
-{
-       /* The vsync interrupt is unusual in that it won't clear until
-        * the end of the first line for the current field, at which
-        * point it clears itself. This can result in repeated vsync
-        * interrupts, or a missed vsync. Read some of the registers
-        * to determine the line being displayed and ensure we handle
-        * one vsync per frame.
-        */
-       unsigned int frame = read_reg(IVTV_REG_DEC_LINE_FIELD) & 1;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int last_dma_frame = atomic_read(&yi->next_dma_frame);
-       struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
-
-       if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
-
-       if (((frame ^ f->sync_field) == 0 &&
-               ((itv->last_vsync_field & 1) ^ f->sync_field)) ||
-                       (frame != (itv->last_vsync_field & 1) && !f->interlaced)) {
-               int next_dma_frame = last_dma_frame;
-
-               if (!(f->interlaced && f->delay && yi->fields_lapsed < 1)) {
-                       if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) {
-                               write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
-                               write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
-                               write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
-                               write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
-                               next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
-                               atomic_set(&yi->next_dma_frame, next_dma_frame);
-                               yi->fields_lapsed = -1;
-                               yi->running = 1;
-                       }
-               }
-       }
-       if (frame != (itv->last_vsync_field & 1)) {
-               static const struct v4l2_event evtop = {
-                       .type = V4L2_EVENT_VSYNC,
-                       .u.vsync.field = V4L2_FIELD_TOP,
-               };
-               static const struct v4l2_event evbottom = {
-                       .type = V4L2_EVENT_VSYNC,
-                       .u.vsync.field = V4L2_FIELD_BOTTOM,
-               };
-               struct ivtv_stream *s = ivtv_get_output_stream(itv);
-
-               itv->last_vsync_field += 1;
-               if (frame == 0) {
-                       clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
-                       clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
-               }
-               else {
-                       set_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
-               }
-               if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) {
-                       set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags);
-                       wake_up(&itv->event_waitq);
-                       if (s)
-                               wake_up(&s->waitq);
-               }
-               if (s && s->vdev)
-                       v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom);
-               wake_up(&itv->vsync_waitq);
-
-               /* Send VBI to saa7127 */
-               if (frame && (itv->output_mode == OUT_PASSTHROUGH ||
-                       test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) ||
-                       test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) ||
-                       test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) {
-                       set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
-                       set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
-               }
-
-               /* Check if we need to update the yuv registers */
-               if (yi->running && (yi->yuv_forced_update || f->update)) {
-                       if (!f->update) {
-                               last_dma_frame =
-                                       (u8)(atomic_read(&yi->next_dma_frame) -
-                                                1) % IVTV_YUV_BUFFERS;
-                               f = &yi->new_frame_info[last_dma_frame];
-                       }
-
-                       if (f->src_w) {
-                               yi->update_frame = last_dma_frame;
-                               f->update = 0;
-                               yi->yuv_forced_update = 0;
-                               set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
-                               set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
-                       }
-               }
-
-               yi->fields_lapsed++;
-       }
-}
-
-#define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT)
-
-irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
-{
-       struct ivtv *itv = (struct ivtv *)dev_id;
-       u32 combo;
-       u32 stat;
-       int i;
-       u8 vsync_force = 0;
-
-       spin_lock(&itv->dma_reg_lock);
-       /* get contents of irq status register */
-       stat = read_reg(IVTV_REG_IRQSTATUS);
-
-       combo = ~itv->irqmask & stat;
-
-       /* Clear out IRQ */
-       if (combo) write_reg(combo, IVTV_REG_IRQSTATUS);
-
-       if (0 == combo) {
-               /* The vsync interrupt is unusual and clears itself. If we
-                * took too long, we may have missed it. Do some checks
-                */
-               if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
-                       /* vsync is enabled, see if we're in a new field */
-                       if ((itv->last_vsync_field & 1) !=
-                           (read_reg(IVTV_REG_DEC_LINE_FIELD) & 1)) {
-                               /* New field, looks like we missed it */
-                               IVTV_DEBUG_YUV("VSync interrupt missed %d\n",
-                                      read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16);
-                               vsync_force = 1;
-                       }
-               }
-
-               if (!vsync_force) {
-                       /* No Vsync expected, wasn't for us */
-                       spin_unlock(&itv->dma_reg_lock);
-                       return IRQ_NONE;
-               }
-       }
-
-       /* Exclude interrupts noted below from the output, otherwise the log is flooded with
-          these messages */
-       if (combo & ~0xff6d0400)
-               IVTV_DEBUG_HI_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo);
-
-       if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) {
-               IVTV_DEBUG_HI_IRQ("DEC DMA COMPLETE\n");
-       }
-
-       if (combo & IVTV_IRQ_DMA_READ) {
-               ivtv_irq_dma_read(itv);
-       }
-
-       if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) {
-               ivtv_irq_enc_dma_complete(itv);
-       }
-
-       if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
-               ivtv_irq_enc_pio_complete(itv);
-       }
-
-       if (combo & IVTV_IRQ_DMA_ERR) {
-               ivtv_irq_dma_err(itv);
-       }
-
-       if (combo & IVTV_IRQ_ENC_START_CAP) {
-               ivtv_irq_enc_start_cap(itv);
-       }
-
-       if (combo & IVTV_IRQ_ENC_VBI_CAP) {
-               ivtv_irq_enc_vbi_cap(itv);
-       }
-
-       if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
-               ivtv_irq_dec_vbi_reinsert(itv);
-       }
-
-       if (combo & IVTV_IRQ_ENC_EOS) {
-               IVTV_DEBUG_IRQ("ENC EOS\n");
-               set_bit(IVTV_F_I_EOS, &itv->i_flags);
-               wake_up(&itv->eos_waitq);
-       }
-
-       if (combo & IVTV_IRQ_DEC_DATA_REQ) {
-               ivtv_irq_dec_data_req(itv);
-       }
-
-       /* Decoder Vertical Sync - We can't rely on 'combo', so check if vsync enabled */
-       if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
-               ivtv_irq_vsync(itv);
-       }
-
-       if (combo & IVTV_IRQ_ENC_VIM_RST) {
-               IVTV_DEBUG_IRQ("VIM RST\n");
-               /*ivtv_vapi(itv, CX2341X_ENC_REFRESH_INPUT, 0); */
-       }
-
-       if (combo & IVTV_IRQ_DEC_AUD_MODE_CHG) {
-               IVTV_DEBUG_INFO("Stereo mode changed\n");
-       }
-
-       if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
-               itv->irq_rr_idx++;
-               for (i = 0; i < IVTV_MAX_STREAMS; i++) {
-                       int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS;
-                       struct ivtv_stream *s = &itv->streams[idx];
-
-                       if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags))
-                               continue;
-                       if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
-                               ivtv_dma_dec_start(s);
-                       else
-                               ivtv_dma_enc_start(s);
-                       break;
-               }
-
-               if (i == IVTV_MAX_STREAMS &&
-                   test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
-                       ivtv_udma_start(itv);
-       }
-
-       if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
-               itv->irq_rr_idx++;
-               for (i = 0; i < IVTV_MAX_STREAMS; i++) {
-                       int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS;
-                       struct ivtv_stream *s = &itv->streams[idx];
-
-                       if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
-                               continue;
-                       if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
-                               ivtv_dma_enc_start(s);
-                       break;
-               }
-       }
-
-       if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
-               queue_kthread_work(&itv->irq_worker, &itv->irq_work);
-       }
-
-       spin_unlock(&itv->dma_reg_lock);
-
-       /* If we've just handled a 'forced' vsync, it's safest to say it
-        * wasn't ours. Another device may have triggered it at just
-        * the right time.
-        */
-       return vsync_force ? IRQ_NONE : IRQ_HANDLED;
-}
-
-void ivtv_unfinished_dma(unsigned long arg)
-{
-       struct ivtv *itv = (struct ivtv *)arg;
-
-       if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
-               return;
-       IVTV_ERR("DMA TIMEOUT %08x %d\n", read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
-
-       write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
-       clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
-       clear_bit(IVTV_F_I_DMA, &itv->i_flags);
-       itv->cur_dma_stream = -1;
-       wake_up(&itv->dma_waitq);
-}
diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h
deleted file mode 100644 (file)
index 1e84433..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-    interrupt handling
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_IRQ_H
-#define IVTV_IRQ_H
-
-#define IVTV_IRQ_ENC_START_CAP         (0x1 << 31)
-#define IVTV_IRQ_ENC_EOS               (0x1 << 30)
-#define IVTV_IRQ_ENC_VBI_CAP           (0x1 << 29)
-#define IVTV_IRQ_ENC_VIM_RST           (0x1 << 28)
-#define IVTV_IRQ_ENC_DMA_COMPLETE      (0x1 << 27)
-#define IVTV_IRQ_ENC_PIO_COMPLETE      (0x1 << 25)
-#define IVTV_IRQ_DEC_AUD_MODE_CHG      (0x1 << 24)
-#define IVTV_IRQ_DEC_DATA_REQ          (0x1 << 22)
-#define IVTV_IRQ_DEC_DMA_COMPLETE      (0x1 << 20)
-#define IVTV_IRQ_DEC_VBI_RE_INSERT     (0x1 << 19)
-#define IVTV_IRQ_DMA_ERR               (0x1 << 18)
-#define IVTV_IRQ_DMA_WRITE             (0x1 << 17)
-#define IVTV_IRQ_DMA_READ              (0x1 << 16)
-#define IVTV_IRQ_DEC_VSYNC             (0x1 << 10)
-
-/* IRQ Masks */
-#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
-               IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
-
-#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
-#define IVTV_IRQ_MASK_DECODE  (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
-
-irqreturn_t ivtv_irq_handler(int irq, void *dev_id);
-
-void ivtv_irq_work_handler(struct kthread_work *work);
-void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock);
-void ivtv_unfinished_dma(unsigned long arg);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c
deleted file mode 100644 (file)
index e3ce967..0000000
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
-    mailbox functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <stdarg.h>
-
-#include "ivtv-driver.h"
-#include "ivtv-mailbox.h"
-
-/* Firmware mailbox flags*/
-#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
-#define IVTV_MBOX_DRIVER_DONE   0x00000002
-#define IVTV_MBOX_DRIVER_BUSY   0x00000001
-#define IVTV_MBOX_FREE                 0x00000000
-
-/* Firmware mailbox standard timeout */
-#define IVTV_API_STD_TIMEOUT   0x02000000
-
-#define API_CACHE       (1 << 0)       /* Allow the command to be stored in the cache */
-#define API_RESULT      (1 << 1)       /* Allow 1 second for this cmd to end */
-#define API_FAST_RESULT         (3 << 1)       /* Allow 0.1 second for this cmd to end */
-#define API_DMA         (1 << 3)       /* DMA mailbox, has special handling */
-#define API_HIGH_VOL    (1 << 5)       /* High volume command (i.e. called during encoding or decoding) */
-#define API_NO_WAIT_MB          (1 << 4)       /* Command may not wait for a free mailbox */
-#define API_NO_WAIT_RES         (1 << 5)       /* Command may not wait for the result */
-#define API_NO_POLL     (1 << 6)       /* Avoid pointless polling */
-
-struct ivtv_api_info {
-       int flags;              /* Flags, see above */
-       const char *name;       /* The name of the command */
-};
-
-#define API_ENTRY(x, f) [x] = { (f), #x }
-
-static const struct ivtv_api_info api_info[256] = {
-       /* MPEG encoder API */
-       API_ENTRY(CX2341X_ENC_PING_FW,                  API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_START_CAPTURE,            API_RESULT | API_NO_POLL),
-       API_ENTRY(CX2341X_ENC_STOP_CAPTURE,             API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_AUDIO_ID,             API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_VIDEO_ID,             API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_PCR_ID,               API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_FRAME_RATE,           API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_FRAME_SIZE,           API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_BIT_RATE,             API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_GOP_PROPERTIES,       API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_ASPECT_RATIO,         API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_MODE,      API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_PROPS,     API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_CORING_LEVELS,        API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,  API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_VBI_LINE,             API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_STREAM_TYPE,          API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_OUTPUT_PORT,          API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_AUDIO_PROPERTIES,     API_CACHE),
-       API_ENTRY(CX2341X_ENC_HALT_FW,                  API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_GET_VERSION,              API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_GOP_CLOSURE,          API_CACHE),
-       API_ENTRY(CX2341X_ENC_GET_SEQ_END,              API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_PGM_INDEX_INFO,       API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_VBI_CONFIG,           API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE,       API_CACHE),
-       API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10,  API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9,   API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST,        API_DMA | API_HIGH_VOL),
-       API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT,         API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE,      API_CACHE),
-       API_ENTRY(CX2341X_ENC_PAUSE_ENCODER,            API_RESULT),
-       API_ENTRY(CX2341X_ENC_REFRESH_INPUT,            API_NO_WAIT_MB | API_HIGH_VOL),
-       API_ENTRY(CX2341X_ENC_SET_COPYRIGHT,            API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION,   API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES,      API_CACHE),
-       API_ENTRY(CX2341X_ENC_SET_PLACEHOLDER,          API_CACHE),
-       API_ENTRY(CX2341X_ENC_MUTE_VIDEO,               API_RESULT),
-       API_ENTRY(CX2341X_ENC_MUTE_AUDIO,               API_RESULT),
-       API_ENTRY(CX2341X_ENC_SET_VERT_CROP_LINE,       API_FAST_RESULT),
-       API_ENTRY(CX2341X_ENC_MISC,                     API_FAST_RESULT),
-       /* Obsolete PULLDOWN API command */
-       API_ENTRY(0xb1,                                 API_CACHE),
-
-       /* MPEG decoder API */
-       API_ENTRY(CX2341X_DEC_PING_FW,                  API_FAST_RESULT),
-       API_ENTRY(CX2341X_DEC_START_PLAYBACK,           API_RESULT | API_NO_POLL),
-       API_ENTRY(CX2341X_DEC_STOP_PLAYBACK,            API_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED,       API_RESULT),
-       API_ENTRY(CX2341X_DEC_STEP_VIDEO,               API_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE,       API_CACHE),
-       API_ENTRY(CX2341X_DEC_GET_XFER_INFO,            API_FAST_RESULT),
-       API_ENTRY(CX2341X_DEC_GET_DMA_STATUS,           API_FAST_RESULT),
-       API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST,      API_DMA | API_HIGH_VOL),
-       API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK,           API_RESULT),
-       API_ENTRY(CX2341X_DEC_HALT_FW,                  API_FAST_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_STANDARD,             API_CACHE),
-       API_ENTRY(CX2341X_DEC_GET_VERSION,              API_FAST_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_STREAM_INPUT,         API_CACHE),
-       API_ENTRY(CX2341X_DEC_GET_TIMING_INFO,          API_RESULT /*| API_NO_WAIT_RES*/),
-       API_ENTRY(CX2341X_DEC_SET_AUDIO_MODE,           API_CACHE),
-       API_ENTRY(CX2341X_DEC_SET_EVENT_NOTIFICATION,   API_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_DISPLAY_BUFFERS,      API_CACHE),
-       API_ENTRY(CX2341X_DEC_EXTRACT_VBI,              API_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_DECODER_SOURCE,       API_FAST_RESULT),
-       API_ENTRY(CX2341X_DEC_SET_PREBUFFERING,         API_CACHE),
-
-       /* OSD API */
-       API_ENTRY(CX2341X_OSD_GET_FRAMEBUFFER,          API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_GET_PIXEL_FORMAT,         API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_PIXEL_FORMAT,         API_CACHE),
-       API_ENTRY(CX2341X_OSD_GET_STATE,                API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_STATE,                API_CACHE),
-       API_ENTRY(CX2341X_OSD_GET_OSD_COORDS,           API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_OSD_COORDS,           API_CACHE),
-       API_ENTRY(CX2341X_OSD_GET_SCREEN_COORDS,        API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_SCREEN_COORDS,        API_CACHE),
-       API_ENTRY(CX2341X_OSD_GET_GLOBAL_ALPHA,         API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_GLOBAL_ALPHA,         API_CACHE),
-       API_ENTRY(CX2341X_OSD_SET_BLEND_COORDS,         API_CACHE),
-       API_ENTRY(CX2341X_OSD_GET_FLICKER_STATE,        API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_FLICKER_STATE,        API_CACHE),
-       API_ENTRY(CX2341X_OSD_BLT_COPY,                 API_RESULT),
-       API_ENTRY(CX2341X_OSD_BLT_FILL,                 API_RESULT),
-       API_ENTRY(CX2341X_OSD_BLT_TEXT,                 API_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_FRAMEBUFFER_WINDOW,   API_CACHE),
-       API_ENTRY(CX2341X_OSD_SET_CHROMA_KEY,           API_CACHE),
-       API_ENTRY(CX2341X_OSD_GET_ALPHA_CONTENT_INDEX,  API_FAST_RESULT),
-       API_ENTRY(CX2341X_OSD_SET_ALPHA_CONTENT_INDEX,  API_CACHE)
-};
-
-static int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb)
-{
-       u32 flags = readl(&mbdata->mbox[mb].flags);
-       int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE);
-
-       /* if the mailbox is free, then try to claim it */
-       if (is_free && !test_and_set_bit(mb, &mbdata->busy)) {
-               write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags);
-               return 1;
-       }
-       return 0;
-}
-
-/* Try to find a free mailbox. Note mailbox 0 is reserved for DMA and so is not
-   attempted here. */
-static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int flags)
-{
-       unsigned long then = jiffies;
-       int i, mb;
-       int max_mbox = mbdata->max_mbox;
-       int retries = 100;
-
-       /* All slow commands use the same mailbox, serializing them and also
-          leaving the other mailbox free for simple fast commands. */
-       if ((flags & API_FAST_RESULT) == API_RESULT)
-               max_mbox = 1;
-
-       /* find free non-DMA mailbox */
-       for (i = 0; i < retries; i++) {
-               for (mb = 1; mb <= max_mbox; mb++)
-                       if (try_mailbox(itv, mbdata, mb))
-                               return mb;
-
-               /* Sleep before a retry, if not atomic */
-               if (!(flags & API_NO_WAIT_MB)) {
-                       if (time_after(jiffies,
-                                      then + msecs_to_jiffies(10*retries)))
-                              break;
-                       ivtv_msleep_timeout(10, 0);
-               }
-       }
-       return -ENODEV;
-}
-
-static void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[])
-{
-       int i;
-
-       write_sync(cmd, &mbox->cmd);
-       write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout);
-
-       for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
-               write_sync(data[i], &mbox->data[i]);
-
-       write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags);
-}
-
-static void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata)
-{
-       int i;
-
-       for (i = 0; i <= mbdata->max_mbox; i++) {
-               IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n",
-                       i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags));
-               write_sync(0, &mbdata->mbox[i].flags);
-               clear_bit(i, &mbdata->busy);
-       }
-}
-
-static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
-{
-       struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox;
-       volatile struct ivtv_mailbox __iomem *mbox;
-       int api_timeout = msecs_to_jiffies(1000);
-       int flags, mb, i;
-       unsigned long then;
-
-       /* sanity checks */
-       if (NULL == mbdata) {
-               IVTV_ERR("No mailbox allocated\n");
-               return -ENODEV;
-       }
-       if (args < 0 || args > CX2341X_MBOX_MAX_DATA ||
-           cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) {
-               IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args);
-               return -EINVAL;
-       }
-
-       if (api_info[cmd].flags & API_HIGH_VOL) {
-           IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name);
-       }
-       else {
-           IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name);
-       }
-
-       /* clear possibly uninitialized part of data array */
-       for (i = args; i < CX2341X_MBOX_MAX_DATA; i++)
-               data[i] = 0;
-
-       /* If this command was issued within the last 30 minutes and with identical
-          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 &&
-           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;
-       }
-
-       flags = api_info[cmd].flags;
-
-       if (flags & API_DMA) {
-               for (i = 0; i < 100; i++) {
-                       mb = i % (mbdata->max_mbox + 1);
-                       if (try_mailbox(itv, mbdata, mb)) {
-                               write_mailbox(&mbdata->mbox[mb], cmd, args, data);
-                               clear_bit(mb, &mbdata->busy);
-                               return 0;
-                       }
-                       IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n",
-                                       api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags));
-               }
-               IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name);
-               clear_all_mailboxes(itv, mbdata);
-               return -EBUSY;
-       }
-
-       if ((flags & API_FAST_RESULT) == API_FAST_RESULT)
-               api_timeout = msecs_to_jiffies(100);
-
-       mb = get_mailbox(itv, mbdata, flags);
-       if (mb < 0) {
-               IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name);
-               clear_all_mailboxes(itv, mbdata);
-               return -EBUSY;
-       }
-       mbox = &mbdata->mbox[mb];
-       write_mailbox(mbox, cmd, args, data);
-       if (flags & API_CACHE) {
-               memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data));
-               itv->api_cache[cmd].last_jiffies = jiffies;
-       }
-       if ((flags & API_RESULT) == 0) {
-               clear_bit(mb, &mbdata->busy);
-               return 0;
-       }
-
-       /* Get results */
-       then = jiffies;
-
-       if (!(flags & API_NO_POLL)) {
-               /* First try to poll, then switch to delays */
-               for (i = 0; i < 100; i++) {
-                       if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)
-                               break;
-               }
-       }
-       while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
-               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);
-                       clear_bit(mb, &mbdata->busy);
-                       return -EIO;
-               }
-               if (flags & API_NO_WAIT_RES)
-                       mdelay(1);
-               else
-                       ivtv_msleep_timeout(1, 0);
-       }
-       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));
-
-       for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
-               data[i] = readl(&mbox->data[i]);
-       write_sync(0, &mbox->flags);
-       clear_bit(mb, &mbdata->busy);
-       return 0;
-}
-
-int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[])
-{
-       int res = ivtv_api_call(itv, cmd, args, data);
-
-       /* Allow a single retry, probably already too late though.
-          If there is no free mailbox then that is usually an indication
-          of a more serious problem. */
-       return (res == -EBUSY) ? ivtv_api_call(itv, cmd, args, data) : res;
-}
-
-int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
-{
-       return ivtv_api(priv, cmd, in, data);
-}
-
-int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...)
-{
-       va_list ap;
-       int i;
-
-       va_start(ap, args);
-       for (i = 0; i < args; i++) {
-               data[i] = va_arg(ap, u32);
-       }
-       va_end(ap);
-       return ivtv_api(itv, cmd, args, data);
-}
-
-int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       va_list ap;
-       int i;
-
-       va_start(ap, args);
-       for (i = 0; i < args; i++) {
-               data[i] = va_arg(ap, u32);
-       }
-       va_end(ap);
-       return ivtv_api(itv, cmd, args, data);
-}
-
-/* This one is for stuff that can't sleep.. irq handlers, etc.. */
-void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
-                      int argc, u32 data[])
-{
-       volatile u32 __iomem *p = mbdata->mbox[mb].data;
-       int i;
-       for (i = 0; i < argc; i++, p++)
-               data[i] = readl(p);
-}
-
-/* Wipe api cache */
-void ivtv_mailbox_cache_invalidate(struct ivtv *itv)
-{
-       int i;
-       for (i = 0; i < 256; i++)
-               itv->api_cache[i].last_jiffies = 0;
-}
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h
deleted file mode 100644 (file)
index 2c834d2..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-    mailbox functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_MAILBOX_H
-#define IVTV_MAILBOX_H
-
-#define IVTV_MBOX_DMA_END         8
-#define IVTV_MBOX_DMA             9
-
-void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
-                      int argc, u32 data[]);
-int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]);
-int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...);
-int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...);
-int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]);
-void ivtv_mailbox_cache_invalidate(struct ivtv *itv);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
deleted file mode 100644 (file)
index 7fde36e..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
-    buffer queues.
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-queue.h"
-
-int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes)
-{
-       if (s->buf_size - buf->bytesused < copybytes)
-               copybytes = s->buf_size - buf->bytesused;
-       if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) {
-               return -EFAULT;
-       }
-       buf->bytesused += copybytes;
-       return copybytes;
-}
-
-void ivtv_buf_swap(struct ivtv_buffer *buf)
-{
-       int i;
-
-       for (i = 0; i < buf->bytesused; i += 4)
-               swab32s((u32 *)(buf->buf + i));
-}
-
-void ivtv_queue_init(struct ivtv_queue *q)
-{
-       INIT_LIST_HEAD(&q->list);
-       q->buffers = 0;
-       q->length = 0;
-       q->bytesused = 0;
-}
-
-void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
-{
-       unsigned long flags;
-
-       /* clear the buffer if it is going to be enqueued to the free queue */
-       if (q == &s->q_free) {
-               buf->bytesused = 0;
-               buf->readpos = 0;
-               buf->b_flags = 0;
-               buf->dma_xfer_cnt = 0;
-       }
-       spin_lock_irqsave(&s->qlock, flags);
-       list_add_tail(&buf->list, &q->list);
-       q->buffers++;
-       q->length += s->buf_size;
-       q->bytesused += buf->bytesused - buf->readpos;
-       spin_unlock_irqrestore(&s->qlock, flags);
-}
-
-struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
-{
-       struct ivtv_buffer *buf = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&s->qlock, flags);
-       if (!list_empty(&q->list)) {
-               buf = list_entry(q->list.next, struct ivtv_buffer, list);
-               list_del_init(q->list.next);
-               q->buffers--;
-               q->length -= s->buf_size;
-               q->bytesused -= buf->bytesused - buf->readpos;
-       }
-       spin_unlock_irqrestore(&s->qlock, flags);
-       return buf;
-}
-
-static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
-               struct ivtv_queue *to, int clear)
-{
-       struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list);
-
-       list_move_tail(from->list.next, &to->list);
-       from->buffers--;
-       from->length -= s->buf_size;
-       from->bytesused -= buf->bytesused - buf->readpos;
-       /* special handling for q_free */
-       if (clear)
-               buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
-       to->buffers++;
-       to->length += s->buf_size;
-       to->bytesused += buf->bytesused - buf->readpos;
-}
-
-/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
-   If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
-   If 'steal' != NULL, then buffers may also taken from that queue if
-   needed, but only if 'from' is the free queue.
-
-   The buffer is automatically cleared if it goes to the free queue. It is
-   also cleared if buffers need to be taken from the 'steal' queue and
-   the 'from' queue is the free queue.
-
-   When 'from' is q_free, then needed_bytes is compared to the total
-   available buffer length, otherwise needed_bytes is compared to the
-   bytesused value. For the 'steal' queue the total available buffer
-   length is always used.
-
-   -ENOMEM is returned if the buffers could not be obtained, 0 if all
-   buffers where obtained from the 'from' list and if non-zero then
-   the number of stolen buffers is returned. */
-int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
-                   struct ivtv_queue *to, int needed_bytes)
-{
-       unsigned long flags;
-       int rc = 0;
-       int from_free = from == &s->q_free;
-       int to_free = to == &s->q_free;
-       int bytes_available, bytes_steal;
-
-       spin_lock_irqsave(&s->qlock, flags);
-       if (needed_bytes == 0) {
-               from_free = 1;
-               needed_bytes = from->length;
-       }
-
-       bytes_available = from_free ? from->length : from->bytesused;
-       bytes_steal = (from_free && steal) ? steal->length : 0;
-
-       if (bytes_available + bytes_steal < needed_bytes) {
-               spin_unlock_irqrestore(&s->qlock, flags);
-               return -ENOMEM;
-       }
-       while (bytes_available < needed_bytes) {
-               struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
-               u16 dma_xfer_cnt = buf->dma_xfer_cnt;
-
-               /* move buffers from the tail of the 'steal' queue to the tail of the
-                  'from' queue. Always copy all the buffers with the same dma_xfer_cnt
-                  value, this ensures that you do not end up with partial frame data
-                  if one frame is stored in multiple buffers. */
-               while (dma_xfer_cnt == buf->dma_xfer_cnt) {
-                       list_move_tail(steal->list.prev, &from->list);
-                       rc++;
-                       steal->buffers--;
-                       steal->length -= s->buf_size;
-                       steal->bytesused -= buf->bytesused - buf->readpos;
-                       buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
-                       from->buffers++;
-                       from->length += s->buf_size;
-                       bytes_available += s->buf_size;
-                       if (list_empty(&steal->list))
-                               break;
-                       buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
-               }
-       }
-       if (from_free) {
-               u32 old_length = to->length;
-
-               while (to->length - old_length < needed_bytes) {
-                       ivtv_queue_move_buf(s, from, to, 1);
-               }
-       }
-       else {
-               u32 old_bytesused = to->bytesused;
-
-               while (to->bytesused - old_bytesused < needed_bytes) {
-                       ivtv_queue_move_buf(s, from, to, to_free);
-               }
-       }
-       spin_unlock_irqrestore(&s->qlock, flags);
-       return rc;
-}
-
-void ivtv_flush_queues(struct ivtv_stream *s)
-{
-       ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
-       ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
-       ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
-       ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
-}
-
-int ivtv_stream_alloc(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-       int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers;
-       int i;
-
-       if (s->buffers == 0)
-               return 0;
-
-       IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n",
-               s->dma != PCI_DMA_NONE ? "DMA " : "",
-               s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
-
-       s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
-       if (s->sg_pending == NULL) {
-               IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
-               return -ENOMEM;
-       }
-       s->sg_pending_size = 0;
-
-       s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
-       if (s->sg_processing == NULL) {
-               IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
-               kfree(s->sg_pending);
-               s->sg_pending = NULL;
-               return -ENOMEM;
-       }
-       s->sg_processing_size = 0;
-
-       s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element),
-                                       GFP_KERNEL|__GFP_NOWARN);
-       if (s->sg_dma == NULL) {
-               IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
-               kfree(s->sg_pending);
-               s->sg_pending = NULL;
-               kfree(s->sg_processing);
-               s->sg_processing = NULL;
-               return -ENOMEM;
-       }
-       if (ivtv_might_use_dma(s)) {
-               s->sg_handle = pci_map_single(itv->pdev, s->sg_dma,
-                               sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
-               ivtv_stream_sync_for_cpu(s);
-       }
-
-       /* allocate stream buffers. Initially all buffers are in q_free. */
-       for (i = 0; i < s->buffers; i++) {
-               struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer),
-                                               GFP_KERNEL|__GFP_NOWARN);
-
-               if (buf == NULL)
-                       break;
-               buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN);
-               if (buf->buf == NULL) {
-                       kfree(buf);
-                       break;
-               }
-               INIT_LIST_HEAD(&buf->list);
-               if (ivtv_might_use_dma(s)) {
-                       buf->dma_handle = pci_map_single(s->itv->pdev,
-                               buf->buf, s->buf_size + 256, s->dma);
-                       ivtv_buf_sync_for_cpu(s, buf);
-               }
-               ivtv_enqueue(s, buf, &s->q_free);
-       }
-       if (i == s->buffers)
-               return 0;
-       IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name);
-       ivtv_stream_free(s);
-       return -ENOMEM;
-}
-
-void ivtv_stream_free(struct ivtv_stream *s)
-{
-       struct ivtv_buffer *buf;
-
-       /* move all buffers to q_free */
-       ivtv_flush_queues(s);
-
-       /* empty q_free */
-       while ((buf = ivtv_dequeue(s, &s->q_free))) {
-               if (ivtv_might_use_dma(s))
-                       pci_unmap_single(s->itv->pdev, buf->dma_handle,
-                               s->buf_size + 256, s->dma);
-               kfree(buf->buf);
-               kfree(buf);
-       }
-
-       /* Free SG Array/Lists */
-       if (s->sg_dma != NULL) {
-               if (s->sg_handle != IVTV_DMA_UNMAPPED) {
-                       pci_unmap_single(s->itv->pdev, s->sg_handle,
-                                sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
-                       s->sg_handle = IVTV_DMA_UNMAPPED;
-               }
-               kfree(s->sg_pending);
-               kfree(s->sg_processing);
-               kfree(s->sg_dma);
-               s->sg_pending = NULL;
-               s->sg_processing = NULL;
-               s->sg_dma = NULL;
-               s->sg_pending_size = 0;
-               s->sg_processing_size = 0;
-       }
-}
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h
deleted file mode 100644 (file)
index 9123383..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
-    buffer queues.
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_QUEUE_H
-#define IVTV_QUEUE_H
-
-#define IVTV_DMA_UNMAPPED      ((u32) -1)
-#define SLICED_VBI_PIO 0
-
-/* ivtv_buffer utility functions */
-
-static inline int ivtv_might_use_pio(struct ivtv_stream *s)
-{
-       return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
-}
-
-static inline int ivtv_use_pio(struct ivtv_stream *s)
-{
-       struct ivtv *itv = s->itv;
-
-       return s->dma == PCI_DMA_NONE ||
-           (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
-}
-
-static inline int ivtv_might_use_dma(struct ivtv_stream *s)
-{
-       return s->dma != PCI_DMA_NONE;
-}
-
-static inline int ivtv_use_dma(struct ivtv_stream *s)
-{
-       return !ivtv_use_pio(s);
-}
-
-static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
-{
-       if (ivtv_use_dma(s))
-               pci_dma_sync_single_for_cpu(s->itv->pdev, buf->dma_handle,
-                               s->buf_size + 256, s->dma);
-}
-
-static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
-{
-       if (ivtv_use_dma(s))
-               pci_dma_sync_single_for_device(s->itv->pdev, buf->dma_handle,
-                               s->buf_size + 256, s->dma);
-}
-
-int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes);
-void ivtv_buf_swap(struct ivtv_buffer *buf);
-
-/* ivtv_queue utility functions */
-void ivtv_queue_init(struct ivtv_queue *q);
-void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q);
-struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q);
-int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
-                   struct ivtv_queue *to, int needed_bytes);
-void ivtv_flush_queues(struct ivtv_stream *s);
-
-/* ivtv_stream utility functions */
-int ivtv_stream_alloc(struct ivtv_stream *s);
-void ivtv_stream_free(struct ivtv_stream *s);
-
-static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
-{
-       if (ivtv_use_dma(s))
-               pci_dma_sync_single_for_cpu(s->itv->pdev, s->sg_handle,
-                       sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
-}
-
-static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
-{
-       if (ivtv_use_dma(s))
-               pci_dma_sync_single_for_device(s->itv->pdev, s->sg_handle,
-                       sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
-}
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-routing.c b/drivers/media/video/ivtv/ivtv-routing.c
deleted file mode 100644 (file)
index 8898c56..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-    Audio/video-routing-related ivtv functions.
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-i2c.h"
-#include "ivtv-cards.h"
-#include "ivtv-gpio.h"
-#include "ivtv-routing.h"
-
-#include <media/msp3400.h>
-#include <media/m52790.h>
-#include <media/upd64031a.h>
-#include <media/upd64083.h>
-
-/* Selects the audio input and output according to the current
-   settings. */
-void ivtv_audio_set_io(struct ivtv *itv)
-{
-       const struct ivtv_card_audio_input *in;
-       u32 input, output = 0;
-
-       /* Determine which input to use */
-       if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
-               in = &itv->card->radio_input;
-       else
-               in = &itv->card->audio_inputs[itv->audio_input];
-
-       /* handle muxer chips */
-       input = in->muxer_input;
-       if (itv->card->hw_muxer & IVTV_HW_M52790)
-               output = M52790_OUT_STEREO;
-       v4l2_subdev_call(itv->sd_muxer, audio, s_routing,
-                       input, output, 0);
-
-       input = in->audio_input;
-       output = 0;
-       if (itv->card->hw_audio & IVTV_HW_MSP34XX)
-               output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
-       ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing,
-                       input, output, 0);
-}
-
-/* Selects the video input and output according to the current
-   settings. */
-void ivtv_video_set_io(struct ivtv *itv)
-{
-       int inp = itv->active_input;
-       u32 input;
-       u32 type;
-
-       v4l2_subdev_call(itv->sd_video, video, s_routing,
-               itv->card->video_inputs[inp].video_input, 0, 0);
-
-       type = itv->card->video_inputs[inp].video_type;
-
-       if (type == IVTV_CARD_INPUT_VID_TUNER) {
-               input = 0;  /* Tuner */
-       } else if (type < IVTV_CARD_INPUT_COMPOSITE1) {
-               input = 2;  /* S-Video */
-       } else {
-               input = 1;  /* Composite */
-       }
-
-       if (itv->card->hw_video & IVTV_HW_GPIO)
-               ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing,
-                               input, 0, 0);
-
-       if (itv->card->hw_video & IVTV_HW_UPD64031A) {
-               if (type == IVTV_CARD_INPUT_VID_TUNER ||
-                   type >= IVTV_CARD_INPUT_COMPOSITE1) {
-                       /* Composite: GR on, connect to 3DYCS */
-                       input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE;
-               } else {
-                       /* S-Video: GR bypassed, turn it off */
-                       input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE;
-               }
-               input |= itv->card->gr_config;
-
-               ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing,
-                               input, 0, 0);
-       }
-
-       if (itv->card->hw_video & IVTV_HW_UPD6408X) {
-               input = UPD64083_YCS_MODE;
-               if (type > IVTV_CARD_INPUT_VID_TUNER &&
-                   type < IVTV_CARD_INPUT_COMPOSITE1) {
-                       /* S-Video uses YCNR mode and internal Y-ADC, the
-                          upd64031a is not used. */
-                       input |= UPD64083_YCNR_MODE;
-               }
-               else if (itv->card->hw_video & IVTV_HW_UPD64031A) {
-                       /* Use upd64031a output for tuner and
-                          composite(CX23416GYC only) inputs */
-                       if (type == IVTV_CARD_INPUT_VID_TUNER ||
-                           itv->card->type == IVTV_CARD_CX23416GYC) {
-                               input |= UPD64083_EXT_Y_ADC;
-                       }
-               }
-               ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing,
-                               input, 0, 0);
-       }
-}
diff --git a/drivers/media/video/ivtv/ivtv-routing.h b/drivers/media/video/ivtv/ivtv-routing.h
deleted file mode 100644 (file)
index c72a973..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-    Audio/video-routing-related ivtv functions.
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_ROUTING_H
-#define IVTV_ROUTING_H
-
-void ivtv_audio_set_io(struct ivtv *itv);
-void ivtv_video_set_io(struct ivtv *itv);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
deleted file mode 100644 (file)
index f08ec17..0000000
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
-    init/start/stop/exit stream functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    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
- */
-
-/* License: GPL
- * Author: Kevin Thayer <nufan_wfk at yahoo dot com>
- *
- * This file will hold API related functions, both internal (firmware api)
- * and external (v4l2, etc)
- *
- * -----
- * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
- *                      and Takeru KOMORIYA<komoriya@paken.org>
- *
- * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
- *                using information provided by Jiun-Kuei Jung @ AVerMedia.
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-fileops.h"
-#include "ivtv-queue.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-irq.h"
-#include "ivtv-yuv.h"
-#include "ivtv-cards.h"
-#include "ivtv-streams.h"
-#include "ivtv-firmware.h"
-#include <media/v4l2-event.h>
-
-static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
-       .owner = THIS_MODULE,
-       .read = ivtv_v4l2_read,
-       .write = ivtv_v4l2_write,
-       .open = ivtv_v4l2_open,
-       .unlocked_ioctl = video_ioctl2,
-       .release = ivtv_v4l2_close,
-       .poll = ivtv_v4l2_enc_poll,
-};
-
-static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
-       .owner = THIS_MODULE,
-       .read = ivtv_v4l2_read,
-       .write = ivtv_v4l2_write,
-       .open = ivtv_v4l2_open,
-       .unlocked_ioctl = video_ioctl2,
-       .release = ivtv_v4l2_close,
-       .poll = ivtv_v4l2_dec_poll,
-};
-
-#define IVTV_V4L2_DEC_MPG_OFFSET  16   /* offset from 0 to register decoder mpg v4l2 minors on */
-#define IVTV_V4L2_ENC_PCM_OFFSET  24   /* offset from 0 to register pcm v4l2 minors on */
-#define IVTV_V4L2_ENC_YUV_OFFSET  32   /* offset from 0 to register yuv v4l2 minors on */
-#define IVTV_V4L2_DEC_YUV_OFFSET  48   /* offset from 0 to register decoder yuv v4l2 minors on */
-#define IVTV_V4L2_DEC_VBI_OFFSET   8   /* offset from 0 to register decoder vbi input v4l2 minors on */
-#define IVTV_V4L2_DEC_VOUT_OFFSET 16   /* offset from 0 to register vbi output v4l2 minors on */
-
-static struct {
-       const char *name;
-       int vfl_type;
-       int num_offset;
-       int dma, pio;
-       enum v4l2_buf_type buf_type;
-       u32 v4l2_caps;
-       const struct v4l2_file_operations *fops;
-} ivtv_stream_info[] = {
-       {       /* IVTV_ENC_STREAM_TYPE_MPG */
-               "encoder MPG",
-               VFL_TYPE_GRABBER, 0,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
-                       V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_enc_fops
-       },
-       {       /* IVTV_ENC_STREAM_TYPE_YUV */
-               "encoder YUV",
-               VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
-                       V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_enc_fops
-       },
-       {       /* IVTV_ENC_STREAM_TYPE_VBI */
-               "encoder VBI",
-               VFL_TYPE_VBI, 0,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE,
-               V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER |
-                       V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_enc_fops
-       },
-       {       /* IVTV_ENC_STREAM_TYPE_PCM */
-               "encoder PCM",
-               VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE,
-               V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_enc_fops
-       },
-       {       /* IVTV_ENC_STREAM_TYPE_RAD */
-               "encoder radio",
-               VFL_TYPE_RADIO, 0,
-               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE,
-               V4L2_CAP_RADIO | V4L2_CAP_TUNER,
-               &ivtv_v4l2_enc_fops
-       },
-       {       /* IVTV_DEC_STREAM_TYPE_MPG */
-               "decoder MPG",
-               VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
-               PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
-               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_dec_fops
-       },
-       {       /* IVTV_DEC_STREAM_TYPE_VBI */
-               "decoder VBI",
-               VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET,
-               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE,
-               V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_enc_fops
-       },
-       {       /* IVTV_DEC_STREAM_TYPE_VOUT */
-               "decoder VOUT",
-               VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET,
-               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT,
-               V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_dec_fops
-       },
-       {       /* IVTV_DEC_STREAM_TYPE_YUV */
-               "decoder YUV",
-               VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET,
-               PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
-               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
-               &ivtv_v4l2_dec_fops
-       }
-};
-
-static void ivtv_stream_init(struct ivtv *itv, int type)
-{
-       struct ivtv_stream *s = &itv->streams[type];
-       struct video_device *vdev = s->vdev;
-
-       /* we need to keep vdev, so restore it afterwards */
-       memset(s, 0, sizeof(*s));
-       s->vdev = vdev;
-
-       /* initialize ivtv_stream fields */
-       s->itv = itv;
-       s->type = type;
-       s->name = ivtv_stream_info[type].name;
-       s->caps = ivtv_stream_info[type].v4l2_caps;
-
-       if (ivtv_stream_info[type].pio)
-               s->dma = PCI_DMA_NONE;
-       else
-               s->dma = ivtv_stream_info[type].dma;
-       s->buf_size = itv->stream_buf_size[type];
-       if (s->buf_size)
-               s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
-       spin_lock_init(&s->qlock);
-       init_waitqueue_head(&s->waitq);
-       s->sg_handle = IVTV_DMA_UNMAPPED;
-       ivtv_queue_init(&s->q_free);
-       ivtv_queue_init(&s->q_full);
-       ivtv_queue_init(&s->q_dma);
-       ivtv_queue_init(&s->q_predma);
-       ivtv_queue_init(&s->q_io);
-}
-
-static int ivtv_prep_dev(struct ivtv *itv, int type)
-{
-       struct ivtv_stream *s = &itv->streams[type];
-       int num_offset = ivtv_stream_info[type].num_offset;
-       int num = itv->instance + ivtv_first_minor + num_offset;
-
-       /* These four fields are always initialized. If vdev == NULL, then
-          this stream is not in use. In that case no other fields but these
-          four can be used. */
-       s->vdev = NULL;
-       s->itv = itv;
-       s->type = type;
-       s->name = ivtv_stream_info[type].name;
-
-       /* Check whether the radio is supported */
-       if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO))
-               return 0;
-       if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return 0;
-
-       /* User explicitly selected 0 buffers for these streams, so don't
-          create them. */
-       if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
-           itv->options.kilobytes[type] == 0) {
-               IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
-               return 0;
-       }
-
-       ivtv_stream_init(itv, type);
-
-       /* allocate and initialize the v4l2 video device structure */
-       s->vdev = video_device_alloc();
-       if (s->vdev == NULL) {
-               IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name);
-               return -ENOMEM;
-       }
-
-       snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s",
-                       itv->v4l2_dev.name, s->name);
-
-       s->vdev->num = num;
-       s->vdev->v4l2_dev = &itv->v4l2_dev;
-       s->vdev->fops = ivtv_stream_info[type].fops;
-       s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
-       s->vdev->release = video_device_release;
-       s->vdev->tvnorms = V4L2_STD_ALL;
-       s->vdev->lock = &itv->serialize_lock;
-       set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
-       ivtv_set_funcs(s->vdev);
-       return 0;
-}
-
-/* Initialize v4l2 variables and prepare v4l2 devices */
-int ivtv_streams_setup(struct ivtv *itv)
-{
-       int type;
-
-       /* Setup V4L2 Devices */
-       for (type = 0; type < IVTV_MAX_STREAMS; type++) {
-               /* Prepare device */
-               if (ivtv_prep_dev(itv, type))
-                       break;
-
-               if (itv->streams[type].vdev == NULL)
-                       continue;
-
-               /* Allocate Stream */
-               if (ivtv_stream_alloc(&itv->streams[type]))
-                       break;
-       }
-       if (type == IVTV_MAX_STREAMS)
-               return 0;
-
-       /* One or more streams could not be initialized. Clean 'em all up. */
-       ivtv_streams_cleanup(itv, 0);
-       return -ENOMEM;
-}
-
-static int ivtv_reg_dev(struct ivtv *itv, int type)
-{
-       struct ivtv_stream *s = &itv->streams[type];
-       int vfl_type = ivtv_stream_info[type].vfl_type;
-       const char *name;
-       int num;
-
-       if (s->vdev == NULL)
-               return 0;
-
-       num = s->vdev->num;
-       /* card number + user defined offset + device offset */
-       if (type != IVTV_ENC_STREAM_TYPE_MPG) {
-               struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG];
-
-               if (s_mpg->vdev)
-                       num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset;
-       }
-       video_set_drvdata(s->vdev, s);
-
-       /* Register device. First try the desired minor, then any free one. */
-       if (video_register_device_no_warn(s->vdev, vfl_type, num)) {
-               IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
-                               s->name, num);
-               video_device_release(s->vdev);
-               s->vdev = NULL;
-               return -ENOMEM;
-       }
-       name = video_device_node_name(s->vdev);
-
-       switch (vfl_type) {
-       case VFL_TYPE_GRABBER:
-               IVTV_INFO("Registered device %s for %s (%d kB)\n",
-                       name, s->name, itv->options.kilobytes[type]);
-               break;
-       case VFL_TYPE_RADIO:
-               IVTV_INFO("Registered device %s for %s\n",
-                       name, s->name);
-               break;
-       case VFL_TYPE_VBI:
-               if (itv->options.kilobytes[type])
-                       IVTV_INFO("Registered device %s for %s (%d kB)\n",
-                               name, s->name, itv->options.kilobytes[type]);
-               else
-                       IVTV_INFO("Registered device %s for %s\n",
-                               name, s->name);
-               break;
-       }
-       return 0;
-}
-
-/* Register v4l2 devices */
-int ivtv_streams_register(struct ivtv *itv)
-{
-       int type;
-       int err = 0;
-
-       /* Register V4L2 devices */
-       for (type = 0; type < IVTV_MAX_STREAMS; type++)
-               err |= ivtv_reg_dev(itv, type);
-
-       if (err == 0)
-               return 0;
-
-       /* One or more streams could not be initialized. Clean 'em all up. */
-       ivtv_streams_cleanup(itv, 1);
-       return -ENOMEM;
-}
-
-/* Unregister v4l2 devices */
-void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
-{
-       int type;
-
-       /* Teardown all streams */
-       for (type = 0; type < IVTV_MAX_STREAMS; type++) {
-               struct video_device *vdev = itv->streams[type].vdev;
-
-               itv->streams[type].vdev = NULL;
-               if (vdev == NULL)
-                       continue;
-
-               ivtv_stream_free(&itv->streams[type]);
-               /* Unregister or release device */
-               if (unregister)
-                       video_unregister_device(vdev);
-               else
-                       video_device_release(vdev);
-       }
-}
-
-static void ivtv_vbi_setup(struct ivtv *itv)
-{
-       int raw = ivtv_raw_vbi(itv);
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       int lines;
-       int i;
-
-       /* Reset VBI */
-       ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
-
-       /* setup VBI registers */
-       if (raw)
-               v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi);
-       else
-               v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced);
-
-       /* determine number of lines and total number of VBI bytes.
-          A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
-          The '- 1' byte is probably an unused U or V byte. Or something...
-          A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
-          header, 42 data bytes + checksum (to be confirmed) */
-       if (raw) {
-               lines = itv->vbi.count * 2;
-       } else {
-               lines = itv->is_60hz ? 24 : 38;
-               if (itv->is_60hz && (itv->hw_flags & IVTV_HW_CX25840))
-                       lines += 2;
-       }
-
-       itv->vbi.enc_size = lines * (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
-
-       /* Note: sliced vs raw flag doesn't seem to have any effect
-          TODO: check mode (0x02) value with older ivtv versions. */
-       data[0] = raw | 0x02 | (0xbd << 8);
-
-       /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
-       data[1] = 1;
-       /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
-       data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
-       /* The start/stop codes determine which VBI lines end up in the raw VBI data area.
-          The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
-          is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
-          code. These values for raw VBI are obtained from a driver disassembly. The sliced
-          start/stop codes was deduced from this, but they do not appear in the driver.
-          Other code pairs that I found are: 0x250E6249/0x13545454 and 0x25256262/0x38137F54.
-          However, I have no idea what these values are for. */
-       if (itv->hw_flags & IVTV_HW_CX25840) {
-               /* Setup VBI for the cx25840 digitizer */
-               if (raw) {
-                       data[3] = 0x20602060;
-                       data[4] = 0x30703070;
-               } else {
-                       data[3] = 0xB0F0B0F0;
-                       data[4] = 0xA0E0A0E0;
-               }
-               /* Lines per frame */
-               data[5] = lines;
-               /* bytes per line */
-               data[6] = (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
-       } else {
-               /* Setup VBI for the saa7115 digitizer */
-               if (raw) {
-                       data[3] = 0x25256262;
-                       data[4] = 0x387F7F7F;
-               } else {
-                       data[3] = 0xABABECEC;
-                       data[4] = 0xB6F1F1F1;
-               }
-               /* Lines per frame */
-               data[5] = lines;
-               /* bytes per line */
-               data[6] = itv->vbi.enc_size / lines;
-       }
-
-       IVTV_DEBUG_INFO(
-               "Setup VBI API header 0x%08x pkts %d buffs %d ln %d sz %d\n",
-                       data[0], data[1], data[2], data[5], data[6]);
-
-       ivtv_api(itv, CX2341X_ENC_SET_VBI_CONFIG, 7, data);
-
-       /* returns the VBI encoder memory area. */
-       itv->vbi.enc_start = data[2];
-       itv->vbi.fpi = data[0];
-       if (!itv->vbi.fpi)
-               itv->vbi.fpi = 1;
-
-       IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n",
-               itv->vbi.enc_start, data[1], itv->vbi.fpi);
-
-       /* select VBI lines.
-          Note that the sliced argument seems to have no effect. */
-       for (i = 2; i <= 24; i++) {
-               int valid;
-
-               if (itv->is_60hz) {
-                       valid = i >= 10 && i < 22;
-               } else {
-                       valid = i >= 6 && i < 24;
-               }
-               ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, i - 1,
-                               valid, 0 , 0, 0);
-               ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, (i - 1) | 0x80000000,
-                               valid, 0, 0, 0);
-       }
-
-       /* Remaining VBI questions:
-          - Is it possible to select particular VBI lines only for inclusion in the MPEG
-          stream? Currently you can only get the first X lines.
-          - Is mixed raw and sliced VBI possible?
-          - What's the meaning of the raw/sliced flag?
-          - What's the meaning of params 2, 3 & 4 of the Select VBI command? */
-}
-
-int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv *itv = s->itv;
-       int captype = 0, subtype = 0;
-       int enable_passthrough = 0;
-
-       if (s->vdev == NULL)
-               return -EINVAL;
-
-       IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
-
-       switch (s->type) {
-       case IVTV_ENC_STREAM_TYPE_MPG:
-               captype = 0;
-               subtype = 3;
-
-               /* Stop Passthrough */
-               if (itv->output_mode == OUT_PASSTHROUGH) {
-                       ivtv_passthrough_mode(itv, 0);
-                       enable_passthrough = 1;
-               }
-               itv->mpg_data_received = itv->vbi_data_inserted = 0;
-               itv->dualwatch_jiffies = jiffies;
-               itv->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
-               itv->search_pack_header = 0;
-               break;
-
-       case IVTV_ENC_STREAM_TYPE_YUV:
-               if (itv->output_mode == OUT_PASSTHROUGH) {
-                       captype = 2;
-                       subtype = 11;   /* video+audio+decoder */
-                       break;
-               }
-               captype = 1;
-               subtype = 1;
-               break;
-       case IVTV_ENC_STREAM_TYPE_PCM:
-               captype = 1;
-               subtype = 2;
-               break;
-       case IVTV_ENC_STREAM_TYPE_VBI:
-               captype = 1;
-               subtype = 4;
-
-               itv->vbi.frame = 0;
-               itv->vbi.inserted_frame = 0;
-               memset(itv->vbi.sliced_mpeg_size,
-                       0, sizeof(itv->vbi.sliced_mpeg_size));
-               break;
-       default:
-               return -EINVAL;
-       }
-       s->subtype = subtype;
-       s->buffers_stolen = 0;
-
-       /* Clear Streamoff flags in case left from last capture */
-       clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-
-       if (atomic_read(&itv->capturing) == 0) {
-               int digitizer;
-
-               /* Always use frame based mode. Experiments have demonstrated that byte
-                  stream based mode results in dropped frames and corruption. Not often,
-                  but occasionally. Many thanks go to Leonard Orb who spent a lot of
-                  effort and time trying to trace the cause of the drop outs. */
-               /* 1 frame per DMA */
-               /*ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 128, 0); */
-               ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 1, 1);
-
-               /* Stuff from Windows, we don't know what it is */
-               ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, 0);
-               /* According to the docs, this should be correct. However, this is
-                  untested. I don't dare enable this without having tested it.
-                  Only very few old cards actually have this hardware combination.
-               ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1,
-                       ((itv->hw_flags & IVTV_HW_SAA7114) && itv->is_60hz) ? 10001 : 0);
-               */
-               ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 3, !itv->has_cx23415);
-               ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 8, 0);
-               ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 4, 1);
-               ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
-
-               /* assign placeholder */
-               ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12,
-                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
-               if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
-                   digitizer = 0xF1;
-               else if (itv->card->hw_all & IVTV_HW_SAA7114)
-                   digitizer = 0xEF;
-               else /* cx25840 */
-                   digitizer = 0x140;
-
-               ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer);
-
-               /* Setup VBI */
-               if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) {
-                       ivtv_vbi_setup(itv);
-               }
-
-               /* assign program index info. Mask 7: select I/P/B, Num_req: 400 max */
-               ivtv_vapi_result(itv, data, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, 7, 400);
-               itv->pgm_info_offset = data[0];
-               itv->pgm_info_num = data[1];
-               itv->pgm_info_write_idx = 0;
-               itv->pgm_info_read_idx = 0;
-
-               IVTV_DEBUG_INFO("PGM Index at 0x%08x with %d elements\n",
-                               itv->pgm_info_offset, itv->pgm_info_num);
-
-               /* Setup API for Stream */
-               cx2341x_handler_setup(&itv->cxhdl);
-
-               /* mute if capturing radio */
-               if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
-                       ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
-                               1 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
-       }
-
-       /* Vsync Setup */
-       if (itv->has_cx23415 && !test_and_set_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
-               /* event notification (on) */
-               ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_ENC_VIM_RST, -1);
-               ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
-       }
-
-       if (atomic_read(&itv->capturing) == 0) {
-               /* Clear all Pending Interrupts */
-               ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
-
-               clear_bit(IVTV_F_I_EOS, &itv->i_flags);
-
-               cx2341x_handler_set_busy(&itv->cxhdl, 1);
-
-               /* Initialize Digitizer for Capture */
-               /* Avoid tinny audio problem - ensure audio clocks are going */
-               v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
-               /* Avoid unpredictable PCI bus hang - disable video clocks */
-               v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
-               ivtv_msleep_timeout(300, 0);
-               ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
-               v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
-       }
-
-       /* begin_capture */
-       if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype))
-       {
-               IVTV_DEBUG_WARN( "Error starting capture!\n");
-               return -EINVAL;
-       }
-
-       /* Start Passthrough */
-       if (enable_passthrough) {
-               ivtv_passthrough_mode(itv, 1);
-       }
-
-       if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
-               ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
-       else
-               ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
-
-       /* you're live! sit back and await interrupts :) */
-       atomic_inc(&itv->capturing);
-       return 0;
-}
-
-static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       struct ivtv *itv = s->itv;
-       int datatype;
-       u16 width;
-       u16 height;
-
-       if (s->vdev == NULL)
-               return -EINVAL;
-
-       IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
-
-       width = itv->cxhdl.width;
-       height = itv->cxhdl.height;
-
-       /* set audio mode to left/stereo  for dual/stereo mode. */
-       ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
-
-       /* set number of internal decoder buffers */
-       ivtv_vapi(itv, CX2341X_DEC_SET_DISPLAY_BUFFERS, 1, 0);
-
-       /* prebuffering */
-       ivtv_vapi(itv, CX2341X_DEC_SET_PREBUFFERING, 1, 1);
-
-       /* extract from user packets */
-       ivtv_vapi_result(itv, data, CX2341X_DEC_EXTRACT_VBI, 1, 1);
-       itv->vbi.dec_start = data[0];
-
-       IVTV_DEBUG_INFO("Decoder VBI RE-Insert start 0x%08x size 0x%08x\n",
-               itv->vbi.dec_start, data[1]);
-
-       /* set decoder source settings */
-       /* Data type: 0 = mpeg from host,
-          1 = yuv from encoder,
-          2 = yuv_from_host */
-       switch (s->type) {
-       case IVTV_DEC_STREAM_TYPE_YUV:
-               if (itv->output_mode == OUT_PASSTHROUGH) {
-                       datatype = 1;
-               } else {
-                       /* Fake size to avoid switching video standard */
-                       datatype = 2;
-                       width = 720;
-                       height = itv->is_out_50hz ? 576 : 480;
-               }
-               IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
-               break;
-       case IVTV_DEC_STREAM_TYPE_MPG:
-       default:
-               datatype = 0;
-               break;
-       }
-       if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
-                       width, height, itv->cxhdl.audio_properties)) {
-               IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
-       }
-
-       /* Decoder sometimes dies here, so wait a moment */
-       ivtv_msleep_timeout(10, 0);
-
-       /* Known failure point for firmware, so check */
-       return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream");
-}
-
-int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
-{
-       struct ivtv *itv = s->itv;
-       int rc;
-
-       if (s->vdev == NULL)
-               return -EINVAL;
-
-       if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
-               return 0;       /* already started */
-
-       IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset);
-
-       rc = ivtv_setup_v4l2_decode_stream(s);
-       if (rc < 0) {
-               clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
-               return rc;
-       }
-
-       /* set dma size to 65536 bytes */
-       ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);
-
-       /* Clear Streamoff */
-       clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-
-       /* Zero out decoder counters */
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[0]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[1]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[2]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[3]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]);
-       writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[3]);
-
-       /* turn on notification of dual/stereo mode change */
-       ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
-
-       /* start playback */
-       ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
-
-       /* Let things settle before we actually start */
-       ivtv_msleep_timeout(10, 0);
-
-       /* Clear the following Interrupt mask bits for decoding */
-       ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
-       IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
-
-       /* you're live! sit back and await interrupts :) */
-       atomic_inc(&itv->decoding);
-       return 0;
-}
-
-void ivtv_stop_all_captures(struct ivtv *itv)
-{
-       int i;
-
-       for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
-               struct ivtv_stream *s = &itv->streams[i];
-
-               if (s->vdev == NULL)
-                       continue;
-               if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
-                       ivtv_stop_v4l2_encode_stream(s, 0);
-               }
-       }
-}
-
-int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
-{
-       struct ivtv *itv = s->itv;
-       DECLARE_WAITQUEUE(wait, current);
-       int cap_type;
-       int stopmode;
-
-       if (s->vdev == NULL)
-               return -EINVAL;
-
-       /* This function assumes that you are allowed to stop the capture
-          and that we are actually capturing */
-
-       IVTV_DEBUG_INFO("Stop Capture\n");
-
-       if (s->type == IVTV_DEC_STREAM_TYPE_VOUT)
-               return 0;
-       if (atomic_read(&itv->capturing) == 0)
-               return 0;
-
-       switch (s->type) {
-       case IVTV_ENC_STREAM_TYPE_YUV:
-               cap_type = 1;
-               break;
-       case IVTV_ENC_STREAM_TYPE_PCM:
-               cap_type = 1;
-               break;
-       case IVTV_ENC_STREAM_TYPE_VBI:
-               cap_type = 1;
-               break;
-       case IVTV_ENC_STREAM_TYPE_MPG:
-       default:
-               cap_type = 0;
-               break;
-       }
-
-       /* Stop Capture Mode */
-       if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
-               stopmode = 0;
-       } else {
-               stopmode = 1;
-       }
-
-       /* end_capture */
-       /* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
-       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);
-
-       if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
-               if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
-                       /* only run these if we're shutting down the last cap */
-                       unsigned long duration;
-                       unsigned long then = jiffies;
-
-                       add_wait_queue(&itv->eos_waitq, &wait);
-
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       /* wait 2s for EOS interrupt */
-                       while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
-                               time_before(jiffies,
-                                           then + msecs_to_jiffies(2000))) {
-                               schedule_timeout(msecs_to_jiffies(10));
-                       }
-
-                       /* To convert jiffies to ms, we must multiply by 1000
-                        * and divide by HZ.  To avoid runtime division, we
-                        * convert this to multiplication by 1000/HZ.
-                        * Since integer division truncates, we get the best
-                        * accuracy if we do a rounding calculation of the constant.
-                        * Think of the case where HZ is 1024.
-                        */
-                       duration = ((1000 + HZ / 2) / HZ) * (jiffies - then);
-
-                       if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) {
-                               IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
-                               IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
-                       } else {
-                               IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
-                       }
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&itv->eos_waitq, &wait);
-                       set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
-               }
-
-               /* Handle any pending interrupts */
-               ivtv_msleep_timeout(100, 0);
-       }
-
-       atomic_dec(&itv->capturing);
-
-       /* Clear capture and no-read bits */
-       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
-
-       if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
-               ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
-
-       if (atomic_read(&itv->capturing) > 0) {
-               return 0;
-       }
-
-       cx2341x_handler_set_busy(&itv->cxhdl, 0);
-
-       /* Set the following Interrupt mask bits for capture */
-       ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
-       del_timer(&itv->dma_timer);
-
-       /* event notification (off) */
-       if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
-               /* type: 0 = refresh */
-               /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
-               ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
-               ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
-       }
-
-       /* Raw-passthrough is implied on start. Make sure it's stopped so
-          the encoder will re-initialize when next started */
-       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7);
-
-       wake_up(&s->waitq);
-
-       return 0;
-}
-
-int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
-{
-       static const struct v4l2_event ev = {
-               .type = V4L2_EVENT_EOS,
-       };
-       struct ivtv *itv = s->itv;
-
-       if (s->vdev == NULL)
-               return -EINVAL;
-
-       if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
-               return -EINVAL;
-
-       if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
-               return 0;
-
-       IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
-
-       /* Stop Decoder */
-       if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) {
-               u32 tmp = 0;
-
-               /* Wait until the decoder is no longer running */
-               if (pts) {
-                       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3,
-                               0, (u32)(pts & 0xffffffff), (u32)(pts >> 32));
-               }
-               while (1) {
-                       u32 data[CX2341X_MBOX_MAX_DATA];
-                       ivtv_vapi_result(itv, data, CX2341X_DEC_GET_XFER_INFO, 0);
-                       if (s->q_full.buffers + s->q_dma.buffers == 0) {
-                               if (tmp == data[3])
-                                       break;
-                               tmp = data[3];
-                       }
-                       if (ivtv_msleep_timeout(100, 1))
-                               break;
-               }
-       }
-       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0);
-
-       /* turn off notification of dual/stereo mode change */
-       ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
-
-       ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
-       del_timer(&itv->dma_timer);
-
-       clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
-       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
-       ivtv_flush_queues(s);
-
-       /* decoder needs time to settle */
-       ivtv_msleep_timeout(40, 0);
-
-       /* decrement decoding */
-       atomic_dec(&itv->decoding);
-
-       set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
-       wake_up(&itv->event_waitq);
-       v4l2_event_queue(s->vdev, &ev);
-
-       /* wake up wait queues */
-       wake_up(&s->waitq);
-
-       return 0;
-}
-
-int ivtv_passthrough_mode(struct ivtv *itv, int enable)
-{
-       struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV];
-       struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
-
-       if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL)
-               return -EINVAL;
-
-       IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");
-
-       /* Prevent others from starting/stopping streams while we
-          initiate/terminate passthrough mode */
-       if (enable) {
-               if (itv->output_mode == OUT_PASSTHROUGH) {
-                       return 0;
-               }
-               if (ivtv_set_output_mode(itv, OUT_PASSTHROUGH) != OUT_PASSTHROUGH)
-                       return -EBUSY;
-
-               /* Fully initialize stream, and then unflag init */
-               set_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
-               set_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
-
-               /* Setup YUV Decoder */
-               ivtv_setup_v4l2_decode_stream(dec_stream);
-
-               /* Start Decoder */
-               ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1);
-               atomic_inc(&itv->decoding);
-
-               /* Setup capture if not already done */
-               if (atomic_read(&itv->capturing) == 0) {
-                       cx2341x_handler_setup(&itv->cxhdl);
-                       cx2341x_handler_set_busy(&itv->cxhdl, 1);
-               }
-
-               /* Start Passthrough Mode */
-               ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, 2, 11);
-               atomic_inc(&itv->capturing);
-               return 0;
-       }
-
-       if (itv->output_mode != OUT_PASSTHROUGH)
-               return 0;
-
-       /* Stop Passthrough Mode */
-       ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 11);
-       ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, 1, 0, 0);
-
-       atomic_dec(&itv->capturing);
-       atomic_dec(&itv->decoding);
-       clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
-       clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
-       itv->output_mode = OUT_NONE;
-       if (atomic_read(&itv->capturing) == 0)
-               cx2341x_handler_set_busy(&itv->cxhdl, 0);
-
-       return 0;
-}
diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h
deleted file mode 100644 (file)
index a653a51..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-    init/start/stop/exit stream functions
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_STREAMS_H
-#define IVTV_STREAMS_H
-
-int ivtv_streams_setup(struct ivtv *itv);
-int ivtv_streams_register(struct ivtv *itv);
-void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
-
-/* Capture related */
-int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
-int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end);
-int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset);
-int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts);
-
-void ivtv_stop_all_captures(struct ivtv *itv);
-int ivtv_passthrough_mode(struct ivtv *itv, int enable);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c
deleted file mode 100644 (file)
index 7338cb2..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
-    User DMA
-
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-udma.h"
-
-void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size)
-{
-       dma_page->uaddr = first & PAGE_MASK;
-       dma_page->offset = first & ~PAGE_MASK;
-       dma_page->tail = 1 + ((first+size-1) & ~PAGE_MASK);
-       dma_page->first = (first & PAGE_MASK) >> PAGE_SHIFT;
-       dma_page->last = ((first+size-1) & PAGE_MASK) >> PAGE_SHIFT;
-       dma_page->page_count = dma_page->last - dma_page->first + 1;
-       if (dma_page->page_count == 1) dma_page->tail -= dma_page->offset;
-}
-
-int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset)
-{
-       int i, offset;
-       unsigned long flags;
-
-       if (map_offset < 0)
-               return map_offset;
-
-       offset = dma_page->offset;
-
-       /* Fill SG Array with new values */
-       for (i = 0; i < dma_page->page_count; i++) {
-               unsigned int len = (i == dma_page->page_count - 1) ?
-                       dma_page->tail : PAGE_SIZE - offset;
-
-               if (PageHighMem(dma->map[map_offset])) {
-                       void *src;
-
-                       if (dma->bouncemap[map_offset] == NULL)
-                               dma->bouncemap[map_offset] = alloc_page(GFP_KERNEL);
-                       if (dma->bouncemap[map_offset] == NULL)
-                               return -1;
-                       local_irq_save(flags);
-                       src = kmap_atomic(dma->map[map_offset]) + offset;
-                       memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
-                       kunmap_atomic(src);
-                       local_irq_restore(flags);
-                       sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset);
-               }
-               else {
-                       sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset);
-               }
-               offset = 0;
-               map_offset++;
-       }
-       return map_offset;
-}
-
-void ivtv_udma_fill_sg_array (struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split) {
-       int i;
-       struct scatterlist *sg;
-
-       for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) {
-               dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg));
-               dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg));
-               dma->SGarray[i].dst = cpu_to_le32(buffer_offset);
-               buffer_offset += sg_dma_len(sg);
-
-               split -= sg_dma_len(sg);
-               if (split == 0)
-                       buffer_offset = buffer_offset_2;
-       }
-}
-
-/* User DMA Buffers */
-void ivtv_udma_alloc(struct ivtv *itv)
-{
-       if (itv->udma.SG_handle == 0) {
-               /* Map DMA Page Array Buffer */
-               itv->udma.SG_handle = pci_map_single(itv->pdev, itv->udma.SGarray,
-                          sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
-               ivtv_udma_sync_for_cpu(itv);
-       }
-}
-
-int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
-                      void __user *userbuf, int size_in_bytes)
-{
-       struct ivtv_dma_page_info user_dma;
-       struct ivtv_user_dma *dma = &itv->udma;
-       int i, err;
-
-       IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr);
-
-       /* Still in USE */
-       if (dma->SG_length || dma->page_count) {
-               IVTV_DEBUG_WARN("ivtv_udma_setup: SG_length %d page_count %d still full?\n",
-                          dma->SG_length, dma->page_count);
-               return -EBUSY;
-       }
-
-       ivtv_udma_get_page_info(&user_dma, (unsigned long)userbuf, size_in_bytes);
-
-       if (user_dma.page_count <= 0) {
-               IVTV_DEBUG_WARN("ivtv_udma_setup: Error %d page_count from %d bytes %d offset\n",
-                          user_dma.page_count, size_in_bytes, user_dma.offset);
-               return -EINVAL;
-       }
-
-       /* Get user pages for DMA Xfer */
-       down_read(&current->mm->mmap_sem);
-       err = get_user_pages(current, current->mm,
-                       user_dma.uaddr, user_dma.page_count, 0, 1, dma->map, NULL);
-       up_read(&current->mm->mmap_sem);
-
-       if (user_dma.page_count != err) {
-               IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
-                          err, user_dma.page_count);
-               if (err >= 0) {
-                       for (i = 0; i < err; i++)
-                               put_page(dma->map[i]);
-                       return -EINVAL;
-               }
-               return err;
-       }
-
-       dma->page_count = user_dma.page_count;
-
-       /* Fill SG List with new values */
-       if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {
-               for (i = 0; i < dma->page_count; i++) {
-                       put_page(dma->map[i]);
-               }
-               dma->page_count = 0;
-               return -ENOMEM;
-       }
-
-       /* Map SG List */
-       dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
-
-       /* Fill SG Array with new values */
-       ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);
-
-       /* Tag SG Array with Interrupt Bit */
-       dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
-
-       ivtv_udma_sync_for_device(itv);
-       return dma->page_count;
-}
-
-void ivtv_udma_unmap(struct ivtv *itv)
-{
-       struct ivtv_user_dma *dma = &itv->udma;
-       int i;
-
-       IVTV_DEBUG_INFO("ivtv_unmap_user_dma\n");
-
-       /* Nothing to free */
-       if (dma->page_count == 0)
-               return;
-
-       /* Unmap Scatterlist */
-       if (dma->SG_length) {
-               pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
-               dma->SG_length = 0;
-       }
-       /* sync DMA */
-       ivtv_udma_sync_for_cpu(itv);
-
-       /* Release User Pages */
-       for (i = 0; i < dma->page_count; i++) {
-               put_page(dma->map[i]);
-       }
-       dma->page_count = 0;
-}
-
-void ivtv_udma_free(struct ivtv *itv)
-{
-       int i;
-
-       /* Unmap SG Array */
-       if (itv->udma.SG_handle) {
-               pci_unmap_single(itv->pdev, itv->udma.SG_handle,
-                        sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
-       }
-
-       /* Unmap Scatterlist */
-       if (itv->udma.SG_length) {
-               pci_unmap_sg(itv->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE);
-       }
-
-       for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) {
-               if (itv->udma.bouncemap[i])
-                       __free_page(itv->udma.bouncemap[i]);
-       }
-}
-
-void ivtv_udma_start(struct ivtv *itv)
-{
-       IVTV_DEBUG_DMA("start UDMA\n");
-       write_reg(itv->udma.SG_handle, IVTV_REG_DECDMAADDR);
-       write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
-       set_bit(IVTV_F_I_DMA, &itv->i_flags);
-       set_bit(IVTV_F_I_UDMA, &itv->i_flags);
-       clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags);
-}
-
-void ivtv_udma_prepare(struct ivtv *itv)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&itv->dma_reg_lock, flags);
-       if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
-               ivtv_udma_start(itv);
-       else
-               set_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags);
-       spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
-}
diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h
deleted file mode 100644 (file)
index ee3c9ef..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-    Copyright (C) 2006-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_UDMA_H
-#define IVTV_UDMA_H
-
-/* User DMA functions */
-void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size);
-int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset);
-void ivtv_udma_fill_sg_array(struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split);
-int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
-                      void __user *userbuf, int size_in_bytes);
-void ivtv_udma_unmap(struct ivtv *itv);
-void ivtv_udma_free(struct ivtv *itv);
-void ivtv_udma_alloc(struct ivtv *itv);
-void ivtv_udma_prepare(struct ivtv *itv);
-void ivtv_udma_start(struct ivtv *itv);
-
-static inline void ivtv_udma_sync_for_device(struct ivtv *itv)
-{
-       pci_dma_sync_single_for_device(itv->pdev, itv->udma.SG_handle,
-               sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
-}
-
-static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv)
-{
-       pci_dma_sync_single_for_cpu(itv->pdev, itv->udma.SG_handle,
-               sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
-}
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
deleted file mode 100644 (file)
index 293db80..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
-    Vertical Blank Interval support functions
-    Copyright (C) 2004-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "ivtv-driver.h"
-#include "ivtv-i2c.h"
-#include "ivtv-ioctl.h"
-#include "ivtv-queue.h"
-#include "ivtv-cards.h"
-#include "ivtv-vbi.h"
-
-static void ivtv_set_vps(struct ivtv *itv, int enabled)
-{
-       struct v4l2_sliced_vbi_data data;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return;
-       data.id = V4L2_SLICED_VPS;
-       data.field = 0;
-       data.line = enabled ? 16 : 0;
-       data.data[2] = itv->vbi.vps_payload.data[0];
-       data.data[8] = itv->vbi.vps_payload.data[1];
-       data.data[9] = itv->vbi.vps_payload.data[2];
-       data.data[10] = itv->vbi.vps_payload.data[3];
-       data.data[11] = itv->vbi.vps_payload.data[4];
-       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
-}
-
-static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
-{
-       struct v4l2_sliced_vbi_data data;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return;
-       data.id = V4L2_SLICED_CAPTION_525;
-       data.field = 0;
-       data.line = (mode & 1) ? 21 : 0;
-       data.data[0] = cc->odd[0];
-       data.data[1] = cc->odd[1];
-       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
-       data.field = 1;
-       data.line = (mode & 2) ? 21 : 0;
-       data.data[0] = cc->even[0];
-       data.data[1] = cc->even[1];
-       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
-}
-
-static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
-{
-       struct v4l2_sliced_vbi_data data;
-
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
-               return;
-       /* When using a 50 Hz system, always turn on the
-          wide screen signal with 4x3 ratio as the default.
-          Turning this signal on and off can confuse certain
-          TVs. As far as I can tell there is no reason not to
-          transmit this signal. */
-       if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
-               enabled = 1;
-               mode = 0x08;  /* 4x3 full format */
-       }
-       data.id = V4L2_SLICED_WSS_625;
-       data.field = 0;
-       data.line = enabled ? 23 : 0;
-       data.data[0] = mode & 0xff;
-       data.data[1] = (mode >> 8) & 0xff;
-       ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
-}
-
-static int odd_parity(u8 c)
-{
-       c ^= (c >> 4);
-       c ^= (c >> 2);
-       c ^= (c >> 1);
-
-       return c & 1;
-}
-
-static void ivtv_write_vbi_line(struct ivtv *itv,
-                               const struct v4l2_sliced_vbi_data *d,
-                               struct vbi_cc *cc, int *found_cc)
-{
-       struct vbi_info *vi = &itv->vbi;
-
-       if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
-               if (d->field) {
-                       cc->even[0] = d->data[0];
-                       cc->even[1] = d->data[1];
-               } else {
-                       cc->odd[0] = d->data[0];
-                       cc->odd[1] = d->data[1];
-               }
-               *found_cc = 1;
-       } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
-               struct vbi_vps vps;
-
-               vps.data[0] = d->data[2];
-               vps.data[1] = d->data[8];
-               vps.data[2] = d->data[9];
-               vps.data[3] = d->data[10];
-               vps.data[4] = d->data[11];
-               if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
-                       vi->vps_payload = vps;
-                       set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
-               }
-       } else if (d->id == V4L2_SLICED_WSS_625 &&
-                  d->line == 23 && d->field == 0) {
-               int wss = d->data[0] | d->data[1] << 8;
-
-               if (vi->wss_payload != wss) {
-                       vi->wss_payload = wss;
-                       set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
-               }
-       }
-}
-
-static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
-{
-       struct vbi_info *vi = &itv->vbi;
-
-       if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
-               memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
-                      sizeof(struct vbi_cc));
-               vi->cc_payload_idx++;
-               set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
-       }
-}
-
-static void ivtv_write_vbi(struct ivtv *itv,
-                          const struct v4l2_sliced_vbi_data *sliced,
-                          size_t cnt)
-{
-       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
-       int found_cc = 0;
-       size_t i;
-
-       for (i = 0; i < cnt; i++)
-               ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
-
-       if (found_cc)
-               ivtv_write_vbi_cc_lines(itv, &cc);
-}
-
-ssize_t
-ivtv_write_vbi_from_user(struct ivtv *itv,
-                        const struct v4l2_sliced_vbi_data __user *sliced,
-                        size_t cnt)
-{
-       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
-       int found_cc = 0;
-       size_t i;
-       struct v4l2_sliced_vbi_data d;
-       ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
-
-       for (i = 0; i < cnt; i++) {
-               if (copy_from_user(&d, sliced + i,
-                                  sizeof(struct v4l2_sliced_vbi_data))) {
-                       ret = -EFAULT;
-                       break;
-               }
-               ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
-       }
-
-       if (found_cc)
-               ivtv_write_vbi_cc_lines(itv, &cc);
-
-       return ret;
-}
-
-static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
-{
-       int line = 0;
-       int i;
-       u32 linemask[2] = { 0, 0 };
-       unsigned short size;
-       static const u8 mpeg_hdr_data[] = {
-               0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
-               0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
-               0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
-               0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
-       };
-       const int sd = sizeof(mpeg_hdr_data);   /* start of vbi data */
-       int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
-       u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
-
-       for (i = 0; i < lines; i++) {
-               int f, l;
-
-               if (itv->vbi.sliced_data[i].id == 0)
-                       continue;
-
-               l = itv->vbi.sliced_data[i].line - 6;
-               f = itv->vbi.sliced_data[i].field;
-               if (f)
-                       l += 18;
-               if (l < 32)
-                       linemask[0] |= (1 << l);
-               else
-                       linemask[1] |= (1 << (l - 32));
-               dst[sd + 12 + line * 43] =
-                       ivtv_service2vbi(itv->vbi.sliced_data[i].id);
-               memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
-               line++;
-       }
-       memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
-       if (line == 36) {
-               /* All lines are used, so there is no space for the linemask
-                  (the max size of the VBI data is 36 * 43 + 4 bytes).
-                  So in this case we use the magic number 'ITV0'. */
-               memcpy(dst + sd, "ITV0", 4);
-               memcpy(dst + sd + 4, dst + sd + 12, line * 43);
-               size = 4 + ((43 * line + 3) & ~3);
-       } else {
-               memcpy(dst + sd, "itv0", 4);
-               cpu_to_le32s(&linemask[0]);
-               cpu_to_le32s(&linemask[1]);
-               memcpy(dst + sd + 4, &linemask[0], 8);
-               size = 12 + ((43 * line + 3) & ~3);
-       }
-       dst[4+16] = (size + 10) >> 8;
-       dst[5+16] = (size + 10) & 0xff;
-       dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
-       dst[10+16] = (pts_stamp >> 22) & 0xff;
-       dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
-       dst[12+16] = (pts_stamp >> 7) & 0xff;
-       dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
-       itv->vbi.sliced_mpeg_size[idx] = sd + size;
-}
-
-static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
-{
-       u32 linemask[2];
-       int i, l, id2;
-       int line = 0;
-
-       if (!memcmp(p, "itv0", 4)) {
-               memcpy(linemask, p + 4, 8);
-               p += 12;
-       } else if (!memcmp(p, "ITV0", 4)) {
-               linemask[0] = 0xffffffff;
-               linemask[1] = 0xf;
-               p += 4;
-       } else {
-               /* unknown VBI data, convert to empty VBI frame */
-               linemask[0] = linemask[1] = 0;
-       }
-       for (i = 0; i < 36; i++) {
-               int err = 0;
-
-               if (i < 32 && !(linemask[0] & (1 << i)))
-                       continue;
-               if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
-                       continue;
-               id2 = *p & 0xf;
-               switch (id2) {
-               case IVTV_SLICED_TYPE_TELETEXT_B:
-                       id2 = V4L2_SLICED_TELETEXT_B;
-                       break;
-               case IVTV_SLICED_TYPE_CAPTION_525:
-                       id2 = V4L2_SLICED_CAPTION_525;
-                       err = !odd_parity(p[1]) || !odd_parity(p[2]);
-                       break;
-               case IVTV_SLICED_TYPE_VPS:
-                       id2 = V4L2_SLICED_VPS;
-                       break;
-               case IVTV_SLICED_TYPE_WSS_625:
-                       id2 = V4L2_SLICED_WSS_625;
-                       break;
-               default:
-                       id2 = 0;
-                       break;
-               }
-               if (err == 0) {
-                       l = (i < 18) ? i + 6 : i - 18 + 6;
-                       itv->vbi.sliced_dec_data[line].line = l;
-                       itv->vbi.sliced_dec_data[line].field = i >= 18;
-                       itv->vbi.sliced_dec_data[line].id = id2;
-                       memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
-                       line++;
-               }
-               p += 43;
-       }
-       while (line < 36) {
-               itv->vbi.sliced_dec_data[line].id = 0;
-               itv->vbi.sliced_dec_data[line].line = 0;
-               itv->vbi.sliced_dec_data[line].field = 0;
-               line++;
-       }
-       return line * sizeof(itv->vbi.sliced_dec_data[0]);
-}
-
-/* Compress raw VBI format, removes leading SAV codes and surplus space after the
-   field.
-   Returns new compressed size. */
-static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
-{
-       u32 line_size = itv->vbi.raw_decoder_line_size;
-       u32 lines = itv->vbi.count;
-       u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
-       u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
-       u8 *q = buf;
-       u8 *p;
-       int i;
-
-       for (i = 0; i < lines; i++) {
-               p = buf + i * line_size;
-
-               /* Look for SAV code */
-               if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
-                       break;
-               }
-               memcpy(q, p + 4, line_size - 4);
-               q += line_size - 4;
-       }
-       return lines * (line_size - 4);
-}
-
-
-/* Compressed VBI format, all found sliced blocks put next to one another
-   Returns new compressed size */
-static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
-{
-       u32 line_size = itv->vbi.sliced_decoder_line_size;
-       struct v4l2_decode_vbi_line vbi;
-       int i;
-       unsigned lines = 0;
-
-       /* find the first valid line */
-       for (i = 0; i < size; i++, buf++) {
-               if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
-                       break;
-       }
-
-       size -= i;
-       if (size < line_size) {
-               return line;
-       }
-       for (i = 0; i < size / line_size; i++) {
-               u8 *p = buf + i * line_size;
-
-               /* Look for SAV code  */
-               if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
-                       continue;
-               }
-               vbi.p = p + 4;
-               v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
-               if (vbi.type && !(lines & (1 << vbi.line))) {
-                       lines |= 1 << vbi.line;
-                       itv->vbi.sliced_data[line].id = vbi.type;
-                       itv->vbi.sliced_data[line].field = vbi.is_second_field;
-                       itv->vbi.sliced_data[line].line = vbi.line;
-                       memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
-                       line++;
-               }
-       }
-       return line;
-}
-
-void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
-                          u64 pts_stamp, int streamtype)
-{
-       u8 *p = (u8 *) buf->buf;
-       u32 size = buf->bytesused;
-       int y;
-
-       /* Raw VBI data */
-       if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
-               u8 type;
-
-               ivtv_buf_swap(buf);
-
-               type = p[3];
-
-               size = buf->bytesused = compress_raw_buf(itv, p, size);
-
-               /* second field of the frame? */
-               if (type == itv->vbi.raw_decoder_sav_even_field) {
-                       /* Dirty hack needed for backwards
-                          compatibility of old VBI software. */
-                       p += size - 4;
-                       memcpy(p, &itv->vbi.frame, 4);
-                       itv->vbi.frame++;
-               }
-               return;
-       }
-
-       /* Sliced VBI data with data insertion */
-       if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
-               int lines;
-
-               ivtv_buf_swap(buf);
-
-               /* first field */
-               lines = compress_sliced_buf(itv, 0, p, size / 2,
-                       itv->vbi.sliced_decoder_sav_odd_field);
-               /* second field */
-               /* experimentation shows that the second half does not always begin
-                  at the exact address. So start a bit earlier (hence 32). */
-               lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
-                       itv->vbi.sliced_decoder_sav_even_field);
-               /* always return at least one empty line */
-               if (lines == 0) {
-                       itv->vbi.sliced_data[0].id = 0;
-                       itv->vbi.sliced_data[0].line = 0;
-                       itv->vbi.sliced_data[0].field = 0;
-                       lines = 1;
-               }
-               buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
-               memcpy(p, &itv->vbi.sliced_data[0], size);
-
-               if (itv->vbi.insert_mpeg) {
-                       copy_vbi_data(itv, lines, pts_stamp);
-               }
-               itv->vbi.frame++;
-               return;
-       }
-
-       /* Sliced VBI re-inserted from an MPEG stream */
-       if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
-               /* If the size is not 4-byte aligned, then the starting address
-                  for the swapping is also shifted. After swapping the data the
-                  real start address of the VBI data is exactly 4 bytes after the
-                  original start. It's a bit fiddly but it works like a charm.
-                  Non-4-byte alignment happens when an lseek is done on the input
-                  mpeg file to a non-4-byte aligned position. So on arrival here
-                  the VBI data is also non-4-byte aligned. */
-               int offset = size & 3;
-               int cnt;
-
-               if (offset) {
-                       p += 4 - offset;
-               }
-               /* Swap Buffer */
-               for (y = 0; y < size; y += 4) {
-                      swab32s((u32 *)(p + y));
-               }
-
-               cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
-               memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
-               buf->bytesused = cnt;
-
-               ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
-                              cnt / sizeof(itv->vbi.sliced_dec_data[0]));
-               return;
-       }
-}
-
-void ivtv_disable_cc(struct ivtv *itv)
-{
-       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
-
-       clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
-       ivtv_set_cc(itv, 0, &cc);
-       itv->vbi.cc_payload_idx = 0;
-}
-
-
-void ivtv_vbi_work_handler(struct ivtv *itv)
-{
-       struct vbi_info *vi = &itv->vbi;
-       struct v4l2_sliced_vbi_data data;
-       struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
-
-       /* Lock */
-       if (itv->output_mode == OUT_PASSTHROUGH) {
-               if (itv->is_50hz) {
-                       data.id = V4L2_SLICED_WSS_625;
-                       data.field = 0;
-
-                       if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
-                               ivtv_set_wss(itv, 1, data.data[0] & 0xf);
-                               vi->wss_missing_cnt = 0;
-                       } else if (vi->wss_missing_cnt == 4) {
-                               ivtv_set_wss(itv, 1, 0x8);  /* 4x3 full format */
-                       } else {
-                               vi->wss_missing_cnt++;
-                       }
-               }
-               else {
-                       int mode = 0;
-
-                       data.id = V4L2_SLICED_CAPTION_525;
-                       data.field = 0;
-                       if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
-                               mode |= 1;
-                               cc.odd[0] = data.data[0];
-                               cc.odd[1] = data.data[1];
-                       }
-                       data.field = 1;
-                       if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
-                               mode |= 2;
-                               cc.even[0] = data.data[0];
-                               cc.even[1] = data.data[1];
-                       }
-                       if (mode) {
-                               vi->cc_missing_cnt = 0;
-                               ivtv_set_cc(itv, mode, &cc);
-                       } else if (vi->cc_missing_cnt == 4) {
-                               ivtv_set_cc(itv, 0, &cc);
-                       } else {
-                               vi->cc_missing_cnt++;
-                       }
-               }
-               return;
-       }
-
-       if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
-               ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
-       }
-
-       if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
-               if (vi->cc_payload_idx == 0) {
-                       clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
-                       ivtv_set_cc(itv, 3, &cc);
-               }
-               while (vi->cc_payload_idx) {
-                       cc = vi->cc_payload[0];
-
-                       memcpy(vi->cc_payload, vi->cc_payload + 1,
-                                       sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
-                       vi->cc_payload_idx--;
-                       if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
-                               continue;
-
-                       ivtv_set_cc(itv, 3, &cc);
-                       break;
-               }
-       }
-
-       if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
-               ivtv_set_vps(itv, 1);
-       }
-}
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h
deleted file mode 100644 (file)
index 166dd0b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-    Vertical Blank Interval support functions
-    Copyright (C) 2004-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_VBI_H
-#define IVTV_VBI_H
-
-ssize_t
-ivtv_write_vbi_from_user(struct ivtv *itv,
-                        const struct v4l2_sliced_vbi_data __user *sliced,
-                        size_t count);
-void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
-                          u64 pts_stamp, int streamtype);
-int ivtv_used_line(struct ivtv *itv, int line, int field);
-void ivtv_disable_cc(struct ivtv *itv);
-void ivtv_set_vbi(unsigned long arg);
-void ivtv_vbi_work_handler(struct ivtv *itv);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h
deleted file mode 100644 (file)
index a20f346..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-    ivtv driver version information
-    Copyright (C) 2005-2007  Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_VERSION_H
-#define IVTV_VERSION_H
-
-#define IVTV_DRIVER_NAME "ivtv"
-#define IVTV_VERSION "1.4.3"
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c
deleted file mode 100644 (file)
index 2ad65eb..0000000
+++ /dev/null
@@ -1,1296 +0,0 @@
-/*
-    yuv support
-
-    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    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 "ivtv-driver.h"
-#include "ivtv-udma.h"
-#include "ivtv-yuv.h"
-
-/* YUV buffer offsets */
-const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
-       0x001a8600,
-       0x00240400,
-       0x002d8200,
-       0x00370000,
-       0x00029000,
-       0x000C0E00,
-       0x006B0400,
-       0x00748200
-};
-
-static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
-                                 struct ivtv_dma_frame *args)
-{
-       struct ivtv_dma_page_info y_dma;
-       struct ivtv_dma_page_info uv_dma;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       u8 frame = yi->draw_frame;
-       struct yuv_frame_info *f = &yi->new_frame_info[frame];
-       int i;
-       int y_pages, uv_pages;
-       unsigned long y_buffer_offset, uv_buffer_offset;
-       int y_decode_height, uv_decode_height, y_size;
-
-       y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
-       uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
-
-       y_decode_height = uv_decode_height = f->src_h + f->src_y;
-
-       if (f->offset_y)
-               y_buffer_offset += 720 * 16;
-
-       if (y_decode_height & 15)
-               y_decode_height = (y_decode_height + 16) & ~15;
-
-       if (uv_decode_height & 31)
-               uv_decode_height = (uv_decode_height + 32) & ~31;
-
-       y_size = 720 * y_decode_height;
-
-       /* Still in USE */
-       if (dma->SG_length || dma->page_count) {
-               IVTV_DEBUG_WARN
-                   ("prep_user_dma: SG_length %d page_count %d still full?\n",
-                    dma->SG_length, dma->page_count);
-               return -EBUSY;
-       }
-
-       ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
-       ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
-
-       /* Get user pages for DMA Xfer */
-       down_read(&current->mm->mmap_sem);
-       y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
-       uv_pages = 0; /* silence gcc. value is set and consumed only if: */
-       if (y_pages == y_dma.page_count) {
-               uv_pages = get_user_pages(current, current->mm,
-                                         uv_dma.uaddr, uv_dma.page_count, 0, 1,
-                                         &dma->map[y_pages], NULL);
-       }
-       up_read(&current->mm->mmap_sem);
-
-       if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
-               int rc = -EFAULT;
-
-               if (y_pages == y_dma.page_count) {
-                       IVTV_DEBUG_WARN
-                               ("failed to map uv user pages, returned %d "
-                                "expecting %d\n", uv_pages, uv_dma.page_count);
-
-                       if (uv_pages >= 0) {
-                               for (i = 0; i < uv_pages; i++)
-                                       put_page(dma->map[y_pages + i]);
-                               rc = -EFAULT;
-                       } else {
-                               rc = uv_pages;
-                       }
-               } else {
-                       IVTV_DEBUG_WARN
-                               ("failed to map y user pages, returned %d "
-                                "expecting %d\n", y_pages, y_dma.page_count);
-               }
-               if (y_pages >= 0) {
-                       for (i = 0; i < y_pages; i++)
-                               put_page(dma->map[i]);
-                       /*
-                        * Inherit the -EFAULT from rc's
-                        * initialization, but allow it to be
-                        * overriden by uv_pages above if it was an
-                        * actual errno.
-                        */
-               } else {
-                       rc = y_pages;
-               }
-               return rc;
-       }
-
-       dma->page_count = y_pages + uv_pages;
-
-       /* Fill & map SG List */
-       if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
-               IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
-               for (i = 0; i < dma->page_count; i++) {
-                       put_page(dma->map[i]);
-               }
-               dma->page_count = 0;
-               return -ENOMEM;
-       }
-       dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
-
-       /* Fill SG Array with new values */
-       ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size);
-
-       /* If we've offset the y plane, ensure top area is blanked */
-       if (f->offset_y && yi->blanking_dmaptr) {
-               dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
-               dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
-               dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
-               dma->SG_length++;
-       }
-
-       /* Tag SG Array with Interrupt Bit */
-       dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
-
-       ivtv_udma_sync_for_device(itv);
-       return 0;
-}
-
-/* We rely on a table held in the firmware - Quick check. */
-int ivtv_yuv_filter_check(struct ivtv *itv)
-{
-       int i, y, uv;
-
-       for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
-               if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
-                   (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
-                       IVTV_WARN ("YUV filter table not found in firmware.\n");
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
-{
-       u32 i, line;
-
-       /* If any filter is -1, then don't update it */
-       if (h_filter > -1) {
-               if (h_filter > 4)
-                       h_filter = 4;
-               i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
-               for (line = 0; line < 16; line++) {
-                       write_reg(read_dec(i), 0x02804);
-                       write_reg(read_dec(i), 0x0281c);
-                       i += 4;
-                       write_reg(read_dec(i), 0x02808);
-                       write_reg(read_dec(i), 0x02820);
-                       i += 4;
-                       write_reg(read_dec(i), 0x0280c);
-                       write_reg(read_dec(i), 0x02824);
-                       i += 4;
-                       write_reg(read_dec(i), 0x02810);
-                       write_reg(read_dec(i), 0x02828);
-                       i += 4;
-                       write_reg(read_dec(i), 0x02814);
-                       write_reg(read_dec(i), 0x0282c);
-                       i += 8;
-                       write_reg(0, 0x02818);
-                       write_reg(0, 0x02830);
-               }
-               IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
-       }
-
-       if (v_filter_1 > -1) {
-               if (v_filter_1 > 4)
-                       v_filter_1 = 4;
-               i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
-               for (line = 0; line < 16; line++) {
-                       write_reg(read_dec(i), 0x02900);
-                       i += 4;
-                       write_reg(read_dec(i), 0x02904);
-                       i += 8;
-                       write_reg(0, 0x02908);
-               }
-               IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
-       }
-
-       if (v_filter_2 > -1) {
-               if (v_filter_2 > 4)
-                       v_filter_2 = 4;
-               i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
-               for (line = 0; line < 16; line++) {
-                       write_reg(read_dec(i), 0x0290c);
-                       i += 4;
-                       write_reg(read_dec(i), 0x02910);
-                       i += 8;
-                       write_reg(0, 0x02914);
-               }
-               IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
-       }
-}
-
-static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       u32 reg_2834, reg_2838, reg_283c;
-       u32 reg_2844, reg_2854, reg_285c;
-       u32 reg_2864, reg_2874, reg_2890;
-       u32 reg_2870, reg_2870_base, reg_2870_offset;
-       int x_cutoff;
-       int h_filter;
-       u32 master_width;
-
-       IVTV_DEBUG_WARN
-           ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
-            f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
-
-       /* How wide is the src image */
-       x_cutoff = f->src_w + f->src_x;
-
-       /* Set the display width */
-       reg_2834 = f->dst_w;
-       reg_2838 = reg_2834;
-
-       /* Set the display position */
-       reg_2890 = f->dst_x;
-
-       /* Index into the image horizontally */
-       reg_2870 = 0;
-
-       /* 2870 is normally fudged to align video coords with osd coords.
-          If running full screen, it causes an unwanted left shift
-          Remove the fudge if we almost fill the screen.
-          Gradually adjust the offset to avoid the video 'snapping'
-          left/right if it gets dragged through this region.
-          Only do this if osd is full width. */
-       if (f->vis_w == 720) {
-               if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
-                       reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
-               else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
-                       reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
-
-               if (f->dst_w >= f->src_w)
-                       reg_2870 = reg_2870 << 16 | reg_2870;
-               else
-                       reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
-       }
-
-       if (f->dst_w < f->src_w)
-               reg_2870 = 0x000d000e - reg_2870;
-       else
-               reg_2870 = 0x0012000e - reg_2870;
-
-       /* We're also using 2870 to shift the image left (src_x & negative dst_x) */
-       reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
-
-       if (f->dst_w >= f->src_w) {
-               x_cutoff &= ~1;
-               master_width = (f->src_w * 0x00200000) / (f->dst_w);
-               if (master_width * f->dst_w != f->src_w * 0x00200000)
-                       master_width++;
-               reg_2834 = (reg_2834 << 16) | x_cutoff;
-               reg_2838 = (reg_2838 << 16) | x_cutoff;
-               reg_283c = master_width >> 2;
-               reg_2844 = master_width >> 2;
-               reg_2854 = master_width;
-               reg_285c = master_width >> 1;
-               reg_2864 = master_width >> 1;
-
-               /* We also need to factor in the scaling
-                  (src_w - dst_w) / (src_w / 4) */
-               if (f->dst_w > f->src_w)
-                       reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
-               else
-                       reg_2870_base = 0;
-
-               reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
-               reg_2874 = 0;
-       } else if (f->dst_w < f->src_w / 2) {
-               master_width = (f->src_w * 0x00080000) / f->dst_w;
-               if (master_width * f->dst_w != f->src_w * 0x00080000)
-                       master_width++;
-               reg_2834 = (reg_2834 << 16) | x_cutoff;
-               reg_2838 = (reg_2838 << 16) | x_cutoff;
-               reg_283c = master_width >> 2;
-               reg_2844 = master_width >> 1;
-               reg_2854 = master_width;
-               reg_285c = master_width >> 1;
-               reg_2864 = master_width >> 1;
-               reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
-               reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
-               reg_2874 = 0x00000012;
-       } else {
-               master_width = (f->src_w * 0x00100000) / f->dst_w;
-               if (master_width * f->dst_w != f->src_w * 0x00100000)
-                       master_width++;
-               reg_2834 = (reg_2834 << 16) | x_cutoff;
-               reg_2838 = (reg_2838 << 16) | x_cutoff;
-               reg_283c = master_width >> 2;
-               reg_2844 = master_width >> 1;
-               reg_2854 = master_width;
-               reg_285c = master_width >> 1;
-               reg_2864 = master_width >> 1;
-               reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
-               reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
-               reg_2874 = 0x00000001;
-       }
-
-       /* Select the horizontal filter */
-       if (f->src_w == f->dst_w) {
-               /* An exact size match uses filter 0 */
-               h_filter = 0;
-       } else {
-               /* Figure out which filter to use */
-               h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
-               h_filter = (h_filter >> 1) + (h_filter & 1);
-               /* Only an exact size match can use filter 0 */
-               h_filter += !h_filter;
-       }
-
-       write_reg(reg_2834, 0x02834);
-       write_reg(reg_2838, 0x02838);
-       IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
-                      yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
-
-       write_reg(reg_283c, 0x0283c);
-       write_reg(reg_2844, 0x02844);
-
-       IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
-                      yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
-
-       write_reg(0x00080514, 0x02840);
-       write_reg(0x00100514, 0x02848);
-       IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
-                      yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
-
-       write_reg(reg_2854, 0x02854);
-       IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
-                      yi->reg_2854, reg_2854);
-
-       write_reg(reg_285c, 0x0285c);
-       write_reg(reg_2864, 0x02864);
-       IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
-                      yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
-
-       write_reg(reg_2874, 0x02874);
-       IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
-                      yi->reg_2874, reg_2874);
-
-       write_reg(reg_2870, 0x02870);
-       IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
-                      yi->reg_2870, reg_2870);
-
-       write_reg(reg_2890, 0x02890);
-       IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
-                      yi->reg_2890, reg_2890);
-
-       /* Only update the filter if we really need to */
-       if (h_filter != yi->h_filter) {
-               ivtv_yuv_filter(itv, h_filter, -1, -1);
-               yi->h_filter = h_filter;
-       }
-}
-
-static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       u32 master_height;
-       u32 reg_2918, reg_291c, reg_2920, reg_2928;
-       u32 reg_2930, reg_2934, reg_293c;
-       u32 reg_2940, reg_2944, reg_294c;
-       u32 reg_2950, reg_2954, reg_2958, reg_295c;
-       u32 reg_2960, reg_2964, reg_2968, reg_296c;
-       u32 reg_289c;
-       u32 src_major_y, src_minor_y;
-       u32 src_major_uv, src_minor_uv;
-       u32 reg_2964_base, reg_2968_base;
-       int v_filter_1, v_filter_2;
-
-       IVTV_DEBUG_WARN
-           ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
-            f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
-
-       /* What scaling mode is being used... */
-       IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
-                      f->interlaced_y ? "Interlaced" : "Progressive");
-
-       IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
-                      f->interlaced_uv ? "Interlaced" : "Progressive");
-
-       /* What is the source video being treated as... */
-       IVTV_DEBUG_WARN("Source video: %s\n",
-                       f->interlaced ? "Interlaced" : "Progressive");
-
-       /* We offset into the image using two different index methods, so split
-          the y source coord into two parts. */
-       if (f->src_y < 8) {
-               src_minor_uv = f->src_y;
-               src_major_uv = 0;
-       } else {
-               src_minor_uv = 8;
-               src_major_uv = f->src_y - 8;
-       }
-
-       src_minor_y = src_minor_uv;
-       src_major_y = src_major_uv;
-
-       if (f->offset_y)
-               src_minor_y += 16;
-
-       if (f->interlaced_y)
-               reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
-       else
-               reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
-
-       if (f->interlaced_uv)
-               reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
-       else
-               reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
-
-       reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
-       reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
-
-       if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
-               master_height = (f->src_h * 0x00400000) / f->dst_h;
-               if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
-                       master_height++;
-               reg_2920 = master_height >> 2;
-               reg_2928 = master_height >> 3;
-               reg_2930 = master_height;
-               reg_2940 = master_height >> 1;
-               reg_2964_base >>= 3;
-               reg_2968_base >>= 3;
-               reg_296c = 0x00000000;
-       } else if (f->dst_h >= f->src_h) {
-               master_height = (f->src_h * 0x00400000) / f->dst_h;
-               master_height = (master_height >> 1) + (master_height & 1);
-               reg_2920 = master_height >> 2;
-               reg_2928 = master_height >> 2;
-               reg_2930 = master_height;
-               reg_2940 = master_height >> 1;
-               reg_296c = 0x00000000;
-               if (f->interlaced_y) {
-                       reg_2964_base >>= 3;
-               } else {
-                       reg_296c++;
-                       reg_2964_base >>= 2;
-               }
-               if (f->interlaced_uv)
-                       reg_2928 >>= 1;
-               reg_2968_base >>= 3;
-       } else if (f->dst_h >= f->src_h / 2) {
-               master_height = (f->src_h * 0x00200000) / f->dst_h;
-               master_height = (master_height >> 1) + (master_height & 1);
-               reg_2920 = master_height >> 2;
-               reg_2928 = master_height >> 2;
-               reg_2930 = master_height;
-               reg_2940 = master_height;
-               reg_296c = 0x00000101;
-               if (f->interlaced_y) {
-                       reg_2964_base >>= 2;
-               } else {
-                       reg_296c++;
-                       reg_2964_base >>= 1;
-               }
-               if (f->interlaced_uv)
-                       reg_2928 >>= 1;
-               reg_2968_base >>= 2;
-       } else {
-               master_height = (f->src_h * 0x00100000) / f->dst_h;
-               master_height = (master_height >> 1) + (master_height & 1);
-               reg_2920 = master_height >> 2;
-               reg_2928 = master_height >> 2;
-               reg_2930 = master_height;
-               reg_2940 = master_height;
-               reg_2964_base >>= 1;
-               reg_2968_base >>= 2;
-               reg_296c = 0x00000102;
-       }
-
-       /* FIXME These registers change depending on scaled / unscaled output
-          We really need to work out what they should be */
-       if (f->src_h == f->dst_h) {
-               reg_2934 = 0x00020000;
-               reg_293c = 0x00100000;
-               reg_2944 = 0x00040000;
-               reg_294c = 0x000b0000;
-       } else {
-               reg_2934 = 0x00000FF0;
-               reg_293c = 0x00000FF0;
-               reg_2944 = 0x00000FF0;
-               reg_294c = 0x00000FF0;
-       }
-
-       /* The first line to be displayed */
-       reg_2950 = 0x00010000 + src_major_y;
-       if (f->interlaced_y)
-               reg_2950 += 0x00010000;
-       reg_2954 = reg_2950 + 1;
-
-       reg_2958 = 0x00010000 + (src_major_y >> 1);
-       if (f->interlaced_uv)
-               reg_2958 += 0x00010000;
-       reg_295c = reg_2958 + 1;
-
-       if (yi->decode_height == 480)
-               reg_289c = 0x011e0017;
-       else
-               reg_289c = 0x01500017;
-
-       if (f->dst_y < 0)
-               reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
-       else
-               reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
-
-       /* How much of the source to decode.
-          Take into account the source offset */
-       reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
-               (((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
-
-       /* Calculate correct value for register 2964 */
-       if (f->src_h == f->dst_h) {
-               reg_2964 = 1;
-       } else {
-               reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
-               reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
-       }
-       reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
-       reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
-
-       /* Okay, we've wasted time working out the correct value,
-          but if we use it, it fouls the the window alignment.
-          Fudge it to what we want... */
-       reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
-       reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
-
-       /* Deviate further from what it should be. I find the flicker headache
-          inducing so try to reduce it slightly. Leave 2968 as-is otherwise
-          colours foul. */
-       if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
-               reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
-
-       if (!f->interlaced_y)
-               reg_2964 -= 0x00010001;
-       if (!f->interlaced_uv)
-               reg_2968 -= 0x00010001;
-
-       reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
-       reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
-
-       /* Select the vertical filter */
-       if (f->src_h == f->dst_h) {
-               /* An exact size match uses filter 0/1 */
-               v_filter_1 = 0;
-               v_filter_2 = 1;
-       } else {
-               /* Figure out which filter to use */
-               v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
-               v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
-               /* Only an exact size match can use filter 0 */
-               v_filter_1 += !v_filter_1;
-               v_filter_2 = v_filter_1;
-       }
-
-       write_reg(reg_2934, 0x02934);
-       write_reg(reg_293c, 0x0293c);
-       IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
-                      yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
-       write_reg(reg_2944, 0x02944);
-       write_reg(reg_294c, 0x0294c);
-       IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
-                      yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
-
-       /* Ensure 2970 is 0 (does it ever change ?) */
-/*     write_reg(0,0x02970); */
-/*     IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
-
-       write_reg(reg_2930, 0x02938);
-       write_reg(reg_2930, 0x02930);
-       IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
-                      yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
-
-       write_reg(reg_2928, 0x02928);
-       write_reg(reg_2928 + 0x514, 0x0292C);
-       IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
-                      yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
-
-       write_reg(reg_2920, 0x02920);
-       write_reg(reg_2920 + 0x514, 0x02924);
-       IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
-                      yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
-
-       write_reg(reg_2918, 0x02918);
-       write_reg(reg_291c, 0x0291C);
-       IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
-                      yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
-
-       write_reg(reg_296c, 0x0296c);
-       IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
-                      yi->reg_296c, reg_296c);
-
-       write_reg(reg_2940, 0x02948);
-       write_reg(reg_2940, 0x02940);
-       IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
-                      yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
-
-       write_reg(reg_2950, 0x02950);
-       write_reg(reg_2954, 0x02954);
-       IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
-                      yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
-
-       write_reg(reg_2958, 0x02958);
-       write_reg(reg_295c, 0x0295C);
-       IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
-                      yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
-
-       write_reg(reg_2960, 0x02960);
-       IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
-                      yi->reg_2960, reg_2960);
-
-       write_reg(reg_2964, 0x02964);
-       write_reg(reg_2968, 0x02968);
-       IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
-                      yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
-
-       write_reg(reg_289c, 0x0289c);
-       IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
-                      yi->reg_289c, reg_289c);
-
-       /* Only update filter 1 if we really need to */
-       if (v_filter_1 != yi->v_filter_1) {
-               ivtv_yuv_filter(itv, -1, v_filter_1, -1);
-               yi->v_filter_1 = v_filter_1;
-       }
-
-       /* Only update filter 2 if we really need to */
-       if (v_filter_2 != yi->v_filter_2) {
-               ivtv_yuv_filter(itv, -1, -1, v_filter_2);
-               yi->v_filter_2 = v_filter_2;
-       }
-}
-
-/* Modify the supplied coordinate information to fit the visible osd area */
-static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
-{
-       struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
-       int osd_crop;
-       u32 osd_scale;
-       u32 yuv_update = 0;
-
-       /* Sorry, but no negative coords for src */
-       if (f->src_x < 0)
-               f->src_x = 0;
-       if (f->src_y < 0)
-               f->src_y = 0;
-
-       /* Can only reduce width down to 1/4 original size */
-       if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
-               f->src_x += osd_crop / 2;
-               f->src_w = (f->src_w - osd_crop) & ~3;
-               f->dst_w = f->src_w / 4;
-               f->dst_w += f->dst_w & 1;
-       }
-
-       /* Can only reduce height down to 1/4 original size */
-       if (f->src_h / f->dst_h >= 2) {
-               /* Overflow may be because we're running progressive,
-                  so force mode switch */
-               f->interlaced_y = 1;
-               /* Make sure we're still within limits for interlace */
-               if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
-                       /* If we reach here we'll have to force the height. */
-                       f->src_y += osd_crop / 2;
-                       f->src_h = (f->src_h - osd_crop) & ~3;
-                       f->dst_h = f->src_h / 4;
-                       f->dst_h += f->dst_h & 1;
-               }
-       }
-
-       /* If there's nothing to safe to display, we may as well stop now */
-       if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
-           (int)f->src_w <= 2 || (int)f->src_h <= 2) {
-               return IVTV_YUV_UPDATE_INVALID;
-       }
-
-       /* Ensure video remains inside OSD area */
-       osd_scale = (f->src_h << 16) / f->dst_h;
-
-       if ((osd_crop = f->pan_y - f->dst_y) > 0) {
-               /* Falls off the upper edge - crop */
-               f->src_y += (osd_scale * osd_crop) >> 16;
-               f->src_h -= (osd_scale * osd_crop) >> 16;
-               f->dst_h -= osd_crop;
-               f->dst_y = 0;
-       } else {
-               f->dst_y -= f->pan_y;
-       }
-
-       if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
-               /* Falls off the lower edge - crop */
-               f->dst_h -= osd_crop;
-               f->src_h -= (osd_scale * osd_crop) >> 16;
-       }
-
-       osd_scale = (f->src_w << 16) / f->dst_w;
-
-       if ((osd_crop = f->pan_x - f->dst_x) > 0) {
-               /* Fall off the left edge - crop */
-               f->src_x += (osd_scale * osd_crop) >> 16;
-               f->src_w -= (osd_scale * osd_crop) >> 16;
-               f->dst_w -= osd_crop;
-               f->dst_x = 0;
-       } else {
-               f->dst_x -= f->pan_x;
-       }
-
-       if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
-               /* Falls off the right edge - crop */
-               f->dst_w -= osd_crop;
-               f->src_w -= (osd_scale * osd_crop) >> 16;
-       }
-
-       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. */
-       f->dst_w &= ~1;
-       f->dst_x &= ~1;
-
-       f->src_w += f->src_x & 1;
-       f->src_x &= ~1;
-
-       f->src_w &= ~1;
-       f->dst_w &= ~1;
-
-       f->dst_h &= ~1;
-       f->dst_y &= ~1;
-
-       f->src_h += f->src_y & 1;
-       f->src_y &= ~1;
-
-       f->src_h &= ~1;
-       f->dst_h &= ~1;
-
-       /* Due to rounding, we may have reduced the output size to <1/4 of
-          the source. Check again, but this time just resize. Don't change
-          source coordinates */
-       if (f->dst_w < f->src_w / 4) {
-               f->src_w &= ~3;
-               f->dst_w = f->src_w / 4;
-               f->dst_w += f->dst_w & 1;
-       }
-       if (f->dst_h < f->src_h / 4) {
-               f->src_h &= ~3;
-               f->dst_h = f->src_h / 4;
-               f->dst_h += f->dst_h & 1;
-       }
-
-       /* Check again. If there's nothing to safe to display, stop now */
-       if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
-           (int)f->src_w <= 2 || (int)f->src_h <= 2) {
-               return IVTV_YUV_UPDATE_INVALID;
-       }
-
-       /* Both x offset & width are linked, so they have to be done together */
-       if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
-           (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
-           (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
-               yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
-       }
-
-       if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
-           (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
-           (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
-           (of->lace_mode != f->lace_mode) ||
-           (of->interlaced_y != f->interlaced_y) ||
-           (of->interlaced_uv != f->interlaced_uv)) {
-               yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
-       }
-
-       return yuv_update;
-}
-
-/* Update the scaling register to the requested value */
-void ivtv_yuv_work_handler(struct ivtv *itv)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       struct yuv_frame_info f;
-       int frame = yi->update_frame;
-       u32 yuv_update;
-
-       IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
-       f = yi->new_frame_info[frame];
-
-       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)))
-               return;
-
-       if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
-               write_reg(0x01008080, 0x2898);
-       } else if (yuv_update) {
-               write_reg(0x00108080, 0x2898);
-
-               if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
-                       ivtv_yuv_handle_horizontal(itv, &f);
-
-               if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
-                       ivtv_yuv_handle_vertical(itv, &f);
-       }
-       yi->old_frame_info = f;
-}
-
-static void ivtv_yuv_init(struct ivtv *itv)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-
-       IVTV_DEBUG_YUV("ivtv_yuv_init\n");
-
-       /* Take a snapshot of the current register settings */
-       yi->reg_2834 = read_reg(0x02834);
-       yi->reg_2838 = read_reg(0x02838);
-       yi->reg_283c = read_reg(0x0283c);
-       yi->reg_2840 = read_reg(0x02840);
-       yi->reg_2844 = read_reg(0x02844);
-       yi->reg_2848 = read_reg(0x02848);
-       yi->reg_2854 = read_reg(0x02854);
-       yi->reg_285c = read_reg(0x0285c);
-       yi->reg_2864 = read_reg(0x02864);
-       yi->reg_2870 = read_reg(0x02870);
-       yi->reg_2874 = read_reg(0x02874);
-       yi->reg_2898 = read_reg(0x02898);
-       yi->reg_2890 = read_reg(0x02890);
-
-       yi->reg_289c = read_reg(0x0289c);
-       yi->reg_2918 = read_reg(0x02918);
-       yi->reg_291c = read_reg(0x0291c);
-       yi->reg_2920 = read_reg(0x02920);
-       yi->reg_2924 = read_reg(0x02924);
-       yi->reg_2928 = read_reg(0x02928);
-       yi->reg_292c = read_reg(0x0292c);
-       yi->reg_2930 = read_reg(0x02930);
-       yi->reg_2934 = read_reg(0x02934);
-       yi->reg_2938 = read_reg(0x02938);
-       yi->reg_293c = read_reg(0x0293c);
-       yi->reg_2940 = read_reg(0x02940);
-       yi->reg_2944 = read_reg(0x02944);
-       yi->reg_2948 = read_reg(0x02948);
-       yi->reg_294c = read_reg(0x0294c);
-       yi->reg_2950 = read_reg(0x02950);
-       yi->reg_2954 = read_reg(0x02954);
-       yi->reg_2958 = read_reg(0x02958);
-       yi->reg_295c = read_reg(0x0295c);
-       yi->reg_2960 = read_reg(0x02960);
-       yi->reg_2964 = read_reg(0x02964);
-       yi->reg_2968 = read_reg(0x02968);
-       yi->reg_296c = read_reg(0x0296c);
-       yi->reg_2970 = read_reg(0x02970);
-
-       yi->v_filter_1 = -1;
-       yi->v_filter_2 = -1;
-       yi->h_filter = -1;
-
-       /* Set some valid size info */
-       yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
-       yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
-
-       /* Bit 2 of reg 2878 indicates current decoder output format
-          0 : NTSC    1 : PAL */
-       if (read_reg(0x2878) & 4)
-               yi->decode_height = 576;
-       else
-               yi->decode_height = 480;
-
-       if (!itv->osd_info) {
-               yi->osd_vis_w = 720 - yi->osd_x_offset;
-               yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
-       } else {
-               /* If no visible size set, assume full size */
-               if (!yi->osd_vis_w)
-                       yi->osd_vis_w = 720 - yi->osd_x_offset;
-
-               if (!yi->osd_vis_h) {
-                       yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
-               } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
-                       /* If output video standard has changed, requested height may
-                          not be legal */
-                       IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
-                                       yi->osd_vis_h + yi->osd_y_offset,
-                                       yi->decode_height);
-                       yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
-               }
-       }
-
-       /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */
-       yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN);
-       if (yi->blanking_ptr) {
-               yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
-       } else {
-               yi->blanking_dmaptr = 0;
-               IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
-       }
-
-       /* Enable YUV decoder output */
-       write_reg_sync(0x01, IVTV_REG_VDM);
-
-       set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
-       atomic_set(&yi->next_dma_frame, 0);
-}
-
-/* Get next available yuv buffer on PVR350 */
-static void ivtv_yuv_next_free(struct ivtv *itv)
-{
-       int draw, display;
-       struct yuv_playback_info *yi = &itv->yuv_info;
-
-       if (atomic_read(&yi->next_dma_frame) == -1)
-               ivtv_yuv_init(itv);
-
-       draw = atomic_read(&yi->next_fill_frame);
-       display = atomic_read(&yi->next_dma_frame);
-
-       if (display > draw)
-               display -= IVTV_YUV_BUFFERS;
-
-       if (draw - display >= yi->max_frames_buffered)
-               draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
-       else
-               yi->new_frame_info[draw].update = 0;
-
-       yi->draw_frame = draw;
-}
-
-/* Set up frame according to ivtv_dma_frame parameters */
-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;
-       u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
-       struct yuv_frame_info *nf = &yi->new_frame_info[frame];
-       struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
-       int lace_threshold = yi->lace_threshold;
-
-       /* Preserve old update flag in case we're overwriting a queued frame */
-       int update = nf->update;
-
-       /* Take a snapshot of the yuv coordinate information */
-       nf->src_x = args->src.left;
-       nf->src_y = args->src.top;
-       nf->src_w = args->src.width;
-       nf->src_h = args->src.height;
-       nf->dst_x = args->dst.left;
-       nf->dst_y = args->dst.top;
-       nf->dst_w = args->dst.width;
-       nf->dst_h = args->dst.height;
-       nf->tru_x = args->dst.left;
-       nf->tru_w = args->src_width;
-       nf->tru_h = args->src_height;
-
-       /* Are we going to offset the Y plane */
-       nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
-
-       nf->update = 0;
-       nf->interlaced_y = 0;
-       nf->interlaced_uv = 0;
-       nf->delay = 0;
-       nf->sync_field = 0;
-       nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
-
-       if (lace_threshold < 0)
-               lace_threshold = yi->decode_height - 1;
-
-       /* Work out the lace settings */
-       switch (nf->lace_mode) {
-       case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
-               nf->interlaced = 0;
-               if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
-                       nf->interlaced_y = 0;
-               else
-                       nf->interlaced_y = 1;
-
-               if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
-                       nf->interlaced_uv = 0;
-               else
-                       nf->interlaced_uv = 1;
-               break;
-
-       case IVTV_YUV_MODE_AUTO:
-               if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
-                       nf->interlaced = 0;
-                       if ((nf->tru_h < 512) ||
-                           (nf->tru_h > 576 && nf->tru_h < 1021) ||
-                           (nf->tru_w > 720 && nf->tru_h < 1021))
-                               nf->interlaced_y = 0;
-                       else
-                               nf->interlaced_y = 1;
-                       if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
-                               nf->interlaced_uv = 0;
-                       else
-                               nf->interlaced_uv = 1;
-               } else {
-                       nf->interlaced = 1;
-                       nf->interlaced_y = 1;
-                       nf->interlaced_uv = 1;
-               }
-               break;
-
-       case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
-       default:
-               nf->interlaced = 1;
-               nf->interlaced_y = 1;
-               nf->interlaced_uv = 1;
-               break;
-       }
-
-       if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
-               yi->old_frame_info_args = *nf;
-               nf->update = 1;
-               IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
-       }
-
-       nf->update |= update;
-       nf->sync_field = yi->lace_sync_field;
-       nf->delay = nf->sync_field != of->sync_field;
-}
-
-/* Frame is complete & ready for display */
-void ivtv_yuv_frame_complete(struct ivtv *itv)
-{
-       atomic_set(&itv->yuv_info.next_fill_frame,
-                       (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
-}
-
-static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
-{
-       DEFINE_WAIT(wait);
-       int rc = 0;
-       int got_sig = 0;
-       /* DMA the frame */
-       mutex_lock(&itv->udma.lock);
-
-       if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
-               mutex_unlock(&itv->udma.lock);
-               return rc;
-       }
-
-       ivtv_udma_prepare(itv);
-       prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
-       /* if no UDMA is pending and no UDMA is in progress, then the DMA
-          is finished */
-       while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
-              test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
-               /* don't interrupt if the DMA is in progress but break off
-                  a still pending DMA. */
-               got_sig = signal_pending(current);
-               if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
-                       break;
-               got_sig = 0;
-               schedule();
-       }
-       finish_wait(&itv->dma_waitq, &wait);
-
-       /* Unmap Last DMA Xfer */
-       ivtv_udma_unmap(itv);
-
-       if (got_sig) {
-               IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
-               mutex_unlock(&itv->udma.lock);
-               return -EINTR;
-       }
-
-       ivtv_yuv_frame_complete(itv);
-
-       mutex_unlock(&itv->udma.lock);
-       return rc;
-}
-
-/* Setup frame according to V4L2 parameters */
-void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       struct ivtv_dma_frame dma_args;
-
-       ivtv_yuv_next_free(itv);
-
-       /* Copy V4L2 parameters to an ivtv_dma_frame struct... */
-       dma_args.y_source = NULL;
-       dma_args.uv_source = NULL;
-       dma_args.src.left = 0;
-       dma_args.src.top = 0;
-       dma_args.src.width = yi->v4l2_src_w;
-       dma_args.src.height = yi->v4l2_src_h;
-       dma_args.dst = yi->main_rect;
-       dma_args.src_width = yi->v4l2_src_w;
-       dma_args.src_height = yi->v4l2_src_h;
-
-       /* ... and use the same setup routine as ivtv_yuv_prep_frame */
-       ivtv_yuv_setup_frame(itv, &dma_args);
-
-       if (!itv->dma_data_req_offset)
-               itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
-}
-
-/* Attempt to dma a frame from a user buffer */
-int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       struct ivtv_dma_frame dma_args;
-       int res;
-
-       ivtv_yuv_setup_stream_frame(itv);
-
-       /* We only need to supply source addresses for this */
-       dma_args.y_source = src;
-       dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
-       /* Wait for frame DMA. Note that serialize_lock is locked,
-          so to allow other processes to access the driver while
-          we are waiting unlock first and later lock again. */
-       mutex_unlock(&itv->serialize_lock);
-       res = ivtv_yuv_udma_frame(itv, &dma_args);
-       mutex_lock(&itv->serialize_lock);
-       return res;
-}
-
-/* IVTV_IOC_DMA_FRAME ioctl handler */
-int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
-{
-       int res;
-
-/*     IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
-       ivtv_yuv_next_free(itv);
-       ivtv_yuv_setup_frame(itv, args);
-       /* Wait for frame DMA. Note that serialize_lock is locked,
-          so to allow other processes to access the driver while
-          we are waiting unlock first and later lock again. */
-       mutex_unlock(&itv->serialize_lock);
-       res = ivtv_yuv_udma_frame(itv, args);
-       mutex_lock(&itv->serialize_lock);
-       return res;
-}
-
-void ivtv_yuv_close(struct ivtv *itv)
-{
-       struct yuv_playback_info *yi = &itv->yuv_info;
-       int h_filter, v_filter_1, v_filter_2;
-
-       IVTV_DEBUG_YUV("ivtv_yuv_close\n");
-       mutex_unlock(&itv->serialize_lock);
-       ivtv_waitq(&itv->vsync_waitq);
-       mutex_lock(&itv->serialize_lock);
-
-       yi->running = 0;
-       atomic_set(&yi->next_dma_frame, -1);
-       atomic_set(&yi->next_fill_frame, 0);
-
-       /* Reset registers we have changed so mpeg playback works */
-
-       /* If we fully restore this register, the display may remain active.
-          Restore, but set one bit to blank the video. Firmware will always
-          clear this bit when needed, so not a problem. */
-       write_reg(yi->reg_2898 | 0x01000000, 0x2898);
-
-       write_reg(yi->reg_2834, 0x02834);
-       write_reg(yi->reg_2838, 0x02838);
-       write_reg(yi->reg_283c, 0x0283c);
-       write_reg(yi->reg_2840, 0x02840);
-       write_reg(yi->reg_2844, 0x02844);
-       write_reg(yi->reg_2848, 0x02848);
-       write_reg(yi->reg_2854, 0x02854);
-       write_reg(yi->reg_285c, 0x0285c);
-       write_reg(yi->reg_2864, 0x02864);
-       write_reg(yi->reg_2870, 0x02870);
-       write_reg(yi->reg_2874, 0x02874);
-       write_reg(yi->reg_2890, 0x02890);
-       write_reg(yi->reg_289c, 0x0289c);
-
-       write_reg(yi->reg_2918, 0x02918);
-       write_reg(yi->reg_291c, 0x0291c);
-       write_reg(yi->reg_2920, 0x02920);
-       write_reg(yi->reg_2924, 0x02924);
-       write_reg(yi->reg_2928, 0x02928);
-       write_reg(yi->reg_292c, 0x0292c);
-       write_reg(yi->reg_2930, 0x02930);
-       write_reg(yi->reg_2934, 0x02934);
-       write_reg(yi->reg_2938, 0x02938);
-       write_reg(yi->reg_293c, 0x0293c);
-       write_reg(yi->reg_2940, 0x02940);
-       write_reg(yi->reg_2944, 0x02944);
-       write_reg(yi->reg_2948, 0x02948);
-       write_reg(yi->reg_294c, 0x0294c);
-       write_reg(yi->reg_2950, 0x02950);
-       write_reg(yi->reg_2954, 0x02954);
-       write_reg(yi->reg_2958, 0x02958);
-       write_reg(yi->reg_295c, 0x0295c);
-       write_reg(yi->reg_2960, 0x02960);
-       write_reg(yi->reg_2964, 0x02964);
-       write_reg(yi->reg_2968, 0x02968);
-       write_reg(yi->reg_296c, 0x0296c);
-       write_reg(yi->reg_2970, 0x02970);
-
-       /* Prepare to restore filters */
-
-       /* First the horizontal filter */
-       if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
-               /* An exact size match uses filter 0 */
-               h_filter = 0;
-       } else {
-               /* Figure out which filter to use */
-               h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
-               h_filter = (h_filter >> 1) + (h_filter & 1);
-               /* Only an exact size match can use filter 0. */
-               h_filter += !h_filter;
-       }
-
-       /* Now the vertical filter */
-       if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
-               /* An exact size match uses filter 0/1 */
-               v_filter_1 = 0;
-               v_filter_2 = 1;
-       } else {
-               /* Figure out which filter to use */
-               v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
-               v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
-               /* Only an exact size match can use filter 0 */
-               v_filter_1 += !v_filter_1;
-               v_filter_2 = v_filter_1;
-       }
-
-       /* Now restore the filters */
-       ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
-
-       /* and clear a few registers */
-       write_reg(0, 0x02814);
-       write_reg(0, 0x0282c);
-       write_reg(0, 0x02904);
-       write_reg(0, 0x02910);
-
-       /* Release the blanking buffer */
-       if (yi->blanking_ptr) {
-               kfree(yi->blanking_ptr);
-               yi->blanking_ptr = NULL;
-               pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
-       }
-
-       /* Invalidate the old dimension information */
-       yi->old_frame_info.src_w = 0;
-       yi->old_frame_info.src_h = 0;
-       yi->old_frame_info_args.src_w = 0;
-       yi->old_frame_info_args.src_h = 0;
-
-       /* All done. */
-       clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
-}
diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h
deleted file mode 100644 (file)
index ca5173f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-    yuv support
-
-    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef IVTV_YUV_H
-#define IVTV_YUV_H
-
-#define IVTV_YUV_BUFFER_UV_OFFSET 0x65400      /* Offset to UV Buffer */
-
-/* Offset to filter table in firmware */
-#define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8
-#define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358
-
-#define IVTV_YUV_UPDATE_HORIZONTAL  0x01
-#define IVTV_YUV_UPDATE_VERTICAL    0x02
-#define IVTV_YUV_UPDATE_INVALID     0x04
-
-extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
-
-int ivtv_yuv_filter_check(struct ivtv *itv);
-void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
-int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src);
-void ivtv_yuv_frame_complete(struct ivtv *itv);
-int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
-void ivtv_yuv_close(struct ivtv *itv);
-void ivtv_yuv_work_handler(struct ivtv *itv);
-
-#endif
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c
deleted file mode 100644 (file)
index 05b94aa..0000000
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
-    On Screen Display cx23415 Framebuffer driver
-
-    This module presents the cx23415 OSD (onscreen display) framebuffer memory
-    as a standard Linux /dev/fb style framebuffer device. The framebuffer has
-    support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
-    mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
-    local alpha. The colorspace is selectable between rgb & yuv.
-    Depending on the TV standard configured in the ivtv module at load time,
-    the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
-    Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
-    or 59.94 (NTSC)
-
-    Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
-
-    Derived from drivers/video/vesafb.c
-    Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
-
-    2.6 kernel port:
-    Copyright (C) 2004 Matthias Badaire
-
-    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
-
-    Copyright (C) 2006  Ian Armstrong <ian@iarmst.demon.co.uk>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/ivtvfb.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "ivtv-driver.h"
-#include "ivtv-cards.h"
-#include "ivtv-i2c.h"
-#include "ivtv-udma.h"
-#include "ivtv-mailbox.h"
-#include "ivtv-firmware.h"
-
-/* card parameters */
-static int ivtvfb_card_id = -1;
-static int ivtvfb_debug = 0;
-static bool osd_laced;
-static int osd_depth;
-static int osd_upper;
-static int osd_left;
-static int osd_yres;
-static int osd_xres;
-
-module_param(ivtvfb_card_id, int, 0444);
-module_param_named(debug,ivtvfb_debug, int, 0644);
-module_param(osd_laced, bool, 0444);
-module_param(osd_depth, int, 0444);
-module_param(osd_upper, int, 0444);
-module_param(osd_left, int, 0444);
-module_param(osd_yres, int, 0444);
-module_param(osd_xres, int, 0444);
-
-MODULE_PARM_DESC(ivtvfb_card_id,
-                "Only use framebuffer of the specified ivtv card (0-31)\n"
-                "\t\t\tdefault -1: initialize all available framebuffers");
-
-MODULE_PARM_DESC(debug,
-                "Debug level (bitmask). Default: errors only\n"
-                "\t\t\t(debug = 3 gives full debugging)");
-
-/* Why upper, left, xres, yres, depth, laced ? To match terminology used
-   by fbset.
-   Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
-
-MODULE_PARM_DESC(osd_laced,
-                "Interlaced mode\n"
-                "\t\t\t0=off\n"
-                "\t\t\t1=on\n"
-                "\t\t\tdefault off");
-
-MODULE_PARM_DESC(osd_depth,
-                "Bits per pixel - 8, 16, 32\n"
-                "\t\t\tdefault 8");
-
-MODULE_PARM_DESC(osd_upper,
-                "Vertical start position\n"
-                "\t\t\tdefault 0 (Centered)");
-
-MODULE_PARM_DESC(osd_left,
-                "Horizontal start position\n"
-                "\t\t\tdefault 0 (Centered)");
-
-MODULE_PARM_DESC(osd_yres,
-                "Display height\n"
-                "\t\t\tdefault 480 (PAL)\n"
-                "\t\t\t        400 (NTSC)");
-
-MODULE_PARM_DESC(osd_xres,
-                "Display width\n"
-                "\t\t\tdefault 640");
-
-MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
-MODULE_LICENSE("GPL");
-
-/* --------------------------------------------------------------------- */
-
-#define IVTVFB_DBGFLG_WARN  (1 << 0)
-#define IVTVFB_DBGFLG_INFO  (1 << 1)
-
-#define IVTVFB_DEBUG(x, type, fmt, args...) \
-       do { \
-               if ((x) & ivtvfb_debug) \
-                       printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
-       } while (0)
-#define IVTVFB_DEBUG_WARN(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
-#define IVTVFB_DEBUG_INFO(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
-
-/* Standard kernel messages */
-#define IVTVFB_ERR(fmt, args...)   printk(KERN_ERR  "ivtvfb%d: " fmt, itv->instance , ## args)
-#define IVTVFB_WARN(fmt, args...)  printk(KERN_WARNING  "ivtvfb%d: " fmt, itv->instance , ## args)
-#define IVTVFB_INFO(fmt, args...)  printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
-
-/* --------------------------------------------------------------------- */
-
-#define IVTV_OSD_MAX_WIDTH  720
-#define IVTV_OSD_MAX_HEIGHT 576
-
-#define IVTV_OSD_BPP_8      0x00
-#define IVTV_OSD_BPP_16_444 0x03
-#define IVTV_OSD_BPP_16_555 0x02
-#define IVTV_OSD_BPP_16_565 0x01
-#define IVTV_OSD_BPP_32     0x04
-
-struct osd_info {
-       /* Physical base address */
-       unsigned long video_pbase;
-       /* Relative base address (relative to start of decoder memory) */
-       u32 video_rbase;
-       /* Mapped base address */
-       volatile char __iomem *video_vbase;
-       /* Buffer size */
-       u32 video_buffer_size;
-
-#ifdef CONFIG_MTRR
-       /* video_base rounded down as required by hardware MTRRs */
-       unsigned long fb_start_aligned_physaddr;
-       /* video_base rounded up as required by hardware MTRRs */
-       unsigned long fb_end_aligned_physaddr;
-#endif
-
-       /* Store the buffer offset */
-       int set_osd_coords_x;
-       int set_osd_coords_y;
-
-       /* Current dimensions (NOT VISIBLE SIZE!) */
-       int display_width;
-       int display_height;
-       int display_byte_stride;
-
-       /* Current bits per pixel */
-       int bits_per_pixel;
-       int bytes_per_pixel;
-
-       /* Frame buffer stuff */
-       struct fb_info ivtvfb_info;
-       struct fb_var_screeninfo ivtvfb_defined;
-       struct fb_fix_screeninfo ivtvfb_fix;
-
-       /* Used for a warm start */
-       struct fb_var_screeninfo fbvar_cur;
-       int blank_cur;
-       u32 palette_cur[256];
-       u32 pan_cur;
-};
-
-struct ivtv_osd_coords {
-       unsigned long offset;
-       unsigned long max_offset;
-       int pixel_stride;
-       int lines;
-       int x;
-       int y;
-};
-
-/* --------------------------------------------------------------------- */
-
-/* ivtv API calls for framebuffer related support */
-
-static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
-                                      u32 *fblength)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       int rc;
-
-       ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
-       rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
-       *fbbase = data[0];
-       *fblength = data[1];
-       return rc;
-}
-
-static int ivtvfb_get_osd_coords(struct ivtv *itv,
-                                     struct ivtv_osd_coords *osd)
-{
-       struct osd_info *oi = itv->osd_info;
-       u32 data[CX2341X_MBOX_MAX_DATA];
-
-       ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
-
-       osd->offset = data[0] - oi->video_rbase;
-       osd->max_offset = oi->display_width * oi->display_height * 4;
-       osd->pixel_stride = data[1];
-       osd->lines = data[2];
-       osd->x = data[3];
-       osd->y = data[4];
-       return 0;
-}
-
-static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
-{
-       struct osd_info *oi = itv->osd_info;
-
-       oi->display_width = osd->pixel_stride;
-       oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
-       oi->set_osd_coords_x += osd->x;
-       oi->set_osd_coords_y = osd->y;
-
-       return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
-                       osd->offset + oi->video_rbase,
-                       osd->pixel_stride,
-                       osd->lines, osd->x, osd->y);
-}
-
-static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
-{
-       int osd_height_limit = itv->is_out_50hz ? 576 : 480;
-
-       /* Only fail if resolution too high, otherwise fudge the start coords. */
-       if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
-               return -EINVAL;
-
-       /* Ensure we don't exceed display limits */
-       if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
-               IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
-                       ivtv_window->top, ivtv_window->height);
-               ivtv_window->top = osd_height_limit - ivtv_window->height;
-       }
-
-       if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
-               IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
-                       ivtv_window->left, ivtv_window->width);
-               ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
-       }
-
-       /* Set the OSD origin */
-       write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
-
-       /* How much to display */
-       write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
-
-       /* Pass this info back the yuv handler */
-       itv->yuv_info.osd_vis_w = ivtv_window->width;
-       itv->yuv_info.osd_vis_h = ivtv_window->height;
-       itv->yuv_info.osd_x_offset = ivtv_window->left;
-       itv->yuv_info.osd_y_offset = ivtv_window->top;
-
-       return 0;
-}
-
-static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
-                                 unsigned long ivtv_dest_addr, void __user *userbuf,
-                                 int size_in_bytes)
-{
-       DEFINE_WAIT(wait);
-       int got_sig = 0;
-
-       mutex_lock(&itv->udma.lock);
-       /* Map User DMA */
-       if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
-               mutex_unlock(&itv->udma.lock);
-               IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
-                              "Error with get_user_pages: %d bytes, %d pages returned\n",
-                              size_in_bytes, itv->udma.page_count);
-
-               /* get_user_pages must have failed completely */
-               return -EIO;
-       }
-
-       IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
-                      size_in_bytes, itv->udma.page_count);
-
-       ivtv_udma_prepare(itv);
-       prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
-       /* if no UDMA is pending and no UDMA is in progress, then the DMA
-          is finished */
-       while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
-              test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
-               /* don't interrupt if the DMA is in progress but break off
-                  a still pending DMA. */
-               got_sig = signal_pending(current);
-               if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
-                       break;
-               got_sig = 0;
-               schedule();
-       }
-       finish_wait(&itv->dma_waitq, &wait);
-
-       /* Unmap Last DMA Xfer */
-       ivtv_udma_unmap(itv);
-       mutex_unlock(&itv->udma.lock);
-       if (got_sig) {
-               IVTV_DEBUG_INFO("User stopped OSD\n");
-               return -EINTR;
-       }
-
-       return 0;
-}
-
-static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
-                             unsigned long dest_offset, int count)
-{
-       DEFINE_WAIT(wait);
-       struct osd_info *oi = itv->osd_info;
-
-       /* Nothing to do */
-       if (count == 0) {
-               IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
-               return -EINVAL;
-       }
-
-       /* Check Total FB Size */
-       if ((dest_offset + count) > oi->video_buffer_size) {
-               IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
-                       dest_offset + count, oi->video_buffer_size);
-               return -E2BIG;
-       }
-
-       /* Not fatal, but will have undesirable results */
-       if ((unsigned long)source & 3)
-               IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
-                       (unsigned long)source);
-
-       if (dest_offset & 3)
-               IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
-
-       if (count & 3)
-               IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
-
-       /* Check Source */
-       if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
-               IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
-                       (unsigned long)source);
-
-               IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
-                       dest_offset, (unsigned long)source,
-                       count);
-               return -EINVAL;
-       }
-
-       /* OSD Address to send DMA to */
-       dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
-
-       /* Fill Buffers */
-       return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
-}
-
-static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
-                                               size_t count, loff_t *ppos)
-{
-       unsigned long p = *ppos;
-       void *dst;
-       int err = 0;
-       int dma_err;
-       unsigned long total_size;
-       struct ivtv *itv = (struct ivtv *) info->par;
-       unsigned long dma_offset =
-                       IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
-       unsigned long dma_size;
-       u16 lead = 0, tail = 0;
-
-       if (info->state != FBINFO_STATE_RUNNING)
-               return -EPERM;
-
-       total_size = info->screen_size;
-
-       if (total_size == 0)
-               total_size = info->fix.smem_len;
-
-       if (p > total_size)
-               return -EFBIG;
-
-       if (count > total_size) {
-               err = -EFBIG;
-               count = total_size;
-       }
-
-       if (count + p > total_size) {
-               if (!err)
-                       err = -ENOSPC;
-               count = total_size - p;
-       }
-
-       dst = (void __force *) (info->screen_base + p);
-
-       if (info->fbops->fb_sync)
-               info->fbops->fb_sync(info);
-
-       /* If transfer size > threshold and both src/dst
-       addresses are aligned, use DMA */
-       if (count >= 4096 &&
-           ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
-               /* Odd address = can't DMA. Align */
-               if ((unsigned long)dst & 3) {
-                       lead = 4 - ((unsigned long)dst & 3);
-                       if (copy_from_user(dst, buf, lead))
-                               return -EFAULT;
-                       buf += lead;
-                       dst += lead;
-               }
-               /* DMA resolution is 32 bits */
-               if ((count - lead) & 3)
-                       tail = (count - lead) & 3;
-               /* DMA the data */
-               dma_size = count - lead - tail;
-               dma_err = ivtvfb_prep_dec_dma_to_device(itv,
-                      p + lead + dma_offset, (void __user *)buf, dma_size);
-               if (dma_err)
-                       return dma_err;
-               dst += dma_size;
-               buf += dma_size;
-               /* Copy any leftover data */
-               if (tail && copy_from_user(dst, buf, tail))
-                       return -EFAULT;
-       } else if (copy_from_user(dst, buf, count)) {
-               return -EFAULT;
-       }
-
-       if  (!err)
-               *ppos += count;
-
-       return (err) ? err : count;
-}
-
-static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
-{
-       DEFINE_WAIT(wait);
-       struct ivtv *itv = (struct ivtv *)info->par;
-       int rc = 0;
-
-       switch (cmd) {
-               case FBIOGET_VBLANK: {
-                       struct fb_vblank vblank;
-                       u32 trace;
-
-                       memset(&vblank, 0, sizeof(struct fb_vblank));
-
-                       vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
-                                       FB_VBLANK_HAVE_VSYNC;
-                       trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
-                       if (itv->is_out_50hz && trace > 312)
-                               trace -= 312;
-                       else if (itv->is_out_60hz && trace > 262)
-                               trace -= 262;
-                       if (trace == 1)
-                               vblank.flags |= FB_VBLANK_VSYNCING;
-                       vblank.count = itv->last_vsync_field;
-                       vblank.vcount = trace;
-                       vblank.hcount = 0;
-                       if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-               case FBIO_WAITFORVSYNC:
-                       prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
-                       if (!schedule_timeout(msecs_to_jiffies(50)))
-                               rc = -ETIMEDOUT;
-                       finish_wait(&itv->vsync_waitq, &wait);
-                       return rc;
-
-               case IVTVFB_IOC_DMA_FRAME: {
-                       struct ivtvfb_dma_frame args;
-
-                       IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
-                       if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
-                               return -EFAULT;
-
-                       return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
-               }
-
-               default:
-                       IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-/* Framebuffer device handling */
-
-static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
-{
-       struct osd_info *oi = itv->osd_info;
-       struct ivtv_osd_coords ivtv_osd;
-       struct v4l2_rect ivtv_window;
-       int osd_mode = -1;
-
-       IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
-
-       /* Select color space */
-       if (var->nonstd) /* YUV */
-               write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
-       else /* RGB  */
-               write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
-
-       /* Set the color mode */
-       switch (var->bits_per_pixel) {
-               case 8:
-                       osd_mode = IVTV_OSD_BPP_8;
-                       break;
-               case 32:
-                       osd_mode = IVTV_OSD_BPP_32;
-                       break;
-               case 16:
-                       switch (var->green.length) {
-                       case 4:
-                               osd_mode = IVTV_OSD_BPP_16_444;
-                               break;
-                       case 5:
-                               osd_mode = IVTV_OSD_BPP_16_555;
-                               break;
-                       case 6:
-                               osd_mode = IVTV_OSD_BPP_16_565;
-                               break;
-                       default:
-                               IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
-                       }
-                       break;
-               default:
-                       IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
-       }
-
-       /* Set video mode. Although rare, the display can become scrambled even
-          if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
-       if (osd_mode != -1) {
-               ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
-               ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
-       }
-
-       oi->bits_per_pixel = var->bits_per_pixel;
-       oi->bytes_per_pixel = var->bits_per_pixel / 8;
-
-       /* Set the flicker filter */
-       switch (var->vmode & FB_VMODE_MASK) {
-               case FB_VMODE_NONINTERLACED: /* Filter on */
-                       ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
-                       break;
-               case FB_VMODE_INTERLACED: /* Filter off */
-                       ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
-                       break;
-               default:
-                       IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
-       }
-
-       /* Read the current osd info */
-       ivtvfb_get_osd_coords(itv, &ivtv_osd);
-
-       /* Now set the OSD to the size we want */
-       ivtv_osd.pixel_stride = var->xres_virtual;
-       ivtv_osd.lines = var->yres_virtual;
-       ivtv_osd.x = 0;
-       ivtv_osd.y = 0;
-       ivtvfb_set_osd_coords(itv, &ivtv_osd);
-
-       /* Can't seem to find the right API combo for this.
-          Use another function which does what we need through direct register access. */
-       ivtv_window.width = var->xres;
-       ivtv_window.height = var->yres;
-
-       /* Minimum margin cannot be 0, as X won't allow such a mode */
-       if (!var->upper_margin)
-               var->upper_margin++;
-       if (!var->left_margin)
-               var->left_margin++;
-       ivtv_window.top = var->upper_margin - 1;
-       ivtv_window.left = var->left_margin - 1;
-
-       ivtvfb_set_display_window(itv, &ivtv_window);
-
-       /* Pass screen size back to yuv handler */
-       itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
-       itv->yuv_info.osd_full_h = ivtv_osd.lines;
-
-       /* Force update of yuv registers */
-       itv->yuv_info.yuv_forced_update = 1;
-
-       /* Keep a copy of these settings */
-       memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
-
-       IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
-                     var->xres, var->yres,
-                     var->xres_virtual, var->yres_virtual,
-                     var->bits_per_pixel);
-
-       IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
-                     var->left_margin, var->upper_margin);
-
-       IVTVFB_DEBUG_INFO("Display filter: %s\n",
-                       (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
-       IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
-
-       return 0;
-}
-
-static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
-{
-       struct osd_info *oi = itv->osd_info;
-
-       IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
-       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
-       fix->smem_start = oi->video_pbase;
-       fix->smem_len = oi->video_buffer_size;
-       fix->type = FB_TYPE_PACKED_PIXELS;
-       fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-       fix->xpanstep = 1;
-       fix->ypanstep = 1;
-       fix->ywrapstep = 0;
-       fix->line_length = oi->display_byte_stride;
-       fix->accel = FB_ACCEL_NONE;
-       return 0;
-}
-
-/* Check the requested display mode, returning -EINVAL if we can't
-   handle it. */
-
-static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
-{
-       struct osd_info *oi = itv->osd_info;
-       int osd_height_limit;
-       u32 pixclock, hlimit, vlimit;
-
-       IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
-
-       /* Set base references for mode calcs. */
-       if (itv->is_out_50hz) {
-               pixclock = 84316;
-               hlimit = 776;
-               vlimit = 591;
-               osd_height_limit = 576;
-       }
-       else {
-               pixclock = 83926;
-               hlimit = 776;
-               vlimit = 495;
-               osd_height_limit = 480;
-       }
-
-       if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
-               var->transp.offset = 24;
-               var->transp.length = 8;
-               var->red.offset = 16;
-               var->red.length = 8;
-               var->green.offset = 8;
-               var->green.length = 8;
-               var->blue.offset = 0;
-               var->blue.length = 8;
-       }
-       else if (var->bits_per_pixel == 16) {
-               /* To find out the true mode, check green length */
-               switch (var->green.length) {
-                       case 4:
-                               var->red.offset = 8;
-                               var->red.length = 4;
-                               var->green.offset = 4;
-                               var->green.length = 4;
-                               var->blue.offset = 0;
-                               var->blue.length = 4;
-                               var->transp.offset = 12;
-                               var->transp.length = 1;
-                               break;
-                       case 5:
-                               var->red.offset = 10;
-                               var->red.length = 5;
-                               var->green.offset = 5;
-                               var->green.length = 5;
-                               var->blue.offset = 0;
-                               var->blue.length = 5;
-                               var->transp.offset = 15;
-                               var->transp.length = 1;
-                               break;
-                       default:
-                               var->red.offset = 11;
-                               var->red.length = 5;
-                               var->green.offset = 5;
-                               var->green.length = 6;
-                               var->blue.offset = 0;
-                               var->blue.length = 5;
-                               var->transp.offset = 0;
-                               var->transp.length = 0;
-                               break;
-               }
-       }
-       else {
-               IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
-               return -EINVAL;
-       }
-
-       /* Check the resolution */
-       if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
-               IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
-                               var->xres, var->yres);
-               return -EINVAL;
-       }
-
-       /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
-       if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
-           var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
-           var->xres_virtual < var->xres ||
-           var->yres_virtual < var->yres) {
-               IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
-                       var->xres_virtual, var->yres_virtual);
-               return -EINVAL;
-       }
-
-       /* Some extra checks if in 8 bit mode */
-       if (var->bits_per_pixel == 8) {
-               /* Width must be a multiple of 4 */
-               if (var->xres & 3) {
-                       IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
-                       return -EINVAL;
-               }
-               if (var->xres_virtual & 3) {
-                       IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
-                       return -EINVAL;
-               }
-       }
-       else if (var->bits_per_pixel == 16) {
-               /* Width must be a multiple of 2 */
-               if (var->xres & 1) {
-                       IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
-                       return -EINVAL;
-               }
-               if (var->xres_virtual & 1) {
-                       IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
-                       return -EINVAL;
-               }
-       }
-
-       /* Now check the offsets */
-       if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
-               IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
-                       var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
-               return -EINVAL;
-       }
-
-       /* Check pixel format */
-       if (var->nonstd > 1) {
-               IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
-               return -EINVAL;
-       }
-
-       /* Check video mode */
-       if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
-               ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
-               IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
-               return -EINVAL;
-       }
-
-       /* Check the left & upper margins
-          If the margins are too large, just center the screen
-          (enforcing margins causes too many problems) */
-
-       if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
-               var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
-
-       if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
-               var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
-                       var->yres) / 2);
-
-       /* Maintain overall 'size' for a constant refresh rate */
-       var->right_margin = hlimit - var->left_margin - var->xres;
-       var->lower_margin = vlimit - var->upper_margin - var->yres;
-
-       /* Fixed sync times */
-       var->hsync_len = 24;
-       var->vsync_len = 2;
-
-       /* Non-interlaced / interlaced mode is used to switch the OSD filter
-          on or off. Adjust the clock timings to maintain a constant
-          vertical refresh rate. */
-       if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
-               var->pixclock = pixclock / 2;
-       else
-               var->pixclock = pixclock;
-
-       itv->osd_rect.width = var->xres;
-       itv->osd_rect.height = var->yres;
-
-       IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
-                     var->xres, var->yres,
-                     var->xres_virtual, var->yres_virtual,
-                     var->bits_per_pixel);
-
-       IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
-                     var->left_margin, var->upper_margin);
-
-       IVTVFB_DEBUG_INFO("Display filter: %s\n",
-                       (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
-       IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
-       return 0;
-}
-
-static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-       struct ivtv *itv = (struct ivtv *) info->par;
-       IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
-       return _ivtvfb_check_var(var, itv);
-}
-
-static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-       u32 osd_pan_index;
-       struct ivtv *itv = (struct ivtv *) info->par;
-
-       if (var->yoffset + info->var.yres > info->var.yres_virtual ||
-           var->xoffset + info->var.xres > info->var.xres_virtual)
-               return -EINVAL;
-
-       osd_pan_index = var->yoffset * info->fix.line_length
-                     + var->xoffset * info->var.bits_per_pixel / 8;
-       write_reg(osd_pan_index, 0x02A0C);
-
-       /* Pass this info back the yuv handler */
-       itv->yuv_info.osd_x_pan = var->xoffset;
-       itv->yuv_info.osd_y_pan = var->yoffset;
-       /* Force update of yuv registers */
-       itv->yuv_info.yuv_forced_update = 1;
-       /* Remember this value */
-       itv->osd_info->pan_cur = osd_pan_index;
-       return 0;
-}
-
-static int ivtvfb_set_par(struct fb_info *info)
-{
-       int rc = 0;
-       struct ivtv *itv = (struct ivtv *) info->par;
-
-       IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
-
-       rc = ivtvfb_set_var(itv, &info->var);
-       ivtvfb_pan_display(&info->var, info);
-       ivtvfb_get_fix(itv, &info->fix);
-       ivtv_firmware_check(itv, "ivtvfb_set_par");
-       return rc;
-}
-
-static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-                               unsigned blue, unsigned transp,
-                               struct fb_info *info)
-{
-       u32 color, *palette;
-       struct ivtv *itv = (struct ivtv *)info->par;
-
-       if (regno >= info->cmap.len)
-               return -EINVAL;
-
-       color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
-       if (info->var.bits_per_pixel <= 8) {
-               write_reg(regno, 0x02a30);
-               write_reg(color, 0x02a34);
-               itv->osd_info->palette_cur[regno] = color;
-               return 0;
-       }
-       if (regno >= 16)
-               return -EINVAL;
-
-       palette = info->pseudo_palette;
-       if (info->var.bits_per_pixel == 16) {
-               switch (info->var.green.length) {
-                       case 4:
-                               color = ((red & 0xf000) >> 4) |
-                                       ((green & 0xf000) >> 8) |
-                                       ((blue & 0xf000) >> 12);
-                               break;
-                       case 5:
-                               color = ((red & 0xf800) >> 1) |
-                                       ((green & 0xf800) >> 6) |
-                                       ((blue & 0xf800) >> 11);
-                               break;
-                       case 6:
-                               color = (red & 0xf800 ) |
-                                       ((green & 0xfc00) >> 5) |
-                                       ((blue & 0xf800) >> 11);
-                               break;
-               }
-       }
-       palette[regno] = color;
-       return 0;
-}
-
-/* We don't really support blanking. All this does is enable or
-   disable the OSD. */
-static int ivtvfb_blank(int blank_mode, struct fb_info *info)
-{
-       struct ivtv *itv = (struct ivtv *)info->par;
-
-       IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
-       switch (blank_mode) {
-       case FB_BLANK_UNBLANK:
-               ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
-               break;
-       case FB_BLANK_NORMAL:
-       case FB_BLANK_HSYNC_SUSPEND:
-       case FB_BLANK_VSYNC_SUSPEND:
-               ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
-               break;
-       case FB_BLANK_POWERDOWN:
-               ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
-               ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
-               break;
-       }
-       itv->osd_info->blank_cur = blank_mode;
-       return 0;
-}
-
-static struct fb_ops ivtvfb_ops = {
-       .owner = THIS_MODULE,
-       .fb_write       = ivtvfb_write,
-       .fb_check_var   = ivtvfb_check_var,
-       .fb_set_par     = ivtvfb_set_par,
-       .fb_setcolreg   = ivtvfb_setcolreg,
-       .fb_fillrect    = cfb_fillrect,
-       .fb_copyarea    = cfb_copyarea,
-       .fb_imageblit   = cfb_imageblit,
-       .fb_cursor      = NULL,
-       .fb_ioctl       = ivtvfb_ioctl,
-       .fb_pan_display = ivtvfb_pan_display,
-       .fb_blank       = ivtvfb_blank,
-};
-
-/* Restore hardware after firmware restart */
-static void ivtvfb_restore(struct ivtv *itv)
-{
-       struct osd_info *oi = itv->osd_info;
-       int i;
-
-       ivtvfb_set_var(itv, &oi->fbvar_cur);
-       ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
-       for (i = 0; i < 256; i++) {
-               write_reg(i, 0x02a30);
-               write_reg(oi->palette_cur[i], 0x02a34);
-       }
-       write_reg(oi->pan_cur, 0x02a0c);
-}
-
-/* Initialization */
-
-
-/* Setup our initial video mode */
-static int ivtvfb_init_vidmode(struct ivtv *itv)
-{
-       struct osd_info *oi = itv->osd_info;
-       struct v4l2_rect start_window;
-       int max_height;
-
-       /* Color mode */
-
-       if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
-               osd_depth = 8;
-       oi->bits_per_pixel = osd_depth;
-       oi->bytes_per_pixel = oi->bits_per_pixel / 8;
-
-       /* Horizontal size & position */
-
-       if (osd_xres > 720)
-               osd_xres = 720;
-
-       /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
-       if (osd_depth == 8)
-               osd_xres &= ~3;
-       else if (osd_depth == 16)
-               osd_xres &= ~1;
-
-       start_window.width = osd_xres ? osd_xres : 640;
-
-       /* Check horizontal start (osd_left). */
-       if (osd_left && osd_left + start_window.width > 721) {
-               IVTVFB_ERR("Invalid osd_left - assuming default\n");
-               osd_left = 0;
-       }
-
-       /* Hardware coords start at 0, user coords start at 1. */
-       osd_left--;
-
-       start_window.left = osd_left >= 0 ?
-                osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
-
-       oi->display_byte_stride =
-                       start_window.width * oi->bytes_per_pixel;
-
-       /* Vertical size & position */
-
-       max_height = itv->is_out_50hz ? 576 : 480;
-
-       if (osd_yres > max_height)
-               osd_yres = max_height;
-
-       start_window.height = osd_yres ?
-               osd_yres : itv->is_out_50hz ? 480 : 400;
-
-       /* Check vertical start (osd_upper). */
-       if (osd_upper + start_window.height > max_height + 1) {
-               IVTVFB_ERR("Invalid osd_upper - assuming default\n");
-               osd_upper = 0;
-       }
-
-       /* Hardware coords start at 0, user coords start at 1. */
-       osd_upper--;
-
-       start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
-
-       oi->display_width = start_window.width;
-       oi->display_height = start_window.height;
-
-       /* Generate a valid fb_var_screeninfo */
-
-       oi->ivtvfb_defined.xres = oi->display_width;
-       oi->ivtvfb_defined.yres = oi->display_height;
-       oi->ivtvfb_defined.xres_virtual = oi->display_width;
-       oi->ivtvfb_defined.yres_virtual = oi->display_height;
-       oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
-       oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
-       oi->ivtvfb_defined.left_margin = start_window.left + 1;
-       oi->ivtvfb_defined.upper_margin = start_window.top + 1;
-       oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
-       oi->ivtvfb_defined.nonstd = 0;
-
-       /* We've filled in the most data, let the usual mode check
-          routine fill in the rest. */
-       _ivtvfb_check_var(&oi->ivtvfb_defined, itv);
-
-       /* Generate valid fb_fix_screeninfo */
-
-       ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
-
-       /* Generate valid fb_info */
-
-       oi->ivtvfb_info.node = -1;
-       oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
-       oi->ivtvfb_info.fbops = &ivtvfb_ops;
-       oi->ivtvfb_info.par = itv;
-       oi->ivtvfb_info.var = oi->ivtvfb_defined;
-       oi->ivtvfb_info.fix = oi->ivtvfb_fix;
-       oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
-       oi->ivtvfb_info.fbops = &ivtvfb_ops;
-
-       /* Supply some monitor specs. Bogus values will do for now */
-       oi->ivtvfb_info.monspecs.hfmin = 8000;
-       oi->ivtvfb_info.monspecs.hfmax = 70000;
-       oi->ivtvfb_info.monspecs.vfmin = 10;
-       oi->ivtvfb_info.monspecs.vfmax = 100;
-
-       /* Allocate color map */
-       if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
-               IVTVFB_ERR("abort, unable to alloc cmap\n");
-               return -ENOMEM;
-       }
-
-       /* Allocate the pseudo palette */
-       oi->ivtvfb_info.pseudo_palette =
-               kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
-
-       if (!oi->ivtvfb_info.pseudo_palette) {
-               IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
-
-static int ivtvfb_init_io(struct ivtv *itv)
-{
-       struct osd_info *oi = itv->osd_info;
-
-       mutex_lock(&itv->serialize_lock);
-       if (ivtv_init_on_first_open(itv)) {
-               mutex_unlock(&itv->serialize_lock);
-               IVTVFB_ERR("Failed to initialize ivtv\n");
-               return -ENXIO;
-       }
-       mutex_unlock(&itv->serialize_lock);
-
-       if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
-                                       &oi->video_buffer_size) < 0) {
-               IVTVFB_ERR("Firmware failed to respond\n");
-               return -EIO;
-       }
-
-       /* The osd buffer size depends on the number of video buffers allocated
-          on the PVR350 itself. For now we'll hardcode the smallest osd buffer
-          size to prevent any overlap. */
-       oi->video_buffer_size = 1704960;
-
-       oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
-       oi->video_vbase = itv->dec_mem + oi->video_rbase;
-
-       if (!oi->video_vbase) {
-               IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
-                    oi->video_buffer_size, oi->video_pbase);
-               return -EIO;
-       }
-
-       IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-                       oi->video_pbase, oi->video_vbase,
-                       oi->video_buffer_size / 1024);
-
-#ifdef CONFIG_MTRR
-       {
-               /* Find the largest power of two that maps the whole buffer */
-               int size_shift = 31;
-
-               while (!(oi->video_buffer_size & (1 << size_shift))) {
-                       size_shift--;
-               }
-               size_shift++;
-               oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
-               oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
-               oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
-               oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
-               if (mtrr_add(oi->fb_start_aligned_physaddr,
-                       oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
-                            MTRR_TYPE_WRCOMB, 1) < 0) {
-                       IVTVFB_INFO("disabled mttr\n");
-                       oi->fb_start_aligned_physaddr = 0;
-                       oi->fb_end_aligned_physaddr = 0;
-               }
-       }
-#endif
-
-       /* Blank the entire osd. */
-       memset_io(oi->video_vbase, 0, oi->video_buffer_size);
-
-       return 0;
-}
-
-/* Release any memory we've grabbed & remove mtrr entry */
-static void ivtvfb_release_buffers (struct ivtv *itv)
-{
-       struct osd_info *oi = itv->osd_info;
-
-       /* Release cmap */
-       if (oi->ivtvfb_info.cmap.len)
-               fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
-
-       /* Release pseudo palette */
-       if (oi->ivtvfb_info.pseudo_palette)
-               kfree(oi->ivtvfb_info.pseudo_palette);
-
-#ifdef CONFIG_MTRR
-       if (oi->fb_end_aligned_physaddr) {
-               mtrr_del(-1, oi->fb_start_aligned_physaddr,
-                       oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
-       }
-#endif
-
-       kfree(oi);
-       itv->osd_info = NULL;
-}
-
-/* Initialize the specified card */
-
-static int ivtvfb_init_card(struct ivtv *itv)
-{
-       int rc;
-
-       if (itv->osd_info) {
-               IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
-               return -EBUSY;
-       }
-
-       itv->osd_info = kzalloc(sizeof(struct osd_info),
-                                       GFP_ATOMIC|__GFP_NOWARN);
-       if (itv->osd_info == NULL) {
-               IVTVFB_ERR("Failed to allocate memory for osd_info\n");
-               return -ENOMEM;
-       }
-
-       /* Find & setup the OSD buffer */
-       rc = ivtvfb_init_io(itv);
-       if (rc) {
-               ivtvfb_release_buffers(itv);
-               return rc;
-       }
-
-       /* Set the startup video mode information */
-       if ((rc = ivtvfb_init_vidmode(itv))) {
-               ivtvfb_release_buffers(itv);
-               return rc;
-       }
-
-       /* Register the framebuffer */
-       if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
-               ivtvfb_release_buffers(itv);
-               return -EINVAL;
-       }
-
-       itv->osd_video_pbase = itv->osd_info->video_pbase;
-
-       /* Set the card to the requested mode */
-       ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
-
-       /* Set color 0 to black */
-       write_reg(0, 0x02a30);
-       write_reg(0, 0x02a34);
-
-       /* Enable the osd */
-       ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
-
-       /* Enable restart */
-       itv->ivtvfb_restore = ivtvfb_restore;
-
-       /* Allocate DMA */
-       ivtv_udma_alloc(itv);
-       return 0;
-
-}
-
-static int __init ivtvfb_callback_init(struct device *dev, void *p)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-       struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
-
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               if (ivtvfb_init_card(itv) == 0) {
-                       IVTVFB_INFO("Framebuffer registered on %s\n",
-                                       itv->v4l2_dev.name);
-                       (*(int *)p)++;
-               }
-       }
-       return 0;
-}
-
-static int ivtvfb_callback_cleanup(struct device *dev, void *p)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-       struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev);
-       struct osd_info *oi = itv->osd_info;
-
-       if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
-               if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
-                       IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
-                                      itv->instance);
-                       return 0;
-               }
-               IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
-               itv->ivtvfb_restore = NULL;
-               ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
-               ivtvfb_release_buffers(itv);
-               itv->osd_video_pbase = 0;
-       }
-       return 0;
-}
-
-static int __init ivtvfb_init(void)
-{
-       struct device_driver *drv;
-       int registered = 0;
-       int err;
-
-       if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
-               printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
-                    IVTV_MAX_CARDS - 1);
-               return -EINVAL;
-       }
-
-       drv = driver_find("ivtv", &pci_bus_type);
-       err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
-       (void)err;      /* suppress compiler warning */
-       if (!registered) {
-               printk(KERN_ERR "ivtvfb:  no cards found\n");
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static void ivtvfb_cleanup(void)
-{
-       struct device_driver *drv;
-       int err;
-
-       printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");
-
-       drv = driver_find("ivtv", &pci_bus_type);
-       err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
-       (void)err;      /* suppress compiler warning */
-}
-
-module_init(ivtvfb_init);
-module_exit(ivtvfb_cleanup);
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
deleted file mode 100644 (file)
index 39fc018..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-config VIDEO_SAA7134
-       tristate "Philips SAA7134 support"
-       depends on VIDEO_DEV && PCI && I2C
-       select VIDEOBUF_DMA_SG
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select CRC32
-       select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         This is a video4linux driver for Philips SAA713x based
-         TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7134.
-
-config VIDEO_SAA7134_ALSA
-       tristate "Philips SAA7134 DMA audio support"
-       depends on VIDEO_SAA7134 && SND
-       select SND_PCM
-       ---help---
-         This is a video4linux driver for direct (DMA) audio in
-         Philips SAA713x based TV cards using ALSA
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7134-alsa.
-
-config VIDEO_SAA7134_RC
-       bool "Philips SAA7134 Remote Controller support"
-       depends on RC_CORE
-       depends on VIDEO_SAA7134
-       depends on !(RC_CORE=m && VIDEO_SAA7134=y)
-       default y
-       ---help---
-         Enables Remote Controller support on saa7134 driver.
-
-config VIDEO_SAA7134_DVB
-       tristate "DVB/ATSC Support for saa7134 based TV cards"
-       depends on VIDEO_SAA7134 && DVB_CORE
-       select VIDEOBUF_DVB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select DVB_NXT200X if !DVB_FE_CUSTOMISE
-       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-       select DVB_TDA826X if !DVB_FE_CUSTOMISE
-       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select DVB_ISL6405 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select DVB_ZL10036 if !DVB_FE_CUSTOMISE
-       select DVB_MT312 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       select DVB_ZL10039 if !DVB_FE_CUSTOMISE
-       ---help---
-         This adds support for DVB cards based on the
-         Philips saa7134 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7134-dvb.
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
deleted file mode 100644 (file)
index aba5008..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-
-saa7134-y :=   saa7134-cards.o saa7134-core.o saa7134-i2c.o
-saa7134-y +=   saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
-saa7134-y +=   saa7134-video.o
-saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
-
-obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o
-
-obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
-
-obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
-
-ccflags-y += -I$(srctree)/drivers/media/video
-ccflags-y += -I$(srctree)/drivers/media/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
deleted file mode 100644 (file)
index f147b05..0000000
+++ /dev/null
@@ -1,1012 +0,0 @@
- /*
-    saa6752hs - i2c-driver for the saa6752hs by Philips
-
-    Copyright (C) 2004 Andrew de Quincey
-
-    AC-3 support:
-
-    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License vs 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 Mvss Ave, Cambridge, MA 02139, USA.
-  */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-chip-ident.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-
-#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
-#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
-#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
-#define MPEG_PID_MAX ((1 << 14) - 1)
-
-
-MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
-MODULE_AUTHOR("Andrew de Quincey");
-MODULE_LICENSE("GPL");
-
-enum saa6752hs_videoformat {
-       SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
-       SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
-       SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
-       SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
-       SAA6752HS_VF_UNKNOWN,
-};
-
-struct saa6752hs_mpeg_params {
-       /* transport streams */
-       __u16                           ts_pid_pmt;
-       __u16                           ts_pid_audio;
-       __u16                           ts_pid_video;
-       __u16                           ts_pid_pcr;
-
-       /* audio */
-       enum v4l2_mpeg_audio_encoding    au_encoding;
-       enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
-       enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
-
-       /* video */
-       enum v4l2_mpeg_video_aspect     vi_aspect;
-       enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
-       __u32                           vi_bitrate;
-       __u32                           vi_bitrate_peak;
-};
-
-static const struct v4l2_format v4l2_format_table[] =
-{
-       [SAA6752HS_VF_D1] =
-               { .fmt = { .pix = { .width = 720, .height = 576 }}},
-       [SAA6752HS_VF_2_3_D1] =
-               { .fmt = { .pix = { .width = 480, .height = 576 }}},
-       [SAA6752HS_VF_1_2_D1] =
-               { .fmt = { .pix = { .width = 352, .height = 576 }}},
-       [SAA6752HS_VF_SIF] =
-               { .fmt = { .pix = { .width = 352, .height = 288 }}},
-       [SAA6752HS_VF_UNKNOWN] =
-               { .fmt = { .pix = { .width = 0, .height = 0}}},
-};
-
-struct saa6752hs_state {
-       struct v4l2_subdev            sd;
-       int                           chip;
-       u32                           revision;
-       int                           has_ac3;
-       struct saa6752hs_mpeg_params  params;
-       enum saa6752hs_videoformat    video_format;
-       v4l2_std_id                   standard;
-};
-
-enum saa6752hs_command {
-       SAA6752HS_COMMAND_RESET = 0,
-       SAA6752HS_COMMAND_STOP = 1,
-       SAA6752HS_COMMAND_START = 2,
-       SAA6752HS_COMMAND_PAUSE = 3,
-       SAA6752HS_COMMAND_RECONFIGURE = 4,
-       SAA6752HS_COMMAND_SLEEP = 5,
-       SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
-
-       SAA6752HS_COMMAND_MAX
-};
-
-static inline struct saa6752hs_state *to_state(struct v4l2_subdev *sd)
-{
-       return container_of(sd, struct saa6752hs_state, sd);
-}
-
-/* ---------------------------------------------------------------------- */
-
-static u8 PAT[] = {
-       0xc2, /* i2c register */
-       0x00, /* table number for encoder */
-
-       0x47, /* sync */
-       0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
-       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
-       0x00, /* PSI pointer to start of table */
-
-       0x00, /* tid(0) */
-       0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
-
-       0x00, 0x01, /* transport_stream_id(1) */
-
-       0xc1, /* version_number(0), current_next_indicator(1) */
-
-       0x00, 0x00, /* section_number(0), last_section_number(0) */
-
-       0x00, 0x01, /* program_number(1) */
-
-       0xe0, 0x00, /* PMT PID */
-
-       0x00, 0x00, 0x00, 0x00 /* CRC32 */
-};
-
-static u8 PMT[] = {
-       0xc2, /* i2c register */
-       0x01, /* table number for encoder */
-
-       0x47, /* sync */
-       0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
-       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
-       0x00, /* PSI pointer to start of table */
-
-       0x02, /* tid(2) */
-       0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
-
-       0x00, 0x01, /* program_number(1) */
-
-       0xc1, /* version_number(0), current_next_indicator(1) */
-
-       0x00, 0x00, /* section_number(0), last_section_number(0) */
-
-       0xe0, 0x00, /* PCR_PID */
-
-       0xf0, 0x00, /* program_info_length(0) */
-
-       0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
-       0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
-
-       0x00, 0x00, 0x00, 0x00 /* CRC32 */
-};
-
-static u8 PMT_AC3[] = {
-       0xc2, /* i2c register */
-       0x01, /* table number for encoder(1) */
-       0x47, /* sync */
-
-       0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
-       0x10, /* PMT PID (0x0010) */
-       0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
-
-       0x00, /* PSI pointer to start of table */
-
-       0x02, /* TID (2) */
-       0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
-
-       0x00, 0x01, /* program_number(1) */
-
-       0xc1, /* version_number(0), current_next_indicator(1) */
-
-       0x00, 0x00, /* section_number(0), last_section_number(0) */
-
-       0xe1, 0x04, /* PCR_PID (0x0104) */
-
-       0xf0, 0x00, /* program_info_length(0) */
-
-       0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
-       0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
-       0x6a, /* AC3 */
-       0x01, /* Descriptor_length(1) */
-       0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
-
-       0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
-};
-
-static struct saa6752hs_mpeg_params param_defaults =
-{
-       .ts_pid_pmt      = 16,
-       .ts_pid_video    = 260,
-       .ts_pid_audio    = 256,
-       .ts_pid_pcr      = 259,
-
-       .vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
-       .vi_bitrate      = 4000,
-       .vi_bitrate_peak = 6000,
-       .vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-
-       .au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-       .au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
-       .au_ac3_bitrate  = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int saa6752hs_chip_command(struct i2c_client *client,
-                                 enum saa6752hs_command command)
-{
-       unsigned char buf[3];
-       unsigned long timeout;
-       int status = 0;
-
-       /* execute the command */
-       switch(command) {
-       case SAA6752HS_COMMAND_RESET:
-               buf[0] = 0x00;
-               break;
-
-       case SAA6752HS_COMMAND_STOP:
-               buf[0] = 0x03;
-               break;
-
-       case SAA6752HS_COMMAND_START:
-               buf[0] = 0x02;
-               break;
-
-       case SAA6752HS_COMMAND_PAUSE:
-               buf[0] = 0x04;
-               break;
-
-       case SAA6752HS_COMMAND_RECONFIGURE:
-               buf[0] = 0x05;
-               break;
-
-       case SAA6752HS_COMMAND_SLEEP:
-               buf[0] = 0x06;
-               break;
-
-       case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
-               buf[0] = 0x07;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* set it and wait for it to be so */
-       i2c_master_send(client, buf, 1);
-       timeout = jiffies + HZ * 3;
-       for (;;) {
-               /* get the current status */
-               buf[0] = 0x10;
-               i2c_master_send(client, buf, 1);
-               i2c_master_recv(client, buf, 1);
-
-               if (!(buf[0] & 0x20))
-                       break;
-               if (time_after(jiffies,timeout)) {
-                       status = -ETIMEDOUT;
-                       break;
-               }
-
-               msleep(10);
-       }
-
-       /* delay a bit to let encoder settle */
-       msleep(50);
-
-       return status;
-}
-
-
-static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
-{
-       u8 buf[2];
-
-       buf[0] = reg;
-       buf[1] = val;
-       i2c_master_send(client, buf, 2);
-}
-
-static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
-{
-       u8 buf[3];
-
-       buf[0] = reg;
-       buf[1] = val >> 8;
-       buf[2] = val & 0xff;
-       i2c_master_send(client, buf, 3);
-}
-
-static int saa6752hs_set_bitrate(struct i2c_client *client,
-                                struct saa6752hs_state *h)
-{
-       struct saa6752hs_mpeg_params *params = &h->params;
-       int tot_bitrate;
-       int is_384k;
-
-       /* set the bitrate mode */
-       set_reg8(client, 0x71,
-               params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-
-       /* set the video bitrate */
-       if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
-               /* set the target bitrate */
-               set_reg16(client, 0x80, params->vi_bitrate);
-
-               /* set the max bitrate */
-               set_reg16(client, 0x81, params->vi_bitrate_peak);
-               tot_bitrate = params->vi_bitrate_peak;
-       } else {
-               /* set the target bitrate (no max bitrate for CBR) */
-               set_reg16(client, 0x81, params->vi_bitrate);
-               tot_bitrate = params->vi_bitrate;
-       }
-
-       /* set the audio encoding */
-       set_reg8(client, 0x93,
-                       params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
-
-       /* set the audio bitrate */
-       if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
-               is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
-       else
-               is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
-       set_reg8(client, 0x94, is_384k);
-       tot_bitrate += is_384k ? 384 : 256;
-
-       /* Note: the total max bitrate is determined by adding the video and audio
-          bitrates together and also adding an extra 768kbit/s to stay on the
-          safe side. If more control should be required, then an extra MPEG control
-          should be added. */
-       tot_bitrate += 768;
-       if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
-               tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
-
-       /* set the total bitrate */
-       set_reg16(client, 0xb1, tot_bitrate);
-       return 0;
-}
-
-
-static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
-               struct v4l2_ext_control *ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_PMT:
-               ctrl->value = params->ts_pid_pmt;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
-               ctrl->value = params->ts_pid_audio;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
-               ctrl->value = params->ts_pid_video;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_PCR:
-               ctrl->value = params->ts_pid_pcr;
-               break;
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               ctrl->value = params->au_encoding;
-               break;
-       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-               ctrl->value = params->au_l2_bitrate;
-               break;
-       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-               if (!has_ac3)
-                       return -EINVAL;
-               ctrl->value = params->au_ac3_bitrate;
-               break;
-       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
-               ctrl->value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               ctrl->value = params->vi_aspect;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               ctrl->value = params->vi_bitrate * 1000;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               ctrl->value = params->vi_bitrate_peak * 1000;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               ctrl->value = params->vi_bitrate_mode;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int handle_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
-               struct v4l2_ext_control *ctrl, int set)
-{
-       int old = 0, new;
-
-       new = ctrl->value;
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
-               if (set && new != old)
-                       return -ERANGE;
-               new = old;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_PMT:
-               old = params->ts_pid_pmt;
-               if (set && new > MPEG_PID_MAX)
-                       return -ERANGE;
-               if (new > MPEG_PID_MAX)
-                       new = MPEG_PID_MAX;
-               params->ts_pid_pmt = new;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
-               old = params->ts_pid_audio;
-               if (set && new > MPEG_PID_MAX)
-                       return -ERANGE;
-               if (new > MPEG_PID_MAX)
-                       new = MPEG_PID_MAX;
-               params->ts_pid_audio = new;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
-               old = params->ts_pid_video;
-               if (set && new > MPEG_PID_MAX)
-                       return -ERANGE;
-               if (new > MPEG_PID_MAX)
-                       new = MPEG_PID_MAX;
-               params->ts_pid_video = new;
-               break;
-       case V4L2_CID_MPEG_STREAM_PID_PCR:
-               old = params->ts_pid_pcr;
-               if (set && new > MPEG_PID_MAX)
-                       return -ERANGE;
-               if (new > MPEG_PID_MAX)
-                       new = MPEG_PID_MAX;
-               params->ts_pid_pcr = new;
-               break;
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               old = params->au_encoding;
-               if (set && new != V4L2_MPEG_AUDIO_ENCODING_LAYER_2 &&
-                   (!has_ac3 || new != V4L2_MPEG_AUDIO_ENCODING_AC3))
-                       return -ERANGE;
-               params->au_encoding = new;
-               break;
-       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-               old = params->au_l2_bitrate;
-               if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
-                          new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
-                       return -ERANGE;
-               if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
-                       new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
-               else
-                       new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
-               params->au_l2_bitrate = new;
-               break;
-       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-               if (!has_ac3)
-                       return -EINVAL;
-               old = params->au_ac3_bitrate;
-               if (set && new != V4L2_MPEG_AUDIO_AC3_BITRATE_256K &&
-                          new != V4L2_MPEG_AUDIO_AC3_BITRATE_384K)
-                       return -ERANGE;
-               if (new <= V4L2_MPEG_AUDIO_AC3_BITRATE_256K)
-                       new = V4L2_MPEG_AUDIO_AC3_BITRATE_256K;
-               else
-                       new = V4L2_MPEG_AUDIO_AC3_BITRATE_384K;
-               params->au_ac3_bitrate = new;
-               break;
-       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
-               old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
-               if (set && new != old)
-                       return -ERANGE;
-               new = old;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
-               if (set && new != old)
-                       return -ERANGE;
-               new = old;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               old = params->vi_aspect;
-               if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
-                          new != V4L2_MPEG_VIDEO_ASPECT_4x3)
-                       return -ERANGE;
-               if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
-                       new = V4L2_MPEG_VIDEO_ASPECT_4x3;
-               params->vi_aspect = new;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               old = params->vi_bitrate * 1000;
-               new = 1000 * (new / 1000);
-               if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-                       return -ERANGE;
-               if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-                       new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
-               params->vi_bitrate = new / 1000;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               old = params->vi_bitrate_peak * 1000;
-               new = 1000 * (new / 1000);
-               if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-                       return -ERANGE;
-               if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
-                       new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
-               params->vi_bitrate_peak = new / 1000;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               old = params->vi_bitrate_mode;
-               params->vi_bitrate_mode = new;
-               break;
-       default:
-               return -EINVAL;
-       }
-       ctrl->value = new;
-       return 0;
-}
-
-
-static int saa6752hs_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
-{
-       struct saa6752hs_state *h = to_state(sd);
-       struct saa6752hs_mpeg_params *params = &h->params;
-       int err;
-
-       switch (qctrl->id) {
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-                               h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
-                                       V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-                               1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
-
-       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_AUDIO_L2_BITRATE_256K,
-                               V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
-                               V4L2_MPEG_AUDIO_L2_BITRATE_256K);
-
-       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-               if (!h->has_ac3)
-                       return -EINVAL;
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
-                               V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
-                               V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
-
-       case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
-                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
-                               V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
-
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
-                               V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
-
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_VIDEO_ASPECT_4x3,
-                               V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
-                               V4L2_MPEG_VIDEO_ASPECT_4x3);
-
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
-               if (err == 0 &&
-                   params->vi_bitrate_mode ==
-                               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
-                       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
-               return err;
-
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
-                               V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
-                               V4L2_MPEG_STREAM_TYPE_MPEG2_TS);
-
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               return v4l2_ctrl_query_fill(qctrl,
-                               V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-                               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
-                               V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
-       case V4L2_CID_MPEG_STREAM_PID_PMT:
-               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
-       case V4L2_CID_MPEG_STREAM_PID_AUDIO:
-               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
-       case V4L2_CID_MPEG_STREAM_PID_VIDEO:
-               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
-       case V4L2_CID_MPEG_STREAM_PID_PCR:
-               return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
-
-       default:
-               break;
-       }
-       return -EINVAL;
-}
-
-static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
-{
-       static const u32 mpeg_audio_encoding[] = {
-               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-               V4L2_CTRL_MENU_IDS_END
-       };
-       static const u32 mpeg_audio_ac3_encoding[] = {
-               V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
-               V4L2_MPEG_AUDIO_ENCODING_AC3,
-               V4L2_CTRL_MENU_IDS_END
-       };
-       static u32 mpeg_audio_l2_bitrate[] = {
-               V4L2_MPEG_AUDIO_L2_BITRATE_256K,
-               V4L2_MPEG_AUDIO_L2_BITRATE_384K,
-               V4L2_CTRL_MENU_IDS_END
-       };
-       static u32 mpeg_audio_ac3_bitrate[] = {
-               V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
-               V4L2_MPEG_AUDIO_AC3_BITRATE_384K,
-               V4L2_CTRL_MENU_IDS_END
-       };
-       struct saa6752hs_state *h = to_state(sd);
-       struct v4l2_queryctrl qctrl;
-       int err;
-
-       qctrl.id = qmenu->id;
-       err = saa6752hs_queryctrl(sd, &qctrl);
-       if (err)
-               return err;
-       switch (qmenu->id) {
-       case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
-               return v4l2_ctrl_query_menu_valid_items(qmenu,
-                               mpeg_audio_l2_bitrate);
-       case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
-               if (!h->has_ac3)
-                       return -EINVAL;
-               return v4l2_ctrl_query_menu_valid_items(qmenu,
-                               mpeg_audio_ac3_bitrate);
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               return v4l2_ctrl_query_menu_valid_items(qmenu,
-                       h->has_ac3 ? mpeg_audio_ac3_encoding :
-                               mpeg_audio_encoding);
-       }
-       return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
-}
-
-static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
-{
-       unsigned char buf[9], buf2[4];
-       struct saa6752hs_state *h = to_state(sd);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       unsigned size;
-       u32 crc;
-       unsigned char localPAT[256];
-       unsigned char localPMT[256];
-
-       /* Set video format - must be done first as it resets other settings */
-       set_reg8(client, 0x41, h->video_format);
-
-       /* Set number of lines in input signal */
-       set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
-
-       /* set bitrate */
-       saa6752hs_set_bitrate(client, h);
-
-       /* Set GOP structure {3, 13} */
-       set_reg16(client, 0x72, 0x030d);
-
-       /* Set minimum Q-scale {4} */
-       set_reg8(client, 0x82, 0x04);
-
-       /* Set maximum Q-scale {12} */
-       set_reg8(client, 0x83, 0x0c);
-
-       /* Set Output Protocol */
-       set_reg8(client, 0xd0, 0x81);
-
-       /* Set video output stream format {TS} */
-       set_reg8(client, 0xb0, 0x05);
-
-       /* Set leading null byte for TS */
-       set_reg16(client, 0xf6, leading_null_bytes);
-
-       /* compute PAT */
-       memcpy(localPAT, PAT, sizeof(PAT));
-       localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
-       localPAT[18] = h->params.ts_pid_pmt & 0xff;
-       crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
-       localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
-       localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
-       localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
-       localPAT[sizeof(PAT) - 1] = crc & 0xFF;
-
-       /* compute PMT */
-       if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
-               size = sizeof(PMT_AC3);
-               memcpy(localPMT, PMT_AC3, size);
-       } else {
-               size = sizeof(PMT);
-               memcpy(localPMT, PMT, size);
-       }
-       localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
-       localPMT[4] = h->params.ts_pid_pmt & 0xff;
-       localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
-       localPMT[16] = h->params.ts_pid_pcr & 0xFF;
-       localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
-       localPMT[21] = h->params.ts_pid_video & 0xFF;
-       localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
-       localPMT[26] = h->params.ts_pid_audio & 0xFF;
-       crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
-       localPMT[size - 4] = (crc >> 24) & 0xFF;
-       localPMT[size - 3] = (crc >> 16) & 0xFF;
-       localPMT[size - 2] = (crc >> 8) & 0xFF;
-       localPMT[size - 1] = crc & 0xFF;
-
-       /* Set Audio PID */
-       set_reg16(client, 0xc1, h->params.ts_pid_audio);
-
-       /* Set Video PID */
-       set_reg16(client, 0xc0, h->params.ts_pid_video);
-
-       /* Set PCR PID */
-       set_reg16(client, 0xc4, h->params.ts_pid_pcr);
-
-       /* Send SI tables */
-       i2c_master_send(client, localPAT, sizeof(PAT));
-       i2c_master_send(client, localPMT, size);
-
-       /* mute then unmute audio. This removes buzzing artefacts */
-       set_reg8(client, 0xa4, 1);
-       set_reg8(client, 0xa4, 0);
-
-       /* start it going */
-       saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
-
-       /* readout current state */
-       buf[0] = 0xE1;
-       buf[1] = 0xA7;
-       buf[2] = 0xFE;
-       buf[3] = 0x82;
-       buf[4] = 0xB0;
-       i2c_master_send(client, buf, 5);
-       i2c_master_recv(client, buf2, 4);
-
-       /* change aspect ratio */
-       buf[0] = 0xE0;
-       buf[1] = 0xA7;
-       buf[2] = 0xFE;
-       buf[3] = 0x82;
-       buf[4] = 0xB0;
-       buf[5] = buf2[0];
-       switch (h->params.vi_aspect) {
-       case V4L2_MPEG_VIDEO_ASPECT_16x9:
-               buf[6] = buf2[1] | 0x40;
-               break;
-       case V4L2_MPEG_VIDEO_ASPECT_4x3:
-       default:
-               buf[6] = buf2[1] & 0xBF;
-               break;
-       }
-       buf[7] = buf2[2];
-       buf[8] = buf2[3];
-       i2c_master_send(client, buf, 9);
-
-       return 0;
-}
-
-static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
-{
-       struct saa6752hs_state *h = to_state(sd);
-       struct saa6752hs_mpeg_params params;
-       int i;
-
-       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       params = h->params;
-       for (i = 0; i < ctrls->count; i++) {
-               int err = handle_ctrl(h->has_ac3, &params, ctrls->controls + i, set);
-
-               if (err) {
-                       ctrls->error_idx = i;
-                       return err;
-               }
-       }
-       if (set)
-               h->params = params;
-       return 0;
-}
-
-static int saa6752hs_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
-{
-       return saa6752hs_do_ext_ctrls(sd, ctrls, 1);
-}
-
-static int saa6752hs_try_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
-{
-       return saa6752hs_do_ext_ctrls(sd, ctrls, 0);
-}
-
-static int saa6752hs_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls)
-{
-       struct saa6752hs_state *h = to_state(sd);
-       int i;
-
-       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       for (i = 0; i < ctrls->count; i++) {
-               int err = get_ctrl(h->has_ac3, &h->params, ctrls->controls + i);
-
-               if (err) {
-                       ctrls->error_idx = i;
-                       return err;
-               }
-       }
-       return 0;
-}
-
-static int saa6752hs_g_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
-       struct saa6752hs_state *h = to_state(sd);
-
-       if (h->video_format == SAA6752HS_VF_UNKNOWN)
-               h->video_format = SAA6752HS_VF_D1;
-       f->width = v4l2_format_table[h->video_format].fmt.pix.width;
-       f->height = v4l2_format_table[h->video_format].fmt.pix.height;
-       f->code = V4L2_MBUS_FMT_FIXED;
-       f->field = V4L2_FIELD_INTERLACED;
-       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       return 0;
-}
-
-static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
-{
-       struct saa6752hs_state *h = to_state(sd);
-       int dist_352, dist_480, dist_720;
-
-       if (f->code != V4L2_MBUS_FMT_FIXED)
-               return -EINVAL;
-
-       /*
-         FIXME: translate and round width/height into EMPRESS
-         subsample type:
-
-         type   |   PAL   |  NTSC
-         ---------------------------
-         SIF    | 352x288 | 352x240
-         1/2 D1 | 352x576 | 352x480
-         2/3 D1 | 480x576 | 480x480
-         D1     | 720x576 | 720x480
-       */
-
-       dist_352 = abs(f->width - 352);
-       dist_480 = abs(f->width - 480);
-       dist_720 = abs(f->width - 720);
-       if (dist_720 < dist_480) {
-               f->width = 720;
-               f->height = 576;
-               h->video_format = SAA6752HS_VF_D1;
-       } else if (dist_480 < dist_352) {
-               f->width = 480;
-               f->height = 576;
-               h->video_format = SAA6752HS_VF_2_3_D1;
-       } else {
-               f->width = 352;
-               if (abs(f->height - 576) <
-                   abs(f->height - 288)) {
-                       f->height = 576;
-                       h->video_format = SAA6752HS_VF_1_2_D1;
-               } else {
-                       f->height = 288;
-                       h->video_format = SAA6752HS_VF_SIF;
-               }
-       }
-       f->field = V4L2_FIELD_INTERLACED;
-       f->colorspace = V4L2_COLORSPACE_SMPTE170M;
-       return 0;
-}
-
-static int saa6752hs_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
-{
-       struct saa6752hs_state *h = to_state(sd);
-
-       h->standard = std;
-       return 0;
-}
-
-static int saa6752hs_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct saa6752hs_state *h = to_state(sd);
-
-       return v4l2_chip_ident_i2c_client(client,
-                       chip, h->chip, h->revision);
-}
-
-/* ----------------------------------------------------------------------- */
-
-static const struct v4l2_subdev_core_ops saa6752hs_core_ops = {
-       .g_chip_ident = saa6752hs_g_chip_ident,
-       .init = saa6752hs_init,
-       .queryctrl = saa6752hs_queryctrl,
-       .querymenu = saa6752hs_querymenu,
-       .g_ext_ctrls = saa6752hs_g_ext_ctrls,
-       .s_ext_ctrls = saa6752hs_s_ext_ctrls,
-       .try_ext_ctrls = saa6752hs_try_ext_ctrls,
-       .s_std = saa6752hs_s_std,
-};
-
-static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
-       .s_mbus_fmt = saa6752hs_s_mbus_fmt,
-       .g_mbus_fmt = saa6752hs_g_mbus_fmt,
-};
-
-static const struct v4l2_subdev_ops saa6752hs_ops = {
-       .core = &saa6752hs_core_ops,
-       .video = &saa6752hs_video_ops,
-};
-
-static int saa6752hs_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
-{
-       struct saa6752hs_state *h = kzalloc(sizeof(*h), GFP_KERNEL);
-       struct v4l2_subdev *sd;
-       u8 addr = 0x13;
-       u8 data[12];
-
-       v4l_info(client, "chip found @ 0x%x (%s)\n",
-                       client->addr << 1, client->adapter->name);
-       if (h == NULL)
-               return -ENOMEM;
-       sd = &h->sd;
-       v4l2_i2c_subdev_init(sd, client, &saa6752hs_ops);
-
-       i2c_master_send(client, &addr, 1);
-       i2c_master_recv(client, data, sizeof(data));
-       h->chip = V4L2_IDENT_SAA6752HS;
-       h->revision = (data[8] << 8) | data[9];
-       h->has_ac3 = 0;
-       if (h->revision == 0x0206) {
-               h->chip = V4L2_IDENT_SAA6752HS_AC3;
-               h->has_ac3 = 1;
-               v4l_info(client, "support AC-3\n");
-       }
-       h->params = param_defaults;
-       h->standard = 0; /* Assume 625 input lines */
-       return 0;
-}
-
-static int saa6752hs_remove(struct i2c_client *client)
-{
-       struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-       v4l2_device_unregister_subdev(sd);
-       kfree(to_state(sd));
-       return 0;
-}
-
-static const struct i2c_device_id saa6752hs_id[] = {
-       { "saa6752hs", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
-
-static struct i2c_driver saa6752hs_driver = {
-       .driver = {
-               .owner  = THIS_MODULE,
-               .name   = "saa6752hs",
-       },
-       .probe          = saa6752hs_probe,
-       .remove         = saa6752hs_remove,
-       .id_table       = saa6752hs_id,
-};
-
-module_i2c_driver(saa6752hs_driver);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
deleted file mode 100644 (file)
index 10460fd..0000000
+++ /dev/null
@@ -1,1209 +0,0 @@
-/*
- *   SAA713x ALSA support for V4L
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation, version 2
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <linux/interrupt.h>
-
-#include "saa7134.h"
-#include "saa7134-reg.h"
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
-
-/*
- * Configuration macros
- */
-
-/* defaults */
-#define MIXER_ADDR_UNSELECTED  -1
-#define MIXER_ADDR_TVTUNER     0
-#define MIXER_ADDR_LINE1       1
-#define MIXER_ADDR_LINE2       2
-#define MIXER_ADDR_LAST                2
-
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
-
-module_param_array(index, int, NULL, 0444);
-module_param_array(enable, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
-MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s).");
-
-#define dprintk(fmt, arg...)    if (debug) \
-       printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg)
-
-
-
-/*
- * Main chip structure
- */
-
-typedef struct snd_card_saa7134 {
-       struct snd_card *card;
-       spinlock_t mixer_lock;
-       int mixer_volume[MIXER_ADDR_LAST+1][2];
-       int capture_source_addr;
-       int capture_source[2];
-       struct snd_kcontrol *capture_ctl[MIXER_ADDR_LAST+1];
-       struct pci_dev *pci;
-       struct saa7134_dev *dev;
-
-       unsigned long iobase;
-       s16 irq;
-       u16 mute_was_on;
-
-       spinlock_t lock;
-} snd_card_saa7134_t;
-
-
-/*
- * PCM structure
- */
-
-typedef struct snd_card_saa7134_pcm {
-       struct saa7134_dev *dev;
-
-       spinlock_t lock;
-
-       struct snd_pcm_substream *substream;
-} snd_card_saa7134_pcm_t;
-
-static struct snd_card *snd_saa7134_cards[SNDRV_CARDS];
-
-
-/*
- * saa7134 DMA audio stop
- *
- *   Called when the capture device is released or the buffer overflows
- *
- *   - Copied verbatim from saa7134-oss's dsp_dma_stop.
- *
- */
-
-static void saa7134_dma_stop(struct saa7134_dev *dev)
-{
-       dev->dmasound.dma_blk     = -1;
-       dev->dmasound.dma_running = 0;
-       saa7134_set_dmabits(dev);
-}
-
-/*
- * saa7134 DMA audio start
- *
- *   Called when preparing the capture device for use
- *
- *   - Copied verbatim from saa7134-oss's dsp_dma_start.
- *
- */
-
-static void saa7134_dma_start(struct saa7134_dev *dev)
-{
-       dev->dmasound.dma_blk     = 0;
-       dev->dmasound.dma_running = 1;
-       saa7134_set_dmabits(dev);
-}
-
-/*
- * saa7134 audio DMA IRQ handler
- *
- *   Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt
- *   Handles shifting between the 2 buffers, manages the read counters,
- *  and notifies ALSA when periods elapse
- *
- *   - Mostly copied from saa7134-oss's saa7134_irq_oss_done.
- *
- */
-
-static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
-                                 unsigned long status)
-{
-       int next_blk, reg = 0;
-
-       spin_lock(&dev->slock);
-       if (UNSET == dev->dmasound.dma_blk) {
-               dprintk("irq: recording stopped\n");
-               goto done;
-       }
-       if (0 != (status & 0x0f000000))
-               dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
-       if (0 == (status & 0x10000000)) {
-               /* odd */
-               if (0 == (dev->dmasound.dma_blk & 0x01))
-                       reg = SAA7134_RS_BA1(6);
-       } else {
-               /* even */
-               if (1 == (dev->dmasound.dma_blk & 0x01))
-                       reg = SAA7134_RS_BA2(6);
-       }
-       if (0 == reg) {
-               dprintk("irq: field oops [%s]\n",
-                       (status & 0x10000000) ? "even" : "odd");
-               goto done;
-       }
-
-       if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
-               dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
-                       dev->dmasound.bufsize, dev->dmasound.blocks);
-               spin_unlock(&dev->slock);
-               snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
-               return;
-       }
-
-       /* next block addr */
-       next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
-       saa_writel(reg,next_blk * dev->dmasound.blksize);
-       if (debug > 2)
-               dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
-                       (status & 0x10000000) ? "even" : "odd ", next_blk,
-                       next_blk * dev->dmasound.blksize, dev->dmasound.blocks, dev->dmasound.blksize, dev->dmasound.read_count);
-
-       /* update status & wake waiting readers */
-       dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
-       dev->dmasound.read_count += dev->dmasound.blksize;
-
-       dev->dmasound.recording_on = reg;
-
-       if (dev->dmasound.read_count >= snd_pcm_lib_period_bytes(dev->dmasound.substream)) {
-               spin_unlock(&dev->slock);
-               snd_pcm_period_elapsed(dev->dmasound.substream);
-               spin_lock(&dev->slock);
-       }
-
- done:
-       spin_unlock(&dev->slock);
-
-}
-
-/*
- * IRQ request handler
- *
- *   Runs along with saa7134's IRQ handler, discards anything that isn't
- *   DMA sound
- *
- */
-
-static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id)
-{
-       struct saa7134_dmasound *dmasound = dev_id;
-       struct saa7134_dev *dev = dmasound->priv_data;
-
-       unsigned long report, status;
-       int loop, handled = 0;
-
-       for (loop = 0; loop < 10; loop++) {
-               report = saa_readl(SAA7134_IRQ_REPORT);
-               status = saa_readl(SAA7134_IRQ_STATUS);
-
-               if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
-                       handled = 1;
-                       saa_writel(SAA7134_IRQ_REPORT,
-                                  SAA7134_IRQ_REPORT_DONE_RA3);
-                       saa7134_irq_alsa_done(dev, status);
-               } else {
-                       goto out;
-               }
-       }
-
-       if (loop == 10) {
-               dprintk("error! looping IRQ!");
-       }
-
-out:
-       return IRQ_RETVAL(handled);
-}
-
-/*
- * ALSA capture trigger
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called whenever a capture is started or stopped. Must be defined,
- *   but there's nothing we want to do here
- *
- */
-
-static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream,
-                                         int cmd)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
-       struct saa7134_dev *dev=pcm->dev;
-       int err = 0;
-
-       spin_lock(&dev->slock);
-       if (cmd == SNDRV_PCM_TRIGGER_START) {
-               /* start dma */
-               saa7134_dma_start(dev);
-       } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
-               /* stop dma */
-               saa7134_dma_stop(dev);
-       } else {
-               err = -EINVAL;
-       }
-       spin_unlock(&dev->slock);
-
-       return err;
-}
-
-/*
- * DMA buffer initialization
- *
- *   Uses V4L functions to initialize the DMA. Shouldn't be necessary in
- *  ALSA, but I was unable to use ALSA's own DMA, and had to force the
- *  usage of V4L's
- *
- *   - Copied verbatim from saa7134-oss.
- *
- */
-
-static int dsp_buffer_init(struct saa7134_dev *dev)
-{
-       int err;
-
-       BUG_ON(!dev->dmasound.bufsize);
-
-       videobuf_dma_init(&dev->dmasound.dma);
-       err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
-                                      (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
-       if (0 != err)
-               return err;
-       return 0;
-}
-
-/*
- * DMA buffer release
- *
- *   Called after closing the device, during snd_card_saa7134_capture_close
- *
- */
-
-static int dsp_buffer_free(struct saa7134_dev *dev)
-{
-       BUG_ON(!dev->dmasound.blksize);
-
-       videobuf_dma_free(&dev->dmasound.dma);
-
-       dev->dmasound.blocks  = 0;
-       dev->dmasound.blksize = 0;
-       dev->dmasound.bufsize = 0;
-
-       return 0;
-}
-
-/*
- * Setting the capture source and updating the ALSA controls
- */
-static int snd_saa7134_capsrc_set(struct snd_kcontrol *kcontrol,
-                                 int left, int right, bool force_notify)
-{
-       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
-       int change = 0, addr = kcontrol->private_value;
-       int active, old_addr;
-       u32 anabar, xbarin;
-       int analog_io, rate;
-       struct saa7134_dev *dev;
-
-       dev = chip->dev;
-
-       spin_lock_irq(&chip->mixer_lock);
-
-       active = left != 0 || right != 0;
-       old_addr = chip->capture_source_addr;
-
-       /* The active capture source cannot be deactivated */
-       if (active) {
-               change = old_addr != addr ||
-                        chip->capture_source[0] != left ||
-                        chip->capture_source[1] != right;
-
-               chip->capture_source[0] = left;
-               chip->capture_source[1] = right;
-               chip->capture_source_addr = addr;
-               dev->dmasound.input = addr;
-       }
-       spin_unlock_irq(&chip->mixer_lock);
-
-       if (change) {
-               switch (dev->pci->device) {
-
-               case PCI_DEVICE_ID_PHILIPS_SAA7134:
-                       switch (addr) {
-                       case MIXER_ADDR_TVTUNER:
-                               saa_andorb(SAA7134_AUDIO_FORMAT_CTRL,
-                                          0xc0, 0xc0);
-                               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,
-                                          0x03, 0x00);
-                               break;
-                       case MIXER_ADDR_LINE1:
-                       case MIXER_ADDR_LINE2:
-                               analog_io = (MIXER_ADDR_LINE1 == addr) ?
-                                            0x00 : 0x08;
-                               rate = (32000 == dev->dmasound.rate) ?
-                                       0x01 : 0x03;
-                               saa_andorb(SAA7134_ANALOG_IO_SELECT,
-                                          0x08, analog_io);
-                               saa_andorb(SAA7134_AUDIO_FORMAT_CTRL,
-                                          0xc0, 0x80);
-                               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,
-                                          0x03, rate);
-                               break;
-                       }
-
-                       break;
-               case PCI_DEVICE_ID_PHILIPS_SAA7133:
-               case PCI_DEVICE_ID_PHILIPS_SAA7135:
-                       xbarin = 0x03; /* adc */
-                       anabar = 0;
-                       switch (addr) {
-                       case MIXER_ADDR_TVTUNER:
-                               xbarin = 0; /* Demodulator */
-                               anabar = 2; /* DACs */
-                               break;
-                       case MIXER_ADDR_LINE1:
-                               anabar = 0;  /* aux1, aux1 */
-                               break;
-                       case MIXER_ADDR_LINE2:
-                               anabar = 9;  /* aux2, aux2 */
-                               break;
-                       }
-
-                       /* output xbar always main channel */
-                       saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1,
-                                      0xbbbb10);
-
-                       if (left || right) {
-                               /* We've got data, turn the input on */
-                               saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1,
-                                              xbarin);
-                               saa_writel(SAA7133_ANALOG_IO_SELECT, anabar);
-                       } else {
-                               saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1,
-                                              0);
-                               saa_writel(SAA7133_ANALOG_IO_SELECT, 0);
-                       }
-                       break;
-               }
-       }
-
-       if (change) {
-               if (force_notify)
-                       snd_ctl_notify(chip->card,
-                                      SNDRV_CTL_EVENT_MASK_VALUE,
-                                      &chip->capture_ctl[addr]->id);
-
-               if (old_addr != MIXER_ADDR_UNSELECTED && old_addr != addr)
-                       snd_ctl_notify(chip->card,
-                                      SNDRV_CTL_EVENT_MASK_VALUE,
-                                      &chip->capture_ctl[old_addr]->id);
-       }
-
-       return change;
-}
-
-/*
- * ALSA PCM preparation
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called right after the capture device is opened, this function configures
- *  the buffer using the previously defined functions, allocates the memory,
- *  sets up the hardware registers, and then starts the DMA. When this function
- *  returns, the audio should be flowing.
- *
- */
-
-static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int bswap, sign;
-       u32 fmt, control;
-       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
-       struct saa7134_dev *dev;
-       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
-
-       pcm->dev->dmasound.substream = substream;
-
-       dev = saa7134->dev;
-
-       if (snd_pcm_format_width(runtime->format) == 8)
-               fmt = 0x00;
-       else
-               fmt = 0x01;
-
-       if (snd_pcm_format_signed(runtime->format))
-               sign = 1;
-       else
-               sign = 0;
-
-       if (snd_pcm_format_big_endian(runtime->format))
-               bswap = 1;
-       else
-               bswap = 0;
-
-       switch (dev->pci->device) {
-         case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               if (1 == runtime->channels)
-                       fmt |= (1 << 3);
-               if (2 == runtime->channels)
-                       fmt |= (3 << 3);
-               if (sign)
-                       fmt |= 0x04;
-
-               fmt |= (MIXER_ADDR_TVTUNER == dev->dmasound.input) ? 0xc0 : 0x80;
-               saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff));
-               saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >>  8);
-               saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16);
-               saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
-
-               break;
-         case PCI_DEVICE_ID_PHILIPS_SAA7133:
-         case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               if (1 == runtime->channels)
-                       fmt |= (1 << 4);
-               if (2 == runtime->channels)
-                       fmt |= (2 << 4);
-               if (!sign)
-                       fmt |= 0x04;
-               saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1);
-               saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
-               break;
-       }
-
-       dprintk("rec_start: afmt=%d ch=%d  =>  fmt=0x%x swap=%c\n",
-               runtime->format, runtime->channels, fmt,
-               bswap ? 'b' : '-');
-       /* dma: setup channel 6 (= AUDIO) */
-       control = SAA7134_RS_CONTROL_BURST_16 |
-               SAA7134_RS_CONTROL_ME |
-               (dev->dmasound.pt.dma >> 12);
-       if (bswap)
-               control |= SAA7134_RS_CONTROL_BSWAP;
-
-       saa_writel(SAA7134_RS_BA1(6),0);
-       saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
-       saa_writel(SAA7134_RS_PITCH(6),0);
-       saa_writel(SAA7134_RS_CONTROL(6),control);
-
-       dev->dmasound.rate = runtime->rate;
-
-       /* Setup and update the card/ALSA controls */
-       snd_saa7134_capsrc_set(saa7134->capture_ctl[dev->dmasound.input], 1, 1,
-                              true);
-
-       return 0;
-
-}
-
-/*
- * ALSA pointer fetching
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called whenever a period elapses, it must return the current hardware
- *  position of the buffer.
- *   Also resets the read counter used to prevent overruns
- *
- */
-
-static snd_pcm_uframes_t
-snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
-       struct saa7134_dev *dev=pcm->dev;
-
-       if (dev->dmasound.read_count) {
-               dev->dmasound.read_count  -= snd_pcm_lib_period_bytes(substream);
-               dev->dmasound.read_offset += snd_pcm_lib_period_bytes(substream);
-               if (dev->dmasound.read_offset == dev->dmasound.bufsize)
-                       dev->dmasound.read_offset = 0;
-       }
-
-       return bytes_to_frames(runtime, dev->dmasound.read_offset);
-}
-
-/*
- * ALSA hardware capabilities definition
- *
- *  Report only 32kHz for ALSA:
- *
- *  - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz
- *    only
- *  - SAA7134 for TV mode uses DemDec mode (32kHz)
- *  - Radio works in 32kHz only
- *  - When recording 48kHz from Line1/Line2, switching of capture source to TV
- *    means
- *    switching to 32kHz without any frequency translation
- */
-
-static struct snd_pcm_hardware snd_card_saa7134_capture =
-{
-       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-                                SNDRV_PCM_INFO_BLOCK_TRANSFER |
-                                SNDRV_PCM_INFO_MMAP_VALID),
-       .formats =              SNDRV_PCM_FMTBIT_S16_LE | \
-                               SNDRV_PCM_FMTBIT_S16_BE | \
-                               SNDRV_PCM_FMTBIT_S8 | \
-                               SNDRV_PCM_FMTBIT_U8 | \
-                               SNDRV_PCM_FMTBIT_U16_LE | \
-                               SNDRV_PCM_FMTBIT_U16_BE,
-       .rates =                SNDRV_PCM_RATE_32000,
-       .rate_min =             32000,
-       .rate_max =             32000,
-       .channels_min =         1,
-       .channels_max =         2,
-       .buffer_bytes_max =     (256*1024),
-       .period_bytes_min =     64,
-       .period_bytes_max =     (256*1024),
-       .periods_min =          4,
-       .periods_max =          1024,
-};
-
-static void snd_card_saa7134_runtime_free(struct snd_pcm_runtime *runtime)
-{
-       snd_card_saa7134_pcm_t *pcm = runtime->private_data;
-
-       kfree(pcm);
-}
-
-
-/*
- * ALSA hardware params
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called on initialization, right before the PCM preparation
- *
- */
-
-static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
-                                     struct snd_pcm_hw_params * hw_params)
-{
-       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
-       struct saa7134_dev *dev;
-       unsigned int period_size, periods;
-       int err;
-
-       period_size = params_period_bytes(hw_params);
-       periods = params_periods(hw_params);
-
-       if (period_size < 0x100 || period_size > 0x10000)
-               return -EINVAL;
-       if (periods < 4)
-               return -EINVAL;
-       if (period_size * periods > 1024 * 1024)
-               return -EINVAL;
-
-       dev = saa7134->dev;
-
-       if (dev->dmasound.blocks == periods &&
-           dev->dmasound.blksize == period_size)
-               return 0;
-
-       /* release the old buffer */
-       if (substream->runtime->dma_area) {
-               saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
-               dsp_buffer_free(dev);
-               substream->runtime->dma_area = NULL;
-       }
-       dev->dmasound.blocks  = periods;
-       dev->dmasound.blksize = period_size;
-       dev->dmasound.bufsize = period_size * periods;
-
-       err = dsp_buffer_init(dev);
-       if (0 != err) {
-               dev->dmasound.blocks  = 0;
-               dev->dmasound.blksize = 0;
-               dev->dmasound.bufsize = 0;
-               return err;
-       }
-
-       if (0 != (err = videobuf_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_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
-               dsp_buffer_free(dev);
-               return err;
-       }
-       if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
-                                               dev->dmasound.dma.sglist,
-                                               dev->dmasound.dma.sglen,
-                                               0))) {
-               saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
-               dsp_buffer_free(dev);
-               return err;
-       }
-
-       /* I should be able to use runtime->dma_addr in the control
-          byte, but it doesn't work. So I allocate the DMA using the
-          V4L functions, and force ALSA to use that as the DMA area */
-
-       substream->runtime->dma_area = dev->dmasound.dma.vaddr;
-       substream->runtime->dma_bytes = dev->dmasound.bufsize;
-       substream->runtime->dma_addr = 0;
-
-       return 0;
-
-}
-
-/*
- * ALSA hardware release
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called after closing the device, but before snd_card_saa7134_capture_close
- *   It stops the DMA audio and releases the buffers.
- *
- */
-
-static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
-{
-       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
-       struct saa7134_dev *dev;
-
-       dev = saa7134->dev;
-
-       if (substream->runtime->dma_area) {
-               saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
-               videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
-               dsp_buffer_free(dev);
-               substream->runtime->dma_area = NULL;
-       }
-
-       return 0;
-}
-
-/*
- * ALSA capture finish
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called after closing the device.
- *
- */
-
-static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream)
-{
-       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
-       struct saa7134_dev *dev = saa7134->dev;
-
-       if (saa7134->mute_was_on) {
-               dev->ctl_mute = 1;
-               saa7134_tvaudio_setmute(dev);
-       }
-       return 0;
-}
-
-/*
- * ALSA capture start
- *
- *   - One of the ALSA capture callbacks.
- *
- *   Called when opening the device. It creates and populates the PCM
- *  structure
- *
- */
-
-static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       snd_card_saa7134_pcm_t *pcm;
-       snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
-       struct saa7134_dev *dev;
-       int amux, err;
-
-       if (!saa7134) {
-               printk(KERN_ERR "BUG: saa7134 can't find device struct."
-                               " Can't proceed with open\n");
-               return -ENODEV;
-       }
-       dev = saa7134->dev;
-       mutex_lock(&dev->dmasound.lock);
-
-       dev->dmasound.read_count  = 0;
-       dev->dmasound.read_offset = 0;
-
-       amux = dev->input->amux;
-       if ((amux < 1) || (amux > 3))
-               amux = 1;
-       dev->dmasound.input  =  amux - 1;
-
-       mutex_unlock(&dev->dmasound.lock);
-
-       pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
-       if (pcm == NULL)
-               return -ENOMEM;
-
-       pcm->dev=saa7134->dev;
-
-       spin_lock_init(&pcm->lock);
-
-       pcm->substream = substream;
-       runtime->private_data = pcm;
-       runtime->private_free = snd_card_saa7134_runtime_free;
-       runtime->hw = snd_card_saa7134_capture;
-
-       if (dev->ctl_mute != 0) {
-               saa7134->mute_was_on = 1;
-               dev->ctl_mute = 0;
-               saa7134_tvaudio_setmute(dev);
-       }
-
-       err = snd_pcm_hw_constraint_integer(runtime,
-                                               SNDRV_PCM_HW_PARAM_PERIODS);
-       if (err < 0)
-               return err;
-
-       err = snd_pcm_hw_constraint_step(runtime, 0,
-                                               SNDRV_PCM_HW_PARAM_PERIODS, 2);
-       if (err < 0)
-               return err;
-
-       return 0;
-}
-
-/*
- * page callback (needed for mmap)
- */
-
-static struct page *snd_card_saa7134_page(struct snd_pcm_substream *substream,
-                                       unsigned long offset)
-{
-       void *pageptr = substream->runtime->dma_area + offset;
-       return vmalloc_to_page(pageptr);
-}
-
-/*
- * ALSA capture callbacks definition
- */
-
-static struct snd_pcm_ops snd_card_saa7134_capture_ops = {
-       .open =                 snd_card_saa7134_capture_open,
-       .close =                snd_card_saa7134_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_card_saa7134_hw_params,
-       .hw_free =              snd_card_saa7134_hw_free,
-       .prepare =              snd_card_saa7134_capture_prepare,
-       .trigger =              snd_card_saa7134_capture_trigger,
-       .pointer =              snd_card_saa7134_capture_pointer,
-       .page =                 snd_card_saa7134_page,
-};
-
-/*
- * ALSA PCM setup
- *
- *   Called when initializing the board. Sets up the name and hooks up
- *  the callbacks
- *
- */
-
-static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device)
-{
-       struct snd_pcm *pcm;
-       int err;
-
-       if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0)
-               return err;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops);
-       pcm->private_data = saa7134;
-       pcm->info_flags = 0;
-       strcpy(pcm->name, "SAA7134 PCM");
-       return 0;
-}
-
-#define SAA713x_VOLUME(xname, xindex, addr) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_saa7134_volume_info, \
-  .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \
-  .private_value = addr }
-
-static int snd_saa7134_volume_info(struct snd_kcontrol * kcontrol,
-                                  struct snd_ctl_elem_info * uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 20;
-       return 0;
-}
-
-static int snd_saa7134_volume_get(struct snd_kcontrol * kcontrol,
-                                 struct snd_ctl_elem_value * ucontrol)
-{
-       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
-       int addr = kcontrol->private_value;
-
-       ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0];
-       ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1];
-       return 0;
-}
-
-static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
-                                 struct snd_ctl_elem_value * ucontrol)
-{
-       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
-       struct saa7134_dev *dev = chip->dev;
-
-       int change, addr = kcontrol->private_value;
-       int left, right;
-
-       left = ucontrol->value.integer.value[0];
-       if (left < 0)
-               left = 0;
-       if (left > 20)
-               left = 20;
-       right = ucontrol->value.integer.value[1];
-       if (right < 0)
-               right = 0;
-       if (right > 20)
-               right = 20;
-       spin_lock_irq(&chip->mixer_lock);
-       change = 0;
-       if (chip->mixer_volume[addr][0] != left) {
-               change = 1;
-               right = left;
-       }
-       if (chip->mixer_volume[addr][1] != right) {
-               change = 1;
-               left = right;
-       }
-       if (change) {
-               switch (dev->pci->device) {
-                       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-                               switch (addr) {
-                                       case MIXER_ADDR_TVTUNER:
-                                               left = 20;
-                                               break;
-                                       case MIXER_ADDR_LINE1:
-                                               saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
-                                                          (left > 10) ? 0x00 : 0x10);
-                                               break;
-                                       case MIXER_ADDR_LINE2:
-                                               saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
-                                                          (left > 10) ? 0x00 : 0x20);
-                                               break;
-                               }
-                               break;
-                       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-                       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-                               switch (addr) {
-                                       case MIXER_ADDR_TVTUNER:
-                                               left = 20;
-                                               break;
-                                       case MIXER_ADDR_LINE1:
-                                               saa_andorb(0x0594,  0x10,
-                                                          (left > 10) ? 0x00 : 0x10);
-                                               break;
-                                       case MIXER_ADDR_LINE2:
-                                               saa_andorb(0x0594,  0x20,
-                                                          (left > 10) ? 0x00 : 0x20);
-                                               break;
-                               }
-                               break;
-               }
-               chip->mixer_volume[addr][0] = left;
-               chip->mixer_volume[addr][1] = right;
-       }
-       spin_unlock_irq(&chip->mixer_lock);
-       return change;
-}
-
-#define SAA713x_CAPSRC(xname, xindex, addr) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_saa7134_capsrc_info, \
-  .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \
-  .private_value = addr }
-
-static int snd_saa7134_capsrc_info(struct snd_kcontrol * kcontrol,
-                                  struct snd_ctl_elem_info * uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
-
-static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol,
-                                 struct snd_ctl_elem_value * ucontrol)
-{
-       snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
-       int addr = kcontrol->private_value;
-
-       spin_lock_irq(&chip->mixer_lock);
-       if (chip->capture_source_addr == addr) {
-               ucontrol->value.integer.value[0] = chip->capture_source[0];
-               ucontrol->value.integer.value[1] = chip->capture_source[1];
-       } else {
-               ucontrol->value.integer.value[0] = 0;
-               ucontrol->value.integer.value[1] = 0;
-       }
-       spin_unlock_irq(&chip->mixer_lock);
-
-       return 0;
-}
-
-static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol,
-                                 struct snd_ctl_elem_value * ucontrol)
-{
-       int left, right;
-       left = ucontrol->value.integer.value[0] & 1;
-       right = ucontrol->value.integer.value[1] & 1;
-
-       return snd_saa7134_capsrc_set(kcontrol, left, right, false);
-}
-
-static struct snd_kcontrol_new snd_saa7134_volume_controls[] = {
-SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER),
-SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1),
-SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2),
-};
-
-static struct snd_kcontrol_new snd_saa7134_capture_controls[] = {
-SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER),
-SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1),
-SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2),
-};
-
-/*
- * ALSA mixer setup
- *
- *   Called when initializing the board. Sets up the name and hooks up
- *  the callbacks
- *
- */
-
-static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
-{
-       struct snd_card *card = chip->card;
-       struct snd_kcontrol *kcontrol;
-       unsigned int idx;
-       int err, addr;
-
-       strcpy(card->mixername, "SAA7134 Mixer");
-
-       for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) {
-               kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx],
-                                       chip);
-               err = snd_ctl_add(card, kcontrol);
-               if (err < 0)
-                       return err;
-       }
-
-       for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_capture_controls); idx++) {
-               kcontrol = snd_ctl_new1(&snd_saa7134_capture_controls[idx],
-                                       chip);
-               addr = snd_saa7134_capture_controls[idx].private_value;
-               chip->capture_ctl[addr] = kcontrol;
-               err = snd_ctl_add(card, kcontrol);
-               if (err < 0)
-                       return err;
-       }
-
-       chip->capture_source_addr = MIXER_ADDR_UNSELECTED;
-       return 0;
-}
-
-static void snd_saa7134_free(struct snd_card * card)
-{
-       snd_card_saa7134_t *chip = card->private_data;
-
-       if (chip->dev->dmasound.priv_data == NULL)
-               return;
-
-       if (chip->irq >= 0)
-               free_irq(chip->irq, &chip->dev->dmasound);
-
-       chip->dev->dmasound.priv_data = NULL;
-
-}
-
-/*
- * ALSA initialization
- *
- *   Called by the init routine, once for each saa7134 device present,
- *  it creates the basic structures and registers the ALSA devices
- *
- */
-
-static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
-{
-
-       struct snd_card *card;
-       snd_card_saa7134_t *chip;
-       int err;
-
-
-       if (devnum >= SNDRV_CARDS)
-               return -ENODEV;
-       if (!enable[devnum])
-               return -ENODEV;
-
-       err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
-                             sizeof(snd_card_saa7134_t), &card);
-       if (err < 0)
-               return err;
-
-       strcpy(card->driver, "SAA7134");
-
-       /* Card "creation" */
-
-       card->private_free = snd_saa7134_free;
-       chip = card->private_data;
-
-       spin_lock_init(&chip->lock);
-       spin_lock_init(&chip->mixer_lock);
-
-       chip->dev = dev;
-
-       chip->card = card;
-
-       chip->pci = dev->pci;
-       chip->iobase = pci_resource_start(dev->pci, 0);
-
-
-       err = request_irq(dev->pci->irq, saa7134_alsa_irq,
-                               IRQF_SHARED | IRQF_DISABLED, dev->name,
-                               (void*) &dev->dmasound);
-
-       if (err < 0) {
-               printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n",
-                       dev->name, dev->pci->irq);
-               goto __nodev;
-       }
-
-       chip->irq = dev->pci->irq;
-
-       mutex_init(&dev->dmasound.lock);
-
-       if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
-               goto __nodev;
-
-       if ((err = snd_card_saa7134_pcm(chip, 0)) < 0)
-               goto __nodev;
-
-       snd_card_set_dev(card, &chip->pci->dev);
-
-       /* End of "creation" */
-
-       strcpy(card->shortname, "SAA7134");
-       sprintf(card->longname, "%s at 0x%lx irq %d",
-               chip->dev->name, chip->iobase, chip->irq);
-
-       printk(KERN_INFO "%s/alsa: %s registered as card %d\n",dev->name,card->longname,index[devnum]);
-
-       if ((err = snd_card_register(card)) == 0) {
-               snd_saa7134_cards[devnum] = card;
-               return 0;
-       }
-
-__nodev:
-       snd_card_free(card);
-       return err;
-}
-
-
-static int alsa_device_init(struct saa7134_dev *dev)
-{
-       dev->dmasound.priv_data = dev;
-       alsa_card_saa7134_create(dev,dev->nr);
-       return 1;
-}
-
-static int alsa_device_exit(struct saa7134_dev *dev)
-{
-
-       snd_card_free(snd_saa7134_cards[dev->nr]);
-       snd_saa7134_cards[dev->nr] = NULL;
-       return 1;
-}
-
-/*
- * Module initializer
- *
- * Loops through present saa7134 cards, and assigns an ALSA device
- * to each one
- *
- */
-
-static int saa7134_alsa_init(void)
-{
-       struct saa7134_dev *dev = NULL;
-       struct list_head *list;
-
-       saa7134_dmasound_init = alsa_device_init;
-       saa7134_dmasound_exit = alsa_device_exit;
-
-       printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
-
-       list_for_each(list,&saa7134_devlist) {
-               dev = list_entry(list, struct saa7134_dev, devlist);
-               if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
-                       printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
-                               dev->name, saa7134_boards[dev->board].name);
-               else
-                       alsa_device_init(dev);
-       }
-
-       if (dev == NULL)
-               printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n");
-
-       return 0;
-
-}
-
-/*
- * Module destructor
- */
-
-static void saa7134_alsa_exit(void)
-{
-       int idx;
-
-       for (idx = 0; idx < SNDRV_CARDS; idx++) {
-               snd_card_free(snd_saa7134_cards[idx]);
-       }
-
-       saa7134_dmasound_init = NULL;
-       saa7134_dmasound_exit = NULL;
-       printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
-
-       return;
-}
-
-/* We initialize this late, to make sure the sound system is up and running */
-late_initcall(saa7134_alsa_init);
-module_exit(saa7134_alsa_exit);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ricardo Cerqueira");
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
deleted file mode 100644 (file)
index bc08f1d..0000000
+++ /dev/null
@@ -1,8026 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * card-specific stuff.
- *
- * (c) 2001-04 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, 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/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"
-#include "tda18271.h"
-#include "xc5000.h"
-#include "s5h1411.h"
-
-/* commly used strings */
-static char name_mute[]    = "mute";
-static char name_radio[]   = "Radio";
-static char name_tv[]      = "Television";
-static char name_tv_mono[] = "TV (mono only)";
-static char name_comp[]    = "Composite";
-static char name_comp1[]   = "Composite1";
-static char name_comp2[]   = "Composite2";
-static char name_comp3[]   = "Composite3";
-static char name_comp4[]   = "Composite4";
-static char name_svideo[]  = "S-Video";
-
-/* ------------------------------------------------------------------ */
-/* board config info                                                  */
-
-/* If radio_type !=UNSET, radio_addr should be specified
- */
-
-struct saa7134_board saa7134_boards[] = {
-       [SAA7134_BOARD_UNKNOWN] = {
-               .name           = "UNKNOWN/GENERIC",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .inputs         = {{
-                       .name = "default",
-                       .vmux = 0,
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_PROTEUS_PRO] = {
-               /* /me */
-               .name           = "Proteus Pro [philips reference design]",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_FLYVIDEO3000] = {
-               /* "Marco d'Itri" <md@Linux.IT> */
-               .name           = "LifeView FlyVIDEO3000",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .gpiomask       = 0xe000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x8000,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x2000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x8000,
-               },
-       },
-       [SAA7134_BOARD_FLYVIDEO2000] = {
-               /* "TC Wan" <tcwan@cs.usm.my> */
-               .name           = "LifeView/Typhoon FlyVIDEO2000",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .gpiomask       = 0xe000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x2000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .gpio = 0x8000,
-               },
-       },
-       [SAA7134_BOARD_FLYTVPLATINUM_MINI] = {
-               /* "Arnaud Quette" <aquette@free.fr> */
-               .name           = "LifeView FlyTV Platinum Mini",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_FLYTVPLATINUM_FM] = {
-               /* LifeView FlyTV Platinum FM (LR214WF) */
-               /* "Peter Missel <peter.missel@onlinehome.de> */
-               .name           = "LifeView FlyTV Platinum FM / Gold",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .gpiomask       = 0x1E000,      /* Set GP16 and unused 15,14,13 to Output */
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x10000,        /* GP16=1 selects TV input */
-                       .tv   = 1,
-               },{
-/*                     .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-*/                     .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-/*                     .gpio = 0x4000,         */
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-/*                     .gpio = 0x4000,         */
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-/*                     .gpio = 0x4000,         */
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x00000,        /* GP16=0 selects FM radio antenna */
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x10000,
-               },
-       },
-       [SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM] = {
-               /* RoverMedia TV Link Pro FM (LR138 REV:I) */
-               /* Eugene Yudin <Eugene.Yudin@gmail.com> */
-               .name           = "RoverMedia TV Link Pro FM",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MFPE05 2 */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0xe000,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x8000,
-                       .tv   = 1,
-               }, {
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               }, {
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x2000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x8000,
-               },
-       },
-       [SAA7134_BOARD_EMPRESS] = {
-               /* "Gert Vervoort" <gert.vervoort@philips.com> */
-               .name           = "EMPRESS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x20,
-
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-               .mpeg      = SAA7134_MPEG_EMPRESS,
-               .video_out = CCIR656,
-       },
-       [SAA7134_BOARD_MONSTERTV] = {
-               /* "K.Ohta" <alpha292@bremen.or.jp> */
-               .name           = "SKNet Monster TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .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 = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_MD9717] = {
-               .name           = "Tevion MD 9717",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       /* workaround for problems with normal TV sound */
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-              .mute = {
-                      .name = name_mute,
-                      .amux = TV,
-              },
-       },
-       [SAA7134_BOARD_TVSTATION_RDS] = {
-               /* Typhoon TV Tuner RDS: Art.Nr. 50694 */
-               .name           = "KNC One TV-Station RDS / Typhoon TV Tuner RDS",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux   = LINE2,
-                       .tv   = 1,
-               },{
-
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-
-                       .name = "CVid over SVid",
-                       .vmux = 0,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_TVSTATION_DVR] = {
-               .name           = "KNC One TV-Station DVR",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x20,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x820000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x20000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x20000,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x20000,
-               }},
-               .radio          = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x20000,
-               },
-               .mpeg           = SAA7134_MPEG_EMPRESS,
-               .video_out      = CCIR656,
-       },
-       [SAA7134_BOARD_CINERGY400] = {
-               .name           = "Terratec Cinergy 400 TV",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .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 = 4,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2, /* CVideo over SVideo Connector */
-                       .vmux = 0,
-                       .amux = LINE1,
-               }}
-       },
-       [SAA7134_BOARD_MD5044] = {
-               .name           = "Medion 5044",
-               .audio_clock    = 0x00187de7, /* was: 0x00200000, */
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       /* workaround for problems with normal TV sound */
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_KWORLD] = {
-               .name           = "Kworld/KuroutoShikou SAA7130-TVPCI",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [SAA7134_BOARD_CINERGY600] = {
-               .name           = "Terratec Cinergy 600 TV",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2, /* CVideo over SVideo Connector */
-                       .vmux = 0,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_MD7134] = {
-               .name           = "Medion 7134",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .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,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE2,
-              },
-              .mute = {
-                      .name = name_mute,
-                      .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_TYPHOON_90031] = {
-               /* aka Typhoon "TV+Radio", Art.Nr 90031 */
-               /* Tom Zoerner <tomzo at users sourceforge net> */
-               .name           = "Typhoon TV+Radio 90031",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .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   = LINE2,
-               },
-       },
-       [SAA7134_BOARD_ELSA] = {
-               .name           = "ELSA EX-VISION 300TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_HITACHI_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 4,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [SAA7134_BOARD_ELSA_500TV] = {
-               .name           = "ELSA EX-VISION 500TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_HITACHI_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 7,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 8,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [SAA7134_BOARD_ELSA_700TV] = {
-               .name           = "ELSA EX-VISION 700TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_HITACHI_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 4,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 6,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 7,
-                       .amux = LINE1,
-               }},
-               .mute           = {
-                       .name = name_mute,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_ASUSTeK_TVFM7134] = {
-               .name           = "ASUS TV-FM 7134",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_ASUSTeK_TVFM7135] = {
-               .name           = "ASUS TV-FM 7135",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x200000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x200000,
-               },
-               .mute  = {
-                       .name = name_mute,
-                       .gpio = 0x0000,
-               },
-
-       },
-       [SAA7134_BOARD_VA1000POWER] = {
-               .name           = "AOPEN VA1000 POWER",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [SAA7134_BOARD_10MOONSTVMASTER] = {
-               /* "lilicheng" <llc@linuxfans.org> */
-               .name           = "10MOONS PCI TV CAPTURE CARD",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0xe000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x2000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .gpio = 0x8000,
-               },
-       },
-       [SAA7134_BOARD_BMK_MPEX_NOTUNER] = {
-               /* "Andrew de Quincey" <adq@lidskialf.net> */
-               .name           = "BMK MPEX No Tuner",
-               .audio_clock    = 0x200000,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x20,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp3,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp4,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .mpeg      = SAA7134_MPEG_EMPRESS,
-               .video_out = CCIR656,
-       },
-       [SAA7134_BOARD_VIDEOMATE_TV] = {
-               .name           = "Compro VideoMate TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS] = {
-               .name           = "Compro VideoMate TV Gold+",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .gpiomask       = 0x800c0000,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x06c00012,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x0ac20012,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x08c20012,
-                       .tv   = 1,
-               }},                             /* radio and probably mute is missing */
-       },
-       [SAA7134_BOARD_CRONOS_PLUS] = {
-               /*
-               gpio pins:
-                       0  .. 3   BASE_ID
-                       4  .. 7   PROTECT_ID
-                       8  .. 11  USER_OUT
-                       12 .. 13  USER_IN
-                       14 .. 15  VIDIN_SEL
-               */
-               .name           = "Matrox CronosPlus",
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0xcf00,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .gpio = 2 << 14,
-               },{
-                       .name = name_comp2,
-                       .vmux = 0,
-                       .gpio = 1 << 14,
-               },{
-                       .name = name_comp3,
-                       .vmux = 0,
-                       .gpio = 0 << 14,
-               },{
-                       .name = name_comp4,
-                       .vmux = 0,
-                       .gpio = 3 << 14,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .gpio = 2 << 14,
-               }},
-       },
-       [SAA7134_BOARD_MD2819] = {
-               .name           = "AverMedia M156 / Medion 2819",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x03,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x00,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               }, {
-                       .name = name_comp2,
-                       .vmux = 0,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-                       .gpio = 0x01,
-               },
-               .mute  = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x00,
-               },
-       },
-       [SAA7134_BOARD_BMK_MPEX_TUNER] = {
-               /* "Greg Wickham <greg.wickham@grangenet.net> */
-               .name           = "BMK MPEX Tuner",
-               .audio_clock    = 0x200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x20,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }},
-               .mpeg      = SAA7134_MPEG_EMPRESS,
-               .video_out = CCIR656,
-       },
-       [SAA7134_BOARD_ASUSTEK_TVFM7133] = {
-               .name           = "ASUS TV-FM 7133",
-               .audio_clock    = 0x00187de7,
-               /* probably wrong, the 7133 one is the NTSC version ...
-               * .tuner_type  = TUNER_PHILIPS_FM1236_MK3 */
-               .tuner_type     = TUNER_LG_NTSC_NEW_TAPC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-
-               },{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_PINNACLE_PCTV_STEREO] = {
-               .name           = "Pinnacle PCTV Stereo (saa7134)",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_MT2032,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 1,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_MANLI_MTV002] = {
-               /* Ognjen Nastic <ognjen@logosoft.ba> */
-               .name           = "Manli MuchTV M-TV002",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_MANLI_MTV001] = {
-               /* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
-               .name           = "Manli MuchTV M-TV001",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_TG3000TV] = {
-               /* TransGear 3000TV */
-               .name           = "Nagase Sangyo TransGear 3000TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_ECS_TVP3XP] = {
-               .name           = "Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) ",
-               .audio_clock    = 0x187de7,  /* xtal 32.1 MHz */
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_tv_mono,
-                       .vmux   = 1,
-                       .amux   = LINE2,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               },{
-                       .name   = "CVid over SVid",
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE2,
-               },
-       },
-       [SAA7134_BOARD_ECS_TVP3XP_4CB5] = {
-               .name           = "Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM)",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_tv_mono,
-                       .vmux   = 1,
-                       .amux   = LINE2,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               },{
-                       .name   = "CVid over SVid",
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE2,
-               },
-       },
-    [SAA7134_BOARD_ECS_TVP3XP_4CB6] = {
-               /* Barry Scott <barry.scott@onelan.co.uk> */
-               .name           = "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_tv_mono,
-                       .vmux   = 1,
-                       .amux   = LINE2,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               },{
-                       .name   = "CVid over SVid",
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE2,
-               },
-       },
-       [SAA7134_BOARD_AVACSSMARTTV] = {
-               /* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */
-               .name           = "AVACS SmartTV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x200000,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER] = {
-               /* Michael Smith <msmith@cbnco.com> */
-               .name           = "AVerMedia DVD EZMaker",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 3,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-               }},
-       },
-       [SAA7134_BOARD_AVERMEDIA_M103] = {
-               /* Massimo Piccioni <dafastidio@libero.it> */
-               .name           = "AVerMedia MiniPCI DVB-T Hybrid M103",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_XC2028,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-                .mpeg           = SAA7134_MPEG_DVB,
-                .inputs         = {{
-                        .name = name_tv,
-                        .vmux = 1,
-                        .amux = TV,
-                        .tv   = 1,
-                } },
-       },
-       [SAA7134_BOARD_NOVAC_PRIMETV7133] = {
-               /* toshii@netbsd.org */
-               .name           = "Noval Prime TV 7133",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_ALPS_TSBH1_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 3,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-               }},
-       },
-       [SAA7134_BOARD_AVERMEDIA_STUDIO_305] = {
-               .name           = "AverMedia AverTV Studio 305",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_STUDIO_505] = {
-               /* Vasiliy Temnikov <vaka@newmail.ru> */
-               .name           = "AverMedia AverTV Studio 505",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               }, {
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_UPMOST_PURPLE_TV] = {
-               .name           = "UPMOST PURPLE TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 7,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 7,
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_ITEMS_MTV005] = {
-               /* Norman Jonas <normanjonas@arcor.de> */
-               .name           = "Items MuchTV Plus / IT-005",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_CINERGY200] = {
-               .name           = "Terratec Cinergy 200 TV",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2, /* CVideo over SVideo Connector */
-                       .vmux = 0,
-                       .amux = LINE1,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_VIDEOMATE_TV_PVR] = {
-               /* Alain St-Denis <alain@topaze.homeip.net> */
-               .name           = "Compro VideoMate TV PVR/FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x808c0080,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x00080,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x00080,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2_LEFT,
-                       .tv   = 1,
-                       .gpio = 0x00080,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x80000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .gpio = 0x40000,
-               },
-       },
-       [SAA7134_BOARD_SABRENT_SBTTVFM] = {
-               /* Michael Rodriguez-Torrent <mrtorrent@asu.edu> */
-               .name           = "Sabrent SBT-TVFM (saa7130)",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE2,
-               },
-       },
-       [SAA7134_BOARD_ZOLID_XPERT_TV7134] = {
-               /* Helge Jensen <helge.jensen@slog.dk> */
-               .name           = ":Zolid Xpert TV7134",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE] = {
-               /* "Matteo Az" <matte.az@nospam.libero.it> ;-) */
-               .name           = "Empire PCI TV-Radio LE",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x4000,
-               .inputs         = {{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x8000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x8000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE1,
-                       .gpio = 0x8000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-                       .gpio = 0x8000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio =0x8000,
-               }
-       },
-       [SAA7134_BOARD_AVERMEDIA_STUDIO_307] = {
-               /*
-               Nickolay V. Shmyrev <nshmyrev@yandex.ru>
-               Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
-               */
-               .name           = "Avermedia AVerTV Studio 307",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x03,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x00,
-               },{
-                       .name = name_comp,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-                       .gpio = 0x01,
-               },
-               .mute  = {
-                       .name = name_mute,
-                       .amux = LINE1,
-                       .gpio = 0x00,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_GO_007_FM] = {
-               .name           = "Avermedia AVerTV GO 007 FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x00300003,
-               /* .gpiomask       = 0x8c240003, */
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x01,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x00300001,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x01,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
-               /* Kees.Blom@cwi.nl */
-               .name           = "AVerMedia Cardbus TV/Radio (E500)",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .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 = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = {
-               /* Oldrich Jedlicka <oldium.pro@seznam.cz> */
-               .name           = "AVerMedia Cardbus TV/Radio (E501R)",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_ALPS_TSBE5_PAL,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = 0x61,
-               .radio_addr     = 0x60,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x08000000,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x08000000,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x08000000,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x08000000,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x00000000,
-               },
-       },
-       [SAA7134_BOARD_CINERGY400_CARDBUS] = {
-               .name           = "Terratec Cinergy 400 mobile",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_ALPS_TSBE5_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_CINERGY600_MK3] = {
-               .name           = "Terratec Cinergy 600 TV MK3",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 4,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2, /* CVideo over SVideo Connector */
-                       .vmux = 0,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_VIDEOMATE_GOLD_PLUS] = {
-               /* Dylan Walkden <dylan_walkden@hotmail.com> */
-               .name           = "Compro VideoMate Gold+ Pal",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x1ce780,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 0,              /* CVideo over SVideo Connector - ok? */
-                       .amux = LINE1,
-                       .gpio = 0x008080,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x008080,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x008080,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x80000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .gpio = 0x0c8000,
-               },
-       },
-       [SAA7134_BOARD_PINNACLE_300I_DVBT_PAL] = {
-               .name           = "Pinnacle PCTV 300i DVB-T + PAL",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_MT2032,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 1,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_PROVIDEO_PV952] = {
-               /* andreas.kretschmer@web.de */
-               .name           = "ProVideo PV952",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_305] = {
-               /* much like the "studio" version but without radio
-               * and another tuner (sirspiritus@yandex.ru) */
-               .name           = "AverMedia AverTV/305",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_FLYDVBTDUO] = {
-               /* LifeView FlyDVB-T DUO */
-               /* "Nico Sabbi <nsabbi@tiscali.it>  Hartmut Hackmann hartmut.hackmann@t-online.de*/
-               .name           = "LifeView FlyDVB-T DUO / MSI TV@nywhere Duo",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x00200000,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x200000,       /* GPIO21=High for TV input */
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
-               },
-       },
-       [SAA7134_BOARD_PHILIPS_TOUGH] = {
-               .name           = "Philips TOUGH DVB-T reference design",
-               .tuner_type     = TUNER_ABSENT,
-               .audio_clock    = 0x00187de7,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = {{
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_AVERMEDIA_307] = {
-               /*
-               Davydov Vladimir <vladimir@iqmedia.com>
-               */
-               .name           = "Avermedia AVerTV 307",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_ADS_INSTANT_TV] = {
-               .name           = "ADS Tech Instant TV (saa7135)",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .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 = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = {
-               .name           = "Kworld/Tevion V-Stream Xpert TV PVR7134",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_PAL_I,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x0700,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-                       .gpio   = 0x000,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,                /* gpio by DScaler */
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE1,
-                       .gpio   = 0x100,
-               },
-               .mute  = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x000,
-               },
-       },
-       [SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
-               .name           = "LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 0x00200000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x200000,       /* GPIO21=High for TV input */
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
-               },
-       },
-       [SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
-               .name           = "Compro VideoMate TV Gold+II",
-               .audio_clock    = 0x002187de7,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = 0x63,
-               .radio_addr     = 0x60,
-               .gpiomask       = 0x8c1880,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 0,
-                       .amux = LINE1,
-                       .gpio = 0x800800,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x801000,
-               },{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x800000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x880000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .gpio = 0x840000,
-               },
-       },
-       [SAA7134_BOARD_KWORLD_XPERT] = {
-               /*
-               FIXME:
-               - Remote control doesn't initialize properly.
-               - Audio volume starts muted,
-               then gradually increases after channel change.
-               - Overlay scaling problems (application error?)
-               - Composite S-Video untested.
-               From: Konrad Rzepecki <hannibal@megapolis.pl>
-               */
-               .name           = "Kworld Xpert TV PVR7134",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_TENA_9533_DI,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = 0x61,
-               .radio_addr     = 0x60,
-               .gpiomask       = 0x0700,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-                       .gpio   = 0x000,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,                /* gpio by DScaler */
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE1,
-                       .gpio   = 0x100,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x000,
-               },
-       },
-       [SAA7134_BOARD_FLYTV_DIGIMATRIX] = {
-               .name           = "FlyTV mini Asus Digimatrix",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_LG_TALN,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,             /* radio unconfirmed */
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_KWORLD_TERMINATOR] = {
-               /* Kworld V-Stream Studio TV Terminator */
-               /* "James Webb <jrwebb@qwest.net> */
-               .name           = "V-Stream Studio TV Terminator",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 1 << 21,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x0000000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x0000000,
-               },{
-                       .name = name_svideo,    /* S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x0000000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_YUAN_TUN900] = {
-               /* FIXME:
-                * S-Video and composite sources untested.
-                * Radio not working.
-                * Remote control not yet implemented.
-                * From : codemaster@webgeeks.be */
-               .name           = "Yuan TUN-900 (saa7135)",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr= ADDR_UNSET,
-               .radio_addr= ADDR_UNSET,
-               .gpiomask       = 0x00010003,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x01,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x02,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE2,
-                       .gpio = 0x02,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-                       .gpio = 0x00010003,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x01,
-               },
-       },
-       [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,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                         .name = name_tv,
-                         .vmux = 3,
-                         .amux = TV,
-                         .tv   = 1,
-               },{
-                         .name = name_comp1,
-                         .vmux = 1,
-                         .amux = LINE1,
-               },{
-                         .name = name_svideo,
-                         .vmux = 8,
-                         .amux = LINE1,
-               }},
-               .radio = {
-                         .name = name_radio,
-                         .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_GOTVIEW_7135] = {
-               /* Mike Baikov <mike@baikov.com> */
-               /* Andrey Cvetcov <ays14@yandex.ru> */
-               .name            = "GoTView 7135 PCI",
-               .audio_clock     = 0x00187de7,
-               .tuner_type      = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type      = UNSET,
-               .tuner_addr      = ADDR_UNSET,
-               .radio_addr      = ADDR_UNSET,
-               .tda9887_conf    = TDA9887_PRESENT,
-               .gpiomask        = 0x00200003,
-               .inputs          = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x00200003,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x00200003,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x00200003,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x00200003,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x00200003,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x00200003,
-               },
-       },
-       [SAA7134_BOARD_PHILIPS_EUROPA] = {
-               .name           = "Philips EUROPA V3 reference design",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TD1316,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x61,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 3,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE2,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_VIDEOMATE_DVBT_300] = {
-               .name           = "Compro Videomate DVB-T300",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TD1316,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x61,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
-               .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,
-               }},
-       },
-       [SAA7134_BOARD_VIDEOMATE_DVBT_200] = {
-               .name           = "Compro Videomate DVB-T200",
-               .tuner_type     = TUNER_ABSENT,
-               .audio_clock    = 0x00187de7,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = {{
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_RTD_VFG7350] = {
-               .name           = "RTD Embedded Technologies VFG7350",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x21,
-               .inputs         = {{
-                       .name   = "Composite 0",
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               },{
-                       .name   = "Composite 1",
-                       .vmux   = 1,
-                       .amux   = LINE2,
-               },{
-                       .name   = "Composite 2",
-                       .vmux   = 2,
-                       .amux   = LINE1,
-               },{
-                       .name   = "Composite 3",
-                       .vmux   = 3,
-                       .amux   = LINE2,
-               },{
-                       .name   = "S-Video 0",
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               },{
-                       .name   = "S-Video 1",
-                       .vmux   = 9,
-                       .amux   = LINE2,
-               }},
-               .mpeg           = SAA7134_MPEG_EMPRESS,
-               .video_out      = CCIR656,
-               .vid_port_opts  = ( SET_T_CODE_POLARITY_NON_INVERTED |
-                                   SET_CLOCK_NOT_DELAYED |
-                                   SET_CLOCK_INVERTED |
-                                   SET_VSYNC_OFF ),
-       },
-       [SAA7134_BOARD_RTD_VFG7330] = {
-               .name           = "RTD Embedded Technologies VFG7330",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name   = "Composite 0",
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               },{
-                       .name   = "Composite 1",
-                       .vmux   = 1,
-                       .amux   = LINE2,
-               },{
-                       .name   = "Composite 2",
-                       .vmux   = 2,
-                       .amux   = LINE1,
-               },{
-                       .name   = "Composite 3",
-                       .vmux   = 3,
-                       .amux   = LINE2,
-               },{
-                       .name   = "S-Video 0",
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               },{
-                       .name   = "S-Video 1",
-                       .vmux   = 9,
-                       .amux   = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = {
-               .name           = "LifeView FlyTV Platinum Mini2",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
-               /* Michael Krufky <mkrufky@m1k.net>
-                * Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
-                * AFAIK, there is no analog demod, thus,
-                * no support for analog television.
-                */
-               .name           = "AVerMedia AVerTVHD MCE A180",
-               .audio_clock    = 0x00187de7,
-               .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 = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_MONSTERTV_MOBILE] = {
-               .name           = "SKNet MonsterTV Mobile",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .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 = 6,
-                         .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_PINNACLE_PCTV_110i] = {
-              .name           = "Pinnacle PCTV 40i/50i/110i (saa7133)",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x080200000,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 4,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE2,
-               }, {
-                       .name = name_comp2,
-                       .vmux = 0,
-                       .amux = LINE2,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_ASUSTeK_P7131_DUAL] = {
-               .name           = "ASUSTeK P7131 Dual",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 1 << 21,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x0000000,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x0200000,
-               },{
-                       .name = name_comp2,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x0200000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x0200000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_SEDNA_PC_TV_CARDBUS] = {
-               /* Paul Tom Zalac <pzalac@gmail.com> */
-               /* Pavel Mihaylov <bin@bash.info> */
-               .name           = "Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)",
-                               /* Sedna/MuchTV (OEM) Cardbus TV Tuner */
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0xe880c0,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV] = {
-               /* "Cyril Lacoux (Yack)" <clacoux@ifeelgood.org> */
-               .name           = "ASUS Digimatrix TV",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .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 = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_PHILIPS_TIGER] = {
-               .name           = "Philips Tiger reference design",
-               .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,
-               .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_MSI_TVATANYWHERE_PLUS] = {
-               .name           = "MSI TV@Anywhere plus",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 1 << 21,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE2,        /* unconfirmed, taken from Philips driver */
-               },{
-                       .name   = name_comp2,
-                       .vmux   = 0,            /* untested, Composite over S-Video */
-                       .amux   = LINE2,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_CINERGY250PCI] = {
-               /* remote-control does not work. The signal about a
-                  key press comes in via gpio, but the key code
-                  doesn't. Neither does it have an i2c remote control
-                  interface. */
-               .name           = "Terratec Cinergy 250 PCI TV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x80200000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,  /* NOT tested */
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_FLYDVB_TRIO] = {
-               /* LifeView LR319 FlyDVB Trio */
-               /* Peter Missel <peter.missel@onlinehome.de> */
-               .name           = "LifeView FlyDVB Trio",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x00200000,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,        /* Analog broadcast/cable TV */
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x200000,       /* GPIO21=High for TV input */
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_777] = {
-               .name           = "AverTV DVB-T 777",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = {{
-                       .name   = name_comp1,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_FLYDVBT_LR301] = {
-               /* LifeView FlyDVB-T */
-               /* Giampiero Giancipoli <gianci@libero.it> */
-               .name           = "LifeView FlyDVB-T / Genius VideoWonder DVB-T",
-               .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,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331] = {
-               .name           = "ADS Instant TV Duo Cardbus PTV331",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-                       .gpio   = 0x00200000,
-               }},
-       },
-       [SAA7134_BOARD_TEVION_DVBT_220RF] = {
-               .name           = "Tevion/KWorld DVB-T 220RF",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 1 << 21,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_comp2,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_KWORLD_DVBT_210] = {
-               .name           = "KWorld DVB-T 210",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 1 << 21,
-               .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_KWORLD_ATSC110] = {
-               .name           = "Kworld ATSC110/115",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TUV1236D,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .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 = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_AVERMEDIA_A169_B] = {
-               /* AVerMedia A169  */
-               /* Rickard Osser <ricky@osser.se>  */
-               /* This card has two saa7134 chips on it,
-                  but only one of them is currently working. */
-               .name           = "AVerMedia A169 B",
-               .audio_clock    = 0x02187de7,
-               .tuner_type     = TUNER_LG_TALN,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x0a60000,
-       },
-       [SAA7134_BOARD_AVERMEDIA_A169_B1] = {
-               /* AVerMedia A169 */
-               /* Rickard Osser <ricky@osser.se> */
-               .name           = "AVerMedia A169 B1",
-               .audio_clock    = 0x02187de7,
-               .tuner_type     = TUNER_LG_TALN,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0xca60000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 4,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x04a61000,
-               },{
-                       .name = name_comp2,  /*  Composite SVIDEO (B/W if signal is carried with SVIDEO) */
-                       .vmux = 1,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 9,           /* 9 is correct as S-VIDEO1 according to a169.inf! */
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_MD7134_BRIDGE_2] = {
-               /* 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",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x200000,       /* GPIO21=High for TV input */
-                       .tv   = 1,
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp1,     /* Composite signal on S-Video input */
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x000000,       /* GPIO21=Low for FM radio antenna */
-               },
-       },
-       [SAA7134_BOARD_FLYVIDEO3000_NTSC] = {
-               /* "Zac Bowling" <zac@zacbowling.com> */
-               .name           = "LifeView FlyVIDEO3000 (NTSC)",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_NTSC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-
-               .gpiomask       = 0xe000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .gpio = 0x8000,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x4000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x2000,
-               },
-                       .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x8000,
-               },
-       },
-       [SAA7134_BOARD_MEDION_MD8800_QUADRO] = {
-               .name           = "Medion Md8800 Quadro",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .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_FLYDVBS_LR300] = {
-               /* LifeView FlyDVB-s */
-               /* Igor M. Liplianin <liplianin@tut.by> */
-               .name           = "LifeView FlyDVB-S /Acorp TV134DS",
-               .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,     /* Composite input */
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,    /* S-Video signal on S-Video input */
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_PROTEUS_2309] = {
-               .name           = "Proteus Pro 2309",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_A16AR] = {
-               /* Petr Baudis <pasky@ucw.cz> */
-               .name           = "AVerMedia TV Hybrid A16AR",
-               .audio_clock    = 0x187de7,
-               .tuner_type     = TUNER_PHILIPS_TD1316, /* untested */
-               .radio_type     = TUNER_TEA5767, /* untested */
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = 0x60,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .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 = LINE1,
-               },
-       },
-       [SAA7134_BOARD_ASUS_EUROPA2_HYBRID] = {
-               .name           = "Asus Europa2 OEM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT| TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 3,
-                       .amux   = TV,
-                       .tv     = 1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 4,
-                       .amux   = LINE2,
-               },{
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               }},
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE1,
-               },
-       },
-       [SAA7134_BOARD_PINNACLE_PCTV_310i] = {
-               .name           = "Pinnacle PCTV 310i",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 1,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 0x000200000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 4,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE2,
-               },{
-                       .name = name_comp2,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_STUDIO_507] = {
-               /* Mikhail Fedotov <mo_fedotov@mail.ru> */
-               .name           = "Avermedia AVerTV Studio 507",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1256_IH3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x03,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x00,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x00,
-               },{
-                       .name = name_comp2,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x00,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x00,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x01,
-               },
-               .mute  = {
-                       .name = name_mute,
-                       .amux = LINE1,
-                       .gpio = 0x00,
-               },
-       },
-       [SAA7134_BOARD_VIDEOMATE_DVBT_200A] = {
-               /* Francis Barber <fedora@barber-family.id.au> */
-               .name           = "Compro Videomate DVB-T200A",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
-               .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,
-               }},
-       },
-       [SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
-               /* Thomas Genty <tomlohave@gmail.com> */
-               /* David Bentham <db260179@hotmail.com> */
-               .name           = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 1,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 0x0200100,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x0000100,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200100,
-               },
-       },
-       [SAA7134_BOARD_HAUPPAUGE_HVR1150] = {
-               .name           = "Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 3,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .ts_type        = SAA7134_MPEG_TS_SERIAL,
-               .ts_force_val   = 1,
-               .gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x0000100,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0800100, /* GPIO 23 HI for FM */
-               },
-       },
-       [SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
-               .name           = "Hauppauge WinTV-HVR1120 DVB-T/Hybrid",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 3,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .ts_type        = SAA7134_MPEG_TS_SERIAL,
-               .gpiomask       = 0x0800100, /* GPIO 21 is an INPUT */
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x0000100,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0800100, /* GPIO 23 HI for FM */
-               },
-       },
-       [SAA7134_BOARD_CINERGY_HT_PCMCIA] = {
-               .name           = "Terratec Cinergy HT PCMCIA",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .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   = 6,
-                       .amux   = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_ENCORE_ENLTV] = {
-       /* Steven Walter <stevenrwalter@gmail.com>
-          Juan Pablo Sormani <sorman@gmail.com> */
-               .name           = "Encore ENLTV",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_TNF_5335MF,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = 3,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 7,
-                       .amux = 4,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = 2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 0,
-                       .amux = 2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-/*                     .gpio = 0x00300001,*/
-                       .gpio = 0x20000,
-
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = 0,
-               },
-       },
-       [SAA7134_BOARD_ENCORE_ENLTV_FM] = {
-  /*   Juan Pablo Sormani <sorman@gmail.com> */
-               .name           = "Encore ENLTV-FM",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FCV1236D,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = 3,
-                       .tv   = 1,
-               },{
-                       .name = name_tv_mono,
-                       .vmux = 7,
-                       .amux = 4,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = 2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 0,
-                       .amux = 2,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x20000,
-
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = 0,
-               },
-       },
-       [SAA7134_BOARD_ENCORE_ENLTV_FM53] = {
-               .name           = "Encore ENLTV-FM v5.3",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_TNF_5335MF,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x7000,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = 1,
-                       .tv   = 1,
-                       .gpio = 0x50000,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = 2,
-                       .gpio = 0x2000,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = 2,
-                       .gpio = 0x2000,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .vmux = 1,
-                       .amux = 1,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .gpio = 0xf000,
-                       .amux = 0,
-               },
-       },
-       [SAA7134_BOARD_ENCORE_ENLTV_FM3] = {
-               .name           = "Encore ENLTV-FM 3",
-               .audio_clock    = 0x02187de7,
-               .tuner_type     = TUNER_TENA_TNF_5337,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = 0x61,
-               .radio_addr     = 0x60,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-                       .gpio = 0x43000,
-               },
-       },
-       [SAA7134_BOARD_CINERGY_HT_PCI] = {
-               .name           = "Terratec Cinergy HT PCI",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .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   = 6,
-                       .amux   = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_PHILIPS_TIGER_S] = {
-               .name           = "Philips Tiger - S Reference design",
-               .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_M102] = {
-               .name           = "Avermedia M102",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 1<<21,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE2,
-               },{
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE2,
-               }},
-       },
-       [SAA7134_BOARD_ASUS_P7131_4871] = {
-               .name           = "ASUS P7131 4871",
-               .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,
-                       .gpio   = 0x0200000,
-               }},
-       },
-       [SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA] = {
-               .name           = "ASUSTeK P7131 Hybrid",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 2,
-               .gpiomask       = 1 << 21,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x0000000,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .gpio = 0x0200000,
-               },{
-                       .name = name_comp2,
-                       .vmux = 0,
-                       .amux = LINE2,
-                       .gpio = 0x0200000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-                       .gpio = 0x0200000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = {
-              .name           = "ASUSTeK P7131 Analog",
-              .audio_clock    = 0x00187de7,
-              .tuner_type     = TUNER_PHILIPS_TDA8290,
-              .radio_type     = UNSET,
-              .tuner_addr     = ADDR_UNSET,
-              .radio_addr     = ADDR_UNSET,
-              .gpiomask       = 1 << 21,
-              .inputs         = {{
-                      .name = name_tv,
-                      .vmux = 1,
-                      .amux = TV,
-                      .tv   = 1,
-                      .gpio = 0x0000000,
-              }, {
-                      .name = name_comp1,
-                      .vmux = 3,
-                      .amux = LINE2,
-              }, {
-                      .name = name_comp2,
-                      .vmux = 0,
-                      .amux = LINE2,
-              }, {
-                      .name = name_svideo,
-                      .vmux = 8,
-                      .amux = LINE2,
-              } },
-              .radio = {
-                      .name = name_radio,
-                      .amux = TV,
-                      .gpio = 0x0200000,
-              },
-       },
-       [SAA7134_BOARD_SABRENT_TV_PCB05] = {
-               .name           = "Sabrent PCMCIA TV-PCB05",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .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_comp2,
-                       .vmux = 0,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_10MOONSTVMASTER3] = {
-               /* Tony Wan <aloha_cn@hotmail.com> */
-               .name           = "10MOONS TM300 TV Card",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x7000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x2000,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x2000,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .gpio = 0x3000,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_SUPER_007] = {
-               .name           = "Avermedia Super 007",
-               .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, /* FIXME: analog tv untested */
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               }},
-       },
-       [SAA7134_BOARD_AVERMEDIA_M135A] = {
-               .name           = "Avermedia PCI pure analog (M135A)",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 2,
-               .gpiomask       = 0x020200000,
-               .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 = 0x00200000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x01,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_M733A] = {
-               .name           = "Avermedia PCI M733A",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 0,
-               .gpiomask       = 0x020200000,
-               .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 = 0x00200000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x01,
-               },
-       },
-       [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,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [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,
-                       .amux = LINE1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [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,
-                       .amux = LINE1,
-               },{
-                       .name   = name_comp1,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [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,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-       },
-       [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,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [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,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0xc0c000,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-                       .gpio = 0xc0c000,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv = 1,
-                       .gpio = 0xc0c000,
-               }},
-       },
-       [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,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs = {{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0xc0c000,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-                       .gpio = 0xc0c000,
-               },{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv = 1,
-                       .gpio = 0xc0c000,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0xc0c000,
-               },
-       },
-       [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,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-       },
-       [SAA7134_BOARD_BEHOLD_505FM] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 505 FM",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_505RDS_MK5] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 505 RDS",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_507_9FM] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 507 FM / BeholdTV 509 FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-                       .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_507RDS_MK5] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 507 RDS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-                       .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_507RDS_MK3] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 507 RDS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-                       .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /* Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV Columbus TV/FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_ALPS_TSBE5_PAL,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = 0xc2 >> 1,
-               .radio_addr     = 0xc0 >> 1,
-               .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_607FM_MK3] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 607 FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_609FM_MK3] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 609 FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_607FM_MK5] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 607 FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_609FM_MK5] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 609 FM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_607RDS_MK3] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 607 RDS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_609RDS_MK3] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 609 RDS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_607RDS_MK5] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 607 RDS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_609RDS_MK5] = {
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               .name           = "Beholder BeholdTV 609 RDS",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               },{
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               },{
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }},
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_M6] = {
-               /* Igor Kuznetsov <igk@igk.ru> */
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
-               /* Alexey Osipov <lion-simba@pridelands.ru> */
-               .name           = "Beholder BeholdTV M6",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x20,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-               .mpeg  = SAA7134_MPEG_EMPRESS,
-               .video_out = CCIR656,
-               .vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
-                                       SET_CLOCK_NOT_DELAYED |
-                                       SET_CLOCK_INVERTED |
-                                       SET_VSYNC_OFF),
-       },
-       [SAA7134_BOARD_BEHOLD_M63] = {
-               /* Igor Kuznetsov <igk@igk.ru> */
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV M63",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .empress_addr   = 0x20,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-               .mpeg  = SAA7134_MPEG_EMPRESS,
-               .video_out = CCIR656,
-               .vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
-                                       SET_CLOCK_NOT_DELAYED |
-                                       SET_CLOCK_INVERTED |
-                                       SET_VSYNC_OFF),
-       },
-       [SAA7134_BOARD_BEHOLD_M6_EXTRA] = {
-               /* Igor Kuznetsov <igk@igk.ru> */
-               /* Andrey Melnikoff <temnota@kmv.ru> */
-               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
-               /* Alexey Osipov <lion-simba@pridelands.ru> */
-               .name           = "Beholder BeholdTV M6 Extra",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216MK5,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .empress_addr   = 0x20,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-               .mpeg  = SAA7134_MPEG_EMPRESS,
-               .video_out = CCIR656,
-               .vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
-                                       SET_CLOCK_NOT_DELAYED |
-                                       SET_CLOCK_INVERTED |
-                                       SET_VSYNC_OFF),
-       },
-       [SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = {
-               .name           = "Twinhan Hybrid DTV-DVB 3056 PCI",
-               .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,            /* untested */
-                       .amux   = LINE1,
-               } },
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_GENIUS_TVGO_A11MCE] = {
-               /* Adrian Pardini <pardo.bsso@gmail.com> */
-               .name           = "Genius TVGO AM11MCE",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_TNF_5335MF,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0xf000,
-               .inputs         = {{
-                       .name = name_tv_mono,
-                       .vmux = 1,
-                       .amux = LINE2,
-                       .gpio = 0x0000,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x2000,
-                       .tv = 1
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x2000,
-       } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x1000,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE2,
-                       .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,
-                .mpeg           = SAA7134_MPEG_DVB,
-                .inputs         = {{
-                        .name = name_tv,
-                        .vmux = 1,
-                        .amux = TV,
-                        .tv   = 1,
-                }, {
-                        .name = name_comp1,
-                        .vmux = 3,
-                        .amux = LINE1,
-                }, {
-                        .name = name_svideo,
-                        .vmux = 8,
-                        .amux = LINE2,
-                } },
-                .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,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               }, {
-                       .name = name_comp,
-                       .vmux = 0,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-               },
-       },
-       [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     = 0x61,
-               .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,
-               .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_XC2028,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = { {
-                       .name   = name_tv,
-                       .vmux   = 4,
-                       .amux   = TV,
-                       .tv     = 1,
-               }, {
-                       .name = name_comp,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_H6] = {
-               /* Igor Kuznetsov <igk@igk.ru> */
-               .name           = "Beholder BeholdTV H6",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
-               .name           = "Asus Tiger 3in1",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 2,
-               .gpiomask       = 1 << 21,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp,
-                       .vmux = 0,
-                       .amux = LINE2,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_ASUSTeK_PS3_100] = {
-               .name           = "Asus My Cinema PS3-100",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tuner_config   = 2,
-               .gpiomask       = 1 << 21,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp,
-                       .vmux = 0,
-                       .amux = LINE2,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_REAL_ANGEL_220] = {
-               .name           = "Zogis Real Angel 220",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_TNF_5335MF,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x801a8087,
-               .inputs = { {
-                       .name   = name_tv,
-                       .vmux   = 3,
-                       .amux   = LINE2,
-                       .tv     = 1,
-                       .gpio   = 0x624000,
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-                       .gpio   = 0x624000,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-                       .gpio   = 0x624000,
-               } },
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = LINE2,
-                       .gpio   = 0x624001,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = {
-               .name           = "ADS Tech Instant HDTV",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TUV1236D,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp,
-                       .vmux = 4,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-       },
-       [SAA7134_BOARD_ASUSTeK_TIGER] = {
-               .name           = "Asus Tiger Rev:1.00",
-               .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,
-               .gpiomask       = 0x0200000,
-               .inputs = { {
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE2,
-               }, {
-                       .name   = name_comp2,
-                       .vmux   = 0,
-                       .amux   = LINE2,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               } },
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0200000,
-               },
-       },
-       [SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG] = {
-               .name           = "Kworld Plus TV Analog Lite PCI",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_YMEC_TVF_5533MF,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = 0x60,
-               .gpiomask       = 0x80000700,
-               .inputs = { {
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = LINE2,
-                       .tv     = 1,
-                       .gpio   = 0x100,
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,
-               } },
-               .radio = {
-                       .name   = name_radio,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-                       .gpio   = 0x100,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .vmux = 8,
-                       .amux = 2,
-               },
-       },
-       [SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = {
-               .name           = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_type     = UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x8e054000,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
-               .inputs = { {
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-#if 0  /* FIXME */
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-                       .gpio   = 0x200,
-#endif
-               } },
-#if 0
-               .radio = {
-                       .name   = name_radio,
-                       .vmux   = 1,
-                       .amux   = LINE1,
-                       .gpio   = 0x100,
-               },
-#endif
-               .mute = {
-                       .name = name_mute,
-                       .vmux = 0,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = {
-               .name           = "Avermedia AVerTV GO 007 FM Plus",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x00300003,
-               /* .gpiomask       = 0x8c240003, */
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x01,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 6,
-                       .amux = LINE1,
-                       .gpio = 0x02,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-                       .gpio = 0x00300001,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-                       .gpio = 0x01,
-               },
-       },
-       [SAA7134_BOARD_AVERMEDIA_STUDIO_507UA] = {
-               /* Andy Shevchenko <andy@smile.org.ua> */
-               .name           = "Avermedia AVerTV Studio 507UA",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* Should be MK5 */
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x03,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-                       .gpio = 0x00,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x00,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-                       .gpio = 0x00,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-                       .gpio = 0x01,
-               },
-               .mute  = {
-                       .name = name_mute,
-                       .amux = LINE1,
-                       .gpio = 0x00,
-               },
-       },
-       [SAA7134_BOARD_VIDEOMATE_S350] = {
-               /* Jan D. Louw <jd.louw@mweb.co.za */
-               .name           = "Compro VideoMate S350/S300",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = { {
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8, /* Not tested */
-                       .amux   = LINE1
-               } },
-       },
-       [SAA7134_BOARD_BEHOLD_X7] = {
-               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV X7",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_XC5000,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 2,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 9,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
-               .name           = "Zolid Hybrid TV Tuner PCI",
-               .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,
-               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               } },
-               .radio = {      /* untested */
-                       .name = name_radio,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_ASUS_EUROPA_HYBRID] = {
-               .name           = "Asus Europa Hybrid OEM",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TD1316,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x61,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = { {
-                       .name   = name_tv,
-                       .vmux   = 3,
-                       .amux   = TV,
-                       .tv     = 1,
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 4,
-                       .amux   = LINE2,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               } },
-       },
-       [SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S] = {
-               .name           = "Leadtek Winfast DTV1000S",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs         = { {
-                       .name = name_comp1,
-                       .vmux = 3,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-               } },
-       },
-       [SAA7134_BOARD_BEHOLD_505RDS_MK3] = {
-               /*       Beholder Intl. Ltd. 2008      */
-               /*Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 505 RDS",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .rds_addr       = 0x10,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .gpiomask       = 0x00008000,
-               .inputs         = {{
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE2,
-               },
-       },
-       [SAA7134_BOARD_HAWELL_HW_404M7] = {
-               /* Hawell HW-404M7 & Hawell HW-808M7  */
-               /* Bogoslovskiy Viktor <bogovic@bk.ru> */
-               .name         = "Hawell HW-404M7",
-               .audio_clock   = 0x00200000,
-               .tuner_type    = UNSET,
-               .radio_type    = UNSET,
-               .tuner_addr   = ADDR_UNSET,
-               .radio_addr   = ADDR_UNSET,
-               .gpiomask      = 0x389c00,
-               .inputs       = {{
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE1,
-                       .gpio = 0x01fc00,
-               } },
-       },
-       [SAA7134_BOARD_BEHOLD_H7] = {
-               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV H7",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_XC5000,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 2,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 9,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_A7] = {
-               /* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV A7",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_XC5000,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 2,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 0,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 9,
-                       .amux = LINE1,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_TECHNOTREND_BUDGET_T3000] = {
-               .name           = "TechoTrend TT-budget T-3000",
-               .tuner_type     = TUNER_PHILIPS_TD1316,
-               .audio_clock    = 0x00187de7,
-               .radio_type     = UNSET,
-               .tuner_addr     = 0x63,
-               .radio_addr     = ADDR_UNSET,
-               .tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .inputs = {{
-                       .name   = name_tv,
-                       .vmux   = 3,
-                       .amux   = TV,
-                       .tv     = 1,
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE2,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               } },
-       },
-       [SAA7134_BOARD_VIDEOMATE_M1F] = {
-               /* Pavel Osnova <pvosnova@gmail.com> */
-               .name           = "Compro VideoMate Vista M1F",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .radio_type     = TUNER_TEA5767,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = 0x60,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 1,
-                       .amux = TV,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 3,
-                       .amux = LINE2,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE2,
-               } },
-               .radio = {
-                       .name = name_radio,
-                       .amux = LINE1,
-               },
-               .mute = {
-                       .name = name_mute,
-                       .amux = TV,
-               },
-       },
-       [SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2] = {
-               /* Timothy Lee <timothy.lee@siriushk.com> */
-               .name           = "MagicPro ProHDTV Pro2 DMB-TH/Hybrid",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_config   = 3,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x02050000,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
-               .inputs         = { {
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-                       .gpio   = 0x00050000,
-               }, {
-                       .name   = name_comp1,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-                       .gpio   = 0x00050000,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-                       .gpio   = 0x00050000,
-               } },
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x00050000,
-               },
-               .mute = {
-                       .name   = name_mute,
-                       .vmux   = 0,
-                       .amux   = TV,
-                       .gpio   = 0x00050000,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_501] = {
-               /*       Beholder Intl. Ltd. 2010       */
-               /* Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 501",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x00008000,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_BEHOLD_503FM] = {
-               /*       Beholder Intl. Ltd. 2010       */
-               /* Dmitry Belimov <d.belimov@gmail.com> */
-               .name           = "Beholder BeholdTV 503 FM",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .gpiomask       = 0x00008000,
-               .inputs         = { {
-                       .name = name_tv,
-                       .vmux = 3,
-                       .amux = LINE2,
-                       .tv   = 1,
-               }, {
-                       .name = name_comp1,
-                       .vmux = 1,
-                       .amux = LINE1,
-               }, {
-                       .name = name_svideo,
-                       .vmux = 8,
-                       .amux = LINE1,
-               } },
-               .mute = {
-                       .name = name_mute,
-                       .amux = LINE1,
-               },
-       },
-       [SAA7134_BOARD_SENSORAY811_911] = {
-               .name           = "Sensoray 811/911",
-               .audio_clock    = 0x00200000,
-               .tuner_type     = TUNER_ABSENT,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .inputs         = {{
-                       .name   = name_comp1,
-                       .vmux   = 0,
-                       .amux   = LINE1,
-               }, {
-                       .name   = name_comp3,
-                       .vmux   = 2,
-                       .amux   = LINE1,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE1,
-               } },
-       },
-       [SAA7134_BOARD_KWORLD_PC150U] = {
-               .name           = "Kworld PC150-U",
-               .audio_clock    = 0x00187de7,
-               .tuner_type     = TUNER_PHILIPS_TDA8290,
-               .radio_type     = UNSET,
-               .tuner_addr     = ADDR_UNSET,
-               .radio_addr     = ADDR_UNSET,
-               .mpeg           = SAA7134_MPEG_DVB,
-               .gpiomask       = 1 << 21,
-               .ts_type        = SAA7134_MPEG_TS_PARALLEL,
-               .inputs = { {
-                       .name   = name_tv,
-                       .vmux   = 1,
-                       .amux   = TV,
-                       .tv     = 1,
-               }, {
-                       .name   = name_comp,
-                       .vmux   = 3,
-                       .amux   = LINE1,
-               }, {
-                       .name   = name_svideo,
-                       .vmux   = 8,
-                       .amux   = LINE2,
-               } },
-               .radio = {
-                       .name   = name_radio,
-                       .amux   = TV,
-                       .gpio   = 0x0000000,
-               },
-       },
-
-};
-
-const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
-
-/* ------------------------------------------------------------------ */
-/* PCI ids + subsystem IDs                                            */
-
-struct pci_device_id saa7134_pci_tbl[] = {
-       {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2001,
-               .driver_data  = SAA7134_BOARD_PROTEUS_PRO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2001,
-               .driver_data  = SAA7134_BOARD_PROTEUS_PRO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x6752,
-               .driver_data  = SAA7134_BOARD_EMPRESS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1131,
-               .subdevice    = 0x4e85,
-               .driver_data  = SAA7134_BOARD_MONSTERTV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1142,
-               .driver_data  = SAA7134_BOARD_CINERGY400,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1143,
-               .driver_data  = SAA7134_BOARD_CINERGY600,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1158,
-               .driver_data  = SAA7134_BOARD_CINERGY600_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1162,
-               .driver_data  = SAA7134_BOARD_CINERGY400_CARDBUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5169,
-               .subdevice    = 0x0138,
-               .driver_data  = SAA7134_BOARD_FLYVIDEO3000_NTSC,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0138,
-               .driver_data  = SAA7134_BOARD_FLYVIDEO3000,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x4e42,                         /* "Typhoon PCI Capture TV Card" Art.No. 50673 */
-               .subdevice    = 0x0138,
-               .driver_data  = SAA7134_BOARD_FLYVIDEO3000,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0138,
-               .driver_data  = SAA7134_BOARD_FLYVIDEO2000,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x4e42,         /* Typhoon */
-               .subdevice    = 0x0138,         /* LifeView FlyTV Prime30 OEM */
-               .driver_data  = SAA7134_BOARD_FLYVIDEO2000,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0212, /* minipci, LR212 */
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x14c0,
-               .subdevice    = 0x1212, /* minipci, LR1212 */
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI2,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x4e42,
-               .subdevice    = 0x0212, /* OEM minipci, LR212 */
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168, /* Animation Technologies (LifeView) */
-               .subdevice    = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168, /* Animation Technologies (LifeView) */
-               .subdevice    = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1489, /* KYE */
-               .subdevice    = 0x0214, /* Genius VideoWonder ProTV */
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM, /* is an LR214WF actually */
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x16be,
-               .subdevice    = 0x0003,
-               .driver_data  = SAA7134_BOARD_MD7134,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x16be, /* CTX946 analog TV, HW mpeg, DVB-T */
-               .subdevice    = 0x5000, /* only analog TV and DVB-T for now */
-               .driver_data  = SAA7134_BOARD_MD7134,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1048,
-               .subdevice    = 0x226b,
-               .driver_data  = SAA7134_BOARD_ELSA,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1048,
-               .subdevice    = 0x226a,
-               .driver_data  = SAA7134_BOARD_ELSA_500TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1048,
-               .subdevice    = 0x226c,
-               .driver_data  = SAA7134_BOARD_ELSA_700TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
-               .subdevice    = 0x4842,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
-               .subdevice    = 0x4845,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7135,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
-               .subdevice    = 0x4830,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
-               .subdevice    = 0x4843,
-               .driver_data  = SAA7134_BOARD_ASUSTEK_TVFM7133,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_ASUSTEK,
-               .subdevice    = 0x4840,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0xfe01,
-               .driver_data  = SAA7134_BOARD_TVSTATION_RDS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1894,
-               .subdevice    = 0xfe01,
-               .driver_data  = SAA7134_BOARD_TVSTATION_RDS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1894,
-               .subdevice    = 0xa006,
-               .driver_data  = SAA7134_BOARD_TVSTATION_DVR,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1131,
-               .subdevice    = 0x7133,
-               .driver_data  = SAA7134_BOARD_VA1000POWER,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2001,
-               .driver_data  = SAA7134_BOARD_10MOONSTVMASTER,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc100,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc100,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_VENDOR_ID_MATROX,
-               .subdevice    = 0x48d0,
-               .driver_data  = SAA7134_BOARD_CRONOS_PLUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .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 */
-               .subdevice    = 0x2115,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_305,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xa115,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_505,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x2108,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_305,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x10ff,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER,
-       },{
-               /* AVerMedia CardBus */
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xd6ee,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS,
-       },{
-               /* AVerMedia CardBus */
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xb7e9,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_501,
-       }, {
-               /* TransGear 3000TV */
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x050c,
-               .driver_data  = SAA7134_BOARD_TG3000TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x11bd,
-               .subdevice    = 0x002b,
-               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_STEREO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x11bd,
-               .subdevice    = 0x002d,
-               .driver_data  = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1019,
-               .subdevice    = 0x4cb4,
-               .driver_data  = SAA7134_BOARD_ECS_TVP3XP,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1019,
-               .subdevice    = 0x4cb5,
-               .driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB5,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1019,
-               .subdevice    = 0x4cb6,
-               .driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB6,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x12ab,
-               .subdevice    = 0x0800,
-               .driver_data  = SAA7134_BOARD_UPMOST_PURPLE_TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1152,
-               .driver_data  = SAA7134_BOARD_CINERGY200,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc100,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_TV_PVR,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x9715,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_307,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xa70a,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_307,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc200,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1540,
-               .subdevice    = 0x9524,
-               .driver_data  = SAA7134_BOARD_PROVIDEO_PV952,
-
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0502,                /* Cardbus version */
-               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0306,                /* PCI version */
-               .driver_data  = SAA7134_BOARD_FLYDVBTDUO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf31f,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
-
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf11d,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_M135A,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x4155,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x4255,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2004,
-               .driver_data  = SAA7134_BOARD_PHILIPS_TOUGH,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1421,
-               .subdevice    = 0x0350,         /* PCI version */
-               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1421,
-               .subdevice    = 0x0351,         /* PCI version, new revision */
-               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1421,
-               .subdevice    = 0x0370,         /* cardbus version */
-               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1421,
-               .subdevice    = 0x1370,        /* cardbus version */
-               .driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
-
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x4e42,         /* Typhoon */
-               .subdevice    = 0x0502,         /* LifeView LR502 OEM */
-               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x0210,         /* mini pci NTSC version */
-               .driver_data  = SAA7134_BOARD_FLYTV_DIGIMATRIX,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x0210,         /* mini pci PAL/SECAM version */
-               .driver_data  = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV,
-
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */
-               .subdevice    = 0x4091,
-               .driver_data  = SAA7134_BOARD_BEHOLD_409FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5456, /* GoTView */
-               .subdevice    = 0x7135,
-               .driver_data  = SAA7134_BOARD_GOTVIEW_7135,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2004,
-               .driver_data  = SAA7134_BOARD_PHILIPS_EUROPA,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc900,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_DVBT_300,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc901,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_DVBT_200,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1435,
-               .subdevice    = 0x7350,
-               .driver_data  = SAA7134_BOARD_RTD_VFG7350,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1435,
-               .subdevice    = 0x7330,
-               .driver_data  = SAA7134_BOARD_RTD_VFG7330,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461,
-               .subdevice    = 0x1044,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1131,
-               .subdevice    = 0x4ee9,
-               .driver_data  = SAA7134_BOARD_MONSTERTV_MOBILE,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x11bd,
-               .subdevice    = 0x002e,
-               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_110i,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4862,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2018,
-               .driver_data  = SAA7134_BOARD_PHILIPS_TIGER,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1462,
-               .subdevice    = 0x6231, /* tda8275a, ks003 IR */
-               .driver_data  = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1462,
-               .subdevice    = 0x8624, /* tda8275, ks003 IR */
-               .driver_data  = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1160,
-               .driver_data  = SAA7134_BOARD_CINERGY250PCI,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,  /* SAA 7131E */
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0319,
-               .driver_data  = SAA7134_BOARD_FLYDVB_TRIO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461,
-               .subdevice    = 0x2c05,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_777,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0301,
-               .driver_data  = SAA7134_BOARD_FLYDVBT_LR301,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0331,
-               .subdevice    = 0x1421,
-               .driver_data  = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x17de,
-               .subdevice    = 0x7201,
-               .driver_data  = SAA7134_BOARD_TEVION_DVBT_220RF,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x17de,
-               .subdevice    = 0x7250,
-               .driver_data  = SAA7134_BOARD_KWORLD_DVBT_210,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
-               .subvendor    = 0x17de,
-               .subdevice    = 0x7350,
-               .driver_data  = SAA7134_BOARD_KWORLD_ATSC110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
-               .subvendor    = 0x17de,
-               .subdevice    = 0x7352,
-               .driver_data  = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
-               .subvendor    = 0x17de,
-               .subdevice    = 0xa134,
-               .driver_data  = SAA7134_BOARD_KWORLD_PC150U,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461,
-               .subdevice    = 0x7360,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_A169_B,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461,
-               .subdevice    = 0x6360,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_A169_B1,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x16be,
-               .subdevice    = 0x0005,
-               .driver_data  = SAA7134_BOARD_MD7134_BRIDGE_2,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x0300,
-               .driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x4e42,
-               .subdevice    = 0x0300,/* LR300 */
-               .driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
-       },{
-               .vendor = PCI_VENDOR_ID_PHILIPS,
-               .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor = 0x1489,
-               .subdevice = 0x0301,
-               .driver_data = SAA7134_BOARD_FLYDVBT_LR301,
-       },{
-               .vendor = PCI_VENDOR_ID_PHILIPS,
-               .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor = 0x5168, /* Animation Technologies (LifeView) */
-               .subdevice = 0x0304,
-               .driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x3306,
-               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x3502,  /* whats the difference to 0x3306 ?*/
-               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5168,
-               .subdevice    = 0x3307, /* FlyDVB-T Hybrid Mini PCI */
-               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x16be,
-               .subdevice    = 0x0007,
-               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x16be,
-               .subdevice    = 0x0008,
-               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x16be,
-               .subdevice    = 0x000d, /* triple CTX948_V1.1.1 */
-               .driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461,
-               .subdevice    = 0x2c05,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_777,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1489,
-               .subdevice    = 0x0502,                /* Cardbus version */
-               .driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x0919, /* Philips Proteus PRO 2309 */
-               .subdevice    = 0x2003,
-               .driver_data  = SAA7134_BOARD_PROTEUS_2309,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461,
-               .subdevice    = 0x2c00,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_A16AR,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4860,
-               .driver_data  = SAA7134_BOARD_ASUS_EUROPA2_HYBRID,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x11bd,
-               .subdevice    = 0x002f,
-               .driver_data  = SAA7134_BOARD_PINNACLE_PCTV_310i,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0x9715,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xa11b,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4876,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6700,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6701,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6702,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6703,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6704,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6705,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6706,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6707,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6708,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x6709,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0070,
-               .subdevice    = 0x670a,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1172,
-               .driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2342,
-               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1131,
-               .subdevice    = 0x2341,
-               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x3016,
-               .subdevice    = 0x2344,
-               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1131,
-               .subdevice    = 0x230f,
-               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x1a7f,
-               .subdevice    = 0x2008,
-               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM53,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1a7f,
-               .subdevice    = 0x2108,
-               .driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM3,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x153b,
-               .subdevice    = 0x1175,
-               .driver_data  = SAA7134_BOARD_CINERGY_HT_PCI,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf31e,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_M102,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x4E42,         /* MSI */
-               .subdevice    = 0x0306,         /* TV@nywhere DUO */
-               .driver_data  = SAA7134_BOARD_FLYDVBTDUO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4871,
-               .driver_data  = SAA7134_BOARD_ASUS_P7131_4871,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4857,         /* REV:1.00 */
-               .driver_data  = SAA7134_BOARD_ASUSTeK_TIGER,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */
-               .subdevice    = 0x2003, /* OEM cardbus */
-               .driver_data  = SAA7134_BOARD_SABRENT_TV_PCB05,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2304,
-               .driver_data  = SAA7134_BOARD_10MOONSTVMASTER3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf01d, /* AVerTV DVB-T Super 007 */
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_SUPER_007,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4016,
-               .driver_data  = SAA7134_BOARD_BEHOLD_401,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4036,
-               .driver_data  = SAA7134_BOARD_BEHOLD_403,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4037,
-               .driver_data  = SAA7134_BOARD_BEHOLD_403FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4050,
-               .driver_data  = SAA7134_BOARD_BEHOLD_405,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4051,
-               .driver_data  = SAA7134_BOARD_BEHOLD_405FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4070,
-               .driver_data  = SAA7134_BOARD_BEHOLD_407,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4071,
-               .driver_data  = SAA7134_BOARD_BEHOLD_407FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x4090,
-               .driver_data  = SAA7134_BOARD_BEHOLD_409,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x505B,
-               .driver_data  = SAA7134_BOARD_BEHOLD_505RDS_MK5,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x5051,
-               .driver_data  = SAA7134_BOARD_BEHOLD_505RDS_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x5050,
-               .driver_data  = SAA7134_BOARD_BEHOLD_505FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x5071,
-               .driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x507B,
-               .driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK5,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x5070,
-               .driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x5090,
-               .driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x0000,
-               .subdevice    = 0x5201,
-               .driver_data  = SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6070,
-               .driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6071,
-               .driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK5,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6072,
-               .driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6073,
-               .driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK5,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6090,
-               .driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6091,
-               .driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK5,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6092,
-               .driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK3,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6093,
-               .driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK5,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6190,
-               .driver_data  = SAA7134_BOARD_BEHOLD_M6,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6193,
-               .driver_data  = SAA7134_BOARD_BEHOLD_M6_EXTRA,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6191,
-               .driver_data  = SAA7134_BOARD_BEHOLD_M63,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x4e42,
-               .subdevice    = 0x3502,
-               .driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .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,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
-               .subvendor    = 0x1421,
-               .subdevice    = 0x0380,
-               .driver_data  = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5169,
-               .subdevice    = 0x1502,
-               .driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x6290,
-               .driver_data  = SAA7134_BOARD_BEHOLD_H6,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf636,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf736,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4878, /* REV:1.02G */
-               .driver_data  = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x48cd,
-               .driver_data  = SAA7134_BOARD_ASUSTeK_PS3_100,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x17de,
-               .subdevice    = 0x7128,
-               .driver_data  = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x17de,
-               .subdevice    = 0xb136,
-               .driver_data  = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x1461, /* Avermedia Technologies Inc */
-               .subdevice    = 0xf31d,
-               .driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc900,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_S350,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
-               .subdevice    = 0x7595,
-               .driver_data  = SAA7134_BOARD_BEHOLD_X7,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x19d1, /* RoverMedia */
-               .subdevice    = 0x0138, /* LifeView FlyTV Prime30 OEM */
-               .driver_data  = SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0x2004,
-               .driver_data  = SAA7134_BOARD_ZOLID_HYBRID_PCI,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x1043,
-               .subdevice    = 0x4847,
-               .driver_data  = SAA7134_BOARD_ASUS_EUROPA_HYBRID,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x107d,
-               .subdevice    = 0x6655,
-               .driver_data  = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x13c2,
-               .subdevice    = 0x2804,
-               .driver_data  = SAA7134_BOARD_TECHNOTREND_BUDGET_T3000,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
-               .subdevice    = 0x7190,
-               .driver_data  = SAA7134_BOARD_BEHOLD_H7,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
-               .subdevice    = 0x7090,
-               .driver_data  = SAA7134_BOARD_BEHOLD_A7,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
-               .subvendor    = 0x185b,
-               .subdevice    = 0xc900,
-               .driver_data  = SAA7134_BOARD_VIDEOMATE_M1F,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x5030,
-               .driver_data  = SAA7134_BOARD_BEHOLD_503FM,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = 0x5ace,
-               .subdevice    = 0x5010,
-               .driver_data  = SAA7134_BOARD_BEHOLD_501,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = 0x17de,
-               .subdevice    = 0xd136,
-               .driver_data  = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x6000,
-               .subdevice    = 0x0811,
-               .driver_data  = SAA7134_BOARD_SENSORAY811_911,
-       }, {
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = 0x6000,
-               .subdevice    = 0x0911,
-               .driver_data  = SAA7134_BOARD_SENSORAY811_911,
-       }, {
-               /* --- boards without eeprom + subsystem ID --- */
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0,
-               .driver_data  = SAA7134_BOARD_NOAUTO,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_VENDOR_ID_PHILIPS,
-               .subdevice    = 0,
-               .driver_data  = SAA7134_BOARD_NOAUTO,
-       },{
-               /* --- default catch --- */
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-               .driver_data  = SAA7134_BOARD_UNKNOWN,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-               .driver_data  = SAA7134_BOARD_UNKNOWN,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-               .driver_data  = SAA7134_BOARD_UNKNOWN,
-       },{
-               .vendor       = PCI_VENDOR_ID_PHILIPS,
-               .device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-               .driver_data  = SAA7134_BOARD_UNKNOWN,
-       },{
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl);
-
-/* ----------------------------------------------------------- */
-/* flyvideo tweaks                                             */
-
-
-static void board_flyvideo(struct saa7134_dev *dev)
-{
-       printk("%s: there are different flyvideo cards with different tuners\n"
-              "%s: out there, you might have to use the tuner=<nr> insmod\n"
-              "%s: option to override the default value.\n",
-              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_GPSTATUS0 >> 2, 0x00008000, 0x00000000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
-               switch (dev->board) {
-               case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
-               case SAA7134_BOARD_AVERMEDIA_M103:
-                       saa7134_set_gpio(dev, 23, 0);
-                       msleep(10);
-                       saa7134_set_gpio(dev, 23, 1);
-               break;
-               case SAA7134_BOARD_AVERMEDIA_A16D:
-                       saa7134_set_gpio(dev, 21, 0);
-                       msleep(10);
-                       saa7134_set_gpio(dev, 21, 1);
-               break;
-               case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
-                       saa7134_set_gpio(dev, 18, 0);
-                       msleep(10);
-                       saa7134_set_gpio(dev, 18, 1);
-               break;
-               case SAA7134_BOARD_VIDEOMATE_T750:
-                       saa7134_set_gpio(dev, 20, 0);
-                       msleep(10);
-                       saa7134_set_gpio(dev, 20, 1);
-               break;
-               }
-       return 0;
-       }
-       return -EINVAL;
-}
-
-static int saa7134_xc5000_callback(struct saa7134_dev *dev,
-                                  int command, int arg)
-{
-       switch (dev->board) {
-       case SAA7134_BOARD_BEHOLD_X7:
-       case SAA7134_BOARD_BEHOLD_H7:
-       case SAA7134_BOARD_BEHOLD_A7:
-               if (command == XC5000_TUNER_RESET) {
-               /* Down and UP pheripherial RESET pin for reset all chips */
-                       saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
-                       msleep(10);
-                       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
-                       msleep(10);
-               }
-               break;
-       default:
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
-               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);
-               break;
-       }
-       return 0;
-}
-
-static int saa7134_tda8290_827x_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;
-}
-
-static inline int saa7134_tda18271_hvr11x0_toggle_agc(struct saa7134_dev *dev,
-                                                     enum tda18271_mode mode)
-{
-       /* toggle AGC switch through GPIO 26 */
-       switch (mode) {
-       case TDA18271_ANALOG:
-               saa7134_set_gpio(dev, 26, 0);
-               break;
-       case TDA18271_DIGITAL:
-               saa7134_set_gpio(dev, 26, 1);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev,
-                                                 enum tda18271_mode mode)
-{
-       /* toggle AGC switch through GPIO 27 */
-       switch (mode) {
-       case TDA18271_ANALOG:
-               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
-               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
-               msleep(20);
-               break;
-       case TDA18271_DIGITAL:
-               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000);
-               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000);
-               msleep(20);
-               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000);
-               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000);
-               msleep(30);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev,
-                                           enum tda18271_mode mode)
-{
-       switch (mode) {
-       case TDA18271_ANALOG:
-               saa7134_set_gpio(dev, 18, 0);
-               break;
-       case TDA18271_DIGITAL:
-               saa7134_set_gpio(dev, 18, 1);
-               msleep(30);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev,
-                                         int command, int arg)
-{
-       int ret = 0;
-
-       switch (command) {
-       case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */
-               switch (dev->board) {
-               case SAA7134_BOARD_HAUPPAUGE_HVR1150:
-               case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-               case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
-                       ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
-                       break;
-               case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
-                       ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg);
-                       break;
-               case SAA7134_BOARD_KWORLD_PC150U:
-                       ret = saa7134_kworld_pc150u_toggle_agc(dev, arg);
-                       break;
-               default:
-                       break;
-               }
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-       return ret;
-}
-
-static int saa7134_tda8290_callback(struct saa7134_dev *dev,
-                                   int command, int arg)
-{
-       int ret;
-
-       switch (dev->board) {
-       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-       case SAA7134_BOARD_AVERMEDIA_M733A:
-       case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
-       case SAA7134_BOARD_KWORLD_PC150U:
-       case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
-               /* tda8290 + tda18271 */
-               ret = saa7134_tda8290_18271_callback(dev, command, arg);
-               break;
-       default:
-               /* tda8290 + tda827x */
-               ret = saa7134_tda8290_827x_callback(dev, command, arg);
-               break;
-       }
-       return ret;
-}
-
-int saa7134_tuner_callback(void *priv, int component, 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);
-               case TUNER_XC5000:
-                       return saa7134_xc5000_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)
-{
-       struct tveeprom tv;
-
-       tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
-
-       /* Make sure we support the board model */
-       switch (tv.model) {
-       case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */
-       case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
-       case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
-       case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
-       case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
-       case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
-       case 67569: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM) */
-       case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */
-       case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
-       case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
-       case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
-       case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
-               break;
-       default:
-               printk(KERN_WARNING "%s: warning: "
-                      "unknown hauppauge model #%d\n", dev->name, tv.model);
-               break;
-       }
-
-       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-              dev->name, tv.model);
-}
-
-/* ----------------------------------------------------------- */
-
-int saa7134_board_init1(struct saa7134_dev *dev)
-{
-       /* Always print gpio, often manufacturers encode tuner type and other info. */
-       saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0);
-       dev->gpio_value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
-       printk(KERN_INFO "%s: board init: gpio is %x\n", dev->name, dev->gpio_value);
-
-       switch (dev->board) {
-       case SAA7134_BOARD_FLYVIDEO2000:
-       case SAA7134_BOARD_FLYVIDEO3000:
-       case SAA7134_BOARD_FLYVIDEO3000_NTSC:
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               board_flyvideo(dev);
-               break;
-       case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
-       case SAA7134_BOARD_FLYTVPLATINUM_FM:
-       case SAA7134_BOARD_CINERGY400:
-       case SAA7134_BOARD_CINERGY600:
-       case SAA7134_BOARD_CINERGY600_MK3:
-       case SAA7134_BOARD_ECS_TVP3XP:
-       case SAA7134_BOARD_ECS_TVP3XP_4CB5:
-       case SAA7134_BOARD_ECS_TVP3XP_4CB6:
-       case SAA7134_BOARD_MD2819:
-       case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
-       case SAA7134_BOARD_KWORLD_XPERT:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
-       case SAA7134_BOARD_AVERMEDIA_305:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
-       case SAA7134_BOARD_AVERMEDIA_307:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
-       case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
-       case SAA7134_BOARD_AVERMEDIA_777:
-       case SAA7134_BOARD_AVERMEDIA_M135A:
-/*      case SAA7134_BOARD_SABRENT_SBTTVFM:  */ /* not finished yet */
-       case SAA7134_BOARD_VIDEOMATE_TV_PVR:
-       case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
-       case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
-       case SAA7134_BOARD_VIDEOMATE_M1F:
-       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
-       case SAA7134_BOARD_MANLI_MTV001:
-       case SAA7134_BOARD_MANLI_MTV002:
-       case SAA7134_BOARD_BEHOLD_409FM:
-       case SAA7134_BOARD_AVACSSMARTTV:
-       case SAA7134_BOARD_GOTVIEW_7135:
-       case SAA7134_BOARD_KWORLD_TERMINATOR:
-       case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
-       case SAA7134_BOARD_FLYDVBT_LR301:
-       case SAA7134_BOARD_ASUSTeK_PS3_100:
-       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
-       case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
-       case SAA7134_BOARD_FLYDVBTDUO:
-       case SAA7134_BOARD_PROTEUS_2309:
-       case SAA7134_BOARD_AVERMEDIA_A16AR:
-       case SAA7134_BOARD_ENCORE_ENLTV:
-       case SAA7134_BOARD_ENCORE_ENLTV_FM:
-       case SAA7134_BOARD_ENCORE_ENLTV_FM53:
-       case SAA7134_BOARD_ENCORE_ENLTV_FM3:
-       case SAA7134_BOARD_10MOONSTVMASTER3:
-       case SAA7134_BOARD_BEHOLD_401:
-       case SAA7134_BOARD_BEHOLD_403:
-       case SAA7134_BOARD_BEHOLD_403FM:
-       case SAA7134_BOARD_BEHOLD_405:
-       case SAA7134_BOARD_BEHOLD_405FM:
-       case SAA7134_BOARD_BEHOLD_407:
-       case SAA7134_BOARD_BEHOLD_407FM:
-       case SAA7134_BOARD_BEHOLD_409:
-       case SAA7134_BOARD_BEHOLD_505FM:
-       case SAA7134_BOARD_BEHOLD_505RDS_MK5:
-       case SAA7134_BOARD_BEHOLD_505RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_507_9FM:
-       case SAA7134_BOARD_BEHOLD_507RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_507RDS_MK5:
-       case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
-       case SAA7134_BOARD_REAL_ANGEL_220:
-       case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
-       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
-       case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
-       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               break;
-       case SAA7134_BOARD_FLYDVBS_LR300:
-               saa_writeb(SAA7134_GPIO_GPMODE3, 0x80);
-               saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x40);
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               break;
-       case SAA7134_BOARD_MD5044:
-               printk("%s: seems there are two different versions of the MD5044\n"
-                      "%s: (with the same ID) out there.  If sound doesn't work for\n"
-                      "%s: you try the audio_clock_override=0x200000 insmod option.\n",
-                      dev->name,dev->name,dev->name);
-               break;
-       case SAA7134_BOARD_CINERGY400_CARDBUS:
-               /* power-up tuner chip */
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
-               break;
-       case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
-               /* this turns the remote control chip off to work around a bug in it */
-               saa_writeb(SAA7134_GPIO_GPMODE1, 0x80);
-               saa_writeb(SAA7134_GPIO_GPSTATUS1, 0x80);
-               break;
-       case SAA7134_BOARD_MONSTERTV_MOBILE:
-               /* power-up tuner chip */
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
-               break;
-       case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               /* turn the fan on */
-               saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
-               saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
-               break;
-       case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
-       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08000000, 0x08000000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS:
-       case SAA7134_BOARD_AVERMEDIA_M115:
-               /* 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(10);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
-               /* power-down tuner chip */
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0);
-               msleep(10);
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000);
-               msleep(10);
-               dev->has_remote = SAA7134_REMOTE_I2C;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
-               saa7134_set_gpio(dev, 23, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 23, 1);
-               dev->has_remote = SAA7134_REMOTE_I2C;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_M103:
-               saa7134_set_gpio(dev, 23, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 23, 1);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A16D:
-               saa7134_set_gpio(dev, 21, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 21, 1);
-               msleep(1);
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               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:
-
-               /*
-                * Make sure Production Test Register at offset 0x1D1 is cleared
-                * to take chip out of test mode.  Clearing bit 4 (TST_EN_AOUT)
-                * prevents pin 105 from remaining low; keeping pin 105 low
-                * continually resets the SAA6752 chip.
-                */
-
-               saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               /* GPIO 26 high for digital, low for analog */
-               saa7134_set_gpio(dev, 26, 0);
-               msleep(1);
-
-               saa7134_set_gpio(dev, 22, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 22, 1);
-               break;
-       /* i2c remotes */
-       case SAA7134_BOARD_PINNACLE_PCTV_110i:
-       case SAA7134_BOARD_PINNACLE_PCTV_310i:
-       case SAA7134_BOARD_UPMOST_PURPLE_TV:
-       case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-       case SAA7134_BOARD_BEHOLD_607FM_MK3:
-       case SAA7134_BOARD_BEHOLD_607FM_MK5:
-       case SAA7134_BOARD_BEHOLD_609FM_MK3:
-       case SAA7134_BOARD_BEHOLD_609FM_MK5:
-       case SAA7134_BOARD_BEHOLD_607RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_607RDS_MK5:
-       case SAA7134_BOARD_BEHOLD_609RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_609RDS_MK5:
-       case SAA7134_BOARD_BEHOLD_M6:
-       case SAA7134_BOARD_BEHOLD_M63:
-       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
-       case SAA7134_BOARD_BEHOLD_H6:
-       case SAA7134_BOARD_BEHOLD_X7:
-       case SAA7134_BOARD_BEHOLD_H7:
-       case SAA7134_BOARD_BEHOLD_A7:
-       case SAA7134_BOARD_KWORLD_PC150U:
-               dev->has_remote = SAA7134_REMOTE_I2C;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A169_B:
-               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",
-                      dev->name,card(dev).name,dev->name,dev->name);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_M102:
-               /* enable tuner */
-              dev->has_remote = SAA7134_REMOTE_GPIO;
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
-       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
-               /* write windows gpio values */
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x80040100, 0x80040100);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100);
-               break;
-       case SAA7134_BOARD_VIDEOMATE_S350:
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0000C000, 0x0000C000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_M733A:
-               saa7134_set_gpio(dev, 1, 1);
-               msleep(10);
-               saa7134_set_gpio(dev, 1, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 1, 1);
-               dev->has_remote = SAA7134_REMOTE_GPIO;
-               break;
-       case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
-               /* enable LGS-8G75 */
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0e050000, 0x0c050000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0e050000, 0x0c050000);
-               break;
-       case SAA7134_BOARD_VIDEOMATE_T750:
-               /* enable the analog tuner */
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00008000, 0x00008000);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
-               break;
-       }
-       return 0;
-}
-
-static void saa7134_tuner_setup(struct saa7134_dev *dev)
-{
-       struct tuner_setup tun_setup;
-       unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
-
-       memset(&tun_setup, 0, sizeof(tun_setup));
-       tun_setup.tuner_callback = saa7134_tuner_callback;
-
-       if (saa7134_boards[dev->board].radio_type != UNSET) {
-               tun_setup.type = saa7134_boards[dev->board].radio_type;
-               tun_setup.addr = saa7134_boards[dev->board].radio_addr;
-
-               tun_setup.mode_mask = T_RADIO;
-
-               saa_call_all(dev, tuner, s_type_addr, &tun_setup);
-               mode_mask &= ~T_RADIO;
-       }
-
-       if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
-               tun_setup.type = dev->tuner_type;
-               tun_setup.addr = dev->tuner_addr;
-               tun_setup.config = saa7134_boards[dev->board].tuner_config;
-               tun_setup.tuner_callback = saa7134_tuner_callback;
-
-               tun_setup.mode_mask = mode_mask;
-
-               saa_call_all(dev, tuner, s_type_addr, &tun_setup);
-       }
-
-       if (dev->tda9887_conf) {
-               struct v4l2_priv_tun_config tda9887_cfg;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv = &dev->tda9887_conf;
-
-               saa_call_all(dev, tuner, s_config, &tda9887_cfg);
-       }
-
-       if (dev->tuner_type == TUNER_XC2028) {
-               struct v4l2_priv_tun_config  xc2028_cfg;
-               struct xc2028_ctrl           ctl;
-
-               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
-               memset(&ctl, 0, sizeof(ctl));
-
-               ctl.fname   = XC2028_DEFAULT_FIRMWARE;
-               ctl.max_len = 64;
-
-               switch (dev->board) {
-               case SAA7134_BOARD_AVERMEDIA_A16D:
-               case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
-               case SAA7134_BOARD_AVERMEDIA_M103:
-               case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
-                       ctl.demod = XC3028_FE_ZARLINK456;
-                       break;
-               default:
-                       ctl.demod = XC3028_FE_OREN538;
-                       ctl.mts = 1;
-               }
-
-               xc2028_cfg.tuner = TUNER_XC2028;
-               xc2028_cfg.priv  = &ctl;
-
-               saa_call_all(dev, tuner, s_config, &xc2028_cfg);
-       }
-}
-
-/* stuff which needs working i2c */
-int saa7134_board_init2(struct saa7134_dev *dev)
-{
-       unsigned char buf;
-       int board;
-
-       /* Put here the code that enables the chips that are needed
-          for analog mode and doesn't depend on the tuner attachment.
-          It is also a good idea to get tuner type from eeprom, etc before
-          initializing tuner, since we can avoid loading tuner driver
-          on devices that has TUNER_ABSENT
-        */
-       switch (dev->board) {
-       case SAA7134_BOARD_BMK_MPEX_NOTUNER:
-       case SAA7134_BOARD_BMK_MPEX_TUNER:
-               /* Checks if the device has a tuner at 0x60 addr
-                  If the device doesn't have a tuner, TUNER_ABSENT
-                  will be used at tuner_type, avoiding loading tuner
-                  without needing it
-                */
-               dev->i2c_client.addr = 0x60;
-               board = (i2c_master_recv(&dev->i2c_client, &buf, 0) < 0)
-                       ? SAA7134_BOARD_BMK_MPEX_NOTUNER
-                       : SAA7134_BOARD_BMK_MPEX_TUNER;
-               if (board == dev->board)
-                       break;
-               dev->board = board;
-               printk("%s: board type fixup: %s\n", dev->name,
-               saa7134_boards[dev->board].name);
-               dev->tuner_type = saa7134_boards[dev->board].tuner_type;
-
-               break;
-       case SAA7134_BOARD_MD7134:
-       {
-               u8 subaddr;
-               u8 data[3];
-               int ret, tuner_t;
-               struct i2c_msg msg[] = {{.addr=0x50, .flags=0, .buf=&subaddr, .len = 1},
-                                       {.addr=0x50, .flags=I2C_M_RD, .buf=data, .len = 3}};
-
-               subaddr= 0x14;
-               tuner_t = 0;
-
-               /* Retrieve device data from eeprom, checking for the
-                  proper tuner_type.
-                */
-               ret = i2c_transfer(&dev->i2c_adap, msg, 2);
-               if (ret != 2) {
-                       printk(KERN_ERR "EEPROM read failure\n");
-               } else if ((data[0] != 0) && (data[0] != 0xff)) {
-                       /* old config structure */
-                       subaddr = data[0] + 2;
-                       msg[1].len = 2;
-                       i2c_transfer(&dev->i2c_adap, msg, 2);
-                       tuner_t = (data[0] << 8) + data[1];
-                       switch (tuner_t){
-                       case 0x0103:
-                               dev->tuner_type = TUNER_PHILIPS_PAL;
-                               break;
-                       case 0x010C:
-                               dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
-                               break;
-                       default:
-                               printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
-                       }
-               } else if ((data[1] != 0) && (data[1] != 0xff)) {
-                       /* new config structure */
-                       subaddr = data[1] + 1;
-                       msg[1].len = 1;
-                       i2c_transfer(&dev->i2c_adap, msg, 2);
-                       subaddr = data[0] + 1;
-                       msg[1].len = 2;
-                       i2c_transfer(&dev->i2c_adap, msg, 2);
-                       tuner_t = (data[1] << 8) + data[0];
-                       switch (tuner_t) {
-                       case 0x0005:
-                               dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
-                               break;
-                       case 0x001d:
-                               dev->tuner_type = TUNER_PHILIPS_FMD1216ME_MK3;
-                                       printk(KERN_INFO "%s Board has DVB-T\n", dev->name);
-                               break;
-                       default:
-                               printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
-                       }
-               } else {
-                       printk(KERN_ERR "%s unexpected config structure\n", dev->name);
-               }
-
-               printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
-               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;
-               }
-               /* break intentionally omitted */
-       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-       case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
-       case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
-       case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000:
-       {
-
-               /* The Philips EUROPA based hybrid boards have the tuner
-                  connected through the channel decoder. We have to make it
-                  transparent to find it
-                */
-               u8 data[] = { 0x07, 0x02};
-               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-               break;
-       }
-       case SAA7134_BOARD_PHILIPS_TIGER:
-       case SAA7134_BOARD_PHILIPS_TIGER_S:
-       {
-               u8 data[] = { 0x3c, 0x33, 0x60};
-               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-               if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
-                       dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
-                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
-                               dev->name, saa7134_boards[dev->board].name);
-               }
-               if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
-                       dev->tuner_type = TUNER_PHILIPS_TDA8290;
-
-                       data[2] = 0x68;
-                       i2c_transfer(&dev->i2c_adap, &msg, 1);
-                       break;
-               }
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       }
-       case SAA7134_BOARD_ASUSTeK_TVFM7135:
-       /* The card below is detected as card=53, but is different */
-              if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
-                      dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
-                      printk(KERN_INFO "%s: P7131 analog only, using "
-                                                      "entry of %s\n",
-                      dev->name, saa7134_boards[dev->board].name);
-
-                       /* IR init has already happened for other cards, so
-                        * we have to catch up. */
-                       dev->has_remote = SAA7134_REMOTE_GPIO;
-                       saa7134_input_init1(dev);
-              }
-              break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-               hauppauge_eeprom(dev, dev->eedata+0x80);
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-               hauppauge_eeprom(dev, dev->eedata+0x80);
-               /* break intentionally omitted */
-       case SAA7134_BOARD_PINNACLE_PCTV_310i:
-       case SAA7134_BOARD_KWORLD_DVBT_210:
-       case SAA7134_BOARD_TEVION_DVBT_220RF:
-       case SAA7134_BOARD_ASUSTeK_TIGER:
-       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
-       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
-                */
-               u8 data[] = { 0x3c, 0x33, 0x60};
-               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       }
-       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
-       {
-               u8 data[] = { 0x3c, 0x33, 0x60};
-               struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
-                                                       .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       }
-       case SAA7134_BOARD_ASUSTeK_PS3_100:
-       {
-               u8 data[] = { 0x3c, 0x33, 0x60};
-               struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
-                                                      .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       }
-       case SAA7134_BOARD_FLYDVB_TRIO:
-       {
-               u8 temp = 0;
-               int rc;
-               u8 data[] = { 0x3c, 0x33, 0x62};
-               struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-               /*
-                * send weak up message to pic16C505 chip
-                * @ LifeView FlyDVB Trio
-                */
-               msg.buf = &temp;
-               msg.addr = 0x0b;
-               msg.len = 1;
-               if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) {
-                       printk(KERN_WARNING "%s: send wake up byte to pic16C505"
-                                       "(IR chip) failed\n", dev->name);
-               } else {
-                       msg.flags = I2C_M_RD;
-                       rc = i2c_transfer(&dev->i2c_adap, &msg, 1);
-                       printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n",
-                                  dev->name, msg.addr,
-                                  (1 == rc) ? "yes" : "no");
-                       if (rc == 1)
-                               dev->has_remote = SAA7134_REMOTE_I2C;
-               }
-               break;
-       }
-       case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
-       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-       {
-               /* initialize analog mode  */
-               u8 data[] = { 0x3c, 0x33, 0x6a};
-               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       }
-       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
-       case SAA7134_BOARD_CINERGY_HT_PCI:
-       {
-               /* initialize analog mode */
-               u8 data[] = { 0x3c, 0x33, 0x68};
-               struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
-               i2c_transfer(&dev->i2c_adap, &msg, 1);
-               break;
-       }
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
-               /* The T200 and the T200A share the same pci id.  Consequently,
-                * we are going to query eeprom to try to find out which one we
-                * are actually looking at. */
-
-               /* Don't do this if the board was specifically selected with an
-                * insmod option or if we have the default configuration T200*/
-               if (!dev->autodetected || (dev->eedata[0x41] == 0xd0))
-                       break;
-               if (dev->eedata[0x41] == 0x02) {
-                       /* Reconfigure board  as T200A */
-                       dev->board = SAA7134_BOARD_VIDEOMATE_DVBT_200A;
-                       dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
-                       dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
-                       printk(KERN_INFO "%s: Reconfigured board as %s\n",
-                               dev->name, saa7134_boards[dev->board].name);
-               } else {
-                       printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
-                               dev->name, dev->eedata[0x41]);
-                       break;
-               }
-               break;
-       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
-       case SAA7134_BOARD_KWORLD_ATSC110:
-       {
-               struct i2c_msg msg = { .addr = 0x0a, .flags = 0 };
-               int i;
-               static u8 buffer[][2] = {
-                       { 0x10, 0x12 },
-                       { 0x13, 0x04 },
-                       { 0x16, 0x00 },
-                       { 0x14, 0x04 },
-                       { 0x17, 0x00 },
-               };
-
-               for (i = 0; i < ARRAY_SIZE(buffer); i++) {
-                       msg.buf = &buffer[i][0];
-                       msg.len = ARRAY_SIZE(buffer[0]);
-                       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
-                               printk(KERN_WARNING
-                                      "%s: Unable to enable tuner(%i).\n",
-                                      dev->name, i);
-               }
-               break;
-       }
-       case SAA7134_BOARD_BEHOLD_H6:
-       {
-               u8 data[] = { 0x09, 0x9f, 0x86, 0x11};
-               struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = data,
-                                                       .len = sizeof(data)};
-
-               /* The tuner TUNER_PHILIPS_FMD1216MEX_MK3 after hardware    */
-               /* start has disabled IF and enabled DVB-T. When saa7134    */
-               /* scan I2C devices it not detect IF tda9887 and can`t      */
-               /* watch TV without software reboot. For solve this problem */
-               /* switch the tuner to analog TV mode manually.             */
-               if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
-                               printk(KERN_WARNING
-                                     "%s: Unable to enable IF of the tuner.\n",
-                                      dev->name);
-               break;
-       }
-       case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
-               saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
-               saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
-
-               saa7134_set_gpio(dev, 27, 0);
-               break;
-       } /* switch() */
-
-       /* initialize tuner */
-       if (TUNER_ABSENT != dev->tuner_type) {
-               int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
-
-               /* Note: radio tuner address is always filled in,
-                  so we do not need to probe for a radio tuner device. */
-               if (dev->radio_type != UNSET)
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "tuner",
-                               dev->radio_addr, NULL);
-               if (has_demod)
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-               if (dev->tuner_addr == ADDR_UNSET) {
-                       enum v4l2_i2c_tuner_type type =
-                               has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
-
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(type));
-               } else {
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "tuner",
-                               dev->tuner_addr, NULL);
-               }
-       }
-
-       saa7134_tuner_setup(dev);
-
-       switch (dev->board) {
-       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
-       {
-               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;
-               saa_call_all(dev, tuner, s_config, &tea5767_cfg);
-               break;
-       }
-       } /* switch() */
-
-       return 0;
-}
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
deleted file mode 100644 (file)
index 5fbb4e4..0000000
+++ /dev/null
@@ -1,1368 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * driver core
- *
- * (c) 2001-03 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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/kmod.h>
-#include <linux/sound.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/dma-mapping.h>
-#include <linux/pm.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
-MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(SAA7134_VERSION);
-
-
-/* ------------------------------------------------------------------ */
-
-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;
-module_param(core_debug, int, 0644);
-MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
-
-static unsigned int gpio_tracking;
-module_param(gpio_tracking, int, 0644);
-MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
-
-static unsigned int alsa = 1;
-module_param(alsa, int, 0644);
-MODULE_PARM_DESC(alsa,"enable/disable ALSA DMA sound [dmasound]");
-
-static unsigned int latency = UNSET;
-module_param(latency, int, 0444);
-MODULE_PARM_DESC(latency,"pci latency timer");
-
-int saa7134_no_overlay=-1;
-module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
-MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
-               " [some VIA/SIS chipsets are known to have problem with overlay]");
-
-static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[]   = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int tuner[]    = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int card[]     = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-
-
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(vbi_nr,   int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-module_param_array(tuner,    int, NULL, 0444);
-module_param_array(card,     int, NULL, 0444);
-
-MODULE_PARM_DESC(video_nr, "video device number");
-MODULE_PARM_DESC(vbi_nr,   "vbi device number");
-MODULE_PARM_DESC(radio_nr, "radio device number");
-MODULE_PARM_DESC(tuner,    "tuner type");
-MODULE_PARM_DESC(card,     "card type");
-
-DEFINE_MUTEX(saa7134_devlist_lock);
-EXPORT_SYMBOL(saa7134_devlist_lock);
-LIST_HEAD(saa7134_devlist);
-EXPORT_SYMBOL(saa7134_devlist);
-static LIST_HEAD(mops_list);
-static unsigned int saa7134_devcount;
-
-int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
-int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
-
-#define dprintk(fmt, arg...)   if (core_debug) \
-       printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
-
-void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
-{
-       unsigned long mode,status;
-
-       if (!gpio_tracking)
-               return;
-       /* rising SAA7134_GPIO_GPRESCAN reads the status */
-       saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,0);
-       saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN);
-       mode   = saa_readl(SAA7134_GPIO_GPMODE0   >> 2) & 0xfffffff;
-       status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff;
-       printk(KERN_DEBUG
-              "%s: gpio: mode=0x%07lx in=0x%07lx out=0x%07lx [%s]\n",
-              dev->name, mode, (~mode) & status, mode & status, msg);
-}
-
-void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
-{
-       u32 index, bitval;
-
-       index = 1 << bit_no;
-       switch (value) {
-       case 0: /* static value */
-       case 1: dprintk("setting GPIO%d to static %d\n", bit_no, value);
-               /* turn sync mode off if necessary */
-               if (index & 0x00c00000)
-                       saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x00);
-               if (value)
-                       bitval = index;
-               else
-                       bitval = 0;
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, index);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, index, bitval);
-               break;
-       case 3: /* tristate */
-               dprintk("setting GPIO%d to tristate\n", bit_no);
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, 0);
-               break;
-       }
-}
-
-/* ------------------------------------------------------------------ */
-
-
-/* ----------------------------------------------------------- */
-/* delayed request_module                                      */
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-
-static void request_module_async(struct work_struct *work){
-       struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk);
-       if (card_is_empress(dev))
-               request_module("saa7134-empress");
-       if (card_is_dvb(dev))
-               request_module("saa7134-dvb");
-       if (alsa) {
-               if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
-                       request_module("saa7134-alsa");
-       }
-}
-
-static void request_submodules(struct saa7134_dev *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_submodules(struct saa7134_dev *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-
-#else
-#define request_submodules(dev)
-#define flush_request_submodules(dev)
-#endif /* CONFIG_MODULES */
-
-/* ------------------------------------------------------------------ */
-
-/* nr of (saa7134-)pages for the given buffer size */
-static int saa7134_buffer_pages(int size)
-{
-       size  = PAGE_ALIGN(size);
-       size += PAGE_SIZE; /* for non-page-aligned buffers */
-       size /= 4096;
-       return size;
-}
-
-/* calc max # of buffers from size (must not exceed the 4MB virtual
- * address space per DMA channel) */
-int saa7134_buffer_count(unsigned int size, unsigned int count)
-{
-       unsigned int maxcount;
-
-       maxcount = 1024 / saa7134_buffer_pages(size);
-       if (count > maxcount)
-               count = maxcount;
-       return count;
-}
-
-int saa7134_buffer_startpage(struct saa7134_buf *buf)
-{
-       return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i;
-}
-
-unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
-{
-       unsigned long base;
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-       base  = saa7134_buffer_startpage(buf) * 4096;
-       base += dma->sglist[0].offset;
-       return base;
-}
-
-/* ------------------------------------------------------------------ */
-
-int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
-{
-       __le32       *cpu;
-       dma_addr_t   dma_addr = 0;
-
-       cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
-       if (NULL == cpu)
-               return -ENOMEM;
-       pt->size = SAA7134_PGTABLE_SIZE;
-       pt->cpu  = cpu;
-       pt->dma  = dma_addr;
-       return 0;
-}
-
-int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
-                         struct scatterlist *list, unsigned int length,
-                         unsigned int startpage)
-{
-       __le32        *ptr;
-       unsigned int  i,p;
-
-       BUG_ON(NULL == pt || NULL == pt->cpu);
-
-       ptr = pt->cpu + startpage;
-       for (i = 0; i < length; i++, list++)
-               for (p = 0; p * 4096 < list->length; p++, ptr++)
-                       *ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
-       return 0;
-}
-
-void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
-{
-       if (NULL == pt->cpu)
-               return;
-       pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
-       pt->cpu = NULL;
-}
-
-/* ------------------------------------------------------------------ */
-
-void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
-{
-       struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-       BUG_ON(in_interrupt());
-
-       videobuf_waiton(q, &buf->vb, 0, 0);
-       videobuf_dma_unmap(q->dev, dma);
-       videobuf_dma_free(dma);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-/* ------------------------------------------------------------------ */
-
-int saa7134_buffer_queue(struct saa7134_dev *dev,
-                        struct saa7134_dmaqueue *q,
-                        struct saa7134_buf *buf)
-{
-       struct saa7134_buf *next = NULL;
-
-       assert_spin_locked(&dev->slock);
-       dprintk("buffer_queue %p\n",buf);
-       if (NULL == q->curr) {
-               if (!q->need_two) {
-                       q->curr = buf;
-                       buf->activate(dev,buf,NULL);
-               } else if (list_empty(&q->queue)) {
-                       list_add_tail(&buf->vb.queue,&q->queue);
-                       buf->vb.state = VIDEOBUF_QUEUED;
-               } else {
-                       next = list_entry(q->queue.next,struct saa7134_buf,
-                                         vb.queue);
-                       q->curr = buf;
-                       buf->activate(dev,buf,next);
-               }
-       } else {
-               list_add_tail(&buf->vb.queue,&q->queue);
-               buf->vb.state = VIDEOBUF_QUEUED;
-       }
-       return 0;
-}
-
-void saa7134_buffer_finish(struct saa7134_dev *dev,
-                          struct saa7134_dmaqueue *q,
-                          unsigned int state)
-{
-       assert_spin_locked(&dev->slock);
-       dprintk("buffer_finish %p\n",q->curr);
-
-       /* finish current buffer */
-       q->curr->vb.state = state;
-       do_gettimeofday(&q->curr->vb.ts);
-       wake_up(&q->curr->vb.done);
-       q->curr = NULL;
-}
-
-void saa7134_buffer_next(struct saa7134_dev *dev,
-                        struct saa7134_dmaqueue *q)
-{
-       struct saa7134_buf *buf,*next = NULL;
-
-       assert_spin_locked(&dev->slock);
-       BUG_ON(NULL != q->curr);
-
-       if (!list_empty(&q->queue)) {
-               /* activate next one from queue */
-               buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue);
-               dprintk("buffer_next %p [prev=%p/next=%p]\n",
-                       buf,q->queue.prev,q->queue.next);
-               list_del(&buf->vb.queue);
-               if (!list_empty(&q->queue))
-                       next = list_entry(q->queue.next,struct saa7134_buf,
-                                         vb.queue);
-               q->curr = buf;
-               buf->activate(dev,buf,next);
-               dprintk("buffer_next #2 prev=%p/next=%p\n",
-                       q->queue.prev,q->queue.next);
-       } else {
-               /* nothing to do -- just stop DMA */
-               dprintk("buffer_next %p\n",NULL);
-               saa7134_set_dmabits(dev);
-               del_timer(&q->timeout);
-
-               if (card_has_mpeg(dev))
-                       if (dev->ts_started)
-                               saa7134_ts_stop(dev);
-       }
-}
-
-void saa7134_buffer_timeout(unsigned long data)
-{
-       struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data;
-       struct saa7134_dev *dev = q->dev;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->slock,flags);
-
-       /* try to reset the hardware (SWRST) */
-       saa_writeb(SAA7134_REGION_ENABLE, 0x00);
-       saa_writeb(SAA7134_REGION_ENABLE, 0x80);
-       saa_writeb(SAA7134_REGION_ENABLE, 0x00);
-
-       /* flag current buffer as failed,
-          try to start over with the next one. */
-       if (q->curr) {
-               dprintk("timeout on %p\n",q->curr);
-               saa7134_buffer_finish(dev,q,VIDEOBUF_ERROR);
-       }
-       saa7134_buffer_next(dev,q);
-       spin_unlock_irqrestore(&dev->slock,flags);
-}
-
-/* ------------------------------------------------------------------ */
-
-int saa7134_set_dmabits(struct saa7134_dev *dev)
-{
-       u32 split, task=0, ctrl=0, irq=0;
-       enum v4l2_field cap = V4L2_FIELD_ANY;
-       enum v4l2_field ov  = V4L2_FIELD_ANY;
-
-       assert_spin_locked(&dev->slock);
-
-       if (dev->insuspend)
-               return 0;
-
-       /* video capture -- dma 0 + video task A */
-       if (dev->video_q.curr) {
-               task |= 0x01;
-               ctrl |= SAA7134_MAIN_CTRL_TE0;
-               irq  |= SAA7134_IRQ1_INTE_RA0_1 |
-                       SAA7134_IRQ1_INTE_RA0_0;
-               cap = dev->video_q.curr->vb.field;
-       }
-
-       /* video capture -- dma 1+2 (planar modes) */
-       if (dev->video_q.curr &&
-           dev->video_q.curr->fmt->planar) {
-               ctrl |= SAA7134_MAIN_CTRL_TE4 |
-                       SAA7134_MAIN_CTRL_TE5;
-       }
-
-       /* screen overlay -- dma 0 + video task B */
-       if (dev->ovenable) {
-               task |= 0x10;
-               ctrl |= SAA7134_MAIN_CTRL_TE1;
-               ov = dev->ovfield;
-       }
-
-       /* vbi capture -- dma 0 + vbi task A+B */
-       if (dev->vbi_q.curr) {
-               task |= 0x22;
-               ctrl |= SAA7134_MAIN_CTRL_TE2 |
-                       SAA7134_MAIN_CTRL_TE3;
-               irq  |= SAA7134_IRQ1_INTE_RA0_7 |
-                       SAA7134_IRQ1_INTE_RA0_6 |
-                       SAA7134_IRQ1_INTE_RA0_5 |
-                       SAA7134_IRQ1_INTE_RA0_4;
-       }
-
-       /* audio capture -- dma 3 */
-       if (dev->dmasound.dma_running) {
-               ctrl |= SAA7134_MAIN_CTRL_TE6;
-               irq  |= SAA7134_IRQ1_INTE_RA3_1 |
-                       SAA7134_IRQ1_INTE_RA3_0;
-       }
-
-       /* TS capture -- dma 5 */
-       if (dev->ts_q.curr) {
-               ctrl |= SAA7134_MAIN_CTRL_TE5;
-               irq  |= SAA7134_IRQ1_INTE_RA2_1 |
-                       SAA7134_IRQ1_INTE_RA2_0;
-       }
-
-       /* set task conditions + field handling */
-       if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
-               /* default config -- use full frames */
-               saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
-               saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
-               saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x02);
-               saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x02);
-               split = 0;
-       } else {
-               /* split fields between tasks */
-               if (V4L2_FIELD_TOP == cap) {
-                       /* odd A, even B, repeat */
-                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
-                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0e);
-               } else {
-                       /* odd B, even A, repeat */
-                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0e);
-                       saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
-               }
-               saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x01);
-               saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x01);
-               split = 1;
-       }
-
-       /* irqs */
-       saa_writeb(SAA7134_REGION_ENABLE, task);
-       saa_writel(SAA7134_IRQ1,          irq);
-       saa_andorl(SAA7134_MAIN_CTRL,
-                  SAA7134_MAIN_CTRL_TE0 |
-                  SAA7134_MAIN_CTRL_TE1 |
-                  SAA7134_MAIN_CTRL_TE2 |
-                  SAA7134_MAIN_CTRL_TE3 |
-                  SAA7134_MAIN_CTRL_TE4 |
-                  SAA7134_MAIN_CTRL_TE5 |
-                  SAA7134_MAIN_CTRL_TE6,
-                  ctrl);
-       dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
-               task, ctrl, irq, split ? "no" : "yes");
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-/* IRQ handler + helpers                                              */
-
-static char *irqbits[] = {
-       "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3",
-       "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
-       "TRIG_ERR", "CONF_ERR", "LOAD_ERR",
-       "GPIO16", "GPIO18", "GPIO22", "GPIO23"
-};
-#define IRQBITS ARRAY_SIZE(irqbits)
-
-static void print_irqstatus(struct saa7134_dev *dev, int loop,
-                           unsigned long report, unsigned long status)
-{
-       unsigned int i;
-
-       printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
-              dev->name,loop,jiffies,report,status);
-       for (i = 0; i < IRQBITS; i++) {
-               if (!(report & (1 << i)))
-                       continue;
-               printk(" %s",irqbits[i]);
-       }
-       if (report & SAA7134_IRQ_REPORT_DONE_RA0) {
-               printk(" | RA0=%s,%s,%s,%ld",
-                      (status & 0x40) ? "vbi"  : "video",
-                      (status & 0x20) ? "b"    : "a",
-                      (status & 0x10) ? "odd"  : "even",
-                      (status & 0x0f));
-       }
-       printk("\n");
-}
-
-static irqreturn_t saa7134_irq(int irq, void *dev_id)
-{
-       struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
-       unsigned long report,status;
-       int loop, handled = 0;
-
-       if (dev->insuspend)
-               goto out;
-
-       for (loop = 0; loop < 10; loop++) {
-               report = saa_readl(SAA7134_IRQ_REPORT);
-               status = saa_readl(SAA7134_IRQ_STATUS);
-
-               /* If dmasound support is active and we get a sound report,
-                * mask out the report and let the saa7134-alsa module deal
-                * with it */
-               if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
-                       (dev->dmasound.priv_data != NULL) )
-               {
-                       if (irq_debug > 1)
-                               printk(KERN_DEBUG "%s/irq: preserving DMA sound interrupt\n",
-                                      dev->name);
-                       report &= ~SAA7134_IRQ_REPORT_DONE_RA3;
-               }
-
-               if (0 == report) {
-                       if (irq_debug > 1)
-                               printk(KERN_DEBUG "%s/irq: no (more) work\n",
-                                      dev->name);
-                       goto out;
-               }
-
-               handled = 1;
-               saa_writel(SAA7134_IRQ_REPORT,report);
-               if (irq_debug)
-                       print_irqstatus(dev,loop,report,status);
-
-
-               if ((report & SAA7134_IRQ_REPORT_RDCAP) ||
-                       (report & SAA7134_IRQ_REPORT_INTL))
-                               saa7134_irq_video_signalchange(dev);
-
-
-               if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
-                   (status & 0x60) == 0)
-                       saa7134_irq_video_done(dev,status);
-
-               if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
-                   (status & 0x40) == 0x40)
-                       saa7134_irq_vbi_done(dev,status);
-
-               if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
-                   card_has_mpeg(dev))
-                       saa7134_irq_ts_done(dev,status);
-
-               if (report & SAA7134_IRQ_REPORT_GPIO16) {
-                       switch (dev->has_remote) {
-                               case SAA7134_REMOTE_GPIO:
-                                       if (!dev->remote)
-                                               break;
-                                       if  (dev->remote->mask_keydown & 0x10000) {
-                                               saa7134_input_irq(dev);
-                                       }
-                                       break;
-
-                               case SAA7134_REMOTE_I2C:
-                                       break;                  /* FIXME: invoke I2C get_key() */
-
-                               default:                        /* GPIO16 not used by IR remote */
-                                       break;
-                       }
-               }
-
-               if (report & SAA7134_IRQ_REPORT_GPIO18) {
-                       switch (dev->has_remote) {
-                               case SAA7134_REMOTE_GPIO:
-                                       if (!dev->remote)
-                                               break;
-                                       if ((dev->remote->mask_keydown & 0x40000) ||
-                                           (dev->remote->mask_keyup & 0x40000)) {
-                                               saa7134_input_irq(dev);
-                                       }
-                                       break;
-
-                               case SAA7134_REMOTE_I2C:
-                                       break;                  /* FIXME: invoke I2C get_key() */
-
-                               default:                        /* GPIO18 not used by IR remote */
-                                       break;
-                       }
-               }
-       }
-
-       if (10 == loop) {
-               print_irqstatus(dev,loop,report,status);
-               if (report & SAA7134_IRQ_REPORT_PE) {
-                       /* disable all parity error */
-                       printk(KERN_WARNING "%s/irq: looping -- "
-                              "clearing PE (parity error!) enable bit\n",dev->name);
-                       saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
-               } else if (report & SAA7134_IRQ_REPORT_GPIO16) {
-                       /* disable gpio16 IRQ */
-                       printk(KERN_WARNING "%s/irq: looping -- "
-                              "clearing GPIO16 enable bit\n",dev->name);
-                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_P);
-                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_N);
-               } else if (report & SAA7134_IRQ_REPORT_GPIO18) {
-                       /* disable gpio18 IRQs */
-                       printk(KERN_WARNING "%s/irq: looping -- "
-                              "clearing GPIO18 enable bit\n",dev->name);
-                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P);
-                       saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_N);
-               } else {
-                       /* disable all irqs */
-                       printk(KERN_WARNING "%s/irq: looping -- "
-                              "clearing all enable bits\n",dev->name);
-                       saa_writel(SAA7134_IRQ1,0);
-                       saa_writel(SAA7134_IRQ2,0);
-               }
-       }
-
- out:
-       return IRQ_RETVAL(handled);
-}
-
-/* ------------------------------------------------------------------ */
-
-/* early init (no i2c, no irq) */
-
-static int saa7134_hw_enable1(struct saa7134_dev *dev)
-{
-       /* RAM FIFO config */
-       saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
-       saa_writel(SAA7134_THRESHOULD, 0x02020202);
-
-       /* enable audio + video processing */
-       saa_writel(SAA7134_MAIN_CTRL,
-                       SAA7134_MAIN_CTRL_VPLLE |
-                       SAA7134_MAIN_CTRL_APLLE |
-                       SAA7134_MAIN_CTRL_EXOSC |
-                       SAA7134_MAIN_CTRL_EVFE1 |
-                       SAA7134_MAIN_CTRL_EVFE2 |
-                       SAA7134_MAIN_CTRL_ESFE  |
-                       SAA7134_MAIN_CTRL_EBDAC);
-
-       /*
-       * Initialize OSS _after_ enabling audio clock PLL and audio processing.
-       * OSS initialization writes to registers via the audio DSP; these
-       * writes will fail unless the audio clock has been started.  At worst,
-       * audio will not work.
-       */
-
-       /* enable peripheral devices */
-       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
-
-       /* set vertical line numbering start (vbi needs this) */
-       saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
-
-       return 0;
-}
-
-static int saa7134_hwinit1(struct saa7134_dev *dev)
-{
-       dprintk("hwinit1\n");
-
-       saa_writel(SAA7134_IRQ1, 0);
-       saa_writel(SAA7134_IRQ2, 0);
-
-       /* Clear any stale IRQ reports */
-       saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
-
-       mutex_init(&dev->lock);
-       spin_lock_init(&dev->slock);
-
-       saa7134_track_gpio(dev,"pre-init");
-       saa7134_video_init1(dev);
-       saa7134_vbi_init1(dev);
-       if (card_has_mpeg(dev))
-               saa7134_ts_init1(dev);
-       saa7134_input_init1(dev);
-
-       saa7134_hw_enable1(dev);
-
-       return 0;
-}
-
-/* late init (with i2c + irq) */
-static int saa7134_hw_enable2(struct saa7134_dev *dev)
-{
-
-       unsigned int irq2_mask;
-
-       /* enable IRQ's */
-       irq2_mask =
-               SAA7134_IRQ2_INTE_DEC3    |
-               SAA7134_IRQ2_INTE_DEC2    |
-               SAA7134_IRQ2_INTE_DEC1    |
-               SAA7134_IRQ2_INTE_DEC0    |
-               SAA7134_IRQ2_INTE_PE      |
-               SAA7134_IRQ2_INTE_AR;
-
-       if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) {
-               if (dev->remote->mask_keydown & 0x10000)
-                       irq2_mask |= SAA7134_IRQ2_INTE_GPIO16_N;
-               else {          /* Allow enabling both IRQ edge triggers */
-                       if (dev->remote->mask_keydown & 0x40000)
-                               irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_P;
-                       if (dev->remote->mask_keyup & 0x40000)
-                               irq2_mask |= SAA7134_IRQ2_INTE_GPIO18_N;
-               }
-       }
-
-       if (dev->has_remote == SAA7134_REMOTE_I2C) {
-               request_module("ir-kbd-i2c");
-       }
-
-       saa_writel(SAA7134_IRQ1, 0);
-       saa_writel(SAA7134_IRQ2, irq2_mask);
-
-       return 0;
-}
-
-static int saa7134_hwinit2(struct saa7134_dev *dev)
-{
-
-       dprintk("hwinit2\n");
-
-       saa7134_video_init2(dev);
-       saa7134_tvaudio_init2(dev);
-
-       saa7134_hw_enable2(dev);
-
-       return 0;
-}
-
-
-/* shutdown */
-static int saa7134_hwfini(struct saa7134_dev *dev)
-{
-       dprintk("hwfini\n");
-
-       if (card_has_mpeg(dev))
-               saa7134_ts_fini(dev);
-       saa7134_input_fini(dev);
-       saa7134_vbi_fini(dev);
-       saa7134_tvaudio_fini(dev);
-       return 0;
-}
-
-static void __devinit must_configure_manually(int has_eeprom)
-{
-       unsigned int i,p;
-
-       if (!has_eeprom)
-               printk(KERN_WARNING
-                      "saa7134: <rant>\n"
-                      "saa7134:  Congratulations!  Your TV card vendor saved a few\n"
-                      "saa7134:  cents for a eeprom, thus your pci board has no\n"
-                      "saa7134:  subsystem ID and I can't identify it automatically\n"
-                      "saa7134: </rant>\n"
-                      "saa7134: I feel better now.  Ok, here are the good news:\n"
-                      "saa7134: You can use the card=<nr> insmod option to specify\n"
-                      "saa7134: which board do you have.  The list:\n");
-       else
-               printk(KERN_WARNING
-                      "saa7134: Board is currently unknown. You might try to use the card=<nr>\n"
-                      "saa7134: insmod option to specify which board do you have, but this is\n"
-                      "saa7134: somewhat risky, as might damage your card. It is better to ask\n"
-                      "saa7134: for support at linux-media@vger.kernel.org.\n"
-                      "saa7134: The supported cards are:\n");
-
-       for (i = 0; i < saa7134_bcount; i++) {
-               printk(KERN_WARNING "saa7134:   card=%d -> %-40.40s",
-                      i,saa7134_boards[i].name);
-               for (p = 0; saa7134_pci_tbl[p].driver_data; p++) {
-                       if (saa7134_pci_tbl[p].driver_data != i)
-                               continue;
-                       printk(" %04x:%04x",
-                              saa7134_pci_tbl[p].subvendor,
-                              saa7134_pci_tbl[p].subdevice);
-               }
-               printk("\n");
-       }
-}
-
-static struct video_device *vdev_init(struct saa7134_dev *dev,
-                                     struct video_device *template,
-                                     char *type)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-       *vfd = *template;
-       vfd->v4l2_dev  = &dev->v4l2_dev;
-       vfd->release = video_device_release;
-       vfd->debug   = video_debug;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
-                dev->name, type, saa7134_boards[dev->board].name);
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-static void saa7134_unregister_video(struct saa7134_dev *dev)
-{
-       if (dev->video_dev) {
-               if (video_is_registered(dev->video_dev))
-                       video_unregister_device(dev->video_dev);
-               else
-                       video_device_release(dev->video_dev);
-               dev->video_dev = NULL;
-       }
-       if (dev->vbi_dev) {
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
-       }
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-}
-
-static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops,
-                           struct saa7134_dev *dev)
-{
-       int err;
-
-       if (NULL != dev->mops)
-               return;
-       if (saa7134_boards[dev->board].mpeg != ops->type)
-               return;
-       err = ops->init(dev);
-       if (0 != err)
-               return;
-       dev->mops = ops;
-}
-
-static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
-                           struct saa7134_dev *dev)
-{
-       if (NULL == dev->mops)
-               return;
-       if (dev->mops != ops)
-               return;
-       dev->mops->fini(dev);
-       dev->mops = NULL;
-}
-
-static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
-{
-       struct saa7134_dev *dev;
-       struct saa7134_mpeg_ops *mops;
-       int err;
-
-       if (saa7134_devcount == SAA7134_MAXBOARDS)
-               return -ENOMEM;
-
-       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-       if (NULL == dev)
-               return -ENOMEM;
-
-       err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
-       if (err)
-               goto fail0;
-
-       /* pci init */
-       dev->pci = pci_dev;
-       if (pci_enable_device(pci_dev)) {
-               err = -EIO;
-               goto fail1;
-       }
-
-       dev->nr = saa7134_devcount;
-       sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr);
-
-       /* pci quirks */
-       if (pci_pci_problems) {
-               if (pci_pci_problems & PCIPCI_TRITON)
-                       printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name);
-               if (pci_pci_problems & PCIPCI_NATOMA)
-                       printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name);
-               if (pci_pci_problems & PCIPCI_VIAETBF)
-                       printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name);
-               if (pci_pci_problems & PCIPCI_VSFX)
-                       printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);
-#ifdef PCIPCI_ALIMAGIK
-               if (pci_pci_problems & PCIPCI_ALIMAGIK) {
-                       printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
-                              dev->name);
-                       latency = 0x0A;
-               }
-#endif
-               if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
-                       printk(KERN_INFO "%s: quirk: this driver and your "
-                                       "chipset may not work together"
-                                       " in overlay mode.\n",dev->name);
-                       if (!saa7134_no_overlay) {
-                               printk(KERN_INFO "%s: quirk: overlay "
-                                               "mode will be disabled.\n",
-                                               dev->name);
-                               saa7134_no_overlay = 1;
-                       } else {
-                               printk(KERN_INFO "%s: quirk: overlay "
-                                               "mode will be forced. Use this"
-                                               " option at your own risk.\n",
-                                               dev->name);
-                       }
-               }
-       }
-       if (UNSET != latency) {
-               printk(KERN_INFO "%s: setting pci latency timer to %d\n",
-                      dev->name,latency);
-               pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
-       }
-
-       /* print pci info */
-       dev->pci_rev = pci_dev->revision;
-       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-       printk(KERN_INFO "%s: 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));
-       pci_set_master(pci_dev);
-       if (!pci_dma_supported(pci_dev, DMA_BIT_MASK(32))) {
-               printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
-               err = -EIO;
-               goto fail1;
-       }
-
-       /* board config */
-       dev->board = pci_id->driver_data;
-       if (card[dev->nr] >= 0 &&
-           card[dev->nr] < saa7134_bcount)
-               dev->board = card[dev->nr];
-       if (SAA7134_BOARD_UNKNOWN == dev->board)
-               must_configure_manually(0);
-       else if (SAA7134_BOARD_NOAUTO == dev->board) {
-               must_configure_manually(1);
-               dev->board = SAA7134_BOARD_UNKNOWN;
-       }
-       dev->autodetected = card[dev->nr] != dev->board;
-       dev->tuner_type = saa7134_boards[dev->board].tuner_type;
-       dev->tuner_addr = saa7134_boards[dev->board].tuner_addr;
-       dev->radio_type = saa7134_boards[dev->board].radio_type;
-       dev->radio_addr = saa7134_boards[dev->board].radio_addr;
-       dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
-       if (UNSET != tuner[dev->nr])
-               dev->tuner_type = tuner[dev->nr];
-       printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-               dev->name,pci_dev->subsystem_vendor,
-               pci_dev->subsystem_device,saa7134_boards[dev->board].name,
-               dev->board, dev->autodetected ?
-               "autodetected" : "insmod option");
-
-       /* get mmio */
-       if (!request_mem_region(pci_resource_start(pci_dev,0),
-                               pci_resource_len(pci_dev,0),
-                               dev->name)) {
-               err = -EBUSY;
-               printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
-                      dev->name,(unsigned long long)pci_resource_start(pci_dev,0));
-               goto fail1;
-       }
-       dev->lmmio = ioremap(pci_resource_start(pci_dev, 0),
-                            pci_resource_len(pci_dev, 0));
-       dev->bmmio = (__u8 __iomem *)dev->lmmio;
-       if (NULL == dev->lmmio) {
-               err = -EIO;
-               printk(KERN_ERR "%s: can't ioremap() MMIO memory\n",
-                      dev->name);
-               goto fail2;
-       }
-
-       /* initialize hardware #1 */
-       saa7134_board_init1(dev);
-       saa7134_hwinit1(dev);
-
-       /* get irq */
-       err = request_irq(pci_dev->irq, saa7134_irq,
-                         IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
-       if (err < 0) {
-               printk(KERN_ERR "%s: can't get IRQ %d\n",
-                      dev->name,pci_dev->irq);
-               goto fail3;
-       }
-
-       /* wait a bit, register i2c bus */
-       msleep(100);
-       saa7134_i2c_register(dev);
-       saa7134_board_init2(dev);
-
-       saa7134_hwinit2(dev);
-
-       /* load i2c helpers */
-       if (card_is_empress(dev)) {
-               struct v4l2_subdev *sd =
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               "saa6752hs",
-                               saa7134_boards[dev->board].empress_addr, NULL);
-
-               if (sd)
-                       sd->grp_id = GRP_EMPRESS;
-       }
-
-       if (saa7134_boards[dev->board].rds_addr) {
-               struct v4l2_subdev *sd;
-
-               sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "saa6588",
-                               0, I2C_ADDRS(saa7134_boards[dev->board].rds_addr));
-               if (sd) {
-                       printk(KERN_INFO "%s: found RDS decoder\n", dev->name);
-                       dev->has_rds = 1;
-               }
-       }
-
-       v4l2_prio_init(&dev->prio);
-
-       mutex_lock(&saa7134_devlist_lock);
-       list_for_each_entry(mops, &mops_list, next)
-               mpeg_ops_attach(mops, dev);
-       list_add_tail(&dev->devlist, &saa7134_devlist);
-       mutex_unlock(&saa7134_devlist_lock);
-
-       /* check for signal */
-       saa7134_irq_video_signalchange(dev);
-
-       if (TUNER_ABSENT != dev->tuner_type)
-               saa_call_all(dev, core, s_power, 0);
-
-       /* register v4l devices */
-       if (saa7134_no_overlay > 0)
-               printk(KERN_INFO "%s: Overlay support disabled.\n", dev->name);
-
-       dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
-       err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
-                                   video_nr[dev->nr]);
-       if (err < 0) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               goto fail4;
-       }
-       printk(KERN_INFO "%s: registered device %s [v4l2]\n",
-              dev->name, video_device_node_name(dev->video_dev));
-
-       dev->vbi_dev = vdev_init(dev, &saa7134_video_template, "vbi");
-
-       err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
-                                   vbi_nr[dev->nr]);
-       if (err < 0)
-               goto fail4;
-       printk(KERN_INFO "%s: registered device %s\n",
-              dev->name, video_device_node_name(dev->vbi_dev));
-
-       if (card_has_radio(dev)) {
-               dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
-               err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
-                                           radio_nr[dev->nr]);
-               if (err < 0)
-                       goto fail4;
-               printk(KERN_INFO "%s: registered device %s\n",
-                      dev->name, video_device_node_name(dev->radio_dev));
-       }
-
-       /* everything worked */
-       saa7134_devcount++;
-
-       if (saa7134_dmasound_init && !dev->dmasound.priv_data)
-               saa7134_dmasound_init(dev);
-
-       request_submodules(dev);
-       return 0;
-
- fail4:
-       saa7134_unregister_video(dev);
-       saa7134_i2c_unregister(dev);
-       free_irq(pci_dev->irq, dev);
- fail3:
-       saa7134_hwfini(dev);
-       iounmap(dev->lmmio);
- fail2:
-       release_mem_region(pci_resource_start(pci_dev,0),
-                          pci_resource_len(pci_dev,0));
- fail1:
-       v4l2_device_unregister(&dev->v4l2_dev);
- fail0:
-       kfree(dev);
-       return err;
-}
-
-static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
-       struct saa7134_mpeg_ops *mops;
-
-       flush_request_submodules(dev);
-
-       /* Release DMA sound modules if present */
-       if (saa7134_dmasound_exit && dev->dmasound.priv_data) {
-               saa7134_dmasound_exit(dev);
-       }
-
-       /* debugging ... */
-       if (irq_debug) {
-               u32 report = saa_readl(SAA7134_IRQ_REPORT);
-               u32 status = saa_readl(SAA7134_IRQ_STATUS);
-               print_irqstatus(dev,42,report,status);
-       }
-
-       /* disable peripheral devices */
-       saa_writeb(SAA7134_SPECIAL_MODE,0);
-
-       /* shutdown hardware */
-       saa_writel(SAA7134_IRQ1,0);
-       saa_writel(SAA7134_IRQ2,0);
-       saa_writel(SAA7134_MAIN_CTRL,0);
-
-       /* shutdown subsystems */
-       saa7134_hwfini(dev);
-
-       /* unregister */
-       mutex_lock(&saa7134_devlist_lock);
-       list_del(&dev->devlist);
-       list_for_each_entry(mops, &mops_list, next)
-               mpeg_ops_detach(mops, dev);
-       mutex_unlock(&saa7134_devlist_lock);
-       saa7134_devcount--;
-
-       saa7134_i2c_unregister(dev);
-       saa7134_unregister_video(dev);
-
-
-       /* the DMA sound modules should be unloaded before reaching
-          this, but just in case they are still present... */
-       if (dev->dmasound.priv_data != NULL) {
-               free_irq(pci_dev->irq, &dev->dmasound);
-               dev->dmasound.priv_data = NULL;
-       }
-
-
-       /* release resources */
-       free_irq(pci_dev->irq, dev);
-       iounmap(dev->lmmio);
-       release_mem_region(pci_resource_start(pci_dev,0),
-                          pci_resource_len(pci_dev,0));
-
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       /* free memory */
-       kfree(dev);
-}
-
-#ifdef CONFIG_PM
-
-/* resends a current buffer in queue after resume */
-static int saa7134_buffer_requeue(struct saa7134_dev *dev,
-                                 struct saa7134_dmaqueue *q)
-{
-       struct saa7134_buf *buf, *next;
-
-       assert_spin_locked(&dev->slock);
-
-       buf  = q->curr;
-       next = buf;
-       dprintk("buffer_requeue\n");
-
-       if (!buf)
-               return 0;
-
-       dprintk("buffer_requeue : resending active buffers \n");
-
-       if (!list_empty(&q->queue))
-               next = list_entry(q->queue.next, struct saa7134_buf,
-                                         vb.queue);
-       buf->activate(dev, buf, next);
-
-       return 0;
-}
-
-static int saa7134_suspend(struct pci_dev *pci_dev , pm_message_t state)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
-
-       /* disable overlay - apps should enable it explicitly on resume*/
-       dev->ovenable = 0;
-
-       /* Disable interrupts, DMA, and rest of the chip*/
-       saa_writel(SAA7134_IRQ1, 0);
-       saa_writel(SAA7134_IRQ2, 0);
-       saa_writel(SAA7134_MAIN_CTRL, 0);
-
-       dev->insuspend = 1;
-       synchronize_irq(pci_dev->irq);
-
-       /* ACK interrupts once more, just in case,
-               since the IRQ handler won't ack them anymore*/
-
-       saa_writel(SAA7134_IRQ_REPORT, saa_readl(SAA7134_IRQ_REPORT));
-
-       /* Disable timeout timers - if we have active buffers, we will
-          fill them on resume*/
-
-       del_timer(&dev->video_q.timeout);
-       del_timer(&dev->vbi_q.timeout);
-       del_timer(&dev->ts_q.timeout);
-
-       if (dev->remote)
-               saa7134_ir_stop(dev);
-
-       pci_save_state(pci_dev);
-       pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
-
-       return 0;
-}
-
-static int saa7134_resume(struct pci_dev *pci_dev)
-{
-       struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
-       struct saa7134_dev *dev = container_of(v4l2_dev, struct saa7134_dev, v4l2_dev);
-       unsigned long flags;
-
-       pci_set_power_state(pci_dev, PCI_D0);
-       pci_restore_state(pci_dev);
-
-       /* Do things that are done in saa7134_initdev ,
-               except of initializing memory structures.*/
-
-       saa7134_board_init1(dev);
-
-       /* saa7134_hwinit1 */
-       if (saa7134_boards[dev->board].video_out)
-               saa7134_videoport_init(dev);
-       if (card_has_mpeg(dev))
-               saa7134_ts_init_hw(dev);
-       if (dev->remote)
-               saa7134_ir_start(dev);
-       saa7134_hw_enable1(dev);
-
-       msleep(100);
-
-       saa7134_board_init2(dev);
-
-       /*saa7134_hwinit2*/
-       saa7134_set_tvnorm_hw(dev);
-       saa7134_tvaudio_setmute(dev);
-       saa7134_tvaudio_setvolume(dev, dev->ctl_volume);
-       saa7134_tvaudio_init(dev);
-       saa7134_enable_i2s(dev);
-       saa7134_hw_enable2(dev);
-
-       saa7134_irq_video_signalchange(dev);
-
-       /*resume unfinished buffer(s)*/
-       spin_lock_irqsave(&dev->slock, flags);
-       saa7134_buffer_requeue(dev, &dev->video_q);
-       saa7134_buffer_requeue(dev, &dev->vbi_q);
-       saa7134_buffer_requeue(dev, &dev->ts_q);
-
-       /* FIXME: Disable DMA audio sound - temporary till proper support
-                 is implemented*/
-
-       dev->dmasound.dma_running = 0;
-
-       /* start DMA now*/
-       dev->insuspend = 0;
-       smp_wmb();
-       saa7134_set_dmabits(dev);
-       spin_unlock_irqrestore(&dev->slock, flags);
-
-       return 0;
-}
-#endif
-
-/* ----------------------------------------------------------- */
-
-int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
-{
-       struct saa7134_dev *dev;
-
-       mutex_lock(&saa7134_devlist_lock);
-       list_for_each_entry(dev, &saa7134_devlist, devlist)
-               mpeg_ops_attach(ops, dev);
-       list_add_tail(&ops->next,&mops_list);
-       mutex_unlock(&saa7134_devlist_lock);
-       return 0;
-}
-
-void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
-{
-       struct saa7134_dev *dev;
-
-       mutex_lock(&saa7134_devlist_lock);
-       list_del(&ops->next);
-       list_for_each_entry(dev, &saa7134_devlist, devlist)
-               mpeg_ops_detach(ops, dev);
-       mutex_unlock(&saa7134_devlist_lock);
-}
-
-EXPORT_SYMBOL(saa7134_ts_register);
-EXPORT_SYMBOL(saa7134_ts_unregister);
-
-/* ----------------------------------------------------------- */
-
-static struct pci_driver saa7134_pci_driver = {
-       .name     = "saa7134",
-       .id_table = saa7134_pci_tbl,
-       .probe    = saa7134_initdev,
-       .remove   = __devexit_p(saa7134_finidev),
-#ifdef CONFIG_PM
-       .suspend  = saa7134_suspend,
-       .resume   = saa7134_resume
-#endif
-};
-
-static int __init saa7134_init(void)
-{
-       INIT_LIST_HEAD(&saa7134_devlist);
-       printk(KERN_INFO "saa7130/34: v4l2 driver version %s loaded\n",
-              SAA7134_VERSION);
-       return pci_register_driver(&saa7134_pci_driver);
-}
-
-static void __exit saa7134_fini(void)
-{
-       pci_unregister_driver(&saa7134_pci_driver);
-}
-
-module_init(saa7134_init);
-module_exit(saa7134_fini);
-
-/* ----------------------------------------------------------- */
-
-EXPORT_SYMBOL(saa7134_set_gpio);
-EXPORT_SYMBOL(saa7134_boards);
-
-/* ----------------- for the DMA sound modules --------------- */
-
-EXPORT_SYMBOL(saa7134_dmasound_init);
-EXPORT_SYMBOL(saa7134_dmasound_exit);
-EXPORT_SYMBOL(saa7134_pgtable_free);
-EXPORT_SYMBOL(saa7134_pgtable_build);
-EXPORT_SYMBOL(saa7134_pgtable_alloc);
-EXPORT_SYMBOL(saa7134_set_dmabits);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
deleted file mode 100644 (file)
index b209de4..0000000
+++ /dev/null
@@ -1,1936 +0,0 @@
-/*
- *
- * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
- *
- *  Extended 3 / 2005 by Hartmut Hackmann to support various
- *  cards with the tda10046 DVB-T channel decoder
- *
- *  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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/suspend.h>
-
-#include "saa7134-reg.h"
-#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 "xc5000.h"
-
-#include "tda10086.h"
-#include "tda826x.h"
-#include "tda827x.h"
-#include "isl6421.h"
-#include "isl6405.h"
-#include "lnbp21.h"
-#include "tuner-simple.h"
-#include "tda10048.h"
-#include "tda18271.h"
-#include "lgdt3305.h"
-#include "tda8290.h"
-#include "mb86a20s.h"
-#include "lgs8gxx.h"
-
-#include "zl10353.h"
-#include "qt1010.h"
-
-#include "zl10036.h"
-#include "zl10039.h"
-#include "mt312.h"
-#include "s5h1411.h"
-
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-
-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;
-module_param(use_frontend, int, 0644);
-MODULE_PARM_DESC(use_frontend,"for cards with multiple frontends (0: terrestrial, 1: satellite)");
-
-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)
-
-/* Print a warning */
-#define wprintk(fmt, arg...) \
-       printk(KERN_WARNING "%s/dvb: " fmt, dev->name, ## arg)
-
-/* ------------------------------------------------------------------
- * mt352 based DVB-T cards
- */
-
-static int pinnacle_antenna_pwr(struct saa7134_dev *dev, int on)
-{
-       u32 ok;
-
-       if (!on) {
-               saa_setl(SAA7134_GPIO_GPMODE0 >> 2,     (1 << 26));
-               saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 26));
-               return 0;
-       }
-
-       saa_setl(SAA7134_GPIO_GPMODE0 >> 2,     (1 << 26));
-       saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
-       udelay(10);
-
-       saa_setl(SAA7134_GPIO_GPMODE0 >> 2,     (1 << 28));
-       saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2, (1 << 28));
-       udelay(10);
-       saa_setl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 28));
-       udelay(10);
-       ok = saa_readl(SAA7134_GPIO_GPSTATUS0) & (1 << 27);
-       dprintk("%s %s\n", __func__, ok ? "on" : "off");
-
-       if (!ok)
-               saa_clearl(SAA7134_GPIO_GPSTATUS0 >> 2,   (1 << 26));
-       return ok;
-}
-
-static int mt352_pinnacle_init(struct dvb_frontend* fe)
-{
-       static u8 clock_config []  = { CLOCK_CTL,  0x3d, 0x28 };
-       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, 0x31 };
-       static u8 fsm_ctl_cfg[]    = { 0x7b,       0x04 };
-       static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x0f };
-       static u8 scan_ctl_cfg []  = { SCAN_CTL,   0x0d };
-       static u8 irq_cfg []       = { INTERRUPT_EN_0, 0x00, 0x00, 0x00, 0x00 };
-       struct saa7134_dev *dev= fe->dvb->priv;
-
-       dprintk("%s called\n", __func__);
-
-       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));
-       mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
-
-       mt352_write(fe, fsm_ctl_cfg,    sizeof(fsm_ctl_cfg));
-       mt352_write(fe, scan_ctl_cfg,   sizeof(scan_ctl_cfg));
-       mt352_write(fe, irq_cfg,        sizeof(irq_cfg));
-
-       return 0;
-}
-
-static int mt352_aver777_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_avermedia_xc3028_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, 0xe };
-       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 dtv_frontend_properties *c = &fe->dtv_property_cache;
-       u8 off[] = { 0x00, 0xf1};
-       u8 on[]  = { 0x00, 0x71};
-       struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)};
-
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct v4l2_frequency f;
-
-       /* set frequency (mt2050) */
-       f.tuner     = 0;
-       f.type      = V4L2_TUNER_DIGITAL_TV;
-       f.frequency = c->frequency / 1000 * 16 / 1000;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-       saa_call_all(dev, tuner, s_frequency, &f);
-       msg.buf = on;
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &msg, 1);
-
-       pinnacle_antenna_pwr(dev, antenna_pwr);
-
-       /* mt352 setup */
-       return mt352_pinnacle_init(fe);
-}
-
-static struct mt352_config pinnacle_300i = {
-       .demod_address = 0x3c >> 1,
-       .adc_clock     = 20333,
-       .if2           = 36150,
-       .no_tuner      = 1,
-       .demod_init    = mt352_pinnacle_init,
-};
-
-static struct mt352_config avermedia_777 = {
-       .demod_address = 0xf,
-       .demod_init    = mt352_aver777_init,
-};
-
-static struct mt352_config avermedia_xc3028_mt352_dev = {
-       .demod_address   = (0x1e >> 1),
-       .no_tuner        = 1,
-       .demod_init      = mt352_avermedia_xc3028_init,
-};
-
-static struct tda18271_std_map mb86a20s_tda18271_std_map = {
-       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
-                     .if_lvl = 7, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config kworld_tda18271_config = {
-       .std_map = &mb86a20s_tda18271_std_map,
-       .gate    = TDA18271_GATE_DIGITAL,
-       .config  = 3,   /* Use tuner callback for AGC */
-
-};
-
-static const struct mb86a20s_config kworld_mb86a20s_config = {
-       .demod_address = 0x10,
-};
-
-static int kworld_sbtvd_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-
-       unsigned char initmsg[] = {0x45, 0x97};
-       unsigned char msg_enable[] = {0x45, 0xc1};
-       unsigned char msg_disable[] = {0x45, 0x81};
-       struct i2c_msg msg = {.addr = 0x4b, .flags = 0, .buf = initmsg, .len = 2};
-
-       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
-               wprintk("could not access the I2C gate\n");
-               return -EIO;
-       }
-       if (enable)
-               msg.buf = msg_enable;
-       else
-               msg.buf = msg_disable;
-       if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1) {
-               wprintk("could not access the I2C gate\n");
-               return -EIO;
-       }
-       msleep(20);
-       return 0;
-}
-
-/* ==================================================================
- * tda1004x based DVB-T cards, helper functions
- */
-
-static int philips_tda1004x_request_firmware(struct dvb_frontend *fe,
-                                          const struct firmware **fw, char *name)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       return request_firmware(fw, name, &dev->pci->dev);
-}
-
-/* ------------------------------------------------------------------
- * these tuners are tu1216, td1316(a)
- */
-
-static int philips_tda6651_pll_set(struct dvb_frontend *fe)
-{
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-       u8 addr = state->config->tuner_address;
-       u8 tuner_buf[4];
-       struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tuner_buf,.len =
-                       sizeof(tuner_buf) };
-       int tuner_frequency = 0;
-       u8 band, cp, filter;
-
-       /* determine charge pump */
-       tuner_frequency = c->frequency + 36166000;
-       if (tuner_frequency < 87000000)
-               return -EINVAL;
-       else if (tuner_frequency < 130000000)
-               cp = 3;
-       else if (tuner_frequency < 160000000)
-               cp = 5;
-       else if (tuner_frequency < 200000000)
-               cp = 6;
-       else if (tuner_frequency < 290000000)
-               cp = 3;
-       else if (tuner_frequency < 420000000)
-               cp = 5;
-       else if (tuner_frequency < 480000000)
-               cp = 6;
-       else if (tuner_frequency < 620000000)
-               cp = 3;
-       else if (tuner_frequency < 830000000)
-               cp = 5;
-       else if (tuner_frequency < 895000000)
-               cp = 7;
-       else
-               return -EINVAL;
-
-       /* determine band */
-       if (c->frequency < 49000000)
-               return -EINVAL;
-       else if (c->frequency < 161000000)
-               band = 1;
-       else if (c->frequency < 444000000)
-               band = 2;
-       else if (c->frequency < 861000000)
-               band = 4;
-       else
-               return -EINVAL;
-
-       /* setup PLL filter */
-       switch (c->bandwidth_hz) {
-       case 6000000:
-               filter = 0;
-               break;
-
-       case 7000000:
-               filter = 0;
-               break;
-
-       case 8000000:
-               filter = 1;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* calculate divisor
-        * ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
-        */
-       tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
-
-       /* setup tuner buffer */
-       tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
-       tuner_buf[1] = tuner_frequency & 0xff;
-       tuner_buf[2] = 0xca;
-       tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1) {
-               wprintk("could not write to tuner at addr: 0x%02x\n",
-                       addr << 1);
-               return -EIO;
-       }
-       msleep(1);
-       return 0;
-}
-
-static int philips_tu1216_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-       u8 addr = state->config->tuner_address;
-       static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
-       struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
-
-       /* setup PLL configuration */
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
-               return -EIO;
-       msleep(1);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static struct tda1004x_config philips_tu1216_60_config = {
-       .demod_address = 0x8,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_4M,
-       .agc_config    = TDA10046_AGC_DEFAULT,
-       .if_freq       = TDA10046_FREQ_3617,
-       .tuner_address = 0x60,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config philips_tu1216_61_config = {
-
-       .demod_address = 0x8,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_4M,
-       .agc_config    = TDA10046_AGC_DEFAULT,
-       .if_freq       = TDA10046_FREQ_3617,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-/* ------------------------------------------------------------------ */
-
-static int philips_td1316_tuner_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-       u8 addr = state->config->tuner_address;
-       static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
-       struct i2c_msg init_msg = {.addr = addr,.flags = 0,.buf = msg,.len = sizeof(msg) };
-
-       /* setup PLL configuration */
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
-               return -EIO;
-       return 0;
-}
-
-static int philips_td1316_tuner_set_params(struct dvb_frontend *fe)
-{
-       return philips_tda6651_pll_set(fe);
-}
-
-static int philips_td1316_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-       u8 addr = state->config->tuner_address;
-       static u8 msg[] = { 0x0b, 0xdc, 0x86, 0xa4 };
-       struct i2c_msg analog_msg = {.addr = addr,.flags = 0,.buf = msg,.len = sizeof(msg) };
-
-       /* switch the tuner to analog mode */
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1)
-               return -EIO;
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int philips_europa_tuner_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       static u8 msg[] = { 0x00, 0x40};
-       struct i2c_msg init_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
-
-
-       if (philips_td1316_tuner_init(fe))
-               return -EIO;
-       msleep(1);
-       if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
-               return -EIO;
-
-       return 0;
-}
-
-static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-
-       static u8 msg[] = { 0x00, 0x14 };
-       struct i2c_msg analog_msg = {.addr = 0x43,.flags = 0,.buf = msg,.len = sizeof(msg) };
-
-       if (philips_td1316_tuner_sleep(fe))
-               return -EIO;
-
-       /* switch the board to analog mode */
-       if (fe->ops.i2c_gate_ctrl)
-               fe->ops.i2c_gate_ctrl(fe, 1);
-       i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
-       return 0;
-}
-
-static int philips_europa_demod_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-
-       if (dev->original_demod_sleep)
-               dev->original_demod_sleep(fe);
-       fe->ops.i2c_gate_ctrl(fe, 1);
-       return 0;
-}
-
-static struct tda1004x_config philips_europa_config = {
-
-       .demod_address = 0x8,
-       .invert        = 0,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_4M,
-       .agc_config    = TDA10046_AGC_IFO_AUTO_POS,
-       .if_freq       = TDA10046_FREQ_052,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config medion_cardbus = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_IFO_AUTO_NEG,
-       .if_freq       = TDA10046_FREQ_3613,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config technotrend_budget_t3000_config = {
-       .demod_address = 0x8,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_4M,
-       .agc_config    = TDA10046_AGC_DEFAULT,
-       .if_freq       = TDA10046_FREQ_3617,
-       .tuner_address = 0x63,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-/* ------------------------------------------------------------------
- * tda 1004x based cards with philips silicon tuner
- */
-
-static int tda8290_i2c_gate_ctrl( struct dvb_frontend* fe, int enable)
-{
-       struct tda1004x_state *state = fe->demodulator_priv;
-
-       u8 addr = state->config->i2c_gate;
-       static u8 tda8290_close[] = { 0x21, 0xc0};
-       static u8 tda8290_open[]  = { 0x21, 0x80};
-       struct i2c_msg tda8290_msg = {.addr = addr,.flags = 0, .len = 2};
-       if (enable) {
-               tda8290_msg.buf = tda8290_close;
-       } else {
-               tda8290_msg.buf = tda8290_open;
-       }
-       if (i2c_transfer(state->i2c, &tda8290_msg, 1) != 1) {
-               struct saa7134_dev *dev = fe->dvb->priv;
-               wprintk("could not access tda8290 I2C gate\n");
-               return -EIO;
-       }
-       msleep(20);
-       return 0;
-}
-
-static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-
-       switch (state->config->antenna_switch) {
-       case 0: break;
-       case 1: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
-               saa7134_set_gpio(dev, 21, 0);
-               break;
-       case 2: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
-               saa7134_set_gpio(dev, 21, 1);
-               break;
-       }
-       return 0;
-}
-
-static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       struct tda1004x_state *state = fe->demodulator_priv;
-
-       switch (state->config->antenna_switch) {
-       case 0: break;
-       case 1: dprintk("setting GPIO21 to 1 (Radio antenna?)\n");
-               saa7134_set_gpio(dev, 21, 1);
-               break;
-       case 2: dprintk("setting GPIO21 to 0 (TV antenna?)\n");
-               saa7134_set_gpio(dev, 21, 0);
-               break;
-       }
-       return 0;
-}
-
-static int configure_tda827x_fe(struct saa7134_dev *dev,
-                               struct tda1004x_config *cdec_conf,
-                               struct tda827x_config *tuner_conf)
-{
-       struct videobuf_dvb_frontend *fe0;
-
-       /* Get the first frontend */
-       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
-
-       fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap);
-       if (fe0->dvb.frontend) {
-               if (cdec_conf->i2c_gate)
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl;
-               if (dvb_attach(tda827x_attach, fe0->dvb.frontend,
-                              cdec_conf->tuner_address,
-                              &dev->i2c_adap, tuner_conf))
-                       return 0;
-
-               wprintk("no tda827x tuner found at addr: %02x\n",
-                               cdec_conf->tuner_address);
-       }
-       return -EINVAL;
-}
-
-/* ------------------------------------------------------------------ */
-
-static struct tda827x_config tda827x_cfg_0 = {
-       .init = philips_tda827x_tuner_init,
-       .sleep = philips_tda827x_tuner_sleep,
-       .config = 0,
-       .switch_addr = 0
-};
-
-static struct tda827x_config tda827x_cfg_1 = {
-       .init = philips_tda827x_tuner_init,
-       .sleep = philips_tda827x_tuner_sleep,
-       .config = 1,
-       .switch_addr = 0x4b
-};
-
-static struct tda827x_config tda827x_cfg_2 = {
-       .init = philips_tda827x_tuner_init,
-       .sleep = philips_tda827x_tuner_sleep,
-       .config = 2,
-       .switch_addr = 0x4b
-};
-
-static struct tda827x_config tda827x_cfg_2_sw42 = {
-       .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,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .tuner_address = 0x60,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config philips_tiger_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch= 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config cinergy_ht_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config cinergy_ht_pci_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x60,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config philips_tiger_s_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch= 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config pinnacle_pctv_310i_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config hauppauge_hvr_1110_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config asus_p7131_dual_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch= 2,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config lifeview_trio_config = {
-       .demod_address = 0x09,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP00_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .tuner_address = 0x60,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config tevion_dvbt220rf_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .tuner_address = 0x60,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config md8800_dvbt_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x60,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config asus_p7131_4871_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch= 2,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config asus_p7131_hybrid_lna_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch= 2,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config kworld_dvb_t_210_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch= 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config avermedia_super_007_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x60,
-       .antenna_switch= 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config twinhan_dtv_dvb_3056_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP01_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x42,
-       .tuner_address = 0x61,
-       .antenna_switch = 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config asus_tiger_3in1_config = {
-       .demod_address = 0x0b,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch = 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct tda1004x_config asus_ps3_100_config = {
-       .demod_address = 0x0b,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP11_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .i2c_gate      = 0x4b,
-       .tuner_address = 0x61,
-       .antenna_switch = 1,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-/* ------------------------------------------------------------------
- * special case: this card uses saa713x GPIO22 for the mode switch
- */
-
-static int ads_duo_tuner_init(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       philips_tda827x_tuner_init(fe);
-       /* route TDA8275a AGC input to the channel decoder */
-       saa7134_set_gpio(dev, 22, 1);
-       return 0;
-}
-
-static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
-{
-       struct saa7134_dev *dev = fe->dvb->priv;
-       /* route TDA8275a AGC input to the analog IF chip*/
-       saa7134_set_gpio(dev, 22, 0);
-       philips_tda827x_tuner_sleep(fe);
-       return 0;
-}
-
-static struct tda827x_config ads_duo_cfg = {
-       .init = ads_duo_tuner_init,
-       .sleep = ads_duo_tuner_sleep,
-       .config = 0
-};
-
-static struct tda1004x_config ads_tech_duo_config = {
-       .demod_address = 0x08,
-       .invert        = 1,
-       .invert_oclk   = 0,
-       .xtal_freq     = TDA10046_XTAL_16M,
-       .agc_config    = TDA10046_AGC_TDA827X,
-       .gpio_config   = TDA10046_GP00_I,
-       .if_freq       = TDA10046_FREQ_045,
-       .tuner_address = 0x61,
-       .request_firmware = philips_tda1004x_request_firmware
-};
-
-static struct zl10353_config behold_h6_config = {
-       .demod_address = 0x1e>>1,
-       .no_tuner      = 1,
-       .parallel_ts   = 1,
-       .disable_i2c_gate_ctrl = 1,
-};
-
-static struct xc5000_config behold_x7_tunerconfig = {
-       .i2c_address      = 0xc2>>1,
-       .if_khz           = 4560,
-       .radio_input      = XC5000_RADIO_FM1,
-};
-
-static struct zl10353_config behold_x7_config = {
-       .demod_address = 0x1e>>1,
-       .if2           = 45600,
-       .no_tuner      = 1,
-       .parallel_ts   = 1,
-       .disable_i2c_gate_ctrl = 1,
-};
-
-static struct zl10353_config videomate_t750_zl10353_config = {
-       .demod_address         = 0x0f,
-       .no_tuner              = 1,
-       .parallel_ts           = 1,
-       .disable_i2c_gate_ctrl = 1,
-};
-
-static struct qt1010_config videomate_t750_qt1010_config = {
-       .i2c_address = 0x62
-};
-
-
-/* ==================================================================
- * tda10086 based DVB-S cards, helper functions
- */
-
-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
- */
-
-static struct nxt200x_config avertvhda180 = {
-       .demod_address    = 0x0a,
-};
-
-static struct nxt200x_config kworldatsc110 = {
-       .demod_address    = 0x0a,
-};
-
-/* ------------------------------------------------------------------ */
-
-static struct mt312_config avertv_a700_mt312 = {
-       .demod_address = 0x0e,
-       .voltage_inverted = 1,
-};
-
-static struct zl10036_config avertv_a700_tuner = {
-       .tuner_address = 0x60,
-};
-
-static struct mt312_config zl10313_compro_s350_config = {
-       .demod_address = 0x0e,
-};
-
-static struct lgdt3305_config hcw_lgdt3305_config = {
-       .i2c_addr           = 0x0e,
-       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
-       .tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
-       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 1,
-       .qam_if_khz         = 4000,
-       .vsb_if_khz         = 3250,
-};
-
-static struct tda10048_config hcw_tda10048_config = {
-       .demod_address    = 0x10 >> 1,
-       .output_mode      = TDA10048_SERIAL_OUTPUT,
-       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
-       .inversion        = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3500,
-       .dtv8_if_freq_khz = TDA10048_IF_4000,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-       .disable_gate_access = 1,
-};
-
-static struct tda18271_std_map hauppauge_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
-                     .if_lvl = 1, .rfagc_top = 0x58, },
-       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
-                     .if_lvl = 1, .rfagc_top = 0x58, },
-};
-
-static struct tda18271_config hcw_tda18271_config = {
-       .std_map = &hauppauge_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-       .config  = 3,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static struct tda829x_config tda829x_no_probe = {
-       .probe_tuner = TDA829X_DONT_PROBE,
-};
-
-static struct tda10048_config zolid_tda10048_config = {
-       .demod_address    = 0x10 >> 1,
-       .output_mode      = TDA10048_PARALLEL_OUTPUT,
-       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
-       .inversion        = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3500,
-       .dtv8_if_freq_khz = TDA10048_IF_4000,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-       .disable_gate_access = 1,
-};
-
-static struct tda18271_config zolid_tda18271_config = {
-       .gate    = TDA18271_GATE_ANALOG,
-};
-
-static struct tda10048_config dtv1000s_tda10048_config = {
-       .demod_address    = 0x10 >> 1,
-       .output_mode      = TDA10048_PARALLEL_OUTPUT,
-       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
-       .inversion        = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3800,
-       .dtv8_if_freq_khz = TDA10048_IF_4300,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-       .disable_gate_access = 1,
-};
-
-static struct tda18271_std_map dtv1000s_tda18271_std_map = {
-       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config dtv1000s_tda18271_config = {
-       .std_map = &dtv1000s_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-};
-
-static struct lgs8gxx_config prohdtv_pro2_lgs8g75_config = {
-       .prod = LGS8GXX_PROD_LGS8G75,
-       .demod_address = 0x1d,
-       .serial_ts = 0,
-       .ts_clk_pol = 1,
-       .ts_clk_gated = 0,
-       .if_clk_freq = 30400, /* 30.4 MHz */
-       .if_freq = 4000, /* 4.00 MHz */
-       .if_neg_center = 0,
-       .ext_adc = 0,
-       .adc_signed = 1,
-       .adc_vpp = 3, /* 2.0 Vpp */
-       .if_neg_edge = 1,
-};
-
-static struct tda18271_config prohdtv_pro2_tda18271_config = {
-       .gate = TDA18271_GATE_ANALOG,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static struct tda18271_std_map kworld_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 3250, .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 kworld_pc150u_tda18271_config = {
-       .std_map = &kworld_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-       .config  = 3,   /* Use tuner callback for AGC */
-       .rf_cal_on_startup = 1
-};
-
-static struct s5h1411_config kworld_s5h1411_config = {
-       .output_mode   = S5H1411_PARALLEL_OUTPUT,
-       .gpio          = S5H1411_GPIO_OFF,
-       .qam_if        = S5H1411_IF_4000,
-       .vsb_if        = S5H1411_IF_3250,
-       .inversion     = S5H1411_INVERSION_ON,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   =
-               S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-
-/* ==================================================================
- * Core code
- */
-
-static int dvb_init(struct saa7134_dev *dev)
-{
-       int ret;
-       int attach_xc3028 = 0;
-       struct videobuf_dvb_frontend *fe0;
-
-       /* FIXME: add support for multi-frontend */
-       mutex_init(&dev->frontends.lock);
-       INIT_LIST_HEAD(&dev->frontends.felist);
-
-       printk(KERN_INFO "%s() allocating 1 frontend\n", __func__);
-       fe0 = videobuf_dvb_alloc_frontend(&dev->frontends, 1);
-       if (!fe0) {
-               printk(KERN_ERR "%s() failed to alloc\n", __func__);
-               return -ENOMEM;
-       }
-
-       /* init struct videobuf_dvb */
-       dev->ts.nr_bufs    = 32;
-       dev->ts.nr_packets = 32*4;
-       fe0->dvb.name = dev->name;
-       videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops,
-                           &dev->pci->dev, &dev->slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                           V4L2_FIELD_ALTERNATE,
-                           sizeof(struct saa7134_buf),
-                           dev, NULL);
-
-       switch (dev->board) {
-       case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
-               dprintk("pinnacle 300i dvb setup\n");
-               fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
-               }
-               break;
-       case SAA7134_BOARD_AVERMEDIA_777:
-       case SAA7134_BOARD_AVERMEDIA_A16AR:
-               dprintk("avertv 777 dvb setup\n");
-               fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x61,
-                                  TUNER_PHILIPS_TD1316);
-               }
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A16D:
-               dprintk("AverMedia A16D dvb setup\n");
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                               &avermedia_xc3028_mt352_dev,
-                                               &dev->i2c_adap);
-               attach_xc3028 = 1;
-               break;
-       case SAA7134_BOARD_MD7134:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &medion_cardbus,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, medion_cardbus.tuner_address,
-                                  TUNER_PHILIPS_FMD1216ME_MK3);
-               }
-               break;
-       case SAA7134_BOARD_PHILIPS_TOUGH:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &philips_tu1216_60_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
-                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
-               }
-               break;
-       case SAA7134_BOARD_FLYDVBTDUO:
-       case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_PHILIPS_EUROPA:
-       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-       case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &philips_europa_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
-                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-                       fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
-                       fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
-                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
-               }
-               break;
-       case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &technotrend_budget_t3000_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
-                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-                       fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
-                       fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
-                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
-               }
-               break;
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &philips_tu1216_61_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init;
-                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set;
-               }
-               break;
-       case SAA7134_BOARD_KWORLD_DVBT_210:
-               if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config,
-                                        &tda827x_cfg_2) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-               fe0->dvb.frontend = dvb_attach(tda10048_attach,
-                                              &hcw_tda10048_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &hcw_tda18271_config);
-               }
-               break;
-       case SAA7134_BOARD_PHILIPS_TIGER:
-               if (configure_tda827x_fe(dev, &philips_tiger_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_PINNACLE_PCTV_310i:
-               if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config,
-                                        &tda827x_cfg_1) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-               if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config,
-                                        &tda827x_cfg_1) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
-               fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
-                                              &hcw_lgdt3305_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &hcw_tda18271_config);
-               }
-               break;
-       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-               if (configure_tda827x_fe(dev, &asus_p7131_dual_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_FLYDVBT_LR301:
-               if (configure_tda827x_fe(dev, &tda827x_lifeview_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_FLYDVB_TRIO:
-               if (!use_frontend) {    /* terrestrial */
-                       if (configure_tda827x_fe(dev, &lifeview_trio_config,
-                                                &tda827x_cfg_0) < 0)
-                               goto detach_frontend;
-               } else {                /* satellite */
-                       fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap);
-                       if (fe0->dvb.frontend) {
-                               if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63,
-                                                                       &dev->i2c_adap, 0) == NULL) {
-                                       wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__);
-                                       goto detach_frontend;
-                               }
-                               if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap,
-                                                                               0x08, 0, 0) == NULL) {
-                                       wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__);
-                                       goto detach_frontend;
-                               }
-                       }
-               }
-               break;
-       case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
-       case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &ads_tech_duo_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (dvb_attach(tda827x_attach,fe0->dvb.frontend,
-                                  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);
-                               goto detach_frontend;
-                       }
-               } else
-                       wprintk("failed to attach tda10046\n");
-               break;
-       case SAA7134_BOARD_TEVION_DVBT_220RF:
-               if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_MEDION_MD8800_QUADRO:
-               if (!use_frontend) {     /* terrestrial */
-                       if (configure_tda827x_fe(dev, &md8800_dvbt_config,
-                                                &tda827x_cfg_0) < 0)
-                               goto detach_frontend;
-               } else {        /* satellite */
-                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
-                                                       &flydvbs, &dev->i2c_adap);
-                       if (fe0->dvb.frontend) {
-                               struct dvb_frontend *fe = fe0->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, fe0->dvb.frontend,
-                                               0x60, &dev->i2c_adap, 0) == NULL) {
-                                       wprintk("%s: Medion Quadro, no tda826x "
-                                               "found !\n", __func__);
-                                       goto detach_frontend;
-                               }
-                               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__);
-                                               goto detach_frontend;
-                                       }
-                                       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:
-               fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend)
-                       dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61,
-                                  NULL, DVB_PLL_TDHU2);
-               break;
-       case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI:
-       case SAA7134_BOARD_KWORLD_ATSC110:
-               fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend)
-                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x61,
-                                  TUNER_PHILIPS_TUV1236D);
-               break;
-       case SAA7134_BOARD_KWORLD_PC150U:
-               saa7134_set_gpio(dev, 18, 1); /* Switch to digital mode */
-               saa7134_tuner_callback(dev, 0,
-                                      TDA18271_CALLBACK_CMD_AGC_ENABLE, 1);
-               fe0->dvb.frontend = dvb_attach(s5h1411_attach,
-                                              &kworld_s5h1411_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &kworld_pc150u_tda18271_config);
-               }
-               break;
-       case SAA7134_BOARD_FLYDVBS_LR300:
-               fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
-                                      &dev->i2c_adap, 0) == NULL) {
-                               wprintk("%s: No tda826x found!\n", __func__);
-                               goto detach_frontend;
-                       }
-                       if (dvb_attach(isl6421_attach, fe0->dvb.frontend,
-                                      &dev->i2c_adap, 0x08, 0, 0) == NULL) {
-                               wprintk("%s: No ISL6421 found!\n", __func__);
-                               goto detach_frontend;
-                       }
-               }
-               break;
-       case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                                              &medion_cardbus,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep;
-                       fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
-
-                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, medion_cardbus.tuner_address,
-                                  TUNER_PHILIPS_FMD1216ME_MK3);
-               }
-               break;
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
-               fe0->dvb.frontend = dvb_attach(tda10046_attach,
-                               &philips_europa_config,
-                               &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init;
-                       fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
-               }
-               break;
-       case SAA7134_BOARD_CINERGY_HT_PCMCIA:
-               if (configure_tda827x_fe(dev, &cinergy_ht_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_CINERGY_HT_PCI:
-               if (configure_tda827x_fe(dev, &cinergy_ht_pci_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_PHILIPS_TIGER_S:
-               if (configure_tda827x_fe(dev, &philips_tiger_s_config,
-                                        &tda827x_cfg_2) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_ASUS_P7131_4871:
-               if (configure_tda827x_fe(dev, &asus_p7131_4871_config,
-                                        &tda827x_cfg_2) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
-               if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config,
-                                        &tda827x_cfg_2) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_SUPER_007:
-               if (configure_tda827x_fe(dev, &avermedia_super_007_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
-               if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config,
-                                        &tda827x_cfg_2_sw42) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_PHILIPS_SNAKE:
-               fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs,
-                                               &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60,
-                                       &dev->i2c_adap, 0) == NULL) {
-                               wprintk("%s: No tda826x found!\n", __func__);
-                               goto detach_frontend;
-                       }
-                       if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
-                                       &dev->i2c_adap, 0, 0) == NULL) {
-                               wprintk("%s: No lnbp21 found!\n", __func__);
-                               goto detach_frontend;
-                       }
-               }
-               break;
-       case SAA7134_BOARD_CREATIX_CTX953:
-               if (configure_tda827x_fe(dev, &md8800_dvbt_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_MSI_TVANYWHERE_AD11:
-               if (configure_tda827x_fe(dev, &philips_tiger_s_config,
-                                        &tda827x_cfg_2) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
-               dprintk("AverMedia E506R dvb setup\n");
-               saa7134_set_gpio(dev, 25, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 25, 1);
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                               &avermedia_xc3028_mt352_dev,
-                                               &dev->i2c_adap);
-               attach_xc3028 = 1;
-               break;
-       case SAA7134_BOARD_MD7134_BRIDGE_2:
-               fe0->dvb.frontend = dvb_attach(tda10086_attach,
-                                               &sd1878_4m, &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       struct dvb_frontend *fe;
-                       if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
-                                 &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
-                               wprintk("%s: MD7134 DVB-S, no SD1878 "
-                                       "found !\n", __func__);
-                               goto detach_frontend;
-                       }
-                       /* we need to open the i2c gate (we know it exists) */
-                       fe = fe0->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__);
-                               goto detach_frontend;
-                       }
-                       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;
-       case SAA7134_BOARD_AVERMEDIA_M103:
-               saa7134_set_gpio(dev, 25, 0);
-               msleep(10);
-               saa7134_set_gpio(dev, 25, 1);
-               fe0->dvb.frontend = dvb_attach(mt352_attach,
-                                               &avermedia_xc3028_mt352_dev,
-                                               &dev->i2c_adap);
-               attach_xc3028 = 1;
-               break;
-       case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
-               if (!use_frontend) {     /* terrestrial */
-                       if (configure_tda827x_fe(dev, &asus_tiger_3in1_config,
-                                                       &tda827x_cfg_2) < 0)
-                               goto detach_frontend;
-               } else {                /* satellite */
-                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
-                                               &flydvbs, &dev->i2c_adap);
-                       if (fe0->dvb.frontend) {
-                               if (dvb_attach(tda826x_attach,
-                                               fe0->dvb.frontend, 0x60,
-                                               &dev->i2c_adap, 0) == NULL) {
-                                       wprintk("%s: Asus Tiger 3in1, no "
-                                               "tda826x found!\n", __func__);
-                                       goto detach_frontend;
-                               }
-                               if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
-                                               &dev->i2c_adap, 0, 0) == NULL) {
-                                       wprintk("%s: Asus Tiger 3in1, no lnbp21"
-                                               " found!\n", __func__);
-                                      goto detach_frontend;
-                              }
-                      }
-              }
-              break;
-       case SAA7134_BOARD_ASUSTeK_PS3_100:
-               if (!use_frontend) {     /* terrestrial */
-                       if (configure_tda827x_fe(dev, &asus_ps3_100_config,
-                                                &tda827x_cfg_2) < 0)
-                               goto detach_frontend;
-              } else {                /* satellite */
-                       fe0->dvb.frontend = dvb_attach(tda10086_attach,
-                                                      &flydvbs, &dev->i2c_adap);
-                       if (fe0->dvb.frontend) {
-                               if (dvb_attach(tda826x_attach,
-                                              fe0->dvb.frontend, 0x60,
-                                              &dev->i2c_adap, 0) == NULL) {
-                                       wprintk("%s: Asus My Cinema PS3-100, no "
-                                               "tda826x found!\n", __func__);
-                                       goto detach_frontend;
-                               }
-                               if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
-                                              &dev->i2c_adap, 0, 0) == NULL) {
-                                       wprintk("%s: Asus My Cinema PS3-100, no lnbp21"
-                                               " found!\n", __func__);
-                                       goto detach_frontend;
-                               }
-                       }
-               }
-               break;
-       case SAA7134_BOARD_ASUSTeK_TIGER:
-               if (configure_tda827x_fe(dev, &philips_tiger_config,
-                                        &tda827x_cfg_0) < 0)
-                       goto detach_frontend;
-               break;
-       case SAA7134_BOARD_BEHOLD_H6:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                               &behold_h6_config,
-                                               &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x61,
-                                  TUNER_PHILIPS_FMD1216MEX_MK3);
-               }
-               break;
-       case SAA7134_BOARD_BEHOLD_X7:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                               &behold_x7_config,
-                                               &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, &behold_x7_tunerconfig);
-               }
-               break;
-       case SAA7134_BOARD_BEHOLD_H7:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                               &behold_x7_config,
-                                               &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       dvb_attach(xc5000_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, &behold_x7_tunerconfig);
-               }
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A700_PRO:
-       case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
-               /* Zarlink ZL10313 */
-               fe0->dvb.frontend = dvb_attach(mt312_attach,
-                       &avertv_a700_mt312, &dev->i2c_adap);
-               if (fe0->dvb.frontend) {
-                       if (dvb_attach(zl10036_attach, fe0->dvb.frontend,
-                                       &avertv_a700_tuner, &dev->i2c_adap) == NULL) {
-                               wprintk("%s: No zl10036 found!\n",
-                                       __func__);
-                       }
-               }
-               break;
-       case SAA7134_BOARD_VIDEOMATE_S350:
-               fe0->dvb.frontend = dvb_attach(mt312_attach,
-                               &zl10313_compro_s350_config, &dev->i2c_adap);
-               if (fe0->dvb.frontend)
-                       if (dvb_attach(zl10039_attach, fe0->dvb.frontend,
-                                       0x60, &dev->i2c_adap) == NULL)
-                               wprintk("%s: No zl10039 found!\n",
-                                       __func__);
-
-               break;
-       case SAA7134_BOARD_VIDEOMATE_T750:
-               fe0->dvb.frontend = dvb_attach(zl10353_attach,
-                                               &videomate_t750_zl10353_config,
-                                               &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       if (dvb_attach(qt1010_attach,
-                                       fe0->dvb.frontend,
-                                       &dev->i2c_adap,
-                                       &videomate_t750_qt1010_config) == NULL)
-                               wprintk("error attaching QT1010\n");
-               }
-               break;
-       case SAA7134_BOARD_ZOLID_HYBRID_PCI:
-               fe0->dvb.frontend = dvb_attach(tda10048_attach,
-                                              &zolid_tda10048_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &zolid_tda18271_config);
-               }
-               break;
-       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
-               fe0->dvb.frontend = dvb_attach(tda10048_attach,
-                                              &dtv1000s_tda10048_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &dtv1000s_tda18271_config);
-               }
-               break;
-       case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
-               /* Switch to digital mode */
-               saa7134_tuner_callback(dev, 0,
-                                      TDA18271_CALLBACK_CMD_AGC_ENABLE, 1);
-               fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
-                                              &kworld_mb86a20s_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl;
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &kworld_tda18271_config);
-               }
-
-               /* mb86a20s need to use the I2C gateway */
-               break;
-       case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
-               fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
-                                              &prohdtv_pro2_lgs8g75_config,
-                                              &dev->i2c_adap);
-               if (fe0->dvb.frontend != NULL) {
-                       dvb_attach(tda829x_attach, fe0->dvb.frontend,
-                                  &dev->i2c_adap, 0x4b,
-                                  &tda829x_no_probe);
-                       dvb_attach(tda18271_attach, fe0->dvb.frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &prohdtv_pro2_tda18271_config);
-               }
-               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 (!fe0->dvb.frontend)
-                       goto detach_frontend;
-
-               fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
-               if (!fe) {
-                       printk(KERN_ERR "%s/2: xc3028 attach failed\n",
-                              dev->name);
-                       goto detach_frontend;
-               }
-       }
-
-       if (NULL == fe0->dvb.frontend) {
-               printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name);
-               goto detach_frontend;
-       }
-       /* define general-purpose callback pointer */
-       fe0->dvb.frontend->callback = saa7134_tuner_callback;
-
-       /* register everything else */
-       ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-                                       &dev->pci->dev, adapter_nr, 0);
-
-       /* this sequence is necessary to make the tda1004x load its firmware
-        * and to enter analog mode of hybrid boards
-        */
-       if (!ret) {
-               if (fe0->dvb.frontend->ops.init)
-                       fe0->dvb.frontend->ops.init(fe0->dvb.frontend);
-               if (fe0->dvb.frontend->ops.sleep)
-                       fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend);
-               if (fe0->dvb.frontend->ops.tuner_ops.sleep)
-                       fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend);
-       }
-       return ret;
-
-detach_frontend:
-       videobuf_dvb_dealloc_frontends(&dev->frontends);
-       return -EINVAL;
-}
-
-static int dvb_fini(struct saa7134_dev *dev)
-{
-       struct videobuf_dvb_frontend *fe0;
-
-       /* Get the first frontend */
-       fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
-       if (!fe0)
-               return -EINVAL;
-
-       /* FIXME: I suspect that this code is bogus, since the entry for
-          Pinnacle 300I DVB-T PAL already defines the proper init to allow
-          the detection of mt2032 (TDA9887_PORT2_INACTIVE)
-        */
-       if (dev->board == SAA7134_BOARD_PINNACLE_300I_DVBT_PAL) {
-               struct v4l2_priv_tun_config tda9887_cfg;
-               static int on  = TDA9887_PRESENT | TDA9887_PORT2_INACTIVE;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv  = &on;
-
-               /* otherwise we don't detect the tuner on next insmod */
-               saa_call_all(dev, tuner, s_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 = fe0->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_bus(&dev->frontends);
-       return 0;
-}
-
-static struct saa7134_mpeg_ops dvb_ops = {
-       .type          = SAA7134_MPEG_DVB,
-       .init          = dvb_init,
-       .fini          = dvb_fini,
-};
-
-static int __init dvb_register(void)
-{
-       return saa7134_ts_register(&dvb_ops);
-}
-
-static void __exit dvb_unregister(void)
-{
-       saa7134_ts_unregister(&dvb_ops);
-}
-
-module_init(dvb_register);
-module_exit(dvb_unregister);
-
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
deleted file mode 100644 (file)
index dde361a..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- *
- * (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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
-#include <media/saa6752hs.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-chip-ident.h>
-
-/* ------------------------------------------------------------------ */
-
-MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
-MODULE_LICENSE("GPL");
-
-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;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
-
-#define dprintk(fmt, arg...)   if (debug)                      \
-       printk(KERN_DEBUG "%s/empress: " fmt, dev->name , ## arg)
-
-/* ------------------------------------------------------------------ */
-
-static void ts_reset_encoder(struct saa7134_dev* dev)
-{
-       if (!dev->empress_started)
-               return;
-
-       saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
-       msleep(10);
-       saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
-       msleep(100);
-       dev->empress_started = 0;
-}
-
-static int ts_init_encoder(struct saa7134_dev* dev)
-{
-       u32 leading_null_bytes = 0;
-
-       /* If more cards start to need this, then this
-          should probably be added to the card definitions. */
-       switch (dev->board) {
-       case SAA7134_BOARD_BEHOLD_M6:
-       case SAA7134_BOARD_BEHOLD_M63:
-       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
-               leading_null_bytes = 1;
-               break;
-       }
-       ts_reset_encoder(dev);
-       saa_call_all(dev, core, init, leading_null_bytes);
-       dev->empress_started = 1;
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int ts_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7134_dev *dev = video_drvdata(file);
-       int err;
-
-       dprintk("open dev=%s\n", video_device_node_name(vdev));
-       err = -EBUSY;
-       if (!mutex_trylock(&dev->empress_tsq.vb_lock))
-               return err;
-       if (atomic_read(&dev->empress_users))
-               goto done;
-
-       /* Unmute audio */
-       saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
-               saa_readb(SAA7134_AUDIO_MUTE_CTRL) & ~(1 << 6));
-
-       atomic_inc(&dev->empress_users);
-       file->private_data = dev;
-       err = 0;
-
-done:
-       mutex_unlock(&dev->empress_tsq.vb_lock);
-       return err;
-}
-
-static int ts_release(struct file *file)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       videobuf_stop(&dev->empress_tsq);
-       videobuf_mmap_free(&dev->empress_tsq);
-
-       /* stop the encoder */
-       ts_reset_encoder(dev);
-
-       /* Mute audio */
-       saa_writeb(SAA7134_AUDIO_MUTE_CTRL,
-               saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6));
-
-       atomic_dec(&dev->empress_users);
-
-       return 0;
-}
-
-static ssize_t
-ts_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       if (!dev->empress_started)
-               ts_init_encoder(dev);
-
-       return videobuf_read_stream(&dev->empress_tsq,
-                                   data, count, ppos, 0,
-                                   file->f_flags & O_NONBLOCK);
-}
-
-static unsigned int
-ts_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_poll_stream(file, &dev->empress_tsq, wait);
-}
-
-
-static int
-ts_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_mmap_mapper(&dev->empress_tsq, vma);
-}
-
-/*
- * This function is _not_ called directly, but from
- * video_generic_ioctl (and maybe others).  userspace
- * copying is done already, arg is a kernel pointer.
- */
-
-static int empress_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       strcpy(cap->driver, "saa7134");
-       strlcpy(cap->card, saa7134_boards[dev->board].name,
-               sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->capabilities =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING;
-       return 0;
-}
-
-static int empress_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *i)
-{
-       if (i->index != 0)
-               return -EINVAL;
-
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-       strcpy(i->name, "CCIR656");
-
-       return 0;
-}
-
-static int empress_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int empress_s_input(struct file *file, void *priv, unsigned int i)
-{
-       if (i != 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int empress_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, "MPEG TS", sizeof(f->description));
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int empress_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7134_dev *dev = file->private_data;
-       struct v4l2_mbus_framefmt mbus_fmt;
-
-       saa_call_all(dev, video, g_mbus_fmt, &mbus_fmt);
-
-       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
-
-       return 0;
-}
-
-static int empress_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7134_dev *dev = file->private_data;
-       struct v4l2_mbus_framefmt mbus_fmt;
-
-       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
-       saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
-       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
-
-       return 0;
-}
-
-static int empress_try_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.sizeimage    = TS_PACKET_SIZE * dev->ts.nr_packets;
-
-       return 0;
-}
-
-static int empress_reqbufs(struct file *file, void *priv,
-                                       struct v4l2_requestbuffers *p)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_reqbufs(&dev->empress_tsq, p);
-}
-
-static int empress_querybuf(struct file *file, void *priv,
-                                       struct v4l2_buffer *b)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_querybuf(&dev->empress_tsq, b);
-}
-
-static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_qbuf(&dev->empress_tsq, b);
-}
-
-static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_dqbuf(&dev->empress_tsq, b,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int empress_streamon(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_streamon(&dev->empress_tsq);
-}
-
-static int empress_streamoff(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return videobuf_streamoff(&dev->empress_tsq);
-}
-
-static int empress_s_ext_ctrls(struct file *file, void *priv,
-                              struct v4l2_ext_controls *ctrls)
-{
-       struct saa7134_dev *dev = file->private_data;
-       int err;
-
-       /* count == 0 is abused in saa6752hs.c, so that special
-               case is handled here explicitly. */
-       if (ctrls->count == 0)
-               return 0;
-
-       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       err = saa_call_empress(dev, core, s_ext_ctrls, ctrls);
-       ts_init_encoder(dev);
-
-       return err;
-}
-
-static int empress_g_ext_ctrls(struct file *file, void *priv,
-                              struct v4l2_ext_controls *ctrls)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-       return saa_call_empress(dev, core, g_ext_ctrls, ctrls);
-}
-
-static int empress_g_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *c)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return saa7134_g_ctrl_internal(dev, NULL, c);
-}
-
-static int empress_s_ctrl(struct file *file, void *priv,
-                                       struct v4l2_control *c)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return saa7134_s_ctrl_internal(dev, NULL, c);
-}
-
-static int empress_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *c)
-{
-       /* Must be sorted from low to high control ID! */
-       static const u32 user_ctrls[] = {
-               V4L2_CID_USER_CLASS,
-               V4L2_CID_BRIGHTNESS,
-               V4L2_CID_CONTRAST,
-               V4L2_CID_SATURATION,
-               V4L2_CID_HUE,
-               V4L2_CID_AUDIO_VOLUME,
-               V4L2_CID_AUDIO_MUTE,
-               V4L2_CID_HFLIP,
-               0
-       };
-
-       /* Must be sorted from low to high control ID! */
-       static const u32 mpeg_ctrls[] = {
-               V4L2_CID_MPEG_CLASS,
-               V4L2_CID_MPEG_STREAM_TYPE,
-               V4L2_CID_MPEG_STREAM_PID_PMT,
-               V4L2_CID_MPEG_STREAM_PID_AUDIO,
-               V4L2_CID_MPEG_STREAM_PID_VIDEO,
-               V4L2_CID_MPEG_STREAM_PID_PCR,
-               V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
-               V4L2_CID_MPEG_AUDIO_ENCODING,
-               V4L2_CID_MPEG_AUDIO_L2_BITRATE,
-               V4L2_CID_MPEG_VIDEO_ENCODING,
-               V4L2_CID_MPEG_VIDEO_ASPECT,
-               V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-               V4L2_CID_MPEG_VIDEO_BITRATE,
-               V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
-               0
-       };
-       static const u32 *ctrl_classes[] = {
-               user_ctrls,
-               mpeg_ctrls,
-               NULL
-       };
-       struct saa7134_dev *dev = file->private_data;
-
-       c->id = v4l2_ctrl_next(ctrl_classes, c->id);
-       if (c->id == 0)
-               return -EINVAL;
-       if (c->id == V4L2_CID_USER_CLASS || c->id == V4L2_CID_MPEG_CLASS)
-               return v4l2_ctrl_query_fill(c, 0, 0, 0, 0);
-       if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
-               return saa7134_queryctrl(file, priv, c);
-       return saa_call_empress(dev, core, queryctrl, c);
-}
-
-static int empress_querymenu(struct file *file, void *priv,
-                                       struct v4l2_querymenu *c)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       if (V4L2_CTRL_ID2CLASS(c->id) != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-       return saa_call_empress(dev, core, querymenu, c);
-}
-
-static int empress_g_chip_ident(struct file *file, void *fh,
-              struct v4l2_dbg_chip_ident *chip)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-       if (chip->match.type == V4L2_CHIP_MATCH_I2C_DRIVER &&
-           !strcmp(chip->match.name, "saa6752hs"))
-               return saa_call_empress(dev, core, g_chip_ident, chip);
-       if (chip->match.type == V4L2_CHIP_MATCH_I2C_ADDR)
-               return saa_call_empress(dev, core, g_chip_ident, chip);
-       return -EINVAL;
-}
-
-static int empress_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       return saa7134_s_std_internal(dev, NULL, id);
-}
-
-static int empress_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct saa7134_dev *dev = file->private_data;
-
-       *id = dev->tvnorm->id;
-       return 0;
-}
-
-static const struct v4l2_file_operations ts_fops =
-{
-       .owner    = THIS_MODULE,
-       .open     = ts_open,
-       .release  = ts_release,
-       .read     = ts_read,
-       .poll     = ts_poll,
-       .mmap     = ts_mmap,
-       .ioctl    = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops ts_ioctl_ops = {
-       .vidioc_querycap                = empress_querycap,
-       .vidioc_enum_fmt_vid_cap        = empress_enum_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap         = empress_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap           = empress_s_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap           = empress_g_fmt_vid_cap,
-       .vidioc_reqbufs                 = empress_reqbufs,
-       .vidioc_querybuf                = empress_querybuf,
-       .vidioc_qbuf                    = empress_qbuf,
-       .vidioc_dqbuf                   = empress_dqbuf,
-       .vidioc_streamon                = empress_streamon,
-       .vidioc_streamoff               = empress_streamoff,
-       .vidioc_s_ext_ctrls             = empress_s_ext_ctrls,
-       .vidioc_g_ext_ctrls             = empress_g_ext_ctrls,
-       .vidioc_enum_input              = empress_enum_input,
-       .vidioc_g_input                 = empress_g_input,
-       .vidioc_s_input                 = empress_s_input,
-       .vidioc_queryctrl               = empress_queryctrl,
-       .vidioc_querymenu               = empress_querymenu,
-       .vidioc_g_ctrl                  = empress_g_ctrl,
-       .vidioc_s_ctrl                  = empress_s_ctrl,
-       .vidioc_g_chip_ident            = empress_g_chip_ident,
-       .vidioc_s_std                   = empress_s_std,
-       .vidioc_g_std                   = empress_g_std,
-};
-
-/* ----------------------------------------------------------- */
-
-static struct video_device saa7134_empress_template = {
-       .name          = "saa7134-empress",
-       .fops          = &ts_fops,
-       .ioctl_ops     = &ts_ioctl_ops,
-
-       .tvnorms                        = SAA7134_NORMS,
-       .current_norm                   = V4L2_STD_PAL,
-};
-
-static void empress_signal_update(struct work_struct *work)
-{
-       struct saa7134_dev* dev =
-               container_of(work, struct saa7134_dev, empress_workqueue);
-
-       if (dev->nosignal) {
-               dprintk("no video signal\n");
-       } else {
-               dprintk("video signal acquired\n");
-       }
-}
-
-static void empress_signal_change(struct saa7134_dev *dev)
-{
-       schedule_work(&dev->empress_workqueue);
-}
-
-
-static int empress_init(struct saa7134_dev *dev)
-{
-       int err;
-
-       dprintk("%s: %s\n",dev->name,__func__);
-       dev->empress_dev = video_device_alloc();
-       if (NULL == dev->empress_dev)
-               return -ENOMEM;
-       *(dev->empress_dev) = saa7134_empress_template;
-       dev->empress_dev->parent  = &dev->pci->dev;
-       dev->empress_dev->release = video_device_release;
-       snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
-                "%s empress (%s)", dev->name,
-                saa7134_boards[dev->board].name);
-
-       INIT_WORK(&dev->empress_workqueue, empress_signal_update);
-
-       video_set_drvdata(dev->empress_dev, dev);
-       err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
-                                   empress_nr[dev->nr]);
-       if (err < 0) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               video_device_release(dev->empress_dev);
-               dev->empress_dev = NULL;
-               return err;
-       }
-       printk(KERN_INFO "%s: registered device %s [mpeg]\n",
-              dev->name, video_device_node_name(dev->empress_dev));
-
-       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),
-                           dev, NULL);
-
-       empress_signal_update(&dev->empress_workqueue);
-       return 0;
-}
-
-static int empress_fini(struct saa7134_dev *dev)
-{
-       dprintk("%s: %s\n",dev->name,__func__);
-
-       if (NULL == dev->empress_dev)
-               return 0;
-       flush_work_sync(&dev->empress_workqueue);
-       video_unregister_device(dev->empress_dev);
-       dev->empress_dev = NULL;
-       return 0;
-}
-
-static struct saa7134_mpeg_ops empress_ops = {
-       .type          = SAA7134_MPEG_EMPRESS,
-       .init          = empress_init,
-       .fini          = empress_fini,
-       .signal_change = empress_signal_change,
-};
-
-static int __init empress_register(void)
-{
-       return saa7134_ts_register(&empress_ops);
-}
-
-static void __exit empress_unregister(void)
-{
-       saa7134_ts_unregister(&empress_ops);
-}
-
-module_init(empress_register);
-module_exit(empress_unregister);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
deleted file mode 100644 (file)
index a176ec3..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * i2c interface support
- *
- * (c) 2001,02 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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-#include <media/v4l2-common.h>
-
-/* ----------------------------------------------------------- */
-
-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;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
-
-#define d1printk if (1 == i2c_debug) printk
-#define d2printk if (2 == i2c_debug) printk
-
-#define I2C_WAIT_DELAY  32
-#define I2C_WAIT_RETRY  16
-
-/* ----------------------------------------------------------- */
-
-static char *str_i2c_status[] = {
-       "IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE",
-       "DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE",
-       "NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR"
-};
-
-enum i2c_status {
-       IDLE          = 0,  // no I2C command pending
-       DONE_STOP     = 1,  // I2C command done and STOP executed
-       BUSY          = 2,  // executing I2C command
-       TO_SCL        = 3,  // executing I2C command, time out on clock stretching
-       TO_ARB        = 4,  // time out on arbitration trial, still trying
-       DONE_WRITE    = 5,  // I2C command done and awaiting next write command
-       DONE_READ     = 6,  // I2C command done and awaiting next read command
-       DONE_WRITE_TO = 7,  // see 5, and time out on status echo
-       DONE_READ_TO  = 8,  // see 6, and time out on status echo
-       NO_DEVICE     = 9,  // no acknowledge on device slave address
-       NO_ACKN       = 10, // no acknowledge after data byte transfer
-       BUS_ERR       = 11, // bus error
-       ARB_LOST      = 12, // arbitration lost during transfer
-       SEQ_ERR       = 13, // erroneous programming sequence
-       ST_ERR        = 14, // wrong status echoing
-       SW_ERR        = 15  // software error
-};
-
-static char *str_i2c_attr[] = {
-       "NOP", "STOP", "CONTINUE", "START"
-};
-
-enum i2c_attr {
-       NOP           = 0,  // no operation on I2C bus
-       STOP          = 1,  // stop condition, no associated byte transfer
-       CONTINUE      = 2,  // continue with byte transfer
-       START         = 3   // start condition with byte transfer
-};
-
-static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
-{
-       enum i2c_status status;
-
-       status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
-       d2printk(KERN_DEBUG "%s: i2c stat <= %s\n",dev->name,
-                str_i2c_status[status]);
-       return status;
-}
-
-static inline void i2c_set_status(struct saa7134_dev *dev,
-                                 enum i2c_status status)
-{
-       d2printk(KERN_DEBUG "%s: i2c stat => %s\n",dev->name,
-                str_i2c_status[status]);
-       saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
-}
-
-static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
-{
-       d2printk(KERN_DEBUG "%s: i2c attr => %s\n",dev->name,
-                str_i2c_attr[attr]);
-       saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
-}
-
-static inline int i2c_is_error(enum i2c_status status)
-{
-       switch (status) {
-       case NO_DEVICE:
-       case NO_ACKN:
-       case BUS_ERR:
-       case ARB_LOST:
-       case SEQ_ERR:
-       case ST_ERR:
-               return true;
-       default:
-               return false;
-       }
-}
-
-static inline int i2c_is_idle(enum i2c_status status)
-{
-       switch (status) {
-       case IDLE:
-       case DONE_STOP:
-               return true;
-       default:
-               return false;
-       }
-}
-
-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;
-       }
-}
-
-static int i2c_is_busy_wait(struct saa7134_dev *dev)
-{
-       enum i2c_status status;
-       int count;
-
-       for (count = 0; count < I2C_WAIT_RETRY; count++) {
-               status = i2c_get_status(dev);
-               if (!i2c_is_busy(status))
-                       break;
-               saa_wait(I2C_WAIT_DELAY);
-       }
-       if (I2C_WAIT_RETRY == count)
-               return false;
-       return true;
-}
-
-static int i2c_reset(struct saa7134_dev *dev)
-{
-       enum i2c_status status;
-       int count;
-
-       d2printk(KERN_DEBUG "%s: i2c reset\n",dev->name);
-       status = i2c_get_status(dev);
-       if (!i2c_is_error(status))
-               return true;
-       i2c_set_status(dev,status);
-
-       for (count = 0; count < I2C_WAIT_RETRY; count++) {
-               status = i2c_get_status(dev);
-               if (!i2c_is_error(status))
-                       break;
-               udelay(I2C_WAIT_DELAY);
-       }
-       if (I2C_WAIT_RETRY == count)
-               return false;
-
-       if (!i2c_is_idle(status))
-               return false;
-
-       i2c_set_attr(dev,NOP);
-       return true;
-}
-
-static inline int i2c_send_byte(struct saa7134_dev *dev,
-                               enum i2c_attr attr,
-                               unsigned char data)
-{
-       enum i2c_status status;
-       __u32 dword;
-
-       /* have to write both attr + data in one 32bit word */
-       dword  = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
-       dword &= 0x0f;
-       dword |= (attr << 6);
-       dword |= ((__u32)data << 8);
-       dword |= 0x00 << 16;  /* 100 kHz */
-//     dword |= 0x40 << 16;  /* 400 kHz */
-       dword |= 0xf0 << 24;
-       saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
-       d2printk(KERN_DEBUG "%s: i2c data => 0x%x\n",dev->name,data);
-
-       if (!i2c_is_busy_wait(dev))
-               return -EIO;
-       status = i2c_get_status(dev);
-       if (i2c_is_error(status))
-               return -EIO;
-       return 0;
-}
-
-static inline int i2c_recv_byte(struct saa7134_dev *dev)
-{
-       enum i2c_status status;
-       unsigned char data;
-
-       i2c_set_attr(dev,CONTINUE);
-       if (!i2c_is_busy_wait(dev))
-               return -EIO;
-       status = i2c_get_status(dev);
-       if (i2c_is_error(status))
-               return -EIO;
-       data = saa_readb(SAA7134_I2C_DATA);
-       d2printk(KERN_DEBUG "%s: i2c data <= 0x%x\n",dev->name,data);
-       return data;
-}
-
-static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
-                           struct i2c_msg *msgs, int num)
-{
-       struct saa7134_dev *dev = i2c_adap->algo_data;
-       enum i2c_status status;
-       unsigned char data;
-       int addr,rc,i,byte;
-
-       status = i2c_get_status(dev);
-       if (!i2c_is_idle(status))
-               if (!i2c_reset(dev))
-                       return -EIO;
-
-       d2printk("start xfer\n");
-       d1printk(KERN_DEBUG "%s: i2c xfer:",dev->name);
-       for (i = 0; i < num; i++) {
-               if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
-                       /* send address */
-                       d2printk("send address\n");
-                       addr  = msgs[i].addr << 1;
-                       if (msgs[i].flags & I2C_M_RD)
-                               addr |= 1;
-                       if (i > 0 && msgs[i].flags &
-                           I2C_M_RD && msgs[i].addr != 0x40 &&
-                           msgs[i].addr != 0x19) {
-                               /* workaround for a saa7134 i2c bug
-                                * needed to talk to the mt352 demux
-                                * thanks to pinnacle for the hint */
-                               int quirk = 0xfe;
-                               d1printk(" [%02x quirk]",quirk);
-                               i2c_send_byte(dev,START,quirk);
-                               i2c_recv_byte(dev);
-                       }
-                       d1printk(" < %02x", addr);
-                       rc = i2c_send_byte(dev,START,addr);
-                       if (rc < 0)
-                                goto err;
-               }
-               if (msgs[i].flags & I2C_M_RD) {
-                       /* read bytes */
-                       d2printk("read bytes\n");
-                       for (byte = 0; byte < msgs[i].len; byte++) {
-                               d1printk(" =");
-                               rc = i2c_recv_byte(dev);
-                               if (rc < 0)
-                                       goto err;
-                               d1printk("%02x", rc);
-                               msgs[i].buf[byte] = rc;
-                       }
-                       /* discard mysterious extra byte when reading
-                          from Samsung S5H1411.  i2c bus gets error
-                          if we do not. */
-                       if (0x19 == msgs[i].addr) {
-                               d1printk(" ?");
-                               rc = i2c_recv_byte(dev);
-                               if (rc < 0)
-                                       goto err;
-                               d1printk("%02x", rc);
-                       }
-               } else {
-                       /* write bytes */
-                       d2printk("write bytes\n");
-                       for (byte = 0; byte < msgs[i].len; byte++) {
-                               data = msgs[i].buf[byte];
-                               d1printk(" %02x", data);
-                               rc = i2c_send_byte(dev,CONTINUE,data);
-                               if (rc < 0)
-                                       goto err;
-                       }
-               }
-       }
-       d2printk("xfer done\n");
-       d1printk(" >");
-       i2c_set_attr(dev,STOP);
-       rc = -EIO;
-       if (!i2c_is_busy_wait(dev))
-               goto err;
-       status = i2c_get_status(dev);
-       if (i2c_is_error(status))
-               goto err;
-       /* ensure that the bus is idle for at least one bit slot */
-       msleep(1);
-
-       d1printk("\n");
-       return num;
- err:
-       if (1 == i2c_debug) {
-               status = i2c_get_status(dev);
-               printk(" ERROR: %s\n",str_i2c_status[status]);
-       }
-       return rc;
-}
-
-/* ----------------------------------------------------------- */
-
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm saa7134_algo = {
-       .master_xfer   = saa7134_i2c_xfer,
-       .functionality = functionality,
-};
-
-static struct i2c_adapter saa7134_adap_template = {
-       .owner         = THIS_MODULE,
-       .name          = "saa7134",
-       .algo          = &saa7134_algo,
-};
-
-static struct i2c_client saa7134_client_template = {
-       .name   = "saa7134 internal",
-};
-
-/* ----------------------------------------------------------- */
-
-static int
-saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
-{
-       unsigned char buf;
-       int i,err;
-
-       dev->i2c_client.addr = 0xa0 >> 1;
-       buf = 0;
-       if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
-               printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
-                      dev->name,err);
-               return -1;
-       }
-       if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
-               printk(KERN_WARNING "%s: i2c eeprom read error (err=%d)\n",
-                      dev->name,err);
-               return -1;
-       }
-       for (i = 0; i < len; i++) {
-               if (0 == (i % 16))
-                       printk(KERN_INFO "%s: i2c eeprom %02x:",dev->name,i);
-               printk(" %02x",eedata[i]);
-               if (15 == (i % 16))
-                       printk("\n");
-       }
-       return 0;
-}
-
-static char *i2c_devs[128] = {
-       [ 0x20      ] = "mpeg encoder (saa6752hs)",
-       [ 0xa0 >> 1 ] = "eeprom",
-       [ 0xc0 >> 1 ] = "tuner (analog)",
-       [ 0x86 >> 1 ] = "tda9887",
-       [ 0x5a >> 1 ] = "remote control",
-};
-
-static void do_i2c_scan(char *name, struct i2c_client *c)
-{
-       unsigned char buf;
-       int i,rc;
-
-       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
-               c->addr = i;
-               rc = i2c_master_recv(c,&buf,0);
-               if (rc < 0)
-                       continue;
-               printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
-                      name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
-       }
-}
-
-int saa7134_i2c_register(struct saa7134_dev *dev)
-{
-       dev->i2c_adap = saa7134_adap_template;
-       dev->i2c_adap.dev.parent = &dev->pci->dev;
-       strcpy(dev->i2c_adap.name,dev->name);
-       dev->i2c_adap.algo_data = dev;
-       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
-       i2c_add_adapter(&dev->i2c_adap);
-
-       dev->i2c_client = saa7134_client_template;
-       dev->i2c_client.adapter = &dev->i2c_adap;
-
-       saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
-       if (i2c_scan)
-               do_i2c_scan(dev->name,&dev->i2c_client);
-
-       /* Instantiate the IR receiver device, if present */
-       saa7134_probe_i2c_ir(dev);
-       return 0;
-}
-
-int saa7134_i2c_unregister(struct saa7134_dev *dev)
-{
-       i2c_del_adapter(&dev->i2c_adap);
-       return 0;
-}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
deleted file mode 100644 (file)
index 0f78f5e..0000000
+++ /dev/null
@@ -1,1041 +0,0 @@
-/*
- *
- * handle saa7134 IR remotes via linux kernel input layer.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
-#define MODULE_NAME "saa7134"
-
-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;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
-
-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)");
-
-#define dprintk(fmt, arg...)   if (ir_debug) \
-       printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
-#define i2cdprintk(fmt, arg...)    if (ir_debug) \
-       printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg)
-
-/* Helper function for raw decoding at GPIO16 or GPIO18 */
-static int saa7134_raw_decode_irq(struct saa7134_dev *dev);
-
-/* -------------------- GPIO generic keycode builder -------------------- */
-
-static int build_key(struct saa7134_dev *dev)
-{
-       struct saa7134_card_ir *ir = dev->remote;
-       u32 gpio, data;
-
-       /* here comes the additional handshake steps for some cards */
-       switch (dev->board) {
-       case SAA7134_BOARD_GOTVIEW_7135:
-               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x80);
-               saa_clearb(SAA7134_GPIO_GPSTATUS1, 0x80);
-               break;
-       }
-       /* rising SAA7134_GPIO_GPRESCAN reads the status */
-       saa_clearb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
-       saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN);
-
-       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
-       if (ir->polling) {
-               if (ir->last_gpio == gpio)
-                       return 0;
-               ir->last_gpio = gpio;
-       }
-
-       data = ir_extract_bits(gpio, ir->mask_keycode);
-       dprintk("build_key gpio=0x%x mask=0x%x data=%d\n",
-               gpio, ir->mask_keycode, data);
-
-       switch (dev->board) {
-       case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
-               if (data == ir->mask_keycode)
-                       rc_keyup(ir->dev);
-               else
-                       rc_keydown_notimeout(ir->dev, data, 0);
-               return 0;
-       }
-
-       if (ir->polling) {
-               if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
-                   (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-                       rc_keydown_notimeout(ir->dev, data, 0);
-               } else {
-                       rc_keyup(ir->dev);
-               }
-       }
-       else {  /* IRQ driven mode - handle key press and release in one go */
-               if ((ir->mask_keydown  &&  (0 != (gpio & ir->mask_keydown))) ||
-                   (ir->mask_keyup    &&  (0 == (gpio & ir->mask_keyup)))) {
-                       rc_keydown_notimeout(ir->dev, data, 0);
-                       rc_keyup(ir->dev);
-               }
-       }
-
-       return 0;
-}
-
-/* --------------------- Chip specific I2C key builders ----------------- */
-
-static int get_key_flydvb_trio(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       int gpio;
-       int attempt = 0;
-       unsigned char b;
-
-       /* We need this to access GPI Used by the saa_readl macro. */
-       struct saa7134_dev *dev = ir->c->adapter->algo_data;
-
-       if (dev == NULL) {
-               i2cdprintk("get_key_flydvb_trio: "
-                          "ir->c->adapter->algo_data is NULL!\n");
-               return -EIO;
-       }
-
-       /* rising SAA7134_GPIGPRESCAN reads the status */
-       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-
-       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
-
-       if (0x40000 & ~gpio)
-               return 0; /* No button press */
-
-       /* No button press - only before first key pressed */
-       if (b == 0xFF)
-               return 0;
-
-       /* poll IR chip */
-       /* weak up the IR chip */
-       b = 0;
-
-       while (1 != i2c_master_send(ir->c, &b, 1)) {
-               if ((attempt++) < 10) {
-                       /*
-                        * wait a bit for next attempt -
-                        * I don't know how make it better
-                        */
-                       msleep(10);
-                       continue;
-               }
-               i2cdprintk("send wake up byte to pic16C505 (IR chip)"
-                          "failed %dx\n", attempt);
-               return -EIO;
-       }
-       if (1 != i2c_master_recv(ir->c, &b, 1)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       *ir_key = b;
-       *ir_raw = b;
-       return 1;
-}
-
-static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key,
-                                      u32 *ir_raw)
-{
-       unsigned char b;
-       int gpio;
-
-       /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
-       struct saa7134_dev *dev = ir->c->adapter->algo_data;
-       if (dev == NULL) {
-               i2cdprintk("get_key_msi_tvanywhere_plus: "
-                          "ir->c->adapter->algo_data is NULL!\n");
-               return -EIO;
-       }
-
-       /* rising SAA7134_GPIO_GPRESCAN reads the status */
-
-       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-
-       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
-
-       /* GPIO&0x40 is pulsed low when a button is pressed. Don't do
-          I2C receive if gpio&0x40 is not low. */
-
-       if (gpio & 0x40)
-               return 0;       /* No button press */
-
-       /* GPIO says there is a button press. Get it. */
-
-       if (1 != i2c_master_recv(ir->c, &b, 1)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       /* No button press */
-
-       if (b == 0xff)
-               return 0;
-
-       /* Button pressed */
-
-       dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b);
-       *ir_key = b;
-       *ir_raw = b;
-       return 1;
-}
-
-/* copied and modified from get_key_msi_tvanywhere_plus() */
-static int get_key_kworld_pc150u(struct IR_i2c *ir, u32 *ir_key,
-                                       u32 *ir_raw)
-{
-       unsigned char b;
-       unsigned int gpio;
-
-       /* <dev> is needed to access GPIO. Used by the saa_readl macro. */
-       struct saa7134_dev *dev = ir->c->adapter->algo_data;
-       if (dev == NULL) {
-               i2cdprintk("get_key_kworld_pc150u: "
-                          "ir->c->adapter->algo_data is NULL!\n");
-               return -EIO;
-       }
-
-       /* rising SAA7134_GPIO_GPRESCAN reads the status */
-
-       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-
-       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
-
-       /* GPIO&0x100 is pulsed low when a button is pressed. Don't do
-          I2C receive if gpio&0x100 is not low. */
-
-       if (gpio & 0x100)
-               return 0;       /* No button press */
-
-       /* GPIO says there is a button press. Get it. */
-
-       if (1 != i2c_master_recv(ir->c, &b, 1)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       /* No button press */
-
-       if (b == 0xff)
-               return 0;
-
-       /* Button pressed */
-
-       dprintk("get_key_kworld_pc150u: Key = 0x%02X\n", b);
-       *ir_key = b;
-       *ir_raw = b;
-       return 1;
-}
-
-static int get_key_purpletv(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)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       /* no button press */
-       if (b==0)
-               return 0;
-
-       /* repeating */
-       if (b & 0x80)
-               return 1;
-
-       *ir_key = b;
-       *ir_raw = b;
-       return 1;
-}
-
-static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       unsigned char buf[5];
-
-       /* poll IR chip */
-       if (5 != i2c_master_recv(ir->c, buf, 5))
-               return -EIO;
-
-       /* Check if some key were pressed */
-       if (!(buf[0] & 0x80))
-               return 0;
-
-       /*
-        * buf[3] & 0x80 is always high.
-        * buf[3] & 0x40 is a parity bit. A repeat event is marked
-        * by preserving it into two separate readings
-        * buf[4] bits 0 and 1, and buf[1] and buf[2] are always
-        * zero.
-        */
-       *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2));
-       *ir_raw = *ir_key;
-       return 1;
-}
-
-
-static int get_key_beholdm6xx(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       unsigned char data[12];
-       u32 gpio;
-
-       struct saa7134_dev *dev = ir->c->adapter->algo_data;
-
-       /* rising SAA7134_GPIO_GPRESCAN reads the status */
-       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-
-       gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
-
-       if (0x400000 & ~gpio)
-               return 0; /* No button press */
-
-       ir->c->addr = 0x5a >> 1;
-
-       if (12 != i2c_master_recv(ir->c, data, 12)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       if (data[9] != (unsigned char)(~data[8]))
-               return 0;
-
-       *ir_raw = ((data[10] << 16) | (data[11] << 8) | (data[9] << 0));
-       *ir_key = *ir_raw;
-
-       return 1;
-}
-
-/* Common (grey or coloured) pinnacle PCTV remote handling
- *
- */
-static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
-                           int parity_offset, int marker, int code_modulo)
-{
-       unsigned char b[4];
-       unsigned int start = 0,parity = 0,code = 0;
-
-       /* poll IR chip */
-       if (4 != i2c_master_recv(ir->c, b, 4)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       for (start = 0; start < ARRAY_SIZE(b); start++) {
-               if (b[start] == marker) {
-                       code=b[(start+parity_offset + 1) % 4];
-                       parity=b[(start+parity_offset) % 4];
-               }
-       }
-
-       /* Empty Request */
-       if (parity == 0)
-               return 0;
-
-       /* Repeating... */
-       if (ir->old == parity)
-               return 0;
-
-       ir->old = parity;
-
-       /* drop special codes when a key is held down a long time for the grey controller
-          In this case, the second bit of the code is asserted */
-       if (marker == 0xfe && (code & 0x40))
-               return 0;
-
-       code %= code_modulo;
-
-       *ir_raw = code;
-       *ir_key = code;
-
-       i2cdprintk("Pinnacle PCTV key %02x\n", code);
-
-       return 1;
-}
-
-/* The grey pinnacle PCTV remote
- *
- *  There are one issue with this remote:
- *   - I2c packet does not change when the same key is pressed quickly. The workaround
- *     is to hold down each key for about half a second, so that another code is generated
- *     in the i2c packet, and the function can distinguish key presses.
- *
- * Sylvain Pasche <sylvain.pasche@gmail.com>
- */
-static int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-
-       return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
-}
-
-
-/* The new pinnacle PCTV remote (with the colored buttons)
- *
- * Ricardo Cerqueira <v4l@cerqueira.org>
- */
-static int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       /* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
-        *
-        * this is the only value that results in 42 unique
-        * codes < 128
-        */
-
-       return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
-}
-
-void saa7134_input_irq(struct saa7134_dev *dev)
-{
-       struct saa7134_card_ir *ir;
-
-       if (!dev || !dev->remote)
-               return;
-
-       ir = dev->remote;
-       if (!ir->running)
-               return;
-
-       if (!ir->polling && !ir->raw_decode) {
-               build_key(dev);
-       } else if (ir->raw_decode) {
-               saa7134_raw_decode_irq(dev);
-       }
-}
-
-static void saa7134_input_timer(unsigned long data)
-{
-       struct saa7134_dev *dev = (struct saa7134_dev *)data;
-       struct saa7134_card_ir *ir = dev->remote;
-
-       build_key(dev);
-       mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
-}
-
-static void ir_raw_decode_timer_end(unsigned long data)
-{
-       struct saa7134_dev *dev = (struct saa7134_dev *)data;
-
-       ir_raw_event_handle(dev->remote->dev);
-}
-
-static int __saa7134_ir_start(void *priv)
-{
-       struct saa7134_dev *dev = priv;
-       struct saa7134_card_ir *ir;
-
-       if (!dev || !dev->remote)
-               return -EINVAL;
-
-       ir  = dev->remote;
-       if (ir->running)
-               return 0;
-
-       /* Moved here from saa7134_input_init1() because the latter
-        * is not called on device resume */
-       switch (dev->board) {
-       case SAA7134_BOARD_MD2819:
-       case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
-       case SAA7134_BOARD_AVERMEDIA_305:
-       case SAA7134_BOARD_AVERMEDIA_307:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
-       case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
-       case SAA7134_BOARD_AVERMEDIA_M102:
-       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
-               /* Without this we won't receive key up events */
-               saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
-               saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_777:
-       case SAA7134_BOARD_AVERMEDIA_A16AR:
-               /* Without this we won't receive key up events */
-               saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
-               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A16D:
-               /* Without this we won't receive key up events */
-               saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
-               saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
-               break;
-       case SAA7134_BOARD_GOTVIEW_7135:
-               saa_setb(SAA7134_GPIO_GPMODE1, 0x80);
-               break;
-       }
-
-       ir->running = true;
-
-       if (ir->polling) {
-               setup_timer(&ir->timer, saa7134_input_timer,
-                           (unsigned long)dev);
-               ir->timer.expires = jiffies + HZ;
-               add_timer(&ir->timer);
-       } else if (ir->raw_decode) {
-               /* set timer_end for code completion */
-               setup_timer(&ir->timer, ir_raw_decode_timer_end,
-                           (unsigned long)dev);
-       }
-
-       return 0;
-}
-
-static void __saa7134_ir_stop(void *priv)
-{
-       struct saa7134_dev *dev = priv;
-       struct saa7134_card_ir *ir;
-
-       if (!dev || !dev->remote)
-               return;
-
-       ir  = dev->remote;
-       if (!ir->running)
-               return;
-
-       if (ir->polling || ir->raw_decode)
-               del_timer_sync(&ir->timer);
-
-       ir->running = false;
-
-       return;
-}
-
-int saa7134_ir_start(struct saa7134_dev *dev)
-{
-       if (dev->remote->users)
-               return __saa7134_ir_start(dev);
-
-       return 0;
-}
-
-void saa7134_ir_stop(struct saa7134_dev *dev)
-{
-       if (dev->remote->users)
-               __saa7134_ir_stop(dev);
-}
-
-static int saa7134_ir_open(struct rc_dev *rc)
-{
-       struct saa7134_dev *dev = rc->priv;
-
-       dev->remote->users++;
-       return __saa7134_ir_start(dev);
-}
-
-static void saa7134_ir_close(struct rc_dev *rc)
-{
-       struct saa7134_dev *dev = rc->priv;
-
-       dev->remote->users--;
-       if (!dev->remote->users)
-               __saa7134_ir_stop(dev);
-}
-
-int saa7134_input_init1(struct saa7134_dev *dev)
-{
-       struct saa7134_card_ir *ir;
-       struct rc_dev *rc;
-       char *ir_codes = NULL;
-       u32 mask_keycode = 0;
-       u32 mask_keydown = 0;
-       u32 mask_keyup   = 0;
-       unsigned polling = 0;
-       bool raw_decode  = false;
-       int err;
-
-       if (dev->has_remote != SAA7134_REMOTE_GPIO)
-               return -ENODEV;
-       if (disable_ir)
-               return -ENODEV;
-
-       /* detect & configure */
-       switch (dev->board) {
-       case SAA7134_BOARD_FLYVIDEO2000:
-       case SAA7134_BOARD_FLYVIDEO3000:
-       case SAA7134_BOARD_FLYTVPLATINUM_FM:
-       case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
-       case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
-               ir_codes     = RC_MAP_FLYVIDEO;
-               mask_keycode = 0xEC00000;
-               mask_keydown = 0x0040000;
-               break;
-       case SAA7134_BOARD_CINERGY400:
-       case SAA7134_BOARD_CINERGY600:
-       case SAA7134_BOARD_CINERGY600_MK3:
-               ir_codes     = RC_MAP_CINERGY;
-               mask_keycode = 0x00003f;
-               mask_keyup   = 0x040000;
-               break;
-       case SAA7134_BOARD_ECS_TVP3XP:
-       case SAA7134_BOARD_ECS_TVP3XP_4CB5:
-               ir_codes     = RC_MAP_EZTV;
-               mask_keycode = 0x00017c;
-               mask_keyup   = 0x000002;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_KWORLD_XPERT:
-       case SAA7134_BOARD_AVACSSMARTTV:
-               ir_codes     = RC_MAP_PIXELVIEW;
-               mask_keycode = 0x00001F;
-               mask_keyup   = 0x000020;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_MD2819:
-       case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
-       case SAA7134_BOARD_AVERMEDIA_305:
-       case SAA7134_BOARD_AVERMEDIA_307:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
-       case SAA7134_BOARD_AVERMEDIA_STUDIO_507UA:
-       case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
-       case SAA7134_BOARD_AVERMEDIA_M102:
-       case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
-               ir_codes     = RC_MAP_AVERMEDIA;
-               mask_keycode = 0x0007C8;
-               mask_keydown = 0x000010;
-               polling      = 50; // ms
-               /* GPIO stuff moved to __saa7134_ir_start() */
-               break;
-       case SAA7134_BOARD_AVERMEDIA_M135A:
-               ir_codes     = RC_MAP_AVERMEDIA_M135A;
-               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
-               mask_keyup   = 0x0040000;
-               mask_keycode = 0xffff;
-               raw_decode   = true;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_M733A:
-               ir_codes     = RC_MAP_AVERMEDIA_M733A_RM_K6;
-               mask_keydown = 0x0040000;
-               mask_keyup   = 0x0040000;
-               mask_keycode = 0xffff;
-               raw_decode   = true;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_777:
-       case SAA7134_BOARD_AVERMEDIA_A16AR:
-               ir_codes     = RC_MAP_AVERMEDIA;
-               mask_keycode = 0x02F200;
-               mask_keydown = 0x000400;
-               polling      = 50; // ms
-               /* GPIO stuff moved to __saa7134_ir_start() */
-               break;
-       case SAA7134_BOARD_AVERMEDIA_A16D:
-               ir_codes     = RC_MAP_AVERMEDIA_A16D;
-               mask_keycode = 0x02F200;
-               mask_keydown = 0x000400;
-               polling      = 50; /* ms */
-               /* GPIO stuff moved to __saa7134_ir_start() */
-               break;
-       case SAA7134_BOARD_KWORLD_TERMINATOR:
-               ir_codes     = RC_MAP_PIXELVIEW;
-               mask_keycode = 0x00001f;
-               mask_keyup   = 0x000060;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_MANLI_MTV001:
-       case SAA7134_BOARD_MANLI_MTV002:
-               ir_codes     = RC_MAP_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:
-       case SAA7134_BOARD_BEHOLD_403FM:
-       case SAA7134_BOARD_BEHOLD_405:
-       case SAA7134_BOARD_BEHOLD_405FM:
-       case SAA7134_BOARD_BEHOLD_407:
-       case SAA7134_BOARD_BEHOLD_407FM:
-       case SAA7134_BOARD_BEHOLD_409:
-       case SAA7134_BOARD_BEHOLD_505FM:
-       case SAA7134_BOARD_BEHOLD_505RDS_MK5:
-       case SAA7134_BOARD_BEHOLD_505RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_507_9FM:
-       case SAA7134_BOARD_BEHOLD_507RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_507RDS_MK5:
-               ir_codes     = RC_MAP_MANLI;
-               mask_keycode = 0x003f00;
-               mask_keyup   = 0x004000;
-               polling      = 50; /* ms */
-               break;
-       case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
-               ir_codes     = RC_MAP_BEHOLD_COLUMBUS;
-               mask_keycode = 0x003f00;
-               mask_keyup   = 0x004000;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
-               ir_codes     = RC_MAP_PCTV_SEDNA;
-               mask_keycode = 0x001f00;
-               mask_keyup   = 0x004000;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_GOTVIEW_7135:
-               ir_codes     = RC_MAP_GOTVIEW7135;
-               mask_keycode = 0x0003CC;
-               mask_keydown = 0x000010;
-               polling      = 5; /* ms */
-               /* GPIO stuff moved to __saa7134_ir_start() */
-               break;
-       case SAA7134_BOARD_VIDEOMATE_TV_PVR:
-       case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
-       case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
-               ir_codes     = RC_MAP_VIDEOMATE_TV_PVR;
-               mask_keycode = 0x00003F;
-               mask_keyup   = 0x400000;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_PROTEUS_2309:
-               ir_codes     = RC_MAP_PROTEUS_2309;
-               mask_keycode = 0x00007F;
-               mask_keyup   = 0x000080;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-       case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-               ir_codes     = RC_MAP_VIDEOMATE_TV_PVR;
-               mask_keycode = 0x003F00;
-               mask_keyup   = 0x040000;
-               break;
-       case SAA7134_BOARD_FLYDVBS_LR300:
-       case SAA7134_BOARD_FLYDVBT_LR301:
-       case SAA7134_BOARD_FLYDVBTDUO:
-               ir_codes     = RC_MAP_FLYDVB;
-               mask_keycode = 0x0001F00;
-               mask_keydown = 0x0040000;
-               break;
-       case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-       case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
-       case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
-               ir_codes     = RC_MAP_ASUS_PC39;
-               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
-               mask_keyup   = 0x0040000;
-               mask_keycode = 0xffff;
-               raw_decode   = true;
-               break;
-       case SAA7134_BOARD_ASUSTeK_PS3_100:
-               ir_codes     = RC_MAP_ASUS_PS3_100;
-               mask_keydown = 0x0040000;
-               mask_keyup   = 0x0040000;
-               mask_keycode = 0xffff;
-               raw_decode   = true;
-               break;
-       case SAA7134_BOARD_ENCORE_ENLTV:
-       case SAA7134_BOARD_ENCORE_ENLTV_FM:
-               ir_codes     = RC_MAP_ENCORE_ENLTV;
-               mask_keycode = 0x00007f;
-               mask_keyup   = 0x040000;
-               polling      = 50; // ms
-               break;
-       case SAA7134_BOARD_ENCORE_ENLTV_FM53:
-       case SAA7134_BOARD_ENCORE_ENLTV_FM3:
-               ir_codes     = RC_MAP_ENCORE_ENLTV_FM53;
-               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
-               mask_keyup   = 0x0040000;
-               mask_keycode = 0xffff;
-               raw_decode   = true;
-               break;
-       case SAA7134_BOARD_10MOONSTVMASTER3:
-               ir_codes     = RC_MAP_ENCORE_ENLTV;
-               mask_keycode = 0x5f80000;
-               mask_keyup   = 0x8000000;
-               polling      = 50; //ms
-               break;
-       case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
-               ir_codes     = RC_MAP_GENIUS_TVGO_A11MCE;
-               mask_keycode = 0xff;
-               mask_keydown = 0xf00000;
-               polling = 50; /* ms */
-               break;
-       case SAA7134_BOARD_REAL_ANGEL_220:
-               ir_codes     = RC_MAP_REAL_AUDIO_220_32_KEYS;
-               mask_keycode = 0x3f00;
-               mask_keyup   = 0x4000;
-               polling = 50; /* ms */
-               break;
-       case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
-               ir_codes     = RC_MAP_KWORLD_PLUS_TV_ANALOG;
-               mask_keycode = 0x7f;
-               polling = 40; /* ms */
-               break;
-       case SAA7134_BOARD_VIDEOMATE_S350:
-               ir_codes     = RC_MAP_VIDEOMATE_S350;
-               mask_keycode = 0x003f00;
-               mask_keydown = 0x040000;
-               break;
-       case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
-               ir_codes     = RC_MAP_WINFAST;
-               mask_keycode = 0x5f00;
-               mask_keyup   = 0x020000;
-               polling      = 50; /* ms */
-               break;
-       case SAA7134_BOARD_VIDEOMATE_M1F:
-               ir_codes     = RC_MAP_VIDEOMATE_K100;
-               mask_keycode = 0x0ff00;
-               mask_keyup   = 0x040000;
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-               ir_codes     = RC_MAP_HAUPPAUGE;
-               mask_keydown = 0x0040000;       /* Enable GPIO18 line on both edges */
-               mask_keyup   = 0x0040000;
-               mask_keycode = 0xffff;
-               raw_decode   = true;
-               break;
-       }
-       if (NULL == ir_codes) {
-               printk("%s: Oops: IR config error [card=%d]\n",
-                      dev->name, dev->board);
-               return -ENODEV;
-       }
-
-       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-       rc = rc_allocate_device();
-       if (!ir || !rc) {
-               err = -ENOMEM;
-               goto err_out_free;
-       }
-
-       ir->dev = rc;
-       dev->remote = ir;
-
-       /* init hardware-specific stuff */
-       ir->mask_keycode = mask_keycode;
-       ir->mask_keydown = mask_keydown;
-       ir->mask_keyup   = mask_keyup;
-       ir->polling      = polling;
-       ir->raw_decode   = raw_decode;
-
-       /* init input device */
-       snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
-                saa7134_boards[dev->board].name);
-       snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
-                pci_name(dev->pci));
-
-       rc->priv = dev;
-       rc->open = saa7134_ir_open;
-       rc->close = saa7134_ir_close;
-       if (raw_decode)
-               rc->driver_type = RC_DRIVER_IR_RAW;
-
-       rc->input_name = ir->name;
-       rc->input_phys = ir->phys;
-       rc->input_id.bustype = BUS_PCI;
-       rc->input_id.version = 1;
-       if (dev->pci->subsystem_vendor) {
-               rc->input_id.vendor  = dev->pci->subsystem_vendor;
-               rc->input_id.product = dev->pci->subsystem_device;
-       } else {
-               rc->input_id.vendor  = dev->pci->vendor;
-               rc->input_id.product = dev->pci->device;
-       }
-       rc->dev.parent = &dev->pci->dev;
-       rc->map_name = ir_codes;
-       rc->driver_name = MODULE_NAME;
-
-       err = rc_register_device(rc);
-       if (err)
-               goto err_out_free;
-
-       return 0;
-
-err_out_free:
-       rc_free_device(rc);
-       dev->remote = NULL;
-       kfree(ir);
-       return err;
-}
-
-void saa7134_input_fini(struct saa7134_dev *dev)
-{
-       if (NULL == dev->remote)
-               return;
-
-       saa7134_ir_stop(dev);
-       rc_unregister_device(dev->remote->dev);
-       kfree(dev->remote);
-       dev->remote = NULL;
-}
-
-void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
-{
-       struct i2c_board_info info;
-       struct i2c_msg msg_msi = {
-               .addr = 0x50,
-               .flags = I2C_M_RD,
-               .len = 0,
-               .buf = NULL,
-       };
-       int rc;
-
-       if (disable_ir) {
-               dprintk("IR has been disabled, not probing for i2c remote\n");
-               return;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       memset(&dev->init_data, 0, sizeof(dev->init_data));
-       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-
-       switch (dev->board) {
-       case SAA7134_BOARD_PINNACLE_PCTV_110i:
-       case SAA7134_BOARD_PINNACLE_PCTV_310i:
-               dev->init_data.name = "Pinnacle PCTV";
-               if (pinnacle_remote == 0) {
-                       dev->init_data.get_key = get_key_pinnacle_color;
-                       dev->init_data.ir_codes = RC_MAP_PINNACLE_COLOR;
-                       info.addr = 0x47;
-               } else {
-                       dev->init_data.get_key = get_key_pinnacle_grey;
-                       dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
-                       info.addr = 0x47;
-               }
-               break;
-       case SAA7134_BOARD_UPMOST_PURPLE_TV:
-               dev->init_data.name = "Purple TV";
-               dev->init_data.get_key = get_key_purpletv;
-               dev->init_data.ir_codes = RC_MAP_PURPLETV;
-               info.addr = 0x7a;
-               break;
-       case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
-               dev->init_data.name = "MSI TV@nywhere Plus";
-               dev->init_data.get_key = get_key_msi_tvanywhere_plus;
-               dev->init_data.ir_codes = RC_MAP_MSI_TVANYWHERE_PLUS;
-               /*
-                * MSI TV@nyware Plus requires more frequent polling
-                * otherwise it will miss some keypresses
-                */
-               dev->init_data.polling_interval = 50;
-               info.addr = 0x30;
-               /* MSI TV@nywhere Plus controller doesn't seem to
-                  respond to probes unless we read something from
-                  an existing device. Weird...
-                  REVISIT: might no longer be needed */
-               rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
-               dprintk("probe 0x%02x @ %s: %s\n",
-                       msg_msi.addr, dev->i2c_adap.name,
-                       (1 == rc) ? "yes" : "no");
-               break;
-       case SAA7134_BOARD_KWORLD_PC150U:
-               /* copied and modified from MSI TV@nywhere Plus */
-               dev->init_data.name = "Kworld PC150-U";
-               dev->init_data.get_key = get_key_kworld_pc150u;
-               dev->init_data.ir_codes = RC_MAP_KWORLD_PC150U;
-               info.addr = 0x30;
-               /* MSI TV@nywhere Plus controller doesn't seem to
-                  respond to probes unless we read something from
-                  an existing device. Weird...
-                  REVISIT: might no longer be needed */
-               rc = i2c_transfer(&dev->i2c_adap, &msg_msi, 1);
-               dprintk("probe 0x%02x @ %s: %s\n",
-                       msg_msi.addr, dev->i2c_adap.name,
-                       (1 == rc) ? "yes" : "no");
-               break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110:
-               dev->init_data.name = "HVR 1110";
-               dev->init_data.get_key = get_key_hvr1110;
-               dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-               info.addr = 0x71;
-               break;
-       case SAA7134_BOARD_BEHOLD_607FM_MK3:
-       case SAA7134_BOARD_BEHOLD_607FM_MK5:
-       case SAA7134_BOARD_BEHOLD_609FM_MK3:
-       case SAA7134_BOARD_BEHOLD_609FM_MK5:
-       case SAA7134_BOARD_BEHOLD_607RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_607RDS_MK5:
-       case SAA7134_BOARD_BEHOLD_609RDS_MK3:
-       case SAA7134_BOARD_BEHOLD_609RDS_MK5:
-       case SAA7134_BOARD_BEHOLD_M6:
-       case SAA7134_BOARD_BEHOLD_M63:
-       case SAA7134_BOARD_BEHOLD_M6_EXTRA:
-       case SAA7134_BOARD_BEHOLD_H6:
-       case SAA7134_BOARD_BEHOLD_X7:
-       case SAA7134_BOARD_BEHOLD_H7:
-       case SAA7134_BOARD_BEHOLD_A7:
-               dev->init_data.name = "BeholdTV";
-               dev->init_data.get_key = get_key_beholdm6xx;
-               dev->init_data.ir_codes = RC_MAP_BEHOLD;
-               dev->init_data.type = RC_TYPE_NEC;
-               info.addr = 0x2d;
-               break;
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
-       case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
-               info.addr = 0x40;
-               break;
-       case SAA7134_BOARD_FLYDVB_TRIO:
-               dev->init_data.name = "FlyDVB Trio";
-               dev->init_data.get_key = get_key_flydvb_trio;
-               dev->init_data.ir_codes = RC_MAP_FLYDVB;
-               info.addr = 0x0b;
-               break;
-       default:
-               dprintk("No I2C IR support for board %x\n", dev->board);
-               return;
-       }
-
-       if (dev->init_data.name)
-               info.platform_data = &dev->init_data;
-       i2c_new_device(&dev->i2c_adap, &info);
-}
-
-static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
-{
-       struct saa7134_card_ir *ir = dev->remote;
-       unsigned long timeout;
-       int space;
-
-       /* Generate initial event */
-       saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-       saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
-       space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
-       ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE);
-
-       /*
-        * Wait 15 ms from the start of the first IR event before processing
-        * the event. This time is enough for NEC protocol. May need adjustments
-        * to work with other protocols.
-        */
-       smp_mb();
-
-       if (!timer_pending(&ir->timer)) {
-               timeout = jiffies + msecs_to_jiffies(15);
-               mod_timer(&ir->timer, timeout);
-       }
-
-       return 1;
-}
diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h
deleted file mode 100644 (file)
index e7e0af1..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- *
- * philips saa7134 registers
- */
-
-/* ------------------------------------------------------------------ */
-/*
- * PCI ID's
- */
-#ifndef PCI_DEVICE_ID_PHILIPS_SAA7130
-# define PCI_DEVICE_ID_PHILIPS_SAA7130 0x7130
-#endif
-#ifndef PCI_DEVICE_ID_PHILIPS_SAA7133
-# define PCI_DEVICE_ID_PHILIPS_SAA7133 0x7133
-#endif
-#ifndef PCI_DEVICE_ID_PHILIPS_SAA7134
-# define PCI_DEVICE_ID_PHILIPS_SAA7134 0x7134
-#endif
-#ifndef PCI_DEVICE_ID_PHILIPS_SAA7135
-# define PCI_DEVICE_ID_PHILIPS_SAA7135 0x7135
-#endif
-
-/* ------------------------------------------------------------------ */
-/*
- *  registers -- 32 bit
- */
-
-/* DMA channels, n = 0 ... 6 */
-#define SAA7134_RS_BA1(n)                      ((0x200 >> 2) + 4*n)
-#define SAA7134_RS_BA2(n)                      ((0x204 >> 2) + 4*n)
-#define SAA7134_RS_PITCH(n)                    ((0x208 >> 2) + 4*n)
-#define SAA7134_RS_CONTROL(n)                  ((0x20c >> 2) + 4*n)
-#define   SAA7134_RS_CONTROL_WSWAP             (0x01 << 25)
-#define   SAA7134_RS_CONTROL_BSWAP             (0x01 << 24)
-#define   SAA7134_RS_CONTROL_BURST_2           (0x01 << 21)
-#define   SAA7134_RS_CONTROL_BURST_4           (0x02 << 21)
-#define   SAA7134_RS_CONTROL_BURST_8           (0x03 << 21)
-#define   SAA7134_RS_CONTROL_BURST_16          (0x04 << 21)
-#define   SAA7134_RS_CONTROL_BURST_32          (0x05 << 21)
-#define   SAA7134_RS_CONTROL_BURST_64          (0x06 << 21)
-#define   SAA7134_RS_CONTROL_BURST_MAX         (0x07 << 21)
-#define   SAA7134_RS_CONTROL_ME                        (0x01 << 20)
-#define SAA7134_FIFO_SIZE                       (0x2a0 >> 2)
-#define SAA7134_THRESHOULD                      (0x2a4 >> 2)
-
-#define SAA7133_NUM_SAMPLES                    (0x588 >> 2)
-#define SAA7133_AUDIO_CHANNEL                  (0x58c >> 2)
-#define SAA7133_AUDIO_FORMAT                   (0x58f >> 2)
-#define SAA7133_DIGITAL_OUTPUT_SEL1            (0x46c >> 2)
-#define SAA7133_DIGITAL_OUTPUT_SEL2            (0x470 >> 2)
-#define SAA7133_DIGITAL_INPUT_XBAR1            (0x464 >> 2)
-#define SAA7133_ANALOG_IO_SELECT                (0x594 >> 2)
-
-/* main control */
-#define SAA7134_MAIN_CTRL                       (0x2a8 >> 2)
-#define   SAA7134_MAIN_CTRL_VPLLE              (1 << 15)
-#define   SAA7134_MAIN_CTRL_APLLE              (1 << 14)
-#define   SAA7134_MAIN_CTRL_EXOSC              (1 << 13)
-#define   SAA7134_MAIN_CTRL_EVFE1              (1 << 12)
-#define   SAA7134_MAIN_CTRL_EVFE2              (1 << 11)
-#define   SAA7134_MAIN_CTRL_ESFE               (1 << 10)
-#define   SAA7134_MAIN_CTRL_EBADC              (1 << 9)
-#define   SAA7134_MAIN_CTRL_EBDAC              (1 << 8)
-#define   SAA7134_MAIN_CTRL_TE6                        (1 << 6)
-#define   SAA7134_MAIN_CTRL_TE5                        (1 << 5)
-#define   SAA7134_MAIN_CTRL_TE4                        (1 << 4)
-#define   SAA7134_MAIN_CTRL_TE3                        (1 << 3)
-#define   SAA7134_MAIN_CTRL_TE2                        (1 << 2)
-#define   SAA7134_MAIN_CTRL_TE1                        (1 << 1)
-#define   SAA7134_MAIN_CTRL_TE0                        (1 << 0)
-
-/* DMA status */
-#define SAA7134_DMA_STATUS                      (0x2ac >> 2)
-
-/* audio / video status */
-#define SAA7134_AV_STATUS                      (0x2c0 >> 2)
-#define   SAA7134_AV_STATUS_STEREO             (1 << 17)
-#define   SAA7134_AV_STATUS_DUAL                (1 << 16)
-#define   SAA7134_AV_STATUS_PILOT               (1 << 15)
-#define   SAA7134_AV_STATUS_SMB                 (1 << 14)
-#define   SAA7134_AV_STATUS_DMB                 (1 << 13)
-#define   SAA7134_AV_STATUS_VDSP                (1 << 12)
-#define   SAA7134_AV_STATUS_IIC_STATUS          (3 << 10)
-#define   SAA7134_AV_STATUS_MVM                 (7 << 7)
-#define   SAA7134_AV_STATUS_FIDT                (1 << 6)
-#define   SAA7134_AV_STATUS_INTL                (1 << 5)
-#define   SAA7134_AV_STATUS_RDCAP               (1 << 4)
-#define   SAA7134_AV_STATUS_PWR_ON              (1 << 3)
-#define   SAA7134_AV_STATUS_LOAD_ERR            (1 << 2)
-#define   SAA7134_AV_STATUS_TRIG_ERR            (1 << 1)
-#define   SAA7134_AV_STATUS_CONF_ERR            (1 << 0)
-
-/* interrupt */
-#define SAA7134_IRQ1                            (0x2c4 >> 2)
-#define   SAA7134_IRQ1_INTE_RA3_1               (1 << 25)
-#define   SAA7134_IRQ1_INTE_RA3_0               (1 << 24)
-#define   SAA7134_IRQ1_INTE_RA2_3               (1 << 19)
-#define   SAA7134_IRQ1_INTE_RA2_2               (1 << 18)
-#define   SAA7134_IRQ1_INTE_RA2_1               (1 << 17)
-#define   SAA7134_IRQ1_INTE_RA2_0               (1 << 16)
-#define   SAA7134_IRQ1_INTE_RA1_3               (1 << 11)
-#define   SAA7134_IRQ1_INTE_RA1_2               (1 << 10)
-#define   SAA7134_IRQ1_INTE_RA1_1               (1 <<  9)
-#define   SAA7134_IRQ1_INTE_RA1_0               (1 <<  8)
-#define   SAA7134_IRQ1_INTE_RA0_7               (1 <<  7)
-#define   SAA7134_IRQ1_INTE_RA0_6               (1 <<  6)
-#define   SAA7134_IRQ1_INTE_RA0_5               (1 <<  5)
-#define   SAA7134_IRQ1_INTE_RA0_4               (1 <<  4)
-#define   SAA7134_IRQ1_INTE_RA0_3               (1 <<  3)
-#define   SAA7134_IRQ1_INTE_RA0_2               (1 <<  2)
-#define   SAA7134_IRQ1_INTE_RA0_1               (1 <<  1)
-#define   SAA7134_IRQ1_INTE_RA0_0               (1 <<  0)
-
-#define SAA7134_IRQ2                            (0x2c8 >> 2)
-#define   SAA7134_IRQ2_INTE_GPIO23_N             (1 << 17)     /* negative edge */
-#define   SAA7134_IRQ2_INTE_GPIO23_P             (1 << 16)     /* positive edge */
-#define   SAA7134_IRQ2_INTE_GPIO22_N             (1 << 15)     /* negative edge */
-#define   SAA7134_IRQ2_INTE_GPIO22_P             (1 << 14)     /* positive edge */
-#define   SAA7134_IRQ2_INTE_GPIO18_N             (1 << 13)     /* negative edge */
-#define   SAA7134_IRQ2_INTE_GPIO18_P             (1 << 12)     /* positive edge */
-#define   SAA7134_IRQ2_INTE_GPIO16_N             (1 << 11)     /* negative edge */
-#define   SAA7134_IRQ2_INTE_GPIO16_P             (1 << 10)     /* positive edge */
-#define   SAA7134_IRQ2_INTE_SC2                 (1 <<  9)
-#define   SAA7134_IRQ2_INTE_SC1                 (1 <<  8)
-#define   SAA7134_IRQ2_INTE_SC0                 (1 <<  7)
-#define   SAA7134_IRQ2_INTE_DEC4                (1 <<  6)
-#define   SAA7134_IRQ2_INTE_DEC3                (1 <<  5)
-#define   SAA7134_IRQ2_INTE_DEC2                (1 <<  4)
-#define   SAA7134_IRQ2_INTE_DEC1                (1 <<  3)
-#define   SAA7134_IRQ2_INTE_DEC0                (1 <<  2)
-#define   SAA7134_IRQ2_INTE_PE                  (1 <<  1)
-#define   SAA7134_IRQ2_INTE_AR                  (1 <<  0)
-
-#define SAA7134_IRQ_REPORT                      (0x2cc >> 2)
-#define   SAA7134_IRQ_REPORT_GPIO23             (1 << 17)
-#define   SAA7134_IRQ_REPORT_GPIO22             (1 << 16)
-#define   SAA7134_IRQ_REPORT_GPIO18             (1 << 15)
-#define   SAA7134_IRQ_REPORT_GPIO16             (1 << 14)
-#define   SAA7134_IRQ_REPORT_LOAD_ERR           (1 << 13)
-#define   SAA7134_IRQ_REPORT_CONF_ERR           (1 << 12)
-#define   SAA7134_IRQ_REPORT_TRIG_ERR           (1 << 11)
-#define   SAA7134_IRQ_REPORT_MMC                (1 << 10)
-#define   SAA7134_IRQ_REPORT_FIDT               (1 <<  9)
-#define   SAA7134_IRQ_REPORT_INTL               (1 <<  8)
-#define   SAA7134_IRQ_REPORT_RDCAP              (1 <<  7)
-#define   SAA7134_IRQ_REPORT_PWR_ON             (1 <<  6)
-#define   SAA7134_IRQ_REPORT_PE                 (1 <<  5)
-#define   SAA7134_IRQ_REPORT_AR                 (1 <<  4)
-#define   SAA7134_IRQ_REPORT_DONE_RA3           (1 <<  3)
-#define   SAA7134_IRQ_REPORT_DONE_RA2           (1 <<  2)
-#define   SAA7134_IRQ_REPORT_DONE_RA1           (1 <<  1)
-#define   SAA7134_IRQ_REPORT_DONE_RA0           (1 <<  0)
-#define SAA7134_IRQ_STATUS                      (0x2d0 >> 2)
-
-
-/* ------------------------------------------------------------------ */
-/*
- *  registers -- 8 bit
- */
-
-/* video decoder */
-#define SAA7134_INCR_DELAY                      0x101
-#define SAA7134_ANALOG_IN_CTRL1                 0x102
-#define SAA7134_ANALOG_IN_CTRL2                 0x103
-#define SAA7134_ANALOG_IN_CTRL3                 0x104
-#define SAA7134_ANALOG_IN_CTRL4                 0x105
-#define SAA7134_HSYNC_START                     0x106
-#define SAA7134_HSYNC_STOP                      0x107
-#define SAA7134_SYNC_CTRL                       0x108
-#define SAA7134_LUMA_CTRL                       0x109
-#define SAA7134_DEC_LUMA_BRIGHT                 0x10a
-#define SAA7134_DEC_LUMA_CONTRAST               0x10b
-#define SAA7134_DEC_CHROMA_SATURATION           0x10c
-#define SAA7134_DEC_CHROMA_HUE                  0x10d
-#define SAA7134_CHROMA_CTRL1                    0x10e
-#define SAA7134_CHROMA_GAIN                     0x10f
-#define SAA7134_CHROMA_CTRL2                    0x110
-#define SAA7134_MODE_DELAY_CTRL                 0x111
-
-#define SAA7134_ANALOG_ADC                      0x114
-#define SAA7134_VGATE_START                     0x115
-#define SAA7134_VGATE_STOP                      0x116
-#define SAA7134_MISC_VGATE_MSB                  0x117
-#define SAA7134_RAW_DATA_GAIN                   0x118
-#define SAA7134_RAW_DATA_OFFSET                 0x119
-#define SAA7134_STATUS_VIDEO1                   0x11e
-#define SAA7134_STATUS_VIDEO2                   0x11f
-
-/* video scaler */
-#define SAA7134_SOURCE_TIMING1                  0x000
-#define SAA7134_SOURCE_TIMING2                  0x001
-#define SAA7134_REGION_ENABLE                   0x004
-#define SAA7134_SCALER_STATUS0                  0x006
-#define SAA7134_SCALER_STATUS1                  0x007
-#define SAA7134_START_GREEN                     0x00c
-#define SAA7134_START_BLUE                      0x00d
-#define SAA7134_START_RED                       0x00e
-#define SAA7134_GREEN_PATH(x)                   (0x010 +x)
-#define SAA7134_BLUE_PATH(x)                    (0x020 +x)
-#define SAA7134_RED_PATH(x)                     (0x030 +x)
-
-#define TASK_A                                  0x040
-#define TASK_B                                  0x080
-#define SAA7134_TASK_CONDITIONS(t)              (0x000 +t)
-#define SAA7134_FIELD_HANDLING(t)               (0x001 +t)
-#define SAA7134_DATA_PATH(t)                    (0x002 +t)
-#define SAA7134_VBI_H_START1(t)                 (0x004 +t)
-#define SAA7134_VBI_H_START2(t)                 (0x005 +t)
-#define SAA7134_VBI_H_STOP1(t)                  (0x006 +t)
-#define SAA7134_VBI_H_STOP2(t)                  (0x007 +t)
-#define SAA7134_VBI_V_START1(t)                 (0x008 +t)
-#define SAA7134_VBI_V_START2(t)                 (0x009 +t)
-#define SAA7134_VBI_V_STOP1(t)                  (0x00a +t)
-#define SAA7134_VBI_V_STOP2(t)                  (0x00b +t)
-#define SAA7134_VBI_H_LEN1(t)                   (0x00c +t)
-#define SAA7134_VBI_H_LEN2(t)                   (0x00d +t)
-#define SAA7134_VBI_V_LEN1(t)                   (0x00e +t)
-#define SAA7134_VBI_V_LEN2(t)                   (0x00f +t)
-
-#define SAA7134_VIDEO_H_START1(t)               (0x014 +t)
-#define SAA7134_VIDEO_H_START2(t)               (0x015 +t)
-#define SAA7134_VIDEO_H_STOP1(t)                (0x016 +t)
-#define SAA7134_VIDEO_H_STOP2(t)                (0x017 +t)
-#define SAA7134_VIDEO_V_START1(t)               (0x018 +t)
-#define SAA7134_VIDEO_V_START2(t)               (0x019 +t)
-#define SAA7134_VIDEO_V_STOP1(t)                (0x01a +t)
-#define SAA7134_VIDEO_V_STOP2(t)                (0x01b +t)
-#define SAA7134_VIDEO_PIXELS1(t)                (0x01c +t)
-#define SAA7134_VIDEO_PIXELS2(t)                (0x01d +t)
-#define SAA7134_VIDEO_LINES1(t)                 (0x01e +t)
-#define SAA7134_VIDEO_LINES2(t)                 (0x01f +t)
-
-#define SAA7134_H_PRESCALE(t)                   (0x020 +t)
-#define SAA7134_ACC_LENGTH(t)                   (0x021 +t)
-#define SAA7134_LEVEL_CTRL(t)                   (0x022 +t)
-#define SAA7134_FIR_PREFILTER_CTRL(t)           (0x023 +t)
-#define SAA7134_LUMA_BRIGHT(t)                  (0x024 +t)
-#define SAA7134_LUMA_CONTRAST(t)                (0x025 +t)
-#define SAA7134_CHROMA_SATURATION(t)            (0x026 +t)
-#define SAA7134_VBI_H_SCALE_INC1(t)             (0x028 +t)
-#define SAA7134_VBI_H_SCALE_INC2(t)             (0x029 +t)
-#define SAA7134_VBI_PHASE_OFFSET_LUMA(t)        (0x02a +t)
-#define SAA7134_VBI_PHASE_OFFSET_CHROMA(t)      (0x02b +t)
-#define SAA7134_H_SCALE_INC1(t)                 (0x02c +t)
-#define SAA7134_H_SCALE_INC2(t)                 (0x02d +t)
-#define SAA7134_H_PHASE_OFF_LUMA(t)             (0x02e +t)
-#define SAA7134_H_PHASE_OFF_CHROMA(t)           (0x02f +t)
-#define SAA7134_V_SCALE_RATIO1(t)               (0x030 +t)
-#define SAA7134_V_SCALE_RATIO2(t)               (0x031 +t)
-#define SAA7134_V_FILTER(t)                     (0x032 +t)
-#define SAA7134_V_PHASE_OFFSET0(t)              (0x034 +t)
-#define SAA7134_V_PHASE_OFFSET1(t)              (0x035 +t)
-#define SAA7134_V_PHASE_OFFSET2(t)              (0x036 +t)
-#define SAA7134_V_PHASE_OFFSET3(t)              (0x037 +t)
-
-/* clipping & dma */
-#define SAA7134_OFMT_VIDEO_A                    0x300
-#define SAA7134_OFMT_DATA_A                     0x301
-#define SAA7134_OFMT_VIDEO_B                    0x302
-#define SAA7134_OFMT_DATA_B                     0x303
-#define SAA7134_ALPHA_NOCLIP                    0x304
-#define SAA7134_ALPHA_CLIP                      0x305
-#define SAA7134_UV_PIXEL                        0x308
-#define SAA7134_CLIP_RED                        0x309
-#define SAA7134_CLIP_GREEN                      0x30a
-#define SAA7134_CLIP_BLUE                       0x30b
-
-/* i2c bus */
-#define SAA7134_I2C_ATTR_STATUS                 0x180
-#define SAA7134_I2C_DATA                        0x181
-#define SAA7134_I2C_CLOCK_SELECT                0x182
-#define SAA7134_I2C_TIMER                       0x183
-
-/* audio */
-#define SAA7134_NICAM_ADD_DATA1                 0x140
-#define SAA7134_NICAM_ADD_DATA2                 0x141
-#define SAA7134_NICAM_STATUS                    0x142
-#define SAA7134_AUDIO_STATUS                    0x143
-#define SAA7134_NICAM_ERROR_COUNT               0x144
-#define SAA7134_IDENT_SIF                       0x145
-#define SAA7134_LEVEL_READOUT1                  0x146
-#define SAA7134_LEVEL_READOUT2                  0x147
-#define SAA7134_NICAM_ERROR_LOW                 0x148
-#define SAA7134_NICAM_ERROR_HIGH                0x149
-#define SAA7134_DCXO_IDENT_CTRL                 0x14a
-#define SAA7134_DEMODULATOR                     0x14b
-#define SAA7134_AGC_GAIN_SELECT                 0x14c
-#define SAA7134_CARRIER1_FREQ0                  0x150
-#define SAA7134_CARRIER1_FREQ1                  0x151
-#define SAA7134_CARRIER1_FREQ2                  0x152
-#define SAA7134_CARRIER2_FREQ0                  0x154
-#define SAA7134_CARRIER2_FREQ1                  0x155
-#define SAA7134_CARRIER2_FREQ2                  0x156
-#define SAA7134_NUM_SAMPLES0                    0x158
-#define SAA7134_NUM_SAMPLES1                    0x159
-#define SAA7134_NUM_SAMPLES2                    0x15a
-#define SAA7134_AUDIO_FORMAT_CTRL               0x15b
-#define SAA7134_MONITOR_SELECT                  0x160
-#define SAA7134_FM_DEEMPHASIS                   0x161
-#define SAA7134_FM_DEMATRIX                     0x162
-#define SAA7134_CHANNEL1_LEVEL                  0x163
-#define SAA7134_CHANNEL2_LEVEL                  0x164
-#define SAA7134_NICAM_CONFIG                    0x165
-#define SAA7134_NICAM_LEVEL_ADJUST              0x166
-#define SAA7134_STEREO_DAC_OUTPUT_SELECT        0x167
-#define SAA7134_I2S_OUTPUT_FORMAT               0x168
-#define SAA7134_I2S_OUTPUT_SELECT               0x169
-#define SAA7134_I2S_OUTPUT_LEVEL                0x16a
-#define SAA7134_DSP_OUTPUT_SELECT               0x16b
-#define SAA7134_AUDIO_MUTE_CTRL                 0x16c
-#define SAA7134_SIF_SAMPLE_FREQ                 0x16d
-#define SAA7134_ANALOG_IO_SELECT                0x16e
-#define SAA7134_AUDIO_CLOCK0                    0x170
-#define SAA7134_AUDIO_CLOCK1                    0x171
-#define SAA7134_AUDIO_CLOCK2                    0x172
-#define SAA7134_AUDIO_PLL_CTRL                  0x173
-#define SAA7134_AUDIO_CLOCKS_PER_FIELD0         0x174
-#define SAA7134_AUDIO_CLOCKS_PER_FIELD1         0x175
-#define SAA7134_AUDIO_CLOCKS_PER_FIELD2         0x176
-
-/* video port output */
-#define SAA7134_VIDEO_PORT_CTRL0                0x190
-#define SAA7134_VIDEO_PORT_CTRL1                0x191
-#define SAA7134_VIDEO_PORT_CTRL2                0x192
-#define SAA7134_VIDEO_PORT_CTRL3                0x193
-#define SAA7134_VIDEO_PORT_CTRL4                0x194
-#define SAA7134_VIDEO_PORT_CTRL5                0x195
-#define SAA7134_VIDEO_PORT_CTRL6                0x196
-#define SAA7134_VIDEO_PORT_CTRL7                0x197
-#define SAA7134_VIDEO_PORT_CTRL8                0x198
-
-/* transport stream interface */
-#define SAA7134_TS_PARALLEL                     0x1a0
-#define SAA7134_TS_PARALLEL_SERIAL              0x1a1
-#define SAA7134_TS_SERIAL0                      0x1a2
-#define SAA7134_TS_SERIAL1                      0x1a3
-#define SAA7134_TS_DMA0                         0x1a4
-#define SAA7134_TS_DMA1                         0x1a5
-#define SAA7134_TS_DMA2                         0x1a6
-
-/* GPIO Controls */
-#define SAA7134_GPIO_GPRESCAN                   0x80
-#define SAA7134_GPIO_27_25                      0x0E
-
-#define SAA7134_GPIO_GPMODE0                    0x1B0
-#define SAA7134_GPIO_GPMODE1                    0x1B1
-#define SAA7134_GPIO_GPMODE2                    0x1B2
-#define SAA7134_GPIO_GPMODE3                    0x1B3
-#define SAA7134_GPIO_GPSTATUS0                  0x1B4
-#define SAA7134_GPIO_GPSTATUS1                  0x1B5
-#define SAA7134_GPIO_GPSTATUS2                  0x1B6
-#define SAA7134_GPIO_GPSTATUS3                  0x1B7
-
-/* I2S output */
-#define SAA7134_I2S_AUDIO_OUTPUT                0x1c0
-
-/* test modes */
-#define SAA7134_SPECIAL_MODE                    0x1d0
-#define SAA7134_PRODUCTION_TEST_MODE            0x1d1
-
-/* audio -- saa7133 + saa7135 only */
-#define SAA7135_DSP_RWSTATE                     0x580
-#define SAA7135_DSP_RWSTATE_ERR                 (1 << 3)
-#define SAA7135_DSP_RWSTATE_IDA                 (1 << 2)
-#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
-
-#define SAA7133_I2S_AUDIO_CONTROL               0x591
-/* ------------------------------------------------------------------ */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c
deleted file mode 100644 (file)
index 2e3f4b4..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * video4linux video interface
- *
- * (c) 2001,02 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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int ts_debug;
-module_param(ts_debug, int, 0644);
-MODULE_PARM_DESC(ts_debug,"enable debug messages [ts]");
-
-#define dprintk(fmt, arg...)   if (ts_debug) \
-       printk(KERN_DEBUG "%s/ts: " fmt, dev->name , ## arg)
-
-/* ------------------------------------------------------------------ */
-
-static int buffer_activate(struct saa7134_dev *dev,
-                          struct saa7134_buf *buf,
-                          struct saa7134_buf *next)
-{
-
-       dprintk("buffer_activate [%p]",buf);
-       buf->vb.state = VIDEOBUF_ACTIVE;
-       buf->top_seen = 0;
-
-       if (NULL == next)
-               next = buf;
-       if (V4L2_FIELD_TOP == buf->vb.field) {
-               dprintk("- [top]     buf=%p next=%p\n",buf,next);
-               saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(buf));
-               saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(next));
-       } else {
-               dprintk("- [bottom]  buf=%p next=%p\n",buf,next);
-               saa_writel(SAA7134_RS_BA1(5),saa7134_buffer_base(next));
-               saa_writel(SAA7134_RS_BA2(5),saa7134_buffer_base(buf));
-       }
-
-       /* start DMA */
-       saa7134_set_dmabits(dev);
-
-       mod_timer(&dev->ts_q.timeout, jiffies+TS_BUFFER_TIMEOUT);
-
-       if (!dev->ts_started)
-               saa7134_ts_start(dev);
-
-       return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
-               enum v4l2_field field)
-{
-       struct saa7134_dev *dev = q->priv_data;
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-       unsigned int lines, llength, size;
-       int err;
-
-       dprintk("buffer_prepare [%p,%s]\n",buf,v4l2_field_names[field]);
-
-       llength = TS_PACKET_SIZE;
-       lines = dev->ts.nr_packets;
-
-       size = lines * llength;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       if (buf->vb.size != size) {
-               saa7134_dma_free(q,buf);
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-
-               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-               dprintk("buffer_prepare: needs_init\n");
-
-               buf->vb.width  = llength;
-               buf->vb.height = lines;
-               buf->vb.size   = size;
-               buf->pt        = &dev->ts.pt_ts;
-
-               err = videobuf_iolock(q,&buf->vb,NULL);
-               if (err)
-                       goto oops;
-               err = saa7134_pgtable_build(dev->pci,buf->pt,
-                                           dma->sglist,
-                                           dma->sglen,
-                                           saa7134_buffer_startpage(buf));
-               if (err)
-                       goto oops;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       buf->activate = buffer_activate;
-       buf->vb.field = field;
-       return 0;
-
- oops:
-       saa7134_dma_free(q,buf);
-       return err;
-}
-
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       struct saa7134_dev *dev = q->priv_data;
-
-       *size = TS_PACKET_SIZE * dev->ts.nr_packets;
-       if (0 == *count)
-               *count = dev->ts.nr_bufs;
-       *count = saa7134_buffer_count(*size,*count);
-
-       return 0;
-}
-
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct saa7134_dev *dev = q->priv_data;
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-
-       saa7134_buffer_queue(dev,&dev->ts_q,buf);
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-       struct saa7134_dev *dev = q->priv_data;
-
-       if (dev->ts_started)
-               saa7134_ts_stop(dev);
-
-       saa7134_dma_free(q,buf);
-}
-
-struct videobuf_queue_ops saa7134_ts_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-EXPORT_SYMBOL_GPL(saa7134_ts_qops);
-
-/* ----------------------------------------------------------- */
-/* exported stuff                                              */
-
-static unsigned int tsbufs = 8;
-module_param(tsbufs, int, 0444);
-MODULE_PARM_DESC(tsbufs, "number of ts buffers for read/write IO, range 2-32");
-
-static unsigned int ts_nr_packets = 64;
-module_param(ts_nr_packets, int, 0444);
-MODULE_PARM_DESC(ts_nr_packets,"size of a ts buffers (in ts packets)");
-
-int saa7134_ts_init_hw(struct saa7134_dev *dev)
-{
-       /* deactivate TS softreset */
-       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-       /* TSSOP high active, TSVAL high active, TSLOCK ignored */
-       saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
-       saa_writeb(SAA7134_TS_PARALLEL_SERIAL, (TS_PACKET_SIZE-1));
-       saa_writeb(SAA7134_TS_DMA0, ((dev->ts.nr_packets-1)&0xff));
-       saa_writeb(SAA7134_TS_DMA1, (((dev->ts.nr_packets-1)>>8)&0xff));
-       /* TSNOPIT=0, TSCOLAP=0 */
-       saa_writeb(SAA7134_TS_DMA2,
-               ((((dev->ts.nr_packets-1)>>16)&0x3f) | 0x00));
-
-       return 0;
-}
-
-int saa7134_ts_init1(struct saa7134_dev *dev)
-{
-       /* sanitycheck insmod options */
-       if (tsbufs < 2)
-               tsbufs = 2;
-       if (tsbufs > VIDEO_MAX_FRAME)
-               tsbufs = VIDEO_MAX_FRAME;
-       if (ts_nr_packets < 4)
-               ts_nr_packets = 4;
-       if (ts_nr_packets > 312)
-               ts_nr_packets = 312;
-       dev->ts.nr_bufs    = tsbufs;
-       dev->ts.nr_packets = ts_nr_packets;
-
-       INIT_LIST_HEAD(&dev->ts_q.queue);
-       init_timer(&dev->ts_q.timeout);
-       dev->ts_q.timeout.function = saa7134_buffer_timeout;
-       dev->ts_q.timeout.data     = (unsigned long)(&dev->ts_q);
-       dev->ts_q.dev              = dev;
-       dev->ts_q.need_two         = 1;
-       dev->ts_started            = 0;
-       saa7134_pgtable_alloc(dev->pci,&dev->ts.pt_ts);
-
-       /* init TS hw */
-       saa7134_ts_init_hw(dev);
-
-       return 0;
-}
-
-/* Function for stop TS */
-int saa7134_ts_stop(struct saa7134_dev *dev)
-{
-       dprintk("TS stop\n");
-
-       BUG_ON(!dev->ts_started);
-
-       /* Stop TS stream */
-       switch (saa7134_boards[dev->board].ts_type) {
-       case SAA7134_MPEG_TS_PARALLEL:
-               saa_writeb(SAA7134_TS_PARALLEL, 0x6c);
-               dev->ts_started = 0;
-               break;
-       case SAA7134_MPEG_TS_SERIAL:
-               saa_writeb(SAA7134_TS_SERIAL0, 0x40);
-               dev->ts_started = 0;
-               break;
-       }
-       return 0;
-}
-
-/* Function for start TS */
-int saa7134_ts_start(struct saa7134_dev *dev)
-{
-       dprintk("TS start\n");
-
-       BUG_ON(dev->ts_started);
-
-       /* dma: setup channel 5 (= TS) */
-       saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff);
-       saa_writeb(SAA7134_TS_DMA1,
-               ((dev->ts.nr_packets - 1) >> 8) & 0xff);
-       /* TSNOPIT=0, TSCOLAP=0 */
-       saa_writeb(SAA7134_TS_DMA2,
-               (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00);
-       saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE);
-       saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 |
-                                         SAA7134_RS_CONTROL_ME |
-                                         (dev->ts.pt_ts.dma >> 12));
-
-       /* reset hardware TS buffers */
-       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-       saa_writeb(SAA7134_TS_SERIAL1, 0x03);
-       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-       saa_writeb(SAA7134_TS_SERIAL1, 0x01);
-
-       /* TS clock non-inverted */
-       saa_writeb(SAA7134_TS_SERIAL1, 0x00);
-
-       /* Start TS stream */
-       switch (saa7134_boards[dev->board].ts_type) {
-       case SAA7134_MPEG_TS_PARALLEL:
-               saa_writeb(SAA7134_TS_SERIAL0, 0x40);
-               saa_writeb(SAA7134_TS_PARALLEL, 0xec |
-                       (saa7134_boards[dev->board].ts_force_val << 4));
-               break;
-       case SAA7134_MPEG_TS_SERIAL:
-               saa_writeb(SAA7134_TS_SERIAL0, 0xd8);
-               saa_writeb(SAA7134_TS_PARALLEL, 0x6c |
-                       (saa7134_boards[dev->board].ts_force_val << 4));
-               saa_writeb(SAA7134_TS_PARALLEL_SERIAL, 0xbc);
-               saa_writeb(SAA7134_TS_SERIAL1, 0x02);
-               break;
-       }
-
-       dev->ts_started = 1;
-
-       return 0;
-}
-
-int saa7134_ts_fini(struct saa7134_dev *dev)
-{
-       saa7134_pgtable_free(dev->pci,&dev->ts.pt_ts);
-       return 0;
-}
-
-void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status)
-{
-       enum v4l2_field field;
-
-       spin_lock(&dev->slock);
-       if (dev->ts_q.curr) {
-               field = dev->ts_q.curr->vb.field;
-               if (field == V4L2_FIELD_TOP) {
-                       if ((status & 0x100000) != 0x000000)
-                               goto done;
-               } else {
-                       if ((status & 0x100000) != 0x100000)
-                               goto done;
-               }
-               saa7134_buffer_finish(dev,&dev->ts_q,VIDEOBUF_DONE);
-       }
-       saa7134_buffer_next(dev,&dev->ts_q);
-
- done:
-       spin_unlock(&dev->slock);
-}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
deleted file mode 100644 (file)
index b7a99be..0000000
+++ /dev/null
@@ -1,1087 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * tv audio decoder (fm stereo, nicam, ...)
- *
- * (c) 2001-03 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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/delay.h>
-#include <linux/freezer.h>
-#include <asm/div64.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
-/* ------------------------------------------------------------------ */
-
-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;
-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;
-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])");
-
-#define dprintk(fmt, arg...)   if (audio_debug) \
-       printk(KERN_DEBUG "%s/audio: " fmt, dev->name , ## arg)
-#define d2printk(fmt, arg...)  if (audio_debug > 1) \
-       printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg)
-
-#define print_regb(reg) printk("%s:   reg 0x%03x [%-16s]: 0x%02x\n", \
-               dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg)))
-
-/* msecs */
-#define SCAN_INITIAL_DELAY     1000
-#define SCAN_SAMPLE_DELAY       200
-#define SCAN_SUBCARRIER_DELAY  2000
-
-/* ------------------------------------------------------------------ */
-/* saa7134 code                                                       */
-
-static struct mainscan {
-       char         *name;
-       v4l2_std_id  std;
-       int          carr;
-} mainscan[] = {
-       {
-               .name = "MN",
-               .std  = V4L2_STD_MN,
-               .carr = 4500,
-       },{
-               .name = "BGH",
-               .std  = V4L2_STD_B | V4L2_STD_GH,
-               .carr = 5500,
-       },{
-               .name = "I",
-               .std  = V4L2_STD_PAL_I,
-               .carr = 6000,
-       },{
-               .name = "DKL",
-               .std  = V4L2_STD_DK | V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC,
-               .carr = 6500,
-       }
-};
-
-static struct saa7134_tvaudio tvaudio[] = {
-       {
-               .name          = "PAL-B/G FM-stereo",
-               .std           = V4L2_STD_PAL_BG,
-               .mode          = TVAUDIO_FM_BG_STEREO,
-               .carr1         = 5500,
-               .carr2         = 5742,
-       },{
-               .name          = "PAL-D/K1 FM-stereo",
-               .std           = V4L2_STD_PAL_DK,
-               .carr1         = 6500,
-               .carr2         = 6258,
-               .mode          = TVAUDIO_FM_BG_STEREO,
-       },{
-               .name          = "PAL-D/K2 FM-stereo",
-               .std           = V4L2_STD_PAL_DK,
-               .carr1         = 6500,
-               .carr2         = 6742,
-               .mode          = TVAUDIO_FM_BG_STEREO,
-       },{
-               .name          = "PAL-D/K3 FM-stereo",
-               .std           = V4L2_STD_PAL_DK,
-               .carr1         = 6500,
-               .carr2         = 5742,
-               .mode          = TVAUDIO_FM_BG_STEREO,
-       },{
-               .name          = "PAL-B/G NICAM",
-               .std           = V4L2_STD_PAL_BG,
-               .carr1         = 5500,
-               .carr2         = 5850,
-               .mode          = TVAUDIO_NICAM_FM,
-       },{
-               .name          = "PAL-I NICAM",
-               .std           = V4L2_STD_PAL_I,
-               .carr1         = 6000,
-               .carr2         = 6552,
-               .mode          = TVAUDIO_NICAM_FM,
-       },{
-               .name          = "PAL-D/K NICAM",
-               .std           = V4L2_STD_PAL_DK,
-               .carr1         = 6500,
-               .carr2         = 5850,
-               .mode          = TVAUDIO_NICAM_FM,
-       },{
-               .name          = "SECAM-L NICAM",
-               .std           = V4L2_STD_SECAM_L,
-               .carr1         = 6500,
-               .carr2         = 5850,
-               .mode          = TVAUDIO_NICAM_AM,
-       },{
-               .name          = "SECAM-D/K NICAM",
-               .std           = V4L2_STD_SECAM_DK,
-               .carr1         = 6500,
-               .carr2         = 5850,
-               .mode          = TVAUDIO_NICAM_FM,
-       },{
-               .name          = "NTSC-A2 FM-stereo",
-               .std           = V4L2_STD_NTSC,
-               .carr1         = 4500,
-               .carr2         = 4724,
-               .mode          = TVAUDIO_FM_K_STEREO,
-       },{
-               .name          = "NTSC-M",
-               .std           = V4L2_STD_NTSC,
-               .carr1         = 4500,
-               .carr2         = -1,
-               .mode          = TVAUDIO_FM_MONO,
-       }
-};
-#define TVAUDIO ARRAY_SIZE(tvaudio)
-
-/* ------------------------------------------------------------------ */
-
-static u32 tvaudio_carr2reg(u32 carrier)
-{
-       u64 a = carrier;
-
-       a <<= 24;
-       do_div(a,12288);
-       return a;
-}
-
-static void tvaudio_setcarrier(struct saa7134_dev *dev,
-                              int primary, int secondary)
-{
-       if (-1 == secondary)
-               secondary = primary;
-       saa_writel(SAA7134_CARRIER1_FREQ0 >> 2, tvaudio_carr2reg(primary));
-       saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary));
-}
-
-#define SAA7134_MUTE_MASK 0xbb
-#define SAA7134_MUTE_ANALOG 0x04
-#define SAA7134_MUTE_I2S 0x40
-
-static void mute_input_7134(struct saa7134_dev *dev)
-{
-       unsigned int mute;
-       struct saa7134_input *in;
-       int ausel=0, ics=0, ocs=0;
-       int mask;
-
-       /* look what is to do ... */
-       in   = dev->input;
-       mute = (dev->ctl_mute ||
-               (dev->automute  &&  (&card(dev).radio) != in));
-       if (card(dev).mute.name) {
-               /*
-                * 7130 - we'll mute using some unconnected audio input
-                * 7134 - we'll probably should switch external mux with gpio
-                */
-               if (mute)
-                       in = &card(dev).mute;
-       }
-
-       if (dev->hw_mute  == mute &&
-               dev->hw_input == in && !dev->insuspend) {
-               dprintk("mute/input: nothing to do [mute=%d,input=%s]\n",
-                       mute,in->name);
-               return;
-       }
-
-       dprintk("ctl_mute=%d automute=%d input=%s  =>  mute=%d input=%s\n",
-               dev->ctl_mute,dev->automute,dev->input->name,mute,in->name);
-       dev->hw_mute  = mute;
-       dev->hw_input = in;
-
-       if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device)
-               /* 7134 mute */
-               saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ?
-                                                   SAA7134_MUTE_MASK |
-                                                   SAA7134_MUTE_ANALOG |
-                                                   SAA7134_MUTE_I2S :
-                                                   SAA7134_MUTE_MASK);
-
-       /* switch internal audio mux */
-       switch (in->amux) {
-       case TV:         ausel=0xc0; ics=0x00; ocs=0x02; break;
-       case LINE1:      ausel=0x80; ics=0x00; ocs=0x00; break;
-       case LINE2:      ausel=0x80; ics=0x08; ocs=0x01; break;
-       case LINE2_LEFT: ausel=0x80; ics=0x08; ocs=0x05; break;
-       }
-       saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel);
-       saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics);
-       saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs);
-       // for oss, we need to change the clock configuration
-       if (in->amux == TV)
-               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x00);
-       else
-               saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x01);
-
-       /* switch gpio-connected external audio mux */
-       if (0 == card(dev).gpiomask)
-               return;
-
-       mask = card(dev).gpiomask;
-       saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
-       saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio);
-       saa7134_track_gpio(dev,in->name);
-}
-
-static void tvaudio_setmode(struct saa7134_dev *dev,
-                           struct saa7134_tvaudio *audio,
-                           char *note)
-{
-       int acpf, tweak = 0;
-
-       if (dev->tvnorm->id == V4L2_STD_NTSC) {
-               acpf = 0x19066;
-       } else {
-               acpf = 0x1e000;
-       }
-       if (audio_clock_tweak > -1024 && audio_clock_tweak < 1024)
-               tweak = audio_clock_tweak;
-
-       if (note)
-               dprintk("tvaudio_setmode: %s %s [%d.%03d/%d.%03d MHz] acpf=%d%+d\n",
-                       note,audio->name,
-                       audio->carr1 / 1000, audio->carr1 % 1000,
-                       audio->carr2 / 1000, audio->carr2 % 1000,
-                       acpf, tweak);
-
-       acpf += tweak;
-       saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD0, (acpf & 0x0000ff) >> 0);
-       saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD1, (acpf & 0x00ff00) >> 8);
-       saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD2, (acpf & 0x030000) >> 16);
-       tvaudio_setcarrier(dev,audio->carr1,audio->carr2);
-
-       switch (audio->mode) {
-       case TVAUDIO_FM_MONO:
-       case TVAUDIO_FM_BG_STEREO:
-               saa_writeb(SAA7134_DEMODULATOR,               0x00);
-               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x00);
-               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x22);
-               saa_writeb(SAA7134_FM_DEMATRIX,               0x80);
-               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa0);
-               break;
-       case TVAUDIO_FM_K_STEREO:
-               saa_writeb(SAA7134_DEMODULATOR,               0x00);
-               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x01);
-               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x22);
-               saa_writeb(SAA7134_FM_DEMATRIX,               0x80);
-               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa0);
-               break;
-       case TVAUDIO_NICAM_FM:
-               saa_writeb(SAA7134_DEMODULATOR,               0x10);
-               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x00);
-               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x44);
-               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa1);
-               saa_writeb(SAA7134_NICAM_CONFIG,              0x00);
-               break;
-       case TVAUDIO_NICAM_AM:
-               saa_writeb(SAA7134_DEMODULATOR,               0x12);
-               saa_writeb(SAA7134_DCXO_IDENT_CTRL,           0x00);
-               saa_writeb(SAA7134_FM_DEEMPHASIS,             0x44);
-               saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT,  0xa1);
-               saa_writeb(SAA7134_NICAM_CONFIG,              0x00);
-               break;
-       case TVAUDIO_FM_SAT_STEREO:
-               /* not implemented (yet) */
-               break;
-       }
-}
-
-static int tvaudio_sleep(struct saa7134_dev *dev, int timeout)
-{
-       if (dev->thread.scan1 == dev->thread.scan2 &&
-           !kthread_should_stop()) {
-               if (timeout < 0) {
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       schedule();
-               } else {
-                       schedule_timeout_interruptible
-                                               (msecs_to_jiffies(timeout));
-               }
-       }
-       return dev->thread.scan1 != dev->thread.scan2;
-}
-
-static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan)
-{
-       __s32 left,right,value;
-
-       if (!(dev->tvnorm->id & scan->std)) {
-               value = 0;
-               dprintk("skipping %d.%03d MHz [%4s]\n",
-                       scan->carr / 1000, scan->carr % 1000, scan->name);
-               return 0;
-       }
-
-       if (audio_debug > 1) {
-               int i;
-               dprintk("debug %d:",scan->carr);
-               for (i = -150; i <= 150; i += 30) {
-                       tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i);
-                       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-                       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-                               return -1;
-                       value = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-                       if (0 == i)
-                               printk("  #  %6d  # ",value >> 16);
-                       else
-                               printk(" %6d",value >> 16);
-               }
-               printk("\n");
-       }
-
-       tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90);
-       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-               return -1;
-       left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-       tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90);
-       saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-       if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY))
-               return -1;
-       right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2);
-
-       left >>= 16;
-       right >>= 16;
-       value = left > right ? left - right : right - left;
-       dprintk("scanning %d.%03d MHz [%4s] =>  dc is %5d [%d/%d]\n",
-               scan->carr / 1000, scan->carr % 1000,
-               scan->name, value, left, right);
-       return value;
-}
-
-
-static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio)
-{
-       __u32 idp, nicam, nicam_status;
-       int retval = -1;
-
-       switch (audio->mode) {
-       case TVAUDIO_FM_MONO:
-               return V4L2_TUNER_SUB_MONO;
-       case TVAUDIO_FM_K_STEREO:
-       case TVAUDIO_FM_BG_STEREO:
-               idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5;
-               dprintk("getstereo: fm/stereo: idp=0x%x\n",idp);
-               if (0x03 == (idp & 0x03))
-                       retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-               else if (0x05 == (idp & 0x05))
-                       retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-               else if (0x01 == (idp & 0x01))
-                       retval = V4L2_TUNER_SUB_MONO;
-               break;
-       case TVAUDIO_FM_SAT_STEREO:
-               /* not implemented (yet) */
-               break;
-       case TVAUDIO_NICAM_FM:
-       case TVAUDIO_NICAM_AM:
-               nicam = saa_readb(SAA7134_AUDIO_STATUS);
-               dprintk("getstereo: nicam=0x%x\n",nicam);
-               if (nicam & 0x1) {
-                       nicam_status = saa_readb(SAA7134_NICAM_STATUS);
-                       dprintk("getstereo: nicam_status=0x%x\n", nicam_status);
-
-                       switch (nicam_status & 0x03) {
-                           case 0x01:
-                               retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-                               break;
-                           case 0x02:
-                               retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-                               break;
-                           default:
-                               retval = V4L2_TUNER_SUB_MONO;
-                       }
-               } else {
-                       /* No nicam detected */
-               }
-               break;
-       }
-       if (retval != -1)
-               dprintk("found audio subchannels:%s%s%s%s\n",
-                       (retval & V4L2_TUNER_SUB_MONO)   ? " mono"   : "",
-                       (retval & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
-                       (retval & V4L2_TUNER_SUB_LANG1)  ? " lang1"  : "",
-                       (retval & V4L2_TUNER_SUB_LANG2)  ? " lang2"  : "");
-       return retval;
-}
-
-static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio,
-                            u32 mode)
-{
-       static char *name[] = {
-               [ V4L2_TUNER_MODE_MONO   ] = "mono",
-               [ V4L2_TUNER_MODE_STEREO ] = "stereo",
-               [ V4L2_TUNER_MODE_LANG1  ] = "lang1",
-               [ V4L2_TUNER_MODE_LANG2  ] = "lang2",
-               [ V4L2_TUNER_MODE_LANG1_LANG2  ] = "lang1+lang2",
-       };
-       static u32 fm[] = {
-               [ V4L2_TUNER_MODE_MONO   ] = 0x00,  /* ch1  */
-               [ V4L2_TUNER_MODE_STEREO ] = 0x80,  /* auto */
-               [ V4L2_TUNER_MODE_LANG1  ] = 0x00,  /* ch1  */
-               [ V4L2_TUNER_MODE_LANG2  ] = 0x01,  /* ch2  */
-               [ V4L2_TUNER_MODE_LANG1_LANG2 ] = 0x80,  /* auto */
-       };
-       u32 reg;
-
-       switch (audio->mode) {
-       case TVAUDIO_FM_MONO:
-               /* nothing to do ... */
-               break;
-       case TVAUDIO_FM_K_STEREO:
-       case TVAUDIO_FM_BG_STEREO:
-       case TVAUDIO_NICAM_AM:
-       case TVAUDIO_NICAM_FM:
-               dprintk("setstereo [fm] => %s\n",
-                       name[ mode % ARRAY_SIZE(name) ]);
-               reg = fm[ mode % ARRAY_SIZE(fm) ];
-               saa_writeb(SAA7134_FM_DEMATRIX, reg);
-               break;
-       case TVAUDIO_FM_SAT_STEREO:
-               /* Not implemented */
-               break;
-       }
-       return 0;
-}
-
-static int tvaudio_thread(void *data)
-{
-       struct saa7134_dev *dev = data;
-       int carr_vals[ARRAY_SIZE(mainscan)];
-       unsigned int i, audio, nscan;
-       int max1,max2,carrier,rx,mode,lastmode,default_carrier;
-
-       set_freezable();
-
-       for (;;) {
-               tvaudio_sleep(dev,-1);
-               if (kthread_should_stop())
-                       goto done;
-
-       restart:
-               try_to_freeze();
-
-               dev->thread.scan1 = dev->thread.scan2;
-               dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
-               dev->tvaudio  = NULL;
-
-               saa_writeb(SAA7134_MONITOR_SELECT,   0xa0);
-               saa_writeb(SAA7134_FM_DEMATRIX,      0x80);
-
-               if (dev->ctl_automute)
-                       dev->automute = 1;
-
-               mute_input_7134(dev);
-
-               /* give the tuner some time */
-               if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY))
-                       goto restart;
-
-               max1 = 0;
-               max2 = 0;
-               nscan = 0;
-               carrier = 0;
-               default_carrier = 0;
-               for (i = 0; i < ARRAY_SIZE(mainscan); i++) {
-                       if (!(dev->tvnorm->id & mainscan[i].std))
-                               continue;
-                       if (!default_carrier)
-                               default_carrier = mainscan[i].carr;
-                       nscan++;
-               }
-
-               if (1 == nscan) {
-                       /* only one candidate -- skip scan ;) */
-                       dprintk("only one main carrier candidate - skipping scan\n");
-                       max1 = 12345;
-                       carrier = default_carrier;
-               } else {
-                       /* scan for the main carrier */
-                       saa_writeb(SAA7134_MONITOR_SELECT,0x00);
-                       tvaudio_setmode(dev,&tvaudio[0],NULL);
-                       for (i = 0; i < ARRAY_SIZE(mainscan); i++) {
-                               carr_vals[i] = tvaudio_checkcarrier(dev, mainscan+i);
-                               if (dev->thread.scan1 != dev->thread.scan2)
-                                       goto restart;
-                       }
-                       for (max1 = 0, max2 = 0, i = 0; i < ARRAY_SIZE(mainscan); i++) {
-                               if (max1 < carr_vals[i]) {
-                                       max2 = max1;
-                                       max1 = carr_vals[i];
-                                       carrier = mainscan[i].carr;
-                               } else if (max2 < carr_vals[i]) {
-                                       max2 = carr_vals[i];
-                               }
-                       }
-               }
-
-               if (0 != carrier && max1 > 2000 && max1 > max2*3) {
-                       /* found good carrier */
-                       dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n",
-                               dev->tvnorm->name, carrier/1000, carrier%1000,
-                               max1, max2);
-                       dev->last_carrier = carrier;
-                       dev->automute = 0;
-
-               } else if (0 != dev->last_carrier) {
-                       /* no carrier -- try last detected one as fallback */
-                       carrier = dev->last_carrier;
-                       dprintk("audio carrier scan failed, "
-                               "using %d.%03d MHz [last detected]\n",
-                               carrier/1000, carrier%1000);
-                       dev->automute = 1;
-
-               } else {
-                       /* no carrier + no fallback -- use default */
-                       carrier = default_carrier;
-                       dprintk("audio carrier scan failed, "
-                               "using %d.%03d MHz [default]\n",
-                               carrier/1000, carrier%1000);
-                       dev->automute = 1;
-               }
-               tvaudio_setcarrier(dev,carrier,carrier);
-               saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00);
-               saa7134_tvaudio_setmute(dev);
-               /* find the exact tv audio norm */
-               for (audio = UNSET, i = 0; i < TVAUDIO; i++) {
-                       if (dev->tvnorm->id != UNSET &&
-                               !(dev->tvnorm->id & tvaudio[i].std))
-                               continue;
-                       if (tvaudio[i].carr1 != carrier)
-                               continue;
-                       /* Note: at least the primary carrier is right here */
-                       if (UNSET == audio)
-                               audio = i;
-                       tvaudio_setmode(dev,&tvaudio[i],"trying");
-                       if (tvaudio_sleep(dev,SCAN_SUBCARRIER_DELAY))
-                               goto restart;
-                       if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) {
-                               audio = i;
-                               break;
-                       }
-               }
-               saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30);
-               if (UNSET == audio)
-                       continue;
-               tvaudio_setmode(dev,&tvaudio[audio],"using");
-
-               tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO);
-               dev->tvaudio = &tvaudio[audio];
-
-               lastmode = 42;
-               for (;;) {
-
-                       try_to_freeze();
-
-                       if (tvaudio_sleep(dev,5000))
-                               goto restart;
-                       if (kthread_should_stop())
-                               break;
-                       if (UNSET == dev->thread.mode) {
-                               rx = tvaudio_getstereo(dev, &tvaudio[audio]);
-                               mode = saa7134_tvaudio_rx2mode(rx);
-                       } else {
-                               mode = dev->thread.mode;
-                       }
-                       if (lastmode != mode) {
-                               tvaudio_setstereo(dev,&tvaudio[audio],mode);
-                               lastmode = mode;
-                       }
-               }
-       }
-
- done:
-       dev->thread.stopped = 1;
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-/* saa7133 / saa7135 code                                             */
-
-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]",
-};
-
-#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)
-{
-       int state, count = DSP_RETRY;
-
-       state = saa_readb(SAA7135_DSP_RWSTATE);
-       if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) {
-               printk(KERN_WARNING "%s: dsp access error\n", dev->name);
-               saa_dsp_reset_error_bit(dev);
-               return -EIO;
-       }
-       while (0 == (state & bit)) {
-               if (unlikely(0 == count)) {
-                       printk("%s: dsp access wait timeout [bit=%s]\n",
-                              dev->name,
-                              (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" :
-                              (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" :
-                              (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" :
-                              "???");
-                       return -EIO;
-               }
-               saa_wait(DSP_DELAY);
-               state = saa_readb(SAA7135_DSP_RWSTATE);
-               count--;
-       }
-       return 0;
-}
-
-
-int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value)
-{
-       int err;
-
-       d2printk("dsp write reg 0x%x = 0x%06x\n",reg<<2,value);
-       err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
-       if (err < 0)
-               return err;
-       saa_writel(reg,value);
-       err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
-       if (err < 0)
-               return err;
-       return 0;
-}
-
-static int getstereo_7133(struct saa7134_dev *dev)
-{
-       int retval = V4L2_TUNER_SUB_MONO;
-       u32 value;
-
-       value = saa_readl(0x528 >> 2);
-       if (value & 0x20)
-               retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
-       if (value & 0x40)
-               retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
-       return retval;
-}
-
-static int mute_input_7133(struct saa7134_dev *dev)
-{
-       u32 reg = 0;
-       u32 xbarin, xbarout;
-       int mask;
-       struct saa7134_input *in;
-
-       xbarin = 0x03;
-       switch (dev->input->amux) {
-       case TV:
-               reg = 0x02;
-               xbarin = 0;
-               break;
-       case LINE1:
-               reg = 0x00;
-               break;
-       case LINE2:
-       case LINE2_LEFT:
-               reg = 0x09;
-               break;
-       }
-       saa_dsp_writel(dev, 0x464 >> 2, xbarin);
-       if (dev->ctl_mute) {
-               reg = 0x07;
-               xbarout = 0xbbbbbb;
-       } else
-               xbarout = 0xbbbb10;
-       saa_dsp_writel(dev, 0x46c >> 2, xbarout);
-
-       saa_writel(0x594 >> 2, reg);
-
-
-       /* switch gpio-connected external audio mux */
-       if (0 != card(dev).gpiomask) {
-               mask = card(dev).gpiomask;
-
-               if (card(dev).mute.name && dev->ctl_mute)
-                       in = &card(dev).mute;
-               else
-                       in = dev->input;
-
-               saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   mask, mask);
-               saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio);
-               saa7134_track_gpio(dev,in->name);
-       }
-
-       return 0;
-}
-
-static int tvaudio_thread_ddep(void *data)
-{
-       struct saa7134_dev *dev = data;
-       u32 value, norms;
-
-       set_freezable();
-       for (;;) {
-               tvaudio_sleep(dev,-1);
-               if (kthread_should_stop())
-                       goto done;
-       restart:
-               try_to_freeze();
-
-               dev->thread.scan1 = dev->thread.scan2;
-               dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
-
-               if (audio_ddep >= 0x04 && audio_ddep <= 0x0e) {
-                       /* insmod option override */
-                       norms = (audio_ddep << 2) | 0x01;
-                       dprintk("ddep override: %s\n",stdres[audio_ddep]);
-               } else if (&card(dev).radio == dev->input) {
-                       dprintk("FM Radio\n");
-                       if (dev->tuner_type == TUNER_PHILIPS_TDA8290) {
-                               norms = (0x11 << 2) | 0x01;
-                               saa_dsp_writel(dev, 0x42c >> 2, 0x729555);
-                       } else {
-                               norms = (0x0f << 2) | 0x01;
-                       }
-               } else {
-                       /* (let chip) scan for sound carrier */
-                       norms = 0;
-                       if (dev->tvnorm->id & (V4L2_STD_B | V4L2_STD_GH))
-                               norms |= 0x04;
-                       if (dev->tvnorm->id & V4L2_STD_PAL_I)
-                               norms |= 0x20;
-                       if (dev->tvnorm->id & V4L2_STD_DK)
-                               norms |= 0x08;
-                       if (dev->tvnorm->id & V4L2_STD_MN)
-                               norms |= 0x40;
-                       if (dev->tvnorm->id & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))
-                               norms |= 0x10;
-                       if (0 == norms)
-                               norms = 0x7c; /* all */
-                       dprintk("scanning:%s%s%s%s%s\n",
-                               (norms & 0x04) ? " B/G"  : "",
-                               (norms & 0x08) ? " D/K"  : "",
-                               (norms & 0x10) ? " L/L'" : "",
-                               (norms & 0x20) ? " I"    : "",
-                               (norms & 0x40) ? " M"    : "");
-               }
-
-               /* kick automatic standard detection */
-               saa_dsp_writel(dev, 0x454 >> 2, 0);
-               saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80);
-
-               /* setup crossbars */
-               saa_dsp_writel(dev, 0x464 >> 2, 0x000000);
-               saa_dsp_writel(dev, 0x470 >> 2, 0x101010);
-
-               if (tvaudio_sleep(dev,3000))
-                       goto restart;
-               value = saa_readl(0x528 >> 2) & 0xffffff;
-
-               dprintk("tvaudio thread status: 0x%x [%s%s%s]\n",
-                       value, stdres[value & 0x1f],
-                       (value & 0x000020) ? ",stereo" : "",
-                       (value & 0x000040) ? ",dual"   : "");
-               dprintk("detailed status: "
-                       "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
-                       (value & 0x000080) ? " A2/EIAJ pilot tone "     : "",
-                       (value & 0x000100) ? " A2/EIAJ dual "           : "",
-                       (value & 0x000200) ? " A2/EIAJ stereo "         : "",
-                       (value & 0x000400) ? " A2/EIAJ noise mute "     : "",
-
-                       (value & 0x000800) ? " BTSC/FM radio pilot "    : "",
-                       (value & 0x001000) ? " SAP carrier "            : "",
-                       (value & 0x002000) ? " BTSC stereo noise mute " : "",
-                       (value & 0x004000) ? " SAP noise mute "         : "",
-                       (value & 0x008000) ? " VDSP "                   : "",
-
-                       (value & 0x010000) ? " NICST "                  : "",
-                       (value & 0x020000) ? " NICDU "                  : "",
-                       (value & 0x040000) ? " NICAM muted "            : "",
-                       (value & 0x080000) ? " NICAM reserve sound "    : "",
-
-                       (value & 0x100000) ? " init done "              : "");
-       }
-
- done:
-       dev->thread.stopped = 1;
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-/* common stuff + external entry points                               */
-
-void saa7134_enable_i2s(struct saa7134_dev *dev)
-{
-       int i2s_format;
-
-       if (!card_is_empress(dev))
-               return;
-
-       if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
-               return;
-
-       /* configure GPIO for out */
-       saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x0E000000, 0x00000000);
-
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-           /* Set I2S format (SONY) Â */
-           saa_writeb(SAA7133_I2S_AUDIO_CONTROL, 0x00);
-           /* Start I2S */
-           saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x11);
-           break;
-
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-           i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01;
-
-           /* enable I2S audio output for the mpeg encoder */
-           saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80);
-           saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format);
-           saa_writeb(SAA7134_I2S_OUTPUT_LEVEL,  0x0F);
-           saa_writeb(SAA7134_I2S_AUDIO_OUTPUT,  0x01);
-
-       default:
-           break;
-       }
-}
-
-int saa7134_tvaudio_rx2mode(u32 rx)
-{
-       u32 mode;
-
-       mode = V4L2_TUNER_MODE_MONO;
-       if (rx & V4L2_TUNER_SUB_STEREO)
-               mode = V4L2_TUNER_MODE_STEREO;
-       else if (rx & V4L2_TUNER_SUB_LANG1)
-               mode = V4L2_TUNER_MODE_LANG1;
-       else if (rx & V4L2_TUNER_SUB_LANG2)
-               mode = V4L2_TUNER_MODE_LANG2;
-       return mode;
-}
-
-void saa7134_tvaudio_setmute(struct saa7134_dev *dev)
-{
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7130:
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               mute_input_7134(dev);
-               break;
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               mute_input_7133(dev);
-               break;
-       }
-}
-
-void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
-                             struct saa7134_input *in)
-{
-       dev->input = in;
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7130:
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               mute_input_7134(dev);
-               break;
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               mute_input_7133(dev);
-               break;
-       }
-       saa7134_enable_i2s(dev);
-}
-
-void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level)
-{
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               saa_writeb(SAA7134_CHANNEL1_LEVEL,     level & 0x1f);
-               saa_writeb(SAA7134_CHANNEL2_LEVEL,     level & 0x1f);
-               saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f);
-               break;
-       }
-}
-
-int saa7134_tvaudio_getstereo(struct saa7134_dev *dev)
-{
-       int retval = V4L2_TUNER_SUB_MONO;
-
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               if (dev->tvaudio)
-                       retval = tvaudio_getstereo(dev,dev->tvaudio);
-               break;
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               retval = getstereo_7133(dev);
-               break;
-       }
-       return retval;
-}
-
-void saa7134_tvaudio_init(struct saa7134_dev *dev)
-{
-       int clock = saa7134_boards[dev->board].audio_clock;
-
-       if (UNSET != audio_clock_override)
-               clock = audio_clock_override;
-
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               /* init all audio registers */
-               saa_writeb(SAA7134_AUDIO_PLL_CTRL,   0x00);
-               if (need_resched())
-                       schedule();
-               else
-                       udelay(10);
-
-               saa_writeb(SAA7134_AUDIO_CLOCK0,      clock        & 0xff);
-               saa_writeb(SAA7134_AUDIO_CLOCK1,     (clock >>  8) & 0xff);
-               saa_writeb(SAA7134_AUDIO_CLOCK2,     (clock >> 16) & 0xff);
-               /* frame locked audio is mandatory for NICAM */
-               saa_writeb(SAA7134_AUDIO_PLL_CTRL,   0x01);
-               saa_writeb(SAA7134_NICAM_ERROR_LOW,  0x14);
-               saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
-               break;
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               saa_writel(0x598 >> 2, clock);
-               saa_dsp_writel(dev, 0x474 >> 2, 0x00);
-               saa_dsp_writel(dev, 0x450 >> 2, 0x00);
-       }
-}
-
-int saa7134_tvaudio_init2(struct saa7134_dev *dev)
-{
-       int (*my_thread)(void *data) = NULL;
-
-       switch (dev->pci->device) {
-       case PCI_DEVICE_ID_PHILIPS_SAA7134:
-               my_thread = tvaudio_thread;
-               break;
-       case PCI_DEVICE_ID_PHILIPS_SAA7133:
-       case PCI_DEVICE_ID_PHILIPS_SAA7135:
-               my_thread = tvaudio_thread_ddep;
-               break;
-       }
-
-       dev->thread.thread = NULL;
-       dev->thread.scan1 = dev->thread.scan2 = 0;
-       if (my_thread) {
-               saa7134_tvaudio_init(dev);
-               /* start tvaudio thread */
-               dev->thread.thread = kthread_run(my_thread, dev, "%s", dev->name);
-               if (IS_ERR(dev->thread.thread)) {
-                       printk(KERN_WARNING "%s: kernel_thread() failed\n",
-                              dev->name);
-                       /* XXX: missing error handling here */
-               }
-       }
-
-       saa7134_enable_i2s(dev);
-       return 0;
-}
-
-int saa7134_tvaudio_close(struct saa7134_dev *dev)
-{
-       dev->automute = 1;
-       /* anything else to undo? */
-       return 0;
-}
-
-int saa7134_tvaudio_fini(struct saa7134_dev *dev)
-{
-       /* shutdown tvaudio thread */
-       if (dev->thread.thread && !dev->thread.stopped)
-               kthread_stop(dev->thread.thread);
-
-       saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */
-       return 0;
-}
-
-int saa7134_tvaudio_do_scan(struct saa7134_dev *dev)
-{
-       if (dev->input->amux != TV) {
-               dprintk("sound IF not in use, skipping scan\n");
-               dev->automute = 0;
-               saa7134_tvaudio_setmute(dev);
-       } else if (dev->thread.thread) {
-               dev->thread.mode = UNSET;
-               dev->thread.scan2++;
-
-               if (!dev->insuspend && !dev->thread.stopped)
-                       wake_up_process(dev->thread.thread);
-       } else {
-               dev->automute = 0;
-               saa7134_tvaudio_setmute(dev);
-       }
-       return 0;
-}
-
-EXPORT_SYMBOL(saa_dsp_writel);
-EXPORT_SYMBOL(saa7134_tvaudio_setmute);
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
deleted file mode 100644 (file)
index e9aa94b..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * video4linux video interface
- *
- * (c) 2001,02 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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-
-/* ------------------------------------------------------------------ */
-
-static unsigned int vbi_debug;
-module_param(vbi_debug, int, 0644);
-MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
-
-static unsigned int vbibufs = 4;
-module_param(vbibufs, int, 0444);
-MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
-
-#define dprintk(fmt, arg...)   if (vbi_debug) \
-       printk(KERN_DEBUG "%s/vbi: " fmt, dev->name , ## arg)
-
-/* ------------------------------------------------------------------ */
-
-#define VBI_LINE_COUNT     16
-#define VBI_LINE_LENGTH  2048
-#define VBI_SCALE       0x200
-
-static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
-                     int task)
-{
-       struct saa7134_tvnorm *norm = dev->tvnorm;
-
-       /* setup video scaler */
-       saa_writeb(SAA7134_VBI_H_START1(task), norm->h_start     &  0xff);
-       saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start     >> 8);
-       saa_writeb(SAA7134_VBI_H_STOP1(task),  norm->h_stop      &  0xff);
-       saa_writeb(SAA7134_VBI_H_STOP2(task),  norm->h_stop      >> 8);
-       saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 &  0xff);
-       saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
-       saa_writeb(SAA7134_VBI_V_STOP1(task),  norm->vbi_v_stop_0  &  0xff);
-       saa_writeb(SAA7134_VBI_V_STOP2(task),  norm->vbi_v_stop_0  >> 8);
-
-       saa_writeb(SAA7134_VBI_H_SCALE_INC1(task),        VBI_SCALE & 0xff);
-       saa_writeb(SAA7134_VBI_H_SCALE_INC2(task),        VBI_SCALE >> 8);
-       saa_writeb(SAA7134_VBI_PHASE_OFFSET_LUMA(task),   0x00);
-       saa_writeb(SAA7134_VBI_PHASE_OFFSET_CHROMA(task), 0x00);
-
-       saa_writeb(SAA7134_VBI_H_LEN1(task), buf->vb.width   & 0xff);
-       saa_writeb(SAA7134_VBI_H_LEN2(task), buf->vb.width   >> 8);
-       saa_writeb(SAA7134_VBI_V_LEN1(task), buf->vb.height  & 0xff);
-       saa_writeb(SAA7134_VBI_V_LEN2(task), buf->vb.height  >> 8);
-
-       saa_andorb(SAA7134_DATA_PATH(task), 0xc0, 0x00);
-}
-
-/* ------------------------------------------------------------------ */
-
-static int buffer_activate(struct saa7134_dev *dev,
-                          struct saa7134_buf *buf,
-                          struct saa7134_buf *next)
-{
-       unsigned long control,base;
-
-       dprintk("buffer_activate [%p]\n",buf);
-       buf->vb.state = VIDEOBUF_ACTIVE;
-       buf->top_seen = 0;
-
-       task_init(dev,buf,TASK_A);
-       task_init(dev,buf,TASK_B);
-       saa_writeb(SAA7134_OFMT_DATA_A, 0x06);
-       saa_writeb(SAA7134_OFMT_DATA_B, 0x06);
-
-       /* DMA: setup channel 2+3 (= VBI Task A+B) */
-       base    = saa7134_buffer_base(buf);
-       control = SAA7134_RS_CONTROL_BURST_16 |
-               SAA7134_RS_CONTROL_ME |
-               (buf->pt->dma >> 12);
-       saa_writel(SAA7134_RS_BA1(2),base);
-       saa_writel(SAA7134_RS_BA2(2),base + buf->vb.size/2);
-       saa_writel(SAA7134_RS_PITCH(2),buf->vb.width);
-       saa_writel(SAA7134_RS_CONTROL(2),control);
-       saa_writel(SAA7134_RS_BA1(3),base);
-       saa_writel(SAA7134_RS_BA2(3),base + buf->vb.size/2);
-       saa_writel(SAA7134_RS_PITCH(3),buf->vb.width);
-       saa_writel(SAA7134_RS_CONTROL(3),control);
-
-       /* start DMA */
-       saa7134_set_dmabits(dev);
-       mod_timer(&dev->vbi_q.timeout, jiffies+BUFFER_TIMEOUT);
-
-       return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q,
-                         struct videobuf_buffer *vb,
-                         enum v4l2_field field)
-{
-       struct saa7134_fh *fh   = q->priv_data;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-       struct saa7134_tvnorm *norm = dev->tvnorm;
-       unsigned int lines, llength, size;
-       int err;
-
-       lines   = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
-       if (lines > VBI_LINE_COUNT)
-               lines = VBI_LINE_COUNT;
-       llength = VBI_LINE_LENGTH;
-       size = lines * llength * 2;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       if (buf->vb.size != size)
-               saa7134_dma_free(q,buf);
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-               buf->vb.width  = llength;
-               buf->vb.height = lines;
-               buf->vb.size   = size;
-               buf->pt        = &fh->pt_vbi;
-
-               err = videobuf_iolock(q,&buf->vb,NULL);
-               if (err)
-                       goto oops;
-               err = saa7134_pgtable_build(dev->pci,buf->pt,
-                                           dma->sglist,
-                                           dma->sglen,
-                                           saa7134_buffer_startpage(buf));
-               if (err)
-                       goto oops;
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       buf->activate = buffer_activate;
-       buf->vb.field = field;
-       return 0;
-
- oops:
-       saa7134_dma_free(q,buf);
-       return err;
-}
-
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       struct saa7134_fh *fh   = q->priv_data;
-       struct saa7134_dev *dev = fh->dev;
-       int llength,lines;
-
-       lines   = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
-       llength = VBI_LINE_LENGTH;
-       *size = lines * llength * 2;
-       if (0 == *count)
-               *count = vbibufs;
-       *count = saa7134_buffer_count(*size,*count);
-       return 0;
-}
-
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct saa7134_fh *fh = q->priv_data;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-
-       saa7134_buffer_queue(dev,&dev->vbi_q,buf);
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-
-       saa7134_dma_free(q,buf);
-}
-
-struct videobuf_queue_ops saa7134_vbi_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-int saa7134_vbi_init1(struct saa7134_dev *dev)
-{
-       INIT_LIST_HEAD(&dev->vbi_q.queue);
-       init_timer(&dev->vbi_q.timeout);
-       dev->vbi_q.timeout.function = saa7134_buffer_timeout;
-       dev->vbi_q.timeout.data     = (unsigned long)(&dev->vbi_q);
-       dev->vbi_q.dev              = dev;
-
-       if (vbibufs < 2)
-               vbibufs = 2;
-       if (vbibufs > VIDEO_MAX_FRAME)
-               vbibufs = VIDEO_MAX_FRAME;
-       return 0;
-}
-
-int saa7134_vbi_fini(struct saa7134_dev *dev)
-{
-       /* nothing */
-       return 0;
-}
-
-void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status)
-{
-       spin_lock(&dev->slock);
-       if (dev->vbi_q.curr) {
-               dev->vbi_fieldcount++;
-               /* make sure we have seen both fields */
-               if ((status & 0x10) == 0x00) {
-                       dev->vbi_q.curr->top_seen = 1;
-                       goto done;
-               }
-               if (!dev->vbi_q.curr->top_seen)
-                       goto done;
-
-               dev->vbi_q.curr->vb.field_count = dev->vbi_fieldcount;
-               saa7134_buffer_finish(dev,&dev->vbi_q,VIDEOBUF_DONE);
-       }
-       saa7134_buffer_next(dev,&dev->vbi_q);
-
- done:
-       spin_unlock(&dev->slock);
-}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
deleted file mode 100644 (file)
index 6de10b1..0000000
+++ /dev/null
@@ -1,2661 +0,0 @@
-/*
- *
- * device driver for philips saa7134 based TV cards
- * video4linux video interface
- *
- * (c) 2001-03 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, 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sort.h>
-
-#include "saa7134-reg.h"
-#include "saa7134.h"
-#include <media/v4l2-common.h>
-#include <media/saa6588.h>
-
-/* ------------------------------------------------------------------ */
-
-unsigned int video_debug;
-static unsigned int gbuffers      = 8;
-static unsigned int noninterlaced; /* 0 */
-static unsigned int gbufsize      = 720*576*4;
-static unsigned int gbufsize_max  = 720*576*4;
-static char secam[] = "--";
-module_param(video_debug, int, 0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
-module_param(gbuffers, int, 0444);
-MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32");
-module_param(noninterlaced, int, 0644);
-MODULE_PARM_DESC(noninterlaced,"capture non interlaced video");
-module_param_string(secam, secam, sizeof(secam), 0644);
-MODULE_PARM_DESC(secam, "force SECAM variant, either DK,L or Lc");
-
-
-#define dprintk(fmt, arg...)   if (video_debug&0x04) \
-       printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg)
-
-/* ------------------------------------------------------------------ */
-/* Defines for Video Output Port Register at address 0x191            */
-
-/* Bit 0: VIP code T bit polarity */
-
-#define VP_T_CODE_P_NON_INVERTED       0x00
-#define VP_T_CODE_P_INVERTED           0x01
-
-/* ------------------------------------------------------------------ */
-/* Defines for Video Output Port Register at address 0x195            */
-
-/* Bit 2: Video output clock delay control */
-
-#define VP_CLK_CTRL2_NOT_DELAYED       0x00
-#define VP_CLK_CTRL2_DELAYED           0x04
-
-/* Bit 1: Video output clock invert control */
-
-#define VP_CLK_CTRL1_NON_INVERTED      0x00
-#define VP_CLK_CTRL1_INVERTED          0x02
-
-/* ------------------------------------------------------------------ */
-/* Defines for Video Output Port Register at address 0x196            */
-
-/* Bits 2 to 0: VSYNC pin video vertical sync type */
-
-#define VP_VS_TYPE_MASK                        0x07
-
-#define VP_VS_TYPE_OFF                 0x00
-#define VP_VS_TYPE_V123                        0x01
-#define VP_VS_TYPE_V_ITU               0x02
-#define VP_VS_TYPE_VGATE_L             0x03
-#define VP_VS_TYPE_RESERVED1           0x04
-#define VP_VS_TYPE_RESERVED2           0x05
-#define VP_VS_TYPE_F_ITU               0x06
-#define VP_VS_TYPE_SC_FID              0x07
-
-/* ------------------------------------------------------------------ */
-/* data structs for video                                             */
-
-static int video_out[][9] = {
-       [CCIR656] = { 0x00, 0xb1, 0x00, 0xa1, 0x00, 0x04, 0x06, 0x00, 0x00 },
-};
-
-static struct saa7134_format formats[] = {
-       {
-               .name     = "8 bpp gray",
-               .fourcc   = V4L2_PIX_FMT_GREY,
-               .depth    = 8,
-               .pm       = 0x06,
-       },{
-               .name     = "15 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB555,
-               .depth    = 16,
-               .pm       = 0x13 | 0x80,
-       },{
-               .name     = "15 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB555X,
-               .depth    = 16,
-               .pm       = 0x13 | 0x80,
-               .bswap    = 1,
-       },{
-               .name     = "16 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_RGB565,
-               .depth    = 16,
-               .pm       = 0x10 | 0x80,
-       },{
-               .name     = "16 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB565X,
-               .depth    = 16,
-               .pm       = 0x10 | 0x80,
-               .bswap    = 1,
-       },{
-               .name     = "24 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR24,
-               .depth    = 24,
-               .pm       = 0x11,
-       },{
-               .name     = "24 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB24,
-               .depth    = 24,
-               .pm       = 0x11,
-               .bswap    = 1,
-       },{
-               .name     = "32 bpp RGB, le",
-               .fourcc   = V4L2_PIX_FMT_BGR32,
-               .depth    = 32,
-               .pm       = 0x12,
-       },{
-               .name     = "32 bpp RGB, be",
-               .fourcc   = V4L2_PIX_FMT_RGB32,
-               .depth    = 32,
-               .pm       = 0x12,
-               .bswap    = 1,
-               .wswap    = 1,
-       },{
-               .name     = "4:2:2 packed, YUYV",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
-               .pm       = 0x00,
-               .bswap    = 1,
-               .yuv      = 1,
-       },{
-               .name     = "4:2:2 packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
-               .pm       = 0x00,
-               .yuv      = 1,
-       },{
-               .name     = "4:2:2 planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YUV422P,
-               .depth    = 16,
-               .pm       = 0x09,
-               .yuv      = 1,
-               .planar   = 1,
-               .hshift   = 1,
-               .vshift   = 0,
-       },{
-               .name     = "4:2:0 planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YUV420,
-               .depth    = 12,
-               .pm       = 0x0a,
-               .yuv      = 1,
-               .planar   = 1,
-               .hshift   = 1,
-               .vshift   = 1,
-       },{
-               .name     = "4:2:0 planar, Y-Cb-Cr",
-               .fourcc   = V4L2_PIX_FMT_YVU420,
-               .depth    = 12,
-               .pm       = 0x0a,
-               .yuv      = 1,
-               .planar   = 1,
-               .uvswap   = 1,
-               .hshift   = 1,
-               .vshift   = 1,
-       }
-};
-#define FORMATS ARRAY_SIZE(formats)
-
-#define NORM_625_50                    \
-               .h_start       = 0,     \
-               .h_stop        = 719,   \
-               .video_v_start = 24,    \
-               .video_v_stop  = 311,   \
-               .vbi_v_start_0 = 7,     \
-               .vbi_v_stop_0  = 22,    \
-               .vbi_v_start_1 = 319,   \
-               .src_timing    = 4
-
-#define NORM_525_60                    \
-               .h_start       = 0,     \
-               .h_stop        = 719,   \
-               .video_v_start = 23,    \
-               .video_v_stop  = 262,   \
-               .vbi_v_start_0 = 10,    \
-               .vbi_v_stop_0  = 21,    \
-               .vbi_v_start_1 = 273,   \
-               .src_timing    = 7
-
-static struct saa7134_tvnorm tvnorms[] = {
-       {
-               .name          = "PAL", /* autodetect */
-               .id            = V4L2_STD_PAL,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0x81,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x06,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "PAL-BG",
-               .id            = V4L2_STD_PAL_BG,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0x81,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x06,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "PAL-I",
-               .id            = V4L2_STD_PAL_I,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0x81,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x06,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "PAL-DK",
-               .id            = V4L2_STD_PAL_DK,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0x81,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x06,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "NTSC",
-               .id            = V4L2_STD_NTSC,
-               NORM_525_60,
-
-               .sync_control  = 0x59,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0x89,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x0e,
-               .vgate_misc    = 0x18,
-
-       },{
-               .name          = "SECAM",
-               .id            = V4L2_STD_SECAM,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x1b,
-               .chroma_ctrl1  = 0xd1,
-               .chroma_gain   = 0x80,
-               .chroma_ctrl2  = 0x00,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "SECAM-DK",
-               .id            = V4L2_STD_SECAM_DK,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x1b,
-               .chroma_ctrl1  = 0xd1,
-               .chroma_gain   = 0x80,
-               .chroma_ctrl2  = 0x00,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "SECAM-L",
-               .id            = V4L2_STD_SECAM_L,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x1b,
-               .chroma_ctrl1  = 0xd1,
-               .chroma_gain   = 0x80,
-               .chroma_ctrl2  = 0x00,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "SECAM-Lc",
-               .id            = V4L2_STD_SECAM_LC,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x1b,
-               .chroma_ctrl1  = 0xd1,
-               .chroma_gain   = 0x80,
-               .chroma_ctrl2  = 0x00,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "PAL-M",
-               .id            = V4L2_STD_PAL_M,
-               NORM_525_60,
-
-               .sync_control  = 0x59,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0xb9,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x0e,
-               .vgate_misc    = 0x18,
-
-       },{
-               .name          = "PAL-Nc",
-               .id            = V4L2_STD_PAL_Nc,
-               NORM_625_50,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0xa1,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x06,
-               .vgate_misc    = 0x1c,
-
-       },{
-               .name          = "PAL-60",
-               .id            = V4L2_STD_PAL_60,
-
-               .h_start       = 0,
-               .h_stop        = 719,
-               .video_v_start = 23,
-               .video_v_stop  = 262,
-               .vbi_v_start_0 = 10,
-               .vbi_v_stop_0  = 21,
-               .vbi_v_start_1 = 273,
-               .src_timing    = 7,
-
-               .sync_control  = 0x18,
-               .luma_control  = 0x40,
-               .chroma_ctrl1  = 0x81,
-               .chroma_gain   = 0x2a,
-               .chroma_ctrl2  = 0x06,
-               .vgate_misc    = 0x1c,
-       }
-};
-#define TVNORMS ARRAY_SIZE(tvnorms)
-
-#define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)
-#define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)
-#define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 3)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 4)
-
-static const struct v4l2_queryctrl no_ctrl = {
-       .name  = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-static const struct v4l2_queryctrl video_ctrls[] = {
-       /* --- video --- */
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 128,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_CONTRAST,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 68,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_SATURATION,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_HUE,
-               .name          = "Hue",
-               .minimum       = -128,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_HFLIP,
-               .name          = "Mirror",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },
-       /* --- audio --- */
-       {
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .name          = "Volume",
-               .minimum       = -15,
-               .maximum       = 15,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },
-       /* --- private --- */
-       {
-               .id            = V4L2_CID_PRIVATE_INVERT,
-               .name          = "Invert",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       },{
-               .id            = V4L2_CID_PRIVATE_Y_ODD,
-               .name          = "y offset odd field",
-               .minimum       = 0,
-               .maximum       = 128,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_PRIVATE_Y_EVEN,
-               .name          = "y offset even field",
-               .minimum       = 0,
-               .maximum       = 128,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       },{
-               .id            = V4L2_CID_PRIVATE_AUTOMUTE,
-               .name          = "automute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .default_value = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       }
-};
-static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
-
-static const struct v4l2_queryctrl* ctrl_by_id(unsigned int id)
-{
-       unsigned int i;
-
-       for (i = 0; i < CTRLS; i++)
-               if (video_ctrls[i].id == id)
-                       return video_ctrls+i;
-       return NULL;
-}
-
-static struct saa7134_format* format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < FORMATS; i++)
-               if (formats[i].fourcc == fourcc)
-                       return formats+i;
-       return NULL;
-}
-
-/* ----------------------------------------------------------------------- */
-/* resource management                                                     */
-
-static int res_get(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bit)
-{
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       /* is it free? */
-       mutex_lock(&dev->lock);
-       if (dev->resources & bit) {
-               /* no, someone else uses it */
-               mutex_unlock(&dev->lock);
-               return 0;
-       }
-       /* it's free, grab it */
-       fh->resources  |= bit;
-       dev->resources |= bit;
-       dprintk("res: get %d\n",bit);
-       mutex_unlock(&dev->lock);
-       return 1;
-}
-
-static int res_check(struct saa7134_fh *fh, unsigned int bit)
-{
-       return (fh->resources & bit);
-}
-
-static int res_locked(struct saa7134_dev *dev, unsigned int bit)
-{
-       return (dev->resources & bit);
-}
-
-static
-void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
-{
-       BUG_ON((fh->resources & bits) != bits);
-
-       mutex_lock(&dev->lock);
-       fh->resources  &= ~bits;
-       dev->resources &= ~bits;
-       dprintk("res: put %d\n",bits);
-       mutex_unlock(&dev->lock);
-}
-
-/* ------------------------------------------------------------------ */
-
-static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
-{
-       dprintk("set tv norm = %s\n",norm->name);
-       dev->tvnorm = norm;
-
-       /* setup cropping */
-       dev->crop_bounds.left    = norm->h_start;
-       dev->crop_defrect.left   = norm->h_start;
-       dev->crop_bounds.width   = norm->h_stop - norm->h_start +1;
-       dev->crop_defrect.width  = norm->h_stop - norm->h_start +1;
-
-       dev->crop_bounds.top     = (norm->vbi_v_stop_0+1)*2;
-       dev->crop_defrect.top    = norm->video_v_start*2;
-       dev->crop_bounds.height  = ((norm->id & V4L2_STD_525_60) ? 524 : 624)
-               - dev->crop_bounds.top;
-       dev->crop_defrect.height = (norm->video_v_stop - norm->video_v_start +1)*2;
-
-       dev->crop_current = dev->crop_defrect;
-
-       saa7134_set_tvnorm_hw(dev);
-}
-
-static void video_mux(struct saa7134_dev *dev, int input)
-{
-       dprintk("video input = %d [%s]\n", input, card_in(dev, input).name);
-       dev->ctl_input = input;
-       set_tvnorm(dev, dev->tvnorm);
-       saa7134_tvaudio_setinput(dev, &card_in(dev, input));
-}
-
-
-static void saa7134_set_decoder(struct saa7134_dev *dev)
-{
-       int luma_control, sync_control, mux;
-
-       struct saa7134_tvnorm *norm = dev->tvnorm;
-       mux = card_in(dev, dev->ctl_input).vmux;
-
-       luma_control = norm->luma_control;
-       sync_control = norm->sync_control;
-
-       if (mux > 5)
-               luma_control |= 0x80; /* svideo */
-       if (noninterlaced || dev->nosignal)
-               sync_control |= 0x20;
-
-       /* setup video decoder */
-       saa_writeb(SAA7134_INCR_DELAY,            0x08);
-       saa_writeb(SAA7134_ANALOG_IN_CTRL1,       0xc0 | mux);
-       saa_writeb(SAA7134_ANALOG_IN_CTRL2,       0x00);
-
-       saa_writeb(SAA7134_ANALOG_IN_CTRL3,       0x90);
-       saa_writeb(SAA7134_ANALOG_IN_CTRL4,       0x90);
-       saa_writeb(SAA7134_HSYNC_START,           0xeb);
-       saa_writeb(SAA7134_HSYNC_STOP,            0xe0);
-       saa_writeb(SAA7134_SOURCE_TIMING1,        norm->src_timing);
-
-       saa_writeb(SAA7134_SYNC_CTRL,             sync_control);
-       saa_writeb(SAA7134_LUMA_CTRL,             luma_control);
-       saa_writeb(SAA7134_DEC_LUMA_BRIGHT,       dev->ctl_bright);
-
-       saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
-               dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
-
-       saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
-               dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
-
-       saa_writeb(SAA7134_DEC_CHROMA_HUE,        dev->ctl_hue);
-       saa_writeb(SAA7134_CHROMA_CTRL1,          norm->chroma_ctrl1);
-       saa_writeb(SAA7134_CHROMA_GAIN,           norm->chroma_gain);
-
-       saa_writeb(SAA7134_CHROMA_CTRL2,          norm->chroma_ctrl2);
-       saa_writeb(SAA7134_MODE_DELAY_CTRL,       0x00);
-
-       saa_writeb(SAA7134_ANALOG_ADC,            0x01);
-       saa_writeb(SAA7134_VGATE_START,           0x11);
-       saa_writeb(SAA7134_VGATE_STOP,            0xfe);
-       saa_writeb(SAA7134_MISC_VGATE_MSB,        norm->vgate_misc);
-       saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);
-       saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);
-}
-
-void saa7134_set_tvnorm_hw(struct saa7134_dev *dev)
-{
-       saa7134_set_decoder(dev);
-
-       if (card_in(dev, dev->ctl_input).tv)
-               saa_call_all(dev, core, s_std, dev->tvnorm->id);
-       /* Set the correct norm for the saa6752hs. This function
-          does nothing if there is no saa6752hs. */
-       saa_call_empress(dev, core, s_std, dev->tvnorm->id);
-}
-
-static void set_h_prescale(struct saa7134_dev *dev, 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;
-
-       for (i = 0; i < count; i++)
-               if (vals[i].xpsc == prescale)
-                       break;
-       if (i == count)
-               return;
-
-       saa_writeb(SAA7134_H_PRESCALE(task), vals[i].xpsc);
-       saa_writeb(SAA7134_ACC_LENGTH(task), vals[i].xacl);
-       saa_writeb(SAA7134_LEVEL_CTRL(task),
-                  (vals[i].xc2_1 << 3) | (vals[i].xdcg));
-       saa_andorb(SAA7134_FIR_PREFILTER_CTRL(task), 0x0f,
-                  (vals[i].vpfy << 2) | vals[i].vpfy);
-}
-
-static void set_v_scale(struct saa7134_dev *dev, int task, int yscale)
-{
-       int val,mirror;
-
-       saa_writeb(SAA7134_V_SCALE_RATIO1(task), yscale &  0xff);
-       saa_writeb(SAA7134_V_SCALE_RATIO2(task), yscale >> 8);
-
-       mirror = (dev->ctl_mirror) ? 0x02 : 0x00;
-       if (yscale < 2048) {
-               /* LPI */
-               dprintk("yscale LPI yscale=%d\n",yscale);
-               saa_writeb(SAA7134_V_FILTER(task), 0x00 | mirror);
-               saa_writeb(SAA7134_LUMA_CONTRAST(task), 0x40);
-               saa_writeb(SAA7134_CHROMA_SATURATION(task), 0x40);
-       } else {
-               /* ACM */
-               val = 0x40 * 1024 / yscale;
-               dprintk("yscale ACM yscale=%d val=0x%x\n",yscale,val);
-               saa_writeb(SAA7134_V_FILTER(task), 0x01 | mirror);
-               saa_writeb(SAA7134_LUMA_CONTRAST(task), val);
-               saa_writeb(SAA7134_CHROMA_SATURATION(task), val);
-       }
-       saa_writeb(SAA7134_LUMA_BRIGHT(task),       0x80);
-}
-
-static void set_size(struct saa7134_dev *dev, int task,
-                    int width, int height, int interlace)
-{
-       int prescale,xscale,yscale,y_even,y_odd;
-       int h_start, h_stop, v_start, v_stop;
-       int div = interlace ? 2 : 1;
-
-       /* setup video scaler */
-       h_start = dev->crop_current.left;
-       v_start = dev->crop_current.top/2;
-       h_stop  = (dev->crop_current.left + dev->crop_current.width -1);
-       v_stop  = (dev->crop_current.top + dev->crop_current.height -1)/2;
-
-       saa_writeb(SAA7134_VIDEO_H_START1(task), h_start &  0xff);
-       saa_writeb(SAA7134_VIDEO_H_START2(task), h_start >> 8);
-       saa_writeb(SAA7134_VIDEO_H_STOP1(task),  h_stop  &  0xff);
-       saa_writeb(SAA7134_VIDEO_H_STOP2(task),  h_stop  >> 8);
-       saa_writeb(SAA7134_VIDEO_V_START1(task), v_start &  0xff);
-       saa_writeb(SAA7134_VIDEO_V_START2(task), v_start >> 8);
-       saa_writeb(SAA7134_VIDEO_V_STOP1(task),  v_stop  &  0xff);
-       saa_writeb(SAA7134_VIDEO_V_STOP2(task),  v_stop  >> 8);
-
-       prescale = dev->crop_current.width / width;
-       if (0 == prescale)
-               prescale = 1;
-       xscale = 1024 * dev->crop_current.width / prescale / width;
-       yscale = 512 * div * dev->crop_current.height / height;
-       dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale);
-       set_h_prescale(dev,task,prescale);
-       saa_writeb(SAA7134_H_SCALE_INC1(task),      xscale &  0xff);
-       saa_writeb(SAA7134_H_SCALE_INC2(task),      xscale >> 8);
-       set_v_scale(dev,task,yscale);
-
-       saa_writeb(SAA7134_VIDEO_PIXELS1(task),     width  & 0xff);
-       saa_writeb(SAA7134_VIDEO_PIXELS2(task),     width  >> 8);
-       saa_writeb(SAA7134_VIDEO_LINES1(task),      height/div & 0xff);
-       saa_writeb(SAA7134_VIDEO_LINES2(task),      height/div >> 8);
-
-       /* deinterlace y offsets */
-       y_odd  = dev->ctl_y_odd;
-       y_even = dev->ctl_y_even;
-       saa_writeb(SAA7134_V_PHASE_OFFSET0(task), y_odd);
-       saa_writeb(SAA7134_V_PHASE_OFFSET1(task), y_even);
-       saa_writeb(SAA7134_V_PHASE_OFFSET2(task), y_odd);
-       saa_writeb(SAA7134_V_PHASE_OFFSET3(task), y_even);
-}
-
-/* ------------------------------------------------------------------ */
-
-struct cliplist {
-       __u16 position;
-       __u8  enable;
-       __u8  disable;
-};
-
-static void set_cliplist(struct saa7134_dev *dev, int reg,
-                       struct cliplist *cl, int entries, char *name)
-{
-       __u8 winbits = 0;
-       int i;
-
-       for (i = 0; i < entries; i++) {
-               winbits |= cl[i].enable;
-               winbits &= ~cl[i].disable;
-               if (i < 15 && cl[i].position == cl[i+1].position)
-                       continue;
-               saa_writeb(reg + 0, winbits);
-               saa_writeb(reg + 2, cl[i].position & 0xff);
-               saa_writeb(reg + 3, cl[i].position >> 8);
-               dprintk("clip: %s winbits=%02x pos=%d\n",
-                       name,winbits,cl[i].position);
-               reg += 8;
-       }
-       for (; reg < 0x400; reg += 8) {
-               saa_writeb(reg+ 0, 0);
-               saa_writeb(reg + 1, 0);
-               saa_writeb(reg + 2, 0);
-               saa_writeb(reg + 3, 0);
-       }
-}
-
-static int clip_range(int val)
-{
-       if (val < 0)
-               val = 0;
-       return val;
-}
-
-/* Sort into smallest position first order */
-static int cliplist_cmp(const void *a, const void *b)
-{
-       const struct cliplist *cla = a;
-       const struct cliplist *clb = b;
-       if (cla->position < clb->position)
-               return -1;
-       if (cla->position > clb->position)
-               return 1;
-       return 0;
-}
-
-static int setup_clipping(struct saa7134_dev *dev, struct v4l2_clip *clips,
-                         int nclips, int interlace)
-{
-       struct cliplist col[16], row[16];
-       int cols = 0, rows = 0, i;
-       int div = interlace ? 2 : 1;
-
-       memset(col, 0, sizeof(col));
-       memset(row, 0, sizeof(row));
-       for (i = 0; i < nclips && i < 8; i++) {
-               col[cols].position = clip_range(clips[i].c.left);
-               col[cols].enable   = (1 << i);
-               cols++;
-               col[cols].position = clip_range(clips[i].c.left+clips[i].c.width);
-               col[cols].disable  = (1 << i);
-               cols++;
-               row[rows].position = clip_range(clips[i].c.top / div);
-               row[rows].enable   = (1 << i);
-               rows++;
-               row[rows].position = clip_range((clips[i].c.top + clips[i].c.height)
-                                               / div);
-               row[rows].disable  = (1 << i);
-               rows++;
-       }
-       sort(col, cols, sizeof col[0], cliplist_cmp, NULL);
-       sort(row, rows, sizeof row[0], cliplist_cmp, NULL);
-       set_cliplist(dev,0x380,col,cols,"cols");
-       set_cliplist(dev,0x384,row,rows,"rows");
-       return 0;
-}
-
-static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win)
-{
-       enum v4l2_field field;
-       int maxw, maxh;
-
-       if (NULL == dev->ovbuf.base)
-               return -EINVAL;
-       if (NULL == dev->ovfmt)
-               return -EINVAL;
-       if (win->w.width < 48 || win->w.height <  32)
-               return -EINVAL;
-       if (win->clipcount > 2048)
-               return -EINVAL;
-
-       field = win->field;
-       maxw  = dev->crop_current.width;
-       maxh  = dev->crop_current.height;
-
-       if (V4L2_FIELD_ANY == field) {
-               field = (win->w.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_TOP;
-       }
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       win->field = field;
-       if (win->w.width > maxw)
-               win->w.width = maxw;
-       if (win->w.height > maxh)
-               win->w.height = maxh;
-       return 0;
-}
-
-static int start_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
-{
-       unsigned long base,control,bpl;
-       int err;
-
-       err = verify_preview(dev,&fh->win);
-       if (0 != err)
-               return err;
-
-       dev->ovfield = fh->win.field;
-       dprintk("start_preview %dx%d+%d+%d %s field=%s\n",
-               fh->win.w.width,fh->win.w.height,
-               fh->win.w.left,fh->win.w.top,
-               dev->ovfmt->name,v4l2_field_names[dev->ovfield]);
-
-       /* setup window + clipping */
-       set_size(dev,TASK_B,fh->win.w.width,fh->win.w.height,
-                V4L2_FIELD_HAS_BOTH(dev->ovfield));
-       setup_clipping(dev,fh->clips,fh->nclips,
-                      V4L2_FIELD_HAS_BOTH(dev->ovfield));
-       if (dev->ovfmt->yuv)
-               saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x03);
-       else
-               saa_andorb(SAA7134_DATA_PATH(TASK_B), 0x3f, 0x01);
-       saa_writeb(SAA7134_OFMT_VIDEO_B, dev->ovfmt->pm | 0x20);
-
-       /* dma: setup channel 1 (= Video Task B) */
-       base  = (unsigned long)dev->ovbuf.base;
-       base += dev->ovbuf.fmt.bytesperline * fh->win.w.top;
-       base += dev->ovfmt->depth/8         * fh->win.w.left;
-       bpl   = dev->ovbuf.fmt.bytesperline;
-       control = SAA7134_RS_CONTROL_BURST_16;
-       if (dev->ovfmt->bswap)
-               control |= SAA7134_RS_CONTROL_BSWAP;
-       if (dev->ovfmt->wswap)
-               control |= SAA7134_RS_CONTROL_WSWAP;
-       if (V4L2_FIELD_HAS_BOTH(dev->ovfield)) {
-               saa_writel(SAA7134_RS_BA1(1),base);
-               saa_writel(SAA7134_RS_BA2(1),base+bpl);
-               saa_writel(SAA7134_RS_PITCH(1),bpl*2);
-               saa_writel(SAA7134_RS_CONTROL(1),control);
-       } else {
-               saa_writel(SAA7134_RS_BA1(1),base);
-               saa_writel(SAA7134_RS_BA2(1),base);
-               saa_writel(SAA7134_RS_PITCH(1),bpl);
-               saa_writel(SAA7134_RS_CONTROL(1),control);
-       }
-
-       /* start dma */
-       dev->ovenable = 1;
-       saa7134_set_dmabits(dev);
-
-       return 0;
-}
-
-static int stop_preview(struct saa7134_dev *dev, struct saa7134_fh *fh)
-{
-       dev->ovenable = 0;
-       saa7134_set_dmabits(dev);
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int buffer_activate(struct saa7134_dev *dev,
-                          struct saa7134_buf *buf,
-                          struct saa7134_buf *next)
-{
-       unsigned long base,control,bpl;
-       unsigned long bpl_uv,lines_uv,base2,base3,tmp; /* planar */
-
-       dprintk("buffer_activate buf=%p\n",buf);
-       buf->vb.state = VIDEOBUF_ACTIVE;
-       buf->top_seen = 0;
-
-       set_size(dev,TASK_A,buf->vb.width,buf->vb.height,
-                V4L2_FIELD_HAS_BOTH(buf->vb.field));
-       if (buf->fmt->yuv)
-               saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x03);
-       else
-               saa_andorb(SAA7134_DATA_PATH(TASK_A), 0x3f, 0x01);
-       saa_writeb(SAA7134_OFMT_VIDEO_A, buf->fmt->pm);
-
-       /* DMA: setup channel 0 (= Video Task A0) */
-       base  = saa7134_buffer_base(buf);
-       if (buf->fmt->planar)
-               bpl = buf->vb.width;
-       else
-               bpl = (buf->vb.width * buf->fmt->depth) / 8;
-       control = SAA7134_RS_CONTROL_BURST_16 |
-               SAA7134_RS_CONTROL_ME |
-               (buf->pt->dma >> 12);
-       if (buf->fmt->bswap)
-               control |= SAA7134_RS_CONTROL_BSWAP;
-       if (buf->fmt->wswap)
-               control |= SAA7134_RS_CONTROL_WSWAP;
-       if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {
-               /* interlaced */
-               saa_writel(SAA7134_RS_BA1(0),base);
-               saa_writel(SAA7134_RS_BA2(0),base+bpl);
-               saa_writel(SAA7134_RS_PITCH(0),bpl*2);
-       } else {
-               /* non-interlaced */
-               saa_writel(SAA7134_RS_BA1(0),base);
-               saa_writel(SAA7134_RS_BA2(0),base);
-               saa_writel(SAA7134_RS_PITCH(0),bpl);
-       }
-       saa_writel(SAA7134_RS_CONTROL(0),control);
-
-       if (buf->fmt->planar) {
-               /* DMA: setup channel 4+5 (= planar task A) */
-               bpl_uv   = bpl >> buf->fmt->hshift;
-               lines_uv = buf->vb.height >> buf->fmt->vshift;
-               base2    = base + bpl * buf->vb.height;
-               base3    = base2 + bpl_uv * lines_uv;
-               if (buf->fmt->uvswap)
-                       tmp = base2, base2 = base3, base3 = tmp;
-               dprintk("uv: bpl=%ld lines=%ld base2/3=%ld/%ld\n",
-                       bpl_uv,lines_uv,base2,base3);
-               if (V4L2_FIELD_HAS_BOTH(buf->vb.field)) {
-                       /* interlaced */
-                       saa_writel(SAA7134_RS_BA1(4),base2);
-                       saa_writel(SAA7134_RS_BA2(4),base2+bpl_uv);
-                       saa_writel(SAA7134_RS_PITCH(4),bpl_uv*2);
-                       saa_writel(SAA7134_RS_BA1(5),base3);
-                       saa_writel(SAA7134_RS_BA2(5),base3+bpl_uv);
-                       saa_writel(SAA7134_RS_PITCH(5),bpl_uv*2);
-               } else {
-                       /* non-interlaced */
-                       saa_writel(SAA7134_RS_BA1(4),base2);
-                       saa_writel(SAA7134_RS_BA2(4),base2);
-                       saa_writel(SAA7134_RS_PITCH(4),bpl_uv);
-                       saa_writel(SAA7134_RS_BA1(5),base3);
-                       saa_writel(SAA7134_RS_BA2(5),base3);
-                       saa_writel(SAA7134_RS_PITCH(5),bpl_uv);
-               }
-               saa_writel(SAA7134_RS_CONTROL(4),control);
-               saa_writel(SAA7134_RS_CONTROL(5),control);
-       }
-
-       /* start DMA */
-       saa7134_set_dmabits(dev);
-       mod_timer(&dev->video_q.timeout, jiffies+BUFFER_TIMEOUT);
-       return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q,
-                         struct videobuf_buffer *vb,
-                         enum v4l2_field field)
-{
-       struct saa7134_fh *fh = q->priv_data;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-       unsigned int size;
-       int err;
-
-       /* sanity checks */
-       if (NULL == fh->fmt)
-               return -EINVAL;
-       if (fh->width    < 48 ||
-           fh->height   < 32 ||
-           fh->width/4  > dev->crop_current.width  ||
-           fh->height/4 > dev->crop_current.height ||
-           fh->width    > dev->crop_bounds.width  ||
-           fh->height   > dev->crop_bounds.height)
-               return -EINVAL;
-       size = (fh->width * fh->height * fh->fmt->depth) >> 3;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-
-       dprintk("buffer_prepare [%d,size=%dx%d,bytes=%d,fields=%s,%s]\n",
-               vb->i,fh->width,fh->height,size,v4l2_field_names[field],
-               fh->fmt->name);
-       if (buf->vb.width  != fh->width  ||
-           buf->vb.height != fh->height ||
-           buf->vb.size   != size       ||
-           buf->vb.field  != field      ||
-           buf->fmt       != fh->fmt) {
-               saa7134_dma_free(q,buf);
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.size   = size;
-               buf->vb.field  = field;
-               buf->fmt       = fh->fmt;
-               buf->pt        = &fh->pt_cap;
-               dev->video_q.curr = NULL;
-
-               err = videobuf_iolock(q,&buf->vb,&dev->ovbuf);
-               if (err)
-                       goto oops;
-               err = saa7134_pgtable_build(dev->pci,buf->pt,
-                                           dma->sglist,
-                                           dma->sglen,
-                                           saa7134_buffer_startpage(buf));
-               if (err)
-                       goto oops;
-       }
-       buf->vb.state = VIDEOBUF_PREPARED;
-       buf->activate = buffer_activate;
-       return 0;
-
- oops:
-       saa7134_dma_free(q,buf);
-       return err;
-}
-
-static int
-buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-       struct saa7134_fh *fh = q->priv_data;
-
-       *size = fh->fmt->depth * fh->width * fh->height >> 3;
-       if (0 == *count)
-               *count = gbuffers;
-       *count = saa7134_buffer_count(*size,*count);
-       return 0;
-}
-
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct saa7134_fh *fh = q->priv_data;
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-
-       saa7134_buffer_queue(fh->dev,&fh->dev->video_q,buf);
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-       struct saa7134_buf *buf = container_of(vb,struct saa7134_buf,vb);
-
-       saa7134_dma_free(q,buf);
-}
-
-static struct videobuf_queue_ops video_qops = {
-       .buf_setup    = buffer_setup,
-       .buf_prepare  = buffer_prepare,
-       .buf_queue    = buffer_queue,
-       .buf_release  = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-int saa7134_g_ctrl_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, struct v4l2_control *c)
-{
-       const struct v4l2_queryctrl* ctrl;
-
-       ctrl = ctrl_by_id(c->id);
-       if (NULL == ctrl)
-               return -EINVAL;
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               c->value = dev->ctl_bright;
-               break;
-       case V4L2_CID_HUE:
-               c->value = dev->ctl_hue;
-               break;
-       case V4L2_CID_CONTRAST:
-               c->value = dev->ctl_contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               c->value = dev->ctl_saturation;
-               break;
-       case V4L2_CID_AUDIO_MUTE:
-               c->value = dev->ctl_mute;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               c->value = dev->ctl_volume;
-               break;
-       case V4L2_CID_PRIVATE_INVERT:
-               c->value = dev->ctl_invert;
-               break;
-       case V4L2_CID_HFLIP:
-               c->value = dev->ctl_mirror;
-               break;
-       case V4L2_CID_PRIVATE_Y_EVEN:
-               c->value = dev->ctl_y_even;
-               break;
-       case V4L2_CID_PRIVATE_Y_ODD:
-               c->value = dev->ctl_y_odd;
-               break;
-       case V4L2_CID_PRIVATE_AUTOMUTE:
-               c->value = dev->ctl_automute;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(saa7134_g_ctrl_internal);
-
-static int saa7134_g_ctrl(struct file *file, void *priv, struct v4l2_control *c)
-{
-       struct saa7134_fh *fh = priv;
-
-       return saa7134_g_ctrl_internal(fh->dev, fh, c);
-}
-
-int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c)
-{
-       const struct v4l2_queryctrl* ctrl;
-       unsigned long flags;
-       int restart_overlay = 0;
-       int err;
-
-       /* When called from the empress code fh == NULL.
-          That needs to be fixed somehow, but for now this is
-          good enough. */
-       if (fh) {
-               err = v4l2_prio_check(&dev->prio, fh->prio);
-               if (0 != err)
-                       return err;
-       }
-       err = -EINVAL;
-
-       mutex_lock(&dev->lock);
-
-       ctrl = ctrl_by_id(c->id);
-       if (NULL == ctrl)
-               goto error;
-
-       dprintk("set_control name=%s val=%d\n",ctrl->name,c->value);
-       switch (ctrl->type) {
-       case V4L2_CTRL_TYPE_BOOLEAN:
-       case V4L2_CTRL_TYPE_MENU:
-       case V4L2_CTRL_TYPE_INTEGER:
-               if (c->value < ctrl->minimum)
-                       c->value = ctrl->minimum;
-               if (c->value > ctrl->maximum)
-                       c->value = ctrl->maximum;
-               break;
-       default:
-               /* nothing */;
-       };
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               dev->ctl_bright = c->value;
-               saa_writeb(SAA7134_DEC_LUMA_BRIGHT, dev->ctl_bright);
-               break;
-       case V4L2_CID_HUE:
-               dev->ctl_hue = c->value;
-               saa_writeb(SAA7134_DEC_CHROMA_HUE, dev->ctl_hue);
-               break;
-       case V4L2_CID_CONTRAST:
-               dev->ctl_contrast = c->value;
-               saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
-                          dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
-               break;
-       case V4L2_CID_SATURATION:
-               dev->ctl_saturation = c->value;
-               saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
-                          dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
-               break;
-       case V4L2_CID_AUDIO_MUTE:
-               dev->ctl_mute = c->value;
-               saa7134_tvaudio_setmute(dev);
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               dev->ctl_volume = c->value;
-               saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
-               break;
-       case V4L2_CID_PRIVATE_INVERT:
-               dev->ctl_invert = c->value;
-               saa_writeb(SAA7134_DEC_LUMA_CONTRAST,
-                          dev->ctl_invert ? -dev->ctl_contrast : dev->ctl_contrast);
-               saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
-                          dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
-               break;
-       case V4L2_CID_HFLIP:
-               dev->ctl_mirror = c->value;
-               restart_overlay = 1;
-               break;
-       case V4L2_CID_PRIVATE_Y_EVEN:
-               dev->ctl_y_even = c->value;
-               restart_overlay = 1;
-               break;
-       case V4L2_CID_PRIVATE_Y_ODD:
-               dev->ctl_y_odd = c->value;
-               restart_overlay = 1;
-               break;
-       case V4L2_CID_PRIVATE_AUTOMUTE:
-       {
-               struct v4l2_priv_tun_config tda9887_cfg;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv = &dev->tda9887_conf;
-
-               dev->ctl_automute = c->value;
-               if (dev->tda9887_conf) {
-                       if (dev->ctl_automute)
-                               dev->tda9887_conf |= TDA9887_AUTOMUTE;
-                       else
-                               dev->tda9887_conf &= ~TDA9887_AUTOMUTE;
-
-                       saa_call_all(dev, tuner, s_config, &tda9887_cfg);
-               }
-               break;
-       }
-       default:
-               goto error;
-       }
-       if (restart_overlay && fh && res_check(fh, RESOURCE_OVERLAY)) {
-               spin_lock_irqsave(&dev->slock,flags);
-               stop_preview(dev,fh);
-               start_preview(dev,fh);
-               spin_unlock_irqrestore(&dev->slock,flags);
-       }
-       err = 0;
-
-error:
-       mutex_unlock(&dev->lock);
-       return err;
-}
-EXPORT_SYMBOL_GPL(saa7134_s_ctrl_internal);
-
-static int saa7134_s_ctrl(struct file *file, void *f, struct v4l2_control *c)
-{
-       struct saa7134_fh *fh = f;
-
-       return saa7134_s_ctrl_internal(fh->dev, fh, c);
-}
-
-/* ------------------------------------------------------------------ */
-
-static struct videobuf_queue* saa7134_queue(struct saa7134_fh *fh)
-{
-       struct videobuf_queue* q = NULL;
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               q = &fh->cap;
-               break;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               q = &fh->vbi;
-               break;
-       default:
-               BUG();
-       }
-       return q;
-}
-
-static int saa7134_resource(struct saa7134_fh *fh)
-{
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return RESOURCE_VIDEO;
-
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               return RESOURCE_VBI;
-
-       BUG();
-       return 0;
-}
-
-static int video_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct saa7134_dev *dev = video_drvdata(file);
-       struct saa7134_fh *fh;
-       enum v4l2_buf_type type = 0;
-       int radio = 0;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       dprintk("open dev=%s radio=%d type=%s\n", video_device_node_name(vdev),
-               radio, v4l2_type_names[type]);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-       if (NULL == fh)
-               return -ENOMEM;
-
-       file->private_data = fh;
-       fh->dev      = dev;
-       fh->radio    = radio;
-       fh->type     = type;
-       fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-       fh->width    = 720;
-       fh->height   = 576;
-       v4l2_prio_open(&dev->prio, &fh->prio);
-
-       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, NULL);
-       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),
-                           fh, NULL);
-       saa7134_pgtable_alloc(dev->pci,&fh->pt_cap);
-       saa7134_pgtable_alloc(dev->pci,&fh->pt_vbi);
-
-       if (fh->radio) {
-               /* switch to radio mode */
-               saa7134_tvaudio_setinput(dev,&card(dev).radio);
-               saa_call_all(dev, tuner, s_radio);
-       } else {
-               /* switch to video/vbi mode */
-               video_mux(dev,dev->ctl_input);
-       }
-       return 0;
-}
-
-static ssize_t
-video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-       struct saa7134_fh *fh = file->private_data;
-
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (res_locked(fh->dev,RESOURCE_VIDEO))
-                       return -EBUSY;
-               return videobuf_read_one(saa7134_queue(fh),
-                                        data, count, ppos,
-                                        file->f_flags & O_NONBLOCK);
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (!res_get(fh->dev,fh,RESOURCE_VBI))
-                       return -EBUSY;
-               return videobuf_read_stream(saa7134_queue(fh),
-                                           data, count, ppos, 1,
-                                           file->f_flags & O_NONBLOCK);
-               break;
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-static unsigned int
-video_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct saa7134_fh *fh = file->private_data;
-       struct videobuf_buffer *buf = NULL;
-       unsigned int rc = 0;
-
-       if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)
-               return videobuf_poll_stream(file, &fh->vbi, wait);
-
-       if (res_check(fh,RESOURCE_VIDEO)) {
-               mutex_lock(&fh->cap.vb_lock);
-               if (!list_empty(&fh->cap.stream))
-                       buf = list_entry(fh->cap.stream.next, struct videobuf_buffer, stream);
-       } else {
-               mutex_lock(&fh->cap.vb_lock);
-               if (UNSET == fh->cap.read_off) {
-                       /* need to capture a new frame */
-                       if (res_locked(fh->dev,RESOURCE_VIDEO))
-                               goto err;
-                       if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field))
-                               goto err;
-                       fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
-                       fh->cap.read_off = 0;
-               }
-               buf = fh->cap.read_buf;
-       }
-
-       if (!buf)
-               goto err;
-
-       poll_wait(file, &buf->done, wait);
-       if (buf->state == VIDEOBUF_DONE ||
-           buf->state == VIDEOBUF_ERROR)
-               rc = POLLIN|POLLRDNORM;
-       mutex_unlock(&fh->cap.vb_lock);
-       return rc;
-
-err:
-       mutex_unlock(&fh->cap.vb_lock);
-       return POLLERR;
-}
-
-static int video_release(struct file *file)
-{
-       struct saa7134_fh  *fh  = file->private_data;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa6588_command cmd;
-       unsigned long flags;
-
-       saa7134_tvaudio_close(dev);
-
-       /* turn off overlay */
-       if (res_check(fh, RESOURCE_OVERLAY)) {
-               spin_lock_irqsave(&dev->slock,flags);
-               stop_preview(dev,fh);
-               spin_unlock_irqrestore(&dev->slock,flags);
-               res_free(dev,fh,RESOURCE_OVERLAY);
-       }
-
-       /* stop video capture */
-       if (res_check(fh, RESOURCE_VIDEO)) {
-               videobuf_streamoff(&fh->cap);
-               res_free(dev,fh,RESOURCE_VIDEO);
-       }
-       if (fh->cap.read_buf) {
-               buffer_release(&fh->cap,fh->cap.read_buf);
-               kfree(fh->cap.read_buf);
-       }
-
-       /* stop vbi capture */
-       if (res_check(fh, RESOURCE_VBI)) {
-               videobuf_stop(&fh->vbi);
-               res_free(dev,fh,RESOURCE_VBI);
-       }
-
-       /* ts-capture will not work in planar mode, so turn it off Hac: 04.05*/
-       saa_andorb(SAA7134_OFMT_VIDEO_A, 0x1f, 0);
-       saa_andorb(SAA7134_OFMT_VIDEO_B, 0x1f, 0);
-       saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0);
-       saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0);
-
-       saa_call_all(dev, core, s_power, 0);
-       if (fh->radio)
-               saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
-
-       /* free stuff */
-       videobuf_mmap_free(&fh->cap);
-       videobuf_mmap_free(&fh->vbi);
-       saa7134_pgtable_free(dev->pci,&fh->pt_cap);
-       saa7134_pgtable_free(dev->pci,&fh->pt_vbi);
-
-       v4l2_prio_close(&dev->prio, fh->prio);
-       file->private_data = NULL;
-       kfree(fh);
-       return 0;
-}
-
-static int video_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       struct saa7134_fh *fh = file->private_data;
-
-       return videobuf_mmap_mapper(saa7134_queue(fh), vma);
-}
-
-static ssize_t radio_read(struct file *file, char __user *data,
-                        size_t count, loff_t *ppos)
-{
-       struct saa7134_fh *fh = file->private_data;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa6588_command cmd;
-
-       cmd.block_count = count/3;
-       cmd.buffer = data;
-       cmd.instance = file;
-       cmd.result = -ENODEV;
-
-       saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd);
-
-       return cmd.result;
-}
-
-static unsigned int radio_poll(struct file *file, poll_table *wait)
-{
-       struct saa7134_fh *fh = file->private_data;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa6588_command cmd;
-
-       cmd.instance = file;
-       cmd.event_list = wait;
-       cmd.result = -ENODEV;
-       saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd);
-
-       return cmd.result;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int saa7134_try_get_set_fmt_vbi_cap(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa7134_tvnorm *norm = dev->tvnorm;
-
-       f->fmt.vbi.sampling_rate = 6750000 * 4;
-       f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
-       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset = 64 * 4;
-       f->fmt.vbi.start[0] = norm->vbi_v_start_0;
-       f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
-       f->fmt.vbi.start[1] = norm->vbi_v_start_1;
-       f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
-       f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */
-
-       return 0;
-}
-
-static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-
-       f->fmt.pix.width        = fh->width;
-       f->fmt.pix.height       = fh->height;
-       f->fmt.pix.field        = fh->cap.field;
-       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fh->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-       return 0;
-}
-
-static int saa7134_g_fmt_vid_overlay(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-
-       if (saa7134_no_overlay > 0) {
-               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-       f->fmt.win = fh->win;
-
-       return 0;
-}
-
-static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa7134_format *fmt;
-       enum v4l2_field field;
-       unsigned int maxw, maxh;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       field = f->fmt.pix.field;
-       maxw  = min(dev->crop_current.width*4,  dev->crop_bounds.width);
-       maxh  = min(dev->crop_current.height*4, dev->crop_bounds.height);
-
-       if (V4L2_FIELD_ANY == field) {
-               field = (f->fmt.pix.height > maxh/2)
-                       ? V4L2_FIELD_INTERLACED
-                       : V4L2_FIELD_BOTTOM;
-       }
-       switch (field) {
-       case V4L2_FIELD_TOP:
-       case V4L2_FIELD_BOTTOM:
-               maxh = maxh / 2;
-               break;
-       case V4L2_FIELD_INTERLACED:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       f->fmt.pix.field = field;
-       if (f->fmt.pix.width  < 48)
-               f->fmt.pix.width  = 48;
-       if (f->fmt.pix.height < 32)
-               f->fmt.pix.height = 32;
-       if (f->fmt.pix.width > maxw)
-               f->fmt.pix.width = maxw;
-       if (f->fmt.pix.height > maxh)
-               f->fmt.pix.height = maxh;
-       f->fmt.pix.width &= ~0x03;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static int saa7134_try_fmt_vid_overlay(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (saa7134_no_overlay > 0) {
-               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       return verify_preview(dev, &f->fmt.win);
-}
-
-static int saa7134_s_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-       int err;
-
-       err = saa7134_try_fmt_vid_cap(file, priv, f);
-       if (0 != err)
-               return err;
-
-       fh->fmt       = format_by_fourcc(f->fmt.pix.pixelformat);
-       fh->width     = f->fmt.pix.width;
-       fh->height    = f->fmt.pix.height;
-       fh->cap.field = f->fmt.pix.field;
-       return 0;
-}
-
-static int saa7134_s_fmt_vid_overlay(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int err;
-       unsigned long flags;
-
-       if (saa7134_no_overlay > 0) {
-               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-       err = verify_preview(dev, &f->fmt.win);
-       if (0 != err)
-               return err;
-
-       mutex_lock(&dev->lock);
-
-       fh->win    = f->fmt.win;
-       fh->nclips = f->fmt.win.clipcount;
-
-       if (fh->nclips > 8)
-               fh->nclips = 8;
-
-       if (copy_from_user(fh->clips, f->fmt.win.clips,
-                          sizeof(struct v4l2_clip)*fh->nclips)) {
-               mutex_unlock(&dev->lock);
-               return -EFAULT;
-       }
-
-       if (res_check(fh, RESOURCE_OVERLAY)) {
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev, fh);
-               start_preview(dev, fh);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       }
-
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c)
-{
-       const struct v4l2_queryctrl *ctrl;
-
-       if ((c->id <  V4L2_CID_BASE ||
-            c->id >= V4L2_CID_LASTP1) &&
-           (c->id <  V4L2_CID_PRIVATE_BASE ||
-            c->id >= V4L2_CID_PRIVATE_LASTP1))
-               return -EINVAL;
-       ctrl = ctrl_by_id(c->id);
-       *c = (NULL != ctrl) ? *ctrl : no_ctrl;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(saa7134_queryctrl);
-
-static int saa7134_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *i)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       unsigned int n;
-
-       n = i->index;
-       if (n >= SAA7134_INPUT_MAX)
-               return -EINVAL;
-       if (NULL == card_in(dev, i->index).name)
-               return -EINVAL;
-       i->index = n;
-       i->type  = V4L2_INPUT_TYPE_CAMERA;
-       strcpy(i->name, card_in(dev, n).name);
-       if (card_in(dev, n).tv)
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       i->audioset = 1;
-       if (n == dev->ctl_input) {
-               int v1 = saa_readb(SAA7134_STATUS_VIDEO1);
-               int v2 = saa_readb(SAA7134_STATUS_VIDEO2);
-
-               if (0 != (v1 & 0x40))
-                       i->status |= V4L2_IN_ST_NO_H_LOCK;
-               if (0 != (v2 & 0x40))
-                       i->status |= V4L2_IN_ST_NO_SYNC;
-               if (0 != (v2 & 0x0e))
-                       i->status |= V4L2_IN_ST_MACROVISION;
-       }
-       i->std = SAA7134_NORMS;
-       return 0;
-}
-
-static int saa7134_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       *i = dev->ctl_input;
-       return 0;
-}
-
-static int saa7134_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int err;
-
-       err = v4l2_prio_check(&dev->prio, fh->prio);
-       if (0 != err)
-               return err;
-
-       if (i >= SAA7134_INPUT_MAX)
-               return -EINVAL;
-       if (NULL == card_in(dev, i).name)
-               return -EINVAL;
-       mutex_lock(&dev->lock);
-       video_mux(dev, i);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-static int saa7134_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       unsigned int tuner_type = dev->tuner_type;
-
-       strcpy(cap->driver, "saa7134");
-       strlcpy(cap->card, saa7134_boards[dev->board].name,
-               sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->capabilities =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_VBI_CAPTURE |
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING |
-               V4L2_CAP_TUNER;
-       if (dev->has_rds)
-               cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
-       if (saa7134_no_overlay <= 0)
-               cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
-
-       if ((tuner_type == TUNER_ABSENT) || (tuner_type == UNSET))
-               cap->capabilities &= ~V4L2_CAP_TUNER;
-       return 0;
-}
-
-int saa7134_s_std_internal(struct saa7134_dev *dev, struct saa7134_fh *fh, v4l2_std_id *id)
-{
-       unsigned long flags;
-       unsigned int i;
-       v4l2_std_id fixup;
-       int err;
-
-       /* When called from the empress code fh == NULL.
-          That needs to be fixed somehow, but for now this is
-          good enough. */
-       if (fh) {
-               err = v4l2_prio_check(&dev->prio, fh->prio);
-               if (0 != err)
-                       return err;
-       } else if (res_locked(dev, RESOURCE_OVERLAY)) {
-               /* Don't change the std from the mpeg device
-                  if overlay is active. */
-               return -EBUSY;
-       }
-
-       for (i = 0; i < TVNORMS; i++)
-               if (*id == tvnorms[i].id)
-                       break;
-
-       if (i == TVNORMS)
-               for (i = 0; i < TVNORMS; i++)
-                       if (*id & tvnorms[i].id)
-                               break;
-       if (i == TVNORMS)
-               return -EINVAL;
-
-       if ((*id & V4L2_STD_SECAM) && (secam[0] != '-')) {
-               if (secam[0] == 'L' || secam[0] == 'l') {
-                       if (secam[1] == 'C' || secam[1] == 'c')
-                               fixup = V4L2_STD_SECAM_LC;
-                       else
-                               fixup = V4L2_STD_SECAM_L;
-               } else {
-                       if (secam[0] == 'D' || secam[0] == 'd')
-                               fixup = V4L2_STD_SECAM_DK;
-                       else
-                               fixup = V4L2_STD_SECAM;
-               }
-               for (i = 0; i < TVNORMS; i++) {
-                       if (fixup == tvnorms[i].id)
-                               break;
-               }
-               if (i == TVNORMS)
-                       return -EINVAL;
-       }
-
-       *id = tvnorms[i].id;
-
-       mutex_lock(&dev->lock);
-       if (fh && res_check(fh, RESOURCE_OVERLAY)) {
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev, fh);
-               spin_unlock_irqrestore(&dev->slock, flags);
-
-               set_tvnorm(dev, &tvnorms[i]);
-
-               spin_lock_irqsave(&dev->slock, flags);
-               start_preview(dev, fh);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       } else
-               set_tvnorm(dev, &tvnorms[i]);
-
-       saa7134_tvaudio_do_scan(dev);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(saa7134_s_std_internal);
-
-static int saa7134_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct saa7134_fh *fh = priv;
-
-       return saa7134_s_std_internal(fh->dev, fh, id);
-}
-
-static int saa7134_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       *id = dev->tvnorm->id;
-       return 0;
-}
-
-static int saa7134_cropcap(struct file *file, void *priv,
-                                       struct v4l2_cropcap *cap)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-               return -EINVAL;
-       cap->bounds  = dev->crop_bounds;
-       cap->defrect = dev->crop_defrect;
-       cap->pixelaspect.numerator   = 1;
-       cap->pixelaspect.denominator = 1;
-       if (dev->tvnorm->id & V4L2_STD_525_60) {
-               cap->pixelaspect.numerator   = 11;
-               cap->pixelaspect.denominator = 10;
-       }
-       if (dev->tvnorm->id & V4L2_STD_625_50) {
-               cap->pixelaspect.numerator   = 54;
-               cap->pixelaspect.denominator = 59;
-       }
-       return 0;
-}
-
-static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-               return -EINVAL;
-       crop->c = dev->crop_current;
-       return 0;
-}
-
-static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-       struct v4l2_rect *b = &dev->crop_bounds;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
-               return -EINVAL;
-       if (crop->c.height < 0)
-               return -EINVAL;
-       if (crop->c.width < 0)
-               return -EINVAL;
-
-       if (res_locked(fh->dev, RESOURCE_OVERLAY))
-               return -EBUSY;
-       if (res_locked(fh->dev, RESOURCE_VIDEO))
-               return -EBUSY;
-
-       if (crop->c.top < b->top)
-               crop->c.top = b->top;
-       if (crop->c.top > b->top + b->height)
-               crop->c.top = b->top + b->height;
-       if (crop->c.height > b->top - crop->c.top + b->height)
-               crop->c.height = b->top - crop->c.top + b->height;
-
-       if (crop->c.left < b->left)
-               crop->c.left = b->left;
-       if (crop->c.left > b->left + b->width)
-               crop->c.left = b->left + b->width;
-       if (crop->c.width > b->left - crop->c.left + b->width)
-               crop->c.width = b->left - crop->c.left + b->width;
-
-       dev->crop_current = crop->c;
-       return 0;
-}
-
-static int saa7134_g_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int n;
-
-       if (0 != t->index)
-               return -EINVAL;
-       memset(t, 0, sizeof(*t));
-       for (n = 0; n < SAA7134_INPUT_MAX; n++) {
-               if (card_in(dev, n).tv)
-                       break;
-       }
-       if (n == SAA7134_INPUT_MAX)
-               return -EINVAL;
-       if (NULL != card_in(dev, n).name) {
-               strcpy(t->name, "Television");
-               t->type = V4L2_TUNER_ANALOG_TV;
-               t->capability = V4L2_TUNER_CAP_NORM |
-                       V4L2_TUNER_CAP_STEREO |
-                       V4L2_TUNER_CAP_LANG1 |
-                       V4L2_TUNER_CAP_LANG2;
-               t->rangehigh = 0xffffffffUL;
-               t->rxsubchans = saa7134_tvaudio_getstereo(dev);
-               t->audmode = saa7134_tvaudio_rx2mode(t->rxsubchans);
-       }
-       if (0 != (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03))
-               t->signal = 0xffff;
-       return 0;
-}
-
-static int saa7134_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int rx, mode, err;
-
-       err = v4l2_prio_check(&dev->prio, fh->prio);
-       if (0 != err)
-               return err;
-
-       mode = dev->thread.mode;
-       if (UNSET == mode) {
-               rx   = saa7134_tvaudio_getstereo(dev);
-               mode = saa7134_tvaudio_rx2mode(rx);
-       }
-       if (mode != t->audmode)
-               dev->thread.mode = t->audmode;
-
-       return 0;
-}
-
-static int saa7134_g_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->ctl_freq;
-
-       return 0;
-}
-
-static int saa7134_s_frequency(struct file *file, void *priv,
-                                       struct v4l2_frequency *f)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int err;
-
-       err = v4l2_prio_check(&dev->prio, fh->prio);
-       if (0 != err)
-               return err;
-
-       if (0 != f->tuner)
-               return -EINVAL;
-       if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
-               return -EINVAL;
-       if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
-               return -EINVAL;
-       mutex_lock(&dev->lock);
-       dev->ctl_freq = f->frequency;
-
-       saa_call_all(dev, tuner, s_frequency, f);
-
-       saa7134_tvaudio_do_scan(dev);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-static int saa7134_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       strcpy(a->name, "audio");
-       return 0;
-}
-
-static int saa7134_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       return 0;
-}
-
-static int saa7134_g_priority(struct file *file, void *f, enum v4l2_priority *p)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-
-       *p = v4l2_prio_max(&dev->prio);
-       return 0;
-}
-
-static int saa7134_s_priority(struct file *file, void *f,
-                                       enum v4l2_priority prio)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-
-       return v4l2_prio_change(&dev->prio, &fh->prio, prio);
-}
-
-static int saa7134_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (f->index >= FORMATS)
-               return -EINVAL;
-
-       strlcpy(f->description, formats[f->index].name,
-               sizeof(f->description));
-
-       f->pixelformat = formats[f->index].fourcc;
-
-       return 0;
-}
-
-static int saa7134_enum_fmt_vid_overlay(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (saa7134_no_overlay > 0) {
-               printk(KERN_ERR "V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
-               return -EINVAL;
-       }
-
-       if ((f->index >= FORMATS) || formats[f->index].planar)
-               return -EINVAL;
-
-       strlcpy(f->description, formats[f->index].name,
-               sizeof(f->description));
-
-       f->pixelformat = formats[f->index].fourcc;
-
-       return 0;
-}
-
-static int saa7134_g_fbuf(struct file *file, void *f,
-                               struct v4l2_framebuffer *fb)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-
-       *fb = dev->ovbuf;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-
-       return 0;
-}
-
-static int saa7134_s_fbuf(struct file *file, void *f,
-                                       struct v4l2_framebuffer *fb)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-       struct saa7134_format *fmt;
-
-       if (!capable(CAP_SYS_ADMIN) &&
-          !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* check args */
-       fmt = format_by_fourcc(fb->fmt.pixelformat);
-       if (NULL == fmt)
-               return -EINVAL;
-
-       /* ok, accept it */
-       dev->ovbuf = *fb;
-       dev->ovfmt = fmt;
-       if (0 == dev->ovbuf.fmt.bytesperline)
-               dev->ovbuf.fmt.bytesperline =
-                       dev->ovbuf.fmt.width*fmt->depth/8;
-       return 0;
-}
-
-static int saa7134_overlay(struct file *file, void *f, unsigned int on)
-{
-       struct saa7134_fh *fh = f;
-       struct saa7134_dev *dev = fh->dev;
-       unsigned long flags;
-
-       if (on) {
-               if (saa7134_no_overlay > 0) {
-                       dprintk("no_overlay\n");
-                       return -EINVAL;
-               }
-
-               if (!res_get(dev, fh, RESOURCE_OVERLAY))
-                       return -EBUSY;
-               spin_lock_irqsave(&dev->slock, flags);
-               start_preview(dev, fh);
-               spin_unlock_irqrestore(&dev->slock, flags);
-       }
-       if (!on) {
-               if (!res_check(fh, RESOURCE_OVERLAY))
-                       return -EINVAL;
-               spin_lock_irqsave(&dev->slock, flags);
-               stop_preview(dev, fh);
-               spin_unlock_irqrestore(&dev->slock, flags);
-               res_free(dev, fh, RESOURCE_OVERLAY);
-       }
-       return 0;
-}
-
-static int saa7134_reqbufs(struct file *file, void *priv,
-                                       struct v4l2_requestbuffers *p)
-{
-       struct saa7134_fh *fh = priv;
-       return videobuf_reqbufs(saa7134_queue(fh), p);
-}
-
-static int saa7134_querybuf(struct file *file, void *priv,
-                                       struct v4l2_buffer *b)
-{
-       struct saa7134_fh *fh = priv;
-       return videobuf_querybuf(saa7134_queue(fh), b);
-}
-
-static int saa7134_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct saa7134_fh *fh = priv;
-       return videobuf_qbuf(saa7134_queue(fh), b);
-}
-
-static int saa7134_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct saa7134_fh *fh = priv;
-       return videobuf_dqbuf(saa7134_queue(fh), b,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int saa7134_streamon(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int res = saa7134_resource(fh);
-
-       if (!res_get(dev, fh, res))
-               return -EBUSY;
-
-       return videobuf_streamon(saa7134_queue(fh));
-}
-
-static int saa7134_streamoff(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       int err;
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-       int res = saa7134_resource(fh);
-
-       err = videobuf_streamoff(saa7134_queue(fh));
-       if (err < 0)
-               return err;
-       res_free(dev, fh, res);
-       return 0;
-}
-
-static int saa7134_g_parm(struct file *file, void *fh,
-                               struct v4l2_streamparm *parm)
-{
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register (struct file *file, void *priv,
-                             struct v4l2_dbg_register *reg)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-       reg->val = saa_readb(reg->reg);
-       reg->size = 1;
-       return 0;
-}
-
-static int vidioc_s_register (struct file *file, void *priv,
-                               struct v4l2_dbg_register *reg)
-{
-       struct saa7134_fh *fh = priv;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-       saa_writeb(reg->reg&0xffffff, reg->val);
-       return 0;
-}
-#endif
-
-static int radio_querycap(struct file *file, void *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct saa7134_fh *fh = file->private_data;
-       struct saa7134_dev *dev = fh->dev;
-
-       strcpy(cap->driver, "saa7134");
-       strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-       cap->capabilities = V4L2_CAP_TUNER;
-       return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct saa7134_fh *fh = file->private_data;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       memset(t, 0, sizeof(*t));
-       strcpy(t->name, "Radio");
-       t->type = V4L2_TUNER_RADIO;
-
-       saa_call_all(dev, tuner, g_tuner, t);
-       if (dev->input->amux == TV) {
-               t->signal = 0xf800 - ((saa_readb(0x581) & 0x1f) << 11);
-               t->rxsubchans = (saa_readb(0x529) & 0x08) ?
-                               V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
-       }
-       return 0;
-}
-static int radio_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct saa7134_fh *fh = file->private_data;
-       struct saa7134_dev *dev = fh->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       saa_call_all(dev, tuner, s_tuner, t);
-       return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *i)
-{
-       if (i->index != 0)
-               return -EINVAL;
-
-       strcpy(i->name, "Radio");
-       i->type = V4L2_INPUT_TYPE_TUNER;
-
-       return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       memset(a, 0, sizeof(*a));
-       strcpy(a->name, "Radio");
-       return 0;
-}
-
-static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
-       return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *c)
-{
-       const struct v4l2_queryctrl *ctrl;
-
-       if (c->id <  V4L2_CID_BASE ||
-           c->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       if (c->id == V4L2_CID_AUDIO_MUTE) {
-               ctrl = ctrl_by_id(c->id);
-               *c = *ctrl;
-       } else
-               *c = no_ctrl;
-       return 0;
-}
-
-static const struct v4l2_file_operations video_fops =
-{
-       .owner    = THIS_MODULE,
-       .open     = video_open,
-       .release  = video_release,
-       .read     = video_read,
-       .poll     = video_poll,
-       .mmap     = video_mmap,
-       .ioctl    = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap                = saa7134_querycap,
-       .vidioc_enum_fmt_vid_cap        = saa7134_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap           = saa7134_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap         = saa7134_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap           = saa7134_s_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_overlay    = saa7134_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_overlay       = saa7134_g_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_overlay     = saa7134_try_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_overlay       = saa7134_s_fmt_vid_overlay,
-       .vidioc_g_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
-       .vidioc_try_fmt_vbi_cap         = saa7134_try_get_set_fmt_vbi_cap,
-       .vidioc_s_fmt_vbi_cap           = saa7134_try_get_set_fmt_vbi_cap,
-       .vidioc_g_audio                 = saa7134_g_audio,
-       .vidioc_s_audio                 = saa7134_s_audio,
-       .vidioc_cropcap                 = saa7134_cropcap,
-       .vidioc_reqbufs                 = saa7134_reqbufs,
-       .vidioc_querybuf                = saa7134_querybuf,
-       .vidioc_qbuf                    = saa7134_qbuf,
-       .vidioc_dqbuf                   = saa7134_dqbuf,
-       .vidioc_s_std                   = saa7134_s_std,
-       .vidioc_g_std                   = saa7134_g_std,
-       .vidioc_enum_input              = saa7134_enum_input,
-       .vidioc_g_input                 = saa7134_g_input,
-       .vidioc_s_input                 = saa7134_s_input,
-       .vidioc_queryctrl               = saa7134_queryctrl,
-       .vidioc_g_ctrl                  = saa7134_g_ctrl,
-       .vidioc_s_ctrl                  = saa7134_s_ctrl,
-       .vidioc_streamon                = saa7134_streamon,
-       .vidioc_streamoff               = saa7134_streamoff,
-       .vidioc_g_tuner                 = saa7134_g_tuner,
-       .vidioc_s_tuner                 = saa7134_s_tuner,
-       .vidioc_g_crop                  = saa7134_g_crop,
-       .vidioc_s_crop                  = saa7134_s_crop,
-       .vidioc_g_fbuf                  = saa7134_g_fbuf,
-       .vidioc_s_fbuf                  = saa7134_s_fbuf,
-       .vidioc_overlay                 = saa7134_overlay,
-       .vidioc_g_priority              = saa7134_g_priority,
-       .vidioc_s_priority              = saa7134_s_priority,
-       .vidioc_g_parm                  = saa7134_g_parm,
-       .vidioc_g_frequency             = saa7134_g_frequency,
-       .vidioc_s_frequency             = saa7134_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register              = vidioc_g_register,
-       .vidioc_s_register              = vidioc_s_register,
-#endif
-};
-
-static const struct v4l2_file_operations radio_fops = {
-       .owner    = THIS_MODULE,
-       .open     = video_open,
-       .read     = radio_read,
-       .release  = video_release,
-       .ioctl    = video_ioctl2,
-       .poll     = radio_poll,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap        = radio_querycap,
-       .vidioc_g_tuner         = radio_g_tuner,
-       .vidioc_enum_input      = radio_enum_input,
-       .vidioc_g_audio         = radio_g_audio,
-       .vidioc_s_tuner         = radio_s_tuner,
-       .vidioc_s_audio         = radio_s_audio,
-       .vidioc_s_input         = radio_s_input,
-       .vidioc_s_std           = radio_s_std,
-       .vidioc_queryctrl       = radio_queryctrl,
-       .vidioc_g_input         = radio_g_input,
-       .vidioc_g_ctrl          = saa7134_g_ctrl,
-       .vidioc_s_ctrl          = saa7134_s_ctrl,
-       .vidioc_g_frequency     = saa7134_g_frequency,
-       .vidioc_s_frequency     = saa7134_s_frequency,
-};
-
-/* ----------------------------------------------------------- */
-/* exported stuff                                              */
-
-struct video_device saa7134_video_template = {
-       .name                           = "saa7134-video",
-       .fops                           = &video_fops,
-       .ioctl_ops                      = &video_ioctl_ops,
-       .tvnorms                        = SAA7134_NORMS,
-       .current_norm                   = V4L2_STD_PAL,
-};
-
-struct video_device saa7134_radio_template = {
-       .name                   = "saa7134-radio",
-       .fops                   = &radio_fops,
-       .ioctl_ops              = &radio_ioctl_ops,
-};
-
-int saa7134_video_init1(struct saa7134_dev *dev)
-{
-       /* sanitycheck insmod options */
-       if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
-               gbuffers = 2;
-       if (gbufsize < 0 || gbufsize > gbufsize_max)
-               gbufsize = gbufsize_max;
-       gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
-
-       /* put some sensible defaults into the data structures ... */
-       dev->ctl_bright     = ctrl_by_id(V4L2_CID_BRIGHTNESS)->default_value;
-       dev->ctl_contrast   = ctrl_by_id(V4L2_CID_CONTRAST)->default_value;
-       dev->ctl_hue        = ctrl_by_id(V4L2_CID_HUE)->default_value;
-       dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
-       dev->ctl_volume     = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
-       dev->ctl_mute       = 1; // ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
-       dev->ctl_invert     = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
-       dev->ctl_automute   = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
-
-       if (dev->tda9887_conf && dev->ctl_automute)
-               dev->tda9887_conf |= TDA9887_AUTOMUTE;
-       dev->automute       = 0;
-
-       INIT_LIST_HEAD(&dev->video_q.queue);
-       init_timer(&dev->video_q.timeout);
-       dev->video_q.timeout.function = saa7134_buffer_timeout;
-       dev->video_q.timeout.data     = (unsigned long)(&dev->video_q);
-       dev->video_q.dev              = dev;
-
-       if (saa7134_boards[dev->board].video_out)
-               saa7134_videoport_init(dev);
-
-       return 0;
-}
-
-int saa7134_videoport_init(struct saa7134_dev *dev)
-{
-       /* enable video output */
-       int vo = saa7134_boards[dev->board].video_out;
-       int video_reg;
-       unsigned int vid_port_opts = saa7134_boards[dev->board].vid_port_opts;
-
-       /* Configure videoport */
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL0, video_out[vo][0]);
-       video_reg = video_out[vo][1];
-       if (vid_port_opts & SET_T_CODE_POLARITY_NON_INVERTED)
-               video_reg &= ~VP_T_CODE_P_INVERTED;
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL1, video_reg);
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL2, video_out[vo][2]);
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL4, video_out[vo][4]);
-       video_reg = video_out[vo][5];
-       if (vid_port_opts & SET_CLOCK_NOT_DELAYED)
-               video_reg &= ~VP_CLK_CTRL2_DELAYED;
-       if (vid_port_opts & SET_CLOCK_INVERTED)
-               video_reg |= VP_CLK_CTRL1_INVERTED;
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL5, video_reg);
-       video_reg = video_out[vo][6];
-       if (vid_port_opts & SET_VSYNC_OFF) {
-               video_reg &= ~VP_VS_TYPE_MASK;
-               video_reg |= VP_VS_TYPE_OFF;
-       }
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL6, video_reg);
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL7, video_out[vo][7]);
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL8, video_out[vo][8]);
-
-       /* Start videoport */
-       saa_writeb(SAA7134_VIDEO_PORT_CTRL3, video_out[vo][3]);
-
-       return 0;
-}
-
-int saa7134_video_init2(struct saa7134_dev *dev)
-{
-       /* init video hw */
-       set_tvnorm(dev,&tvnorms[0]);
-       video_mux(dev,0);
-       saa7134_tvaudio_setmute(dev);
-       saa7134_tvaudio_setvolume(dev,dev->ctl_volume);
-       return 0;
-}
-
-void saa7134_irq_video_signalchange(struct saa7134_dev *dev)
-{
-       static const char *st[] = {
-               "(no signal)", "NTSC", "PAL", "SECAM" };
-       u32 st1,st2;
-
-       st1 = saa_readb(SAA7134_STATUS_VIDEO1);
-       st2 = saa_readb(SAA7134_STATUS_VIDEO2);
-       dprintk("DCSDT: pll: %s, sync: %s, norm: %s\n",
-               (st1 & 0x40) ? "not locked" : "locked",
-               (st2 & 0x40) ? "no"         : "yes",
-               st[st1 & 0x03]);
-       dev->nosignal = (st1 & 0x40) || (st2 & 0x40)  || !(st2 & 0x1);
-
-       if (dev->nosignal) {
-               /* no video signal -> mute audio */
-               if (dev->ctl_automute)
-                       dev->automute = 1;
-               saa7134_tvaudio_setmute(dev);
-       } else {
-               /* wake up tvaudio audio carrier scan thread */
-               saa7134_tvaudio_do_scan(dev);
-       }
-
-       if ((st2 & 0x80) && !noninterlaced && !dev->nosignal)
-               saa_clearb(SAA7134_SYNC_CTRL, 0x20);
-       else
-               saa_setb(SAA7134_SYNC_CTRL, 0x20);
-
-       if (dev->mops && dev->mops->signal_change)
-               dev->mops->signal_change(dev);
-}
-
-
-void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status)
-{
-       enum v4l2_field field;
-
-       spin_lock(&dev->slock);
-       if (dev->video_q.curr) {
-               dev->video_fieldcount++;
-               field = dev->video_q.curr->vb.field;
-               if (V4L2_FIELD_HAS_BOTH(field)) {
-                       /* make sure we have seen both fields */
-                       if ((status & 0x10) == 0x00) {
-                               dev->video_q.curr->top_seen = 1;
-                               goto done;
-                       }
-                       if (!dev->video_q.curr->top_seen)
-                               goto done;
-               } else if (field == V4L2_FIELD_TOP) {
-                       if ((status & 0x10) != 0x10)
-                               goto done;
-               } else if (field == V4L2_FIELD_BOTTOM) {
-                       if ((status & 0x10) != 0x00)
-                               goto done;
-               }
-               dev->video_q.curr->vb.field_count = dev->video_fieldcount;
-               saa7134_buffer_finish(dev,&dev->video_q,VIDEOBUF_DONE);
-       }
-       saa7134_buffer_next(dev,&dev->video_q);
-
- done:
-       spin_unlock(&dev->slock);
-}
-
-/* ----------------------------------------------------------- */
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
deleted file mode 100644 (file)
index c24b651..0000000
+++ /dev/null
@@ -1,855 +0,0 @@
-/*
- *
- * v4l2 device driver for philips saa7134 based TV cards
- *
- * (c) 2001,02 Gerd Knorr <kraxel@bytesex.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.
- */
-
-#define SAA7134_VERSION "0, 2, 17"
-
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <linux/kdev_t.h>
-#include <linux/input.h>
-#include <linux/notifier.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <media/tuner.h>
-#include <media/rc-core.h>
-#include <media/ir-kbd-i2c.h>
-#include <media/videobuf-dma-sg.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
-#include <media/videobuf-dvb.h>
-#endif
-
-#define UNSET (-1U)
-
-/* ----------------------------------------------------------- */
-/* enums                                                       */
-
-enum saa7134_tvaudio_mode {
-       TVAUDIO_FM_MONO       = 1,
-       TVAUDIO_FM_BG_STEREO  = 2,
-       TVAUDIO_FM_SAT_STEREO = 3,
-       TVAUDIO_FM_K_STEREO   = 4,
-       TVAUDIO_NICAM_AM      = 5,
-       TVAUDIO_NICAM_FM      = 6,
-};
-
-enum saa7134_audio_in {
-       TV    = 1,
-       LINE1 = 2,
-       LINE2 = 3,
-       LINE2_LEFT,
-};
-
-enum saa7134_video_out {
-       CCIR656 = 1,
-};
-
-/* ----------------------------------------------------------- */
-/* static data                                                 */
-
-struct saa7134_tvnorm {
-       char          *name;
-       v4l2_std_id   id;
-
-       /* video decoder */
-       unsigned int  sync_control;
-       unsigned int  luma_control;
-       unsigned int  chroma_ctrl1;
-       unsigned int  chroma_gain;
-       unsigned int  chroma_ctrl2;
-       unsigned int  vgate_misc;
-
-       /* video scaler */
-       unsigned int  h_start;
-       unsigned int  h_stop;
-       unsigned int  video_v_start;
-       unsigned int  video_v_stop;
-       unsigned int  vbi_v_start_0;
-       unsigned int  vbi_v_stop_0;
-       unsigned int  src_timing;
-       unsigned int  vbi_v_start_1;
-};
-
-struct saa7134_tvaudio {
-       char         *name;
-       v4l2_std_id  std;
-       enum         saa7134_tvaudio_mode mode;
-       int          carr1;
-       int          carr2;
-};
-
-struct saa7134_format {
-       char           *name;
-       unsigned int   fourcc;
-       unsigned int   depth;
-       unsigned int   pm;
-       unsigned int   vshift;   /* vertical downsampling (for planar yuv) */
-       unsigned int   hshift;   /* horizontal downsampling (for planar yuv) */
-       unsigned int   bswap:1;
-       unsigned int   wswap:1;
-       unsigned int   yuv:1;
-       unsigned int   planar:1;
-       unsigned int   uvswap:1;
-};
-
-struct saa7134_card_ir {
-       struct rc_dev           *dev;
-
-       char                    name[32];
-       char                    phys[32];
-       unsigned                users;
-
-       u32                     polling;
-       u32                     last_gpio;
-       u32                     mask_keycode, mask_keydown, mask_keyup;
-
-       bool                    running;
-
-       struct timer_list       timer;
-
-       /* IR core raw decoding */
-       u32                     raw_decode;
-};
-
-/* ----------------------------------------------------------- */
-/* card configuration                                          */
-
-#define SAA7134_BOARD_NOAUTO        UNSET
-#define SAA7134_BOARD_UNKNOWN           0
-#define SAA7134_BOARD_PROTEUS_PRO       1
-#define SAA7134_BOARD_FLYVIDEO3000      2
-#define SAA7134_BOARD_FLYVIDEO2000      3
-#define SAA7134_BOARD_EMPRESS           4
-#define SAA7134_BOARD_MONSTERTV         5
-#define SAA7134_BOARD_MD9717            6
-#define SAA7134_BOARD_TVSTATION_RDS     7
-#define SAA7134_BOARD_CINERGY400       8
-#define SAA7134_BOARD_MD5044           9
-#define SAA7134_BOARD_KWORLD           10
-#define SAA7134_BOARD_CINERGY600       11
-#define SAA7134_BOARD_MD7134           12
-#define SAA7134_BOARD_TYPHOON_90031    13
-#define SAA7134_BOARD_ELSA             14
-#define SAA7134_BOARD_ELSA_500TV       15
-#define SAA7134_BOARD_ASUSTeK_TVFM7134 16
-#define SAA7134_BOARD_VA1000POWER      17
-#define SAA7134_BOARD_BMK_MPEX_NOTUNER 18
-#define SAA7134_BOARD_VIDEOMATE_TV     19
-#define SAA7134_BOARD_CRONOS_PLUS      20
-#define SAA7134_BOARD_10MOONSTVMASTER  21
-#define SAA7134_BOARD_MD2819           22
-#define SAA7134_BOARD_BMK_MPEX_TUNER   23
-#define SAA7134_BOARD_TVSTATION_DVR    24
-#define SAA7134_BOARD_ASUSTEK_TVFM7133 25
-#define SAA7134_BOARD_PINNACLE_PCTV_STEREO 26
-#define SAA7134_BOARD_MANLI_MTV002     27
-#define SAA7134_BOARD_MANLI_MTV001     28
-#define SAA7134_BOARD_TG3000TV         29
-#define SAA7134_BOARD_ECS_TVP3XP       30
-#define SAA7134_BOARD_ECS_TVP3XP_4CB5  31
-#define SAA7134_BOARD_AVACSSMARTTV     32
-#define SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER 33
-#define SAA7134_BOARD_NOVAC_PRIMETV7133 34
-#define SAA7134_BOARD_AVERMEDIA_STUDIO_305 35
-#define SAA7134_BOARD_UPMOST_PURPLE_TV 36
-#define SAA7134_BOARD_ITEMS_MTV005     37
-#define SAA7134_BOARD_CINERGY200       38
-#define SAA7134_BOARD_FLYTVPLATINUM_MINI 39
-#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40
-#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS 41
-#define SAA7134_BOARD_SABRENT_SBTTVFM  42
-#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43
-#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44
-#define SAA7134_BOARD_AVERMEDIA_STUDIO_307    45
-#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
-#define SAA7134_BOARD_CINERGY400_CARDBUS 47
-#define SAA7134_BOARD_CINERGY600_MK3   48
-#define SAA7134_BOARD_VIDEOMATE_GOLD_PLUS 49
-#define SAA7134_BOARD_PINNACLE_300I_DVBT_PAL 50
-#define SAA7134_BOARD_PROVIDEO_PV952   51
-#define SAA7134_BOARD_AVERMEDIA_305    52
-#define SAA7134_BOARD_ASUSTeK_TVFM7135 53
-#define SAA7134_BOARD_FLYTVPLATINUM_FM 54
-#define SAA7134_BOARD_FLYDVBTDUO 55
-#define SAA7134_BOARD_AVERMEDIA_307    56
-#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
-#define SAA7134_BOARD_ADS_INSTANT_TV 58
-#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
-#define SAA7134_BOARD_FLYDVBT_DUO_CARDBUS 60
-#define SAA7134_BOARD_PHILIPS_TOUGH 61
-#define SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII 62
-#define SAA7134_BOARD_KWORLD_XPERT 63
-#define SAA7134_BOARD_FLYTV_DIGIMATRIX 64
-#define SAA7134_BOARD_KWORLD_TERMINATOR 65
-#define SAA7134_BOARD_YUAN_TUN900 66
-#define SAA7134_BOARD_BEHOLD_409FM 67
-#define SAA7134_BOARD_GOTVIEW_7135 68
-#define SAA7134_BOARD_PHILIPS_EUROPA  69
-#define SAA7134_BOARD_VIDEOMATE_DVBT_300 70
-#define SAA7134_BOARD_VIDEOMATE_DVBT_200 71
-#define SAA7134_BOARD_RTD_VFG7350 72
-#define SAA7134_BOARD_RTD_VFG7330 73
-#define SAA7134_BOARD_FLYTVPLATINUM_MINI2 74
-#define SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180 75
-#define SAA7134_BOARD_MONSTERTV_MOBILE 76
-#define SAA7134_BOARD_PINNACLE_PCTV_110i 77
-#define SAA7134_BOARD_ASUSTeK_P7131_DUAL 78
-#define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS     79
-#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
-#define SAA7134_BOARD_PHILIPS_TIGER  81
-#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS  82
-#define SAA7134_BOARD_CINERGY250PCI 83
-#define SAA7134_BOARD_FLYDVB_TRIO 84
-#define SAA7134_BOARD_AVERMEDIA_777 85
-#define SAA7134_BOARD_FLYDVBT_LR301 86
-#define SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331 87
-#define SAA7134_BOARD_TEVION_DVBT_220RF 88
-#define SAA7134_BOARD_ELSA_700TV       89
-#define SAA7134_BOARD_KWORLD_ATSC110   90
-#define SAA7134_BOARD_AVERMEDIA_A169_B 91
-#define SAA7134_BOARD_AVERMEDIA_A169_B1 92
-#define SAA7134_BOARD_MD7134_BRIDGE_2     93
-#define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
-#define SAA7134_BOARD_FLYVIDEO3000_NTSC 95
-#define SAA7134_BOARD_MEDION_MD8800_QUADRO 96
-#define SAA7134_BOARD_FLYDVBS_LR300 97
-#define SAA7134_BOARD_PROTEUS_2309 98
-#define SAA7134_BOARD_AVERMEDIA_A16AR   99
-#define SAA7134_BOARD_ASUS_EUROPA2_HYBRID 100
-#define SAA7134_BOARD_PINNACLE_PCTV_310i  101
-#define SAA7134_BOARD_AVERMEDIA_STUDIO_507 102
-#define SAA7134_BOARD_VIDEOMATE_DVBT_200A  103
-#define SAA7134_BOARD_HAUPPAUGE_HVR1110    104
-#define SAA7134_BOARD_CINERGY_HT_PCMCIA    105
-#define SAA7134_BOARD_ENCORE_ENLTV         106
-#define SAA7134_BOARD_ENCORE_ENLTV_FM      107
-#define SAA7134_BOARD_CINERGY_HT_PCI       108
-#define SAA7134_BOARD_PHILIPS_TIGER_S      109
-#define SAA7134_BOARD_AVERMEDIA_M102      110
-#define SAA7134_BOARD_ASUS_P7131_4871     111
-#define SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA 112
-#define SAA7134_BOARD_ECS_TVP3XP_4CB6  113
-#define SAA7134_BOARD_KWORLD_DVBT_210 114
-#define SAA7134_BOARD_SABRENT_TV_PCB05     115
-#define SAA7134_BOARD_10MOONSTVMASTER3     116
-#define SAA7134_BOARD_AVERMEDIA_SUPER_007  117
-#define SAA7134_BOARD_BEHOLD_401       118
-#define SAA7134_BOARD_BEHOLD_403       119
-#define SAA7134_BOARD_BEHOLD_403FM     120
-#define SAA7134_BOARD_BEHOLD_405       121
-#define SAA7134_BOARD_BEHOLD_405FM     122
-#define SAA7134_BOARD_BEHOLD_407       123
-#define SAA7134_BOARD_BEHOLD_407FM     124
-#define SAA7134_BOARD_BEHOLD_409       125
-#define SAA7134_BOARD_BEHOLD_505FM     126
-#define SAA7134_BOARD_BEHOLD_507_9FM   127
-#define SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM 128
-#define SAA7134_BOARD_BEHOLD_607FM_MK3 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_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_BOARD_BEHOLD_H6      142
-#define SAA7134_BOARD_BEHOLD_M63      143
-#define SAA7134_BOARD_BEHOLD_M6_EXTRA    144
-#define SAA7134_BOARD_AVERMEDIA_M103    145
-#define SAA7134_BOARD_ASUSTeK_P7131_ANALOG 146
-#define SAA7134_BOARD_ASUSTeK_TIGER_3IN1   147
-#define SAA7134_BOARD_ENCORE_ENLTV_FM53 148
-#define SAA7134_BOARD_AVERMEDIA_M135A    149
-#define SAA7134_BOARD_REAL_ANGEL_220     150
-#define SAA7134_BOARD_ADS_INSTANT_HDTV_PCI  151
-#define SAA7134_BOARD_ASUSTeK_TIGER         152
-#define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
-#define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
-#define SAA7134_BOARD_HAUPPAUGE_HVR1150     155
-#define SAA7134_BOARD_HAUPPAUGE_HVR1120   156
-#define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157
-#define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158
-#define SAA7134_BOARD_BEHOLD_505RDS_MK5     159
-#define SAA7134_BOARD_BEHOLD_507RDS_MK3     160
-#define SAA7134_BOARD_BEHOLD_507RDS_MK5     161
-#define SAA7134_BOARD_BEHOLD_607FM_MK5      162
-#define SAA7134_BOARD_BEHOLD_609FM_MK3      163
-#define SAA7134_BOARD_BEHOLD_609FM_MK5      164
-#define SAA7134_BOARD_BEHOLD_607RDS_MK3     165
-#define SAA7134_BOARD_BEHOLD_607RDS_MK5     166
-#define SAA7134_BOARD_BEHOLD_609RDS_MK3     167
-#define SAA7134_BOARD_BEHOLD_609RDS_MK5     168
-#define SAA7134_BOARD_VIDEOMATE_S350        169
-#define SAA7134_BOARD_AVERMEDIA_STUDIO_505  170
-#define SAA7134_BOARD_BEHOLD_X7             171
-#define SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM 172
-#define SAA7134_BOARD_ZOLID_HYBRID_PCI         173
-#define SAA7134_BOARD_ASUS_EUROPA_HYBRID       174
-#define SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S 175
-#define SAA7134_BOARD_BEHOLD_505RDS_MK3     176
-#define SAA7134_BOARD_HAWELL_HW_404M7          177
-#define SAA7134_BOARD_BEHOLD_H7             178
-#define SAA7134_BOARD_BEHOLD_A7             179
-#define SAA7134_BOARD_AVERMEDIA_M733A       180
-#define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181
-#define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182
-#define SAA7134_BOARD_VIDEOMATE_M1F         183
-#define SAA7134_BOARD_ENCORE_ENLTV_FM3      184
-#define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185
-#define SAA7134_BOARD_BEHOLD_501            186
-#define SAA7134_BOARD_BEHOLD_503FM          187
-#define SAA7134_BOARD_SENSORAY811_911       188
-#define SAA7134_BOARD_KWORLD_PC150U         189
-#define SAA7134_BOARD_ASUSTeK_PS3_100      190
-
-#define SAA7134_MAXBOARDS 32
-#define SAA7134_INPUT_MAX 8
-
-/* ----------------------------------------------------------- */
-/* Since we support 2 remote types, lets tell them apart       */
-
-#define SAA7134_REMOTE_GPIO  1
-#define SAA7134_REMOTE_I2C   2
-
-/* ----------------------------------------------------------- */
-/* Video Output Port Register Initialization Options           */
-
-#define SET_T_CODE_POLARITY_NON_INVERTED       (1 << 0)
-#define SET_CLOCK_NOT_DELAYED                  (1 << 1)
-#define SET_CLOCK_INVERTED                     (1 << 2)
-#define SET_VSYNC_OFF                          (1 << 3)
-
-struct saa7134_input {
-       char                    *name;
-       unsigned int            vmux;
-       enum saa7134_audio_in   amux;
-       unsigned int            gpio;
-       unsigned int            tv:1;
-};
-
-enum saa7134_mpeg_type {
-       SAA7134_MPEG_UNUSED,
-       SAA7134_MPEG_EMPRESS,
-       SAA7134_MPEG_DVB,
-};
-
-enum saa7134_mpeg_ts_type {
-       SAA7134_MPEG_TS_PARALLEL = 0,
-       SAA7134_MPEG_TS_SERIAL,
-};
-
-struct saa7134_board {
-       char                    *name;
-       unsigned int            audio_clock;
-
-       /* input switching */
-       unsigned int            gpiomask;
-       struct saa7134_input    inputs[SAA7134_INPUT_MAX];
-       struct saa7134_input    radio;
-       struct saa7134_input    mute;
-
-       /* i2c chip info */
-       unsigned int            tuner_type;
-       unsigned int            radio_type;
-       unsigned char           tuner_addr;
-       unsigned char           radio_addr;
-       unsigned char           empress_addr;
-       unsigned char           rds_addr;
-
-       unsigned int            tda9887_conf;
-       unsigned int            tuner_config;
-
-       /* peripheral I/O */
-       enum saa7134_video_out  video_out;
-       enum saa7134_mpeg_type  mpeg;
-       enum saa7134_mpeg_ts_type ts_type;
-       unsigned int            vid_port_opts;
-       unsigned int            ts_force_val:1;
-};
-
-#define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
-#define card_is_empress(dev)  (SAA7134_MPEG_EMPRESS == saa7134_boards[dev->board].mpeg)
-#define card_is_dvb(dev)      (SAA7134_MPEG_DVB     == saa7134_boards[dev->board].mpeg)
-#define card_has_mpeg(dev)    (SAA7134_MPEG_UNUSED  != saa7134_boards[dev->board].mpeg)
-#define card(dev)             (saa7134_boards[dev->board])
-#define card_in(dev,n)        (saa7134_boards[dev->board].inputs[n])
-
-/* ----------------------------------------------------------- */
-/* device / file handle status                                 */
-
-#define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO         2
-#define RESOURCE_VBI           4
-
-#define INTERLACE_AUTO         0
-#define INTERLACE_ON           1
-#define INTERLACE_OFF          2
-
-#define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
-#define TS_BUFFER_TIMEOUT  msecs_to_jiffies(1000)  /* 1 second */
-
-struct saa7134_dev;
-struct saa7134_dma;
-
-/* saa7134 page table */
-struct saa7134_pgtable {
-       unsigned int               size;
-       __le32                     *cpu;
-       dma_addr_t                 dma;
-};
-
-/* tvaudio thread status */
-struct saa7134_thread {
-       struct task_struct         *thread;
-       unsigned int               scan1;
-       unsigned int               scan2;
-       unsigned int               mode;
-       unsigned int               stopped;
-};
-
-/* buffer for one video/vbi/ts frame */
-struct saa7134_buf {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       /* saa7134 specific */
-       struct saa7134_format   *fmt;
-       unsigned int            top_seen;
-       int (*activate)(struct saa7134_dev *dev,
-                       struct saa7134_buf *buf,
-                       struct saa7134_buf *next);
-
-       /* page tables */
-       struct saa7134_pgtable  *pt;
-};
-
-struct saa7134_dmaqueue {
-       struct saa7134_dev         *dev;
-       struct saa7134_buf         *curr;
-       struct list_head           queue;
-       struct timer_list          timeout;
-       unsigned int               need_two;
-};
-
-/* video filehandle status */
-struct saa7134_fh {
-       struct saa7134_dev         *dev;
-       unsigned int               radio;
-       enum v4l2_buf_type         type;
-       unsigned int               resources;
-       enum v4l2_priority         prio;
-
-       /* video overlay */
-       struct v4l2_window         win;
-       struct v4l2_clip           clips[8];
-       unsigned int               nclips;
-
-       /* video capture */
-       struct saa7134_format      *fmt;
-       unsigned int               width,height;
-       struct videobuf_queue      cap;
-       struct saa7134_pgtable     pt_cap;
-
-       /* vbi capture */
-       struct videobuf_queue      vbi;
-       struct saa7134_pgtable     pt_vbi;
-};
-
-/* dmasound dsp status */
-struct saa7134_dmasound {
-       struct mutex               lock;
-       int                        minor_mixer;
-       int                        minor_dsp;
-       unsigned int               users_dsp;
-
-       /* mixer */
-       enum saa7134_audio_in      input;
-       unsigned int               count;
-       unsigned int               line1;
-       unsigned int               line2;
-
-       /* dsp */
-       unsigned int               afmt;
-       unsigned int               rate;
-       unsigned int               channels;
-       unsigned int               recording_on;
-       unsigned int               dma_running;
-       unsigned int               blocks;
-       unsigned int               blksize;
-       unsigned int               bufsize;
-       struct saa7134_pgtable     pt;
-       struct videobuf_dmabuf     dma;
-       unsigned int               dma_blk;
-       unsigned int               read_offset;
-       unsigned int               read_count;
-       void *                     priv_data;
-       struct snd_pcm_substream   *substream;
-};
-
-/* ts/mpeg status */
-struct saa7134_ts {
-       /* TS capture */
-       struct saa7134_pgtable     pt_ts;
-       int                        nr_packets;
-       int                        nr_bufs;
-};
-
-/* ts/mpeg ops */
-struct saa7134_mpeg_ops {
-       enum saa7134_mpeg_type     type;
-       struct list_head           next;
-       int                        (*init)(struct saa7134_dev *dev);
-       int                        (*fini)(struct saa7134_dev *dev);
-       void                       (*signal_change)(struct saa7134_dev *dev);
-};
-
-/* global device status */
-struct saa7134_dev {
-       struct list_head           devlist;
-       struct mutex               lock;
-       spinlock_t                 slock;
-       struct v4l2_prio_state     prio;
-       struct v4l2_device         v4l2_dev;
-       /* workstruct for loading modules */
-       struct work_struct request_module_wk;
-
-       /* insmod option/autodetected */
-       int                        autodetected;
-
-       /* various device info */
-       unsigned int               resources;
-       struct video_device        *video_dev;
-       struct video_device        *radio_dev;
-       struct video_device        *vbi_dev;
-       struct saa7134_dmasound    dmasound;
-
-       /* infrared remote */
-       int                        has_remote;
-       struct saa7134_card_ir     *remote;
-
-       /* pci i/o */
-       char                       name[32];
-       int                        nr;
-       struct pci_dev             *pci;
-       unsigned char              pci_rev,pci_lat;
-       __u32                      __iomem *lmmio;
-       __u8                       __iomem *bmmio;
-
-       /* config info */
-       unsigned int               board;
-       unsigned int               tuner_type;
-       unsigned int               radio_type;
-       unsigned char              tuner_addr;
-       unsigned char              radio_addr;
-
-       unsigned int               tda9887_conf;
-       unsigned int               gpio_value;
-
-       /* i2c i/o */
-       struct i2c_adapter         i2c_adap;
-       struct i2c_client          i2c_client;
-       unsigned char              eedata[256];
-       int                        has_rds;
-
-       /* video overlay */
-       struct v4l2_framebuffer    ovbuf;
-       struct saa7134_format      *ovfmt;
-       unsigned int               ovenable;
-       enum v4l2_field            ovfield;
-
-       /* video+ts+vbi capture */
-       struct saa7134_dmaqueue    video_q;
-       struct saa7134_dmaqueue    vbi_q;
-       unsigned int               video_fieldcount;
-       unsigned int               vbi_fieldcount;
-
-       /* various v4l controls */
-       struct saa7134_tvnorm      *tvnorm;              /* video */
-       struct saa7134_tvaudio     *tvaudio;
-       unsigned int               ctl_input;
-       int                        ctl_bright;
-       int                        ctl_contrast;
-       int                        ctl_hue;
-       int                        ctl_saturation;
-       int                        ctl_freq;
-       int                        ctl_mute;             /* audio */
-       int                        ctl_volume;
-       int                        ctl_invert;           /* private */
-       int                        ctl_mirror;
-       int                        ctl_y_odd;
-       int                        ctl_y_even;
-       int                        ctl_automute;
-
-       /* crop */
-       struct v4l2_rect           crop_bounds;
-       struct v4l2_rect           crop_defrect;
-       struct v4l2_rect           crop_current;
-
-       /* other global state info */
-       unsigned int               automute;
-       struct saa7134_thread      thread;
-       struct saa7134_input       *input;
-       struct saa7134_input       *hw_input;
-       unsigned int               hw_mute;
-       int                        last_carrier;
-       int                        nosignal;
-       unsigned int               insuspend;
-
-       /* I2C keyboard data */
-       struct IR_i2c_init_data    init_data;
-
-       /* SAA7134_MPEG_* */
-       struct saa7134_ts          ts;
-       struct saa7134_dmaqueue    ts_q;
-       int                        ts_started;
-       struct saa7134_mpeg_ops    *mops;
-
-       /* SAA7134_MPEG_EMPRESS only */
-       struct video_device        *empress_dev;
-       struct videobuf_queue      empress_tsq;
-       atomic_t                   empress_users;
-       struct work_struct         empress_workqueue;
-       int                        empress_started;
-
-#if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE)
-       /* SAA7134_MPEG_DVB only */
-       struct videobuf_dvb_frontends frontends;
-       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
-       void (*gate_ctrl)(struct saa7134_dev *dev, int open);
-};
-
-/* ----------------------------------------------------------- */
-
-#define saa_readl(reg)             readl(dev->lmmio + (reg))
-#define saa_writel(reg,value)      writel((value), dev->lmmio + (reg));
-#define saa_andorl(reg,mask,value) \
-  writel((readl(dev->lmmio+(reg)) & ~(mask)) |\
-  ((value) & (mask)), dev->lmmio+(reg))
-#define saa_setl(reg,bit)          saa_andorl((reg),(bit),(bit))
-#define saa_clearl(reg,bit)        saa_andorl((reg),(bit),0)
-
-#define saa_readb(reg)             readb(dev->bmmio + (reg))
-#define saa_writeb(reg,value)      writeb((value), dev->bmmio + (reg));
-#define saa_andorb(reg,mask,value) \
-  writeb((readb(dev->bmmio+(reg)) & ~(mask)) |\
-  ((value) & (mask)), dev->bmmio+(reg))
-#define saa_setb(reg,bit)          saa_andorb((reg),(bit),(bit))
-#define saa_clearb(reg,bit)        saa_andorb((reg),(bit),0)
-
-#define saa_wait(us) { udelay(us); }
-
-#define SAA7134_NORMS  (\
-               V4L2_STD_PAL    | V4L2_STD_PAL_N | \
-               V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
-               V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
-               V4L2_STD_PAL_60)
-
-#define GRP_EMPRESS (1)
-#define saa_call_all(dev, o, f, args...) do {                          \
-       if (dev->gate_ctrl)                                             \
-               dev->gate_ctrl(dev, 1);                                 \
-       v4l2_device_call_all(&(dev)->v4l2_dev, 0, o, f , ##args);       \
-       if (dev->gate_ctrl)                                             \
-               dev->gate_ctrl(dev, 0);                                 \
-} while (0)
-
-#define saa_call_empress(dev, o, f, args...) ({                                \
-       long _rc;                                                       \
-       if (dev->gate_ctrl)                                             \
-               dev->gate_ctrl(dev, 1);                                 \
-       _rc = v4l2_device_call_until_err(&(dev)->v4l2_dev,              \
-                                        GRP_EMPRESS, o, f , ##args);   \
-       if (dev->gate_ctrl)                                             \
-               dev->gate_ctrl(dev, 0);                                 \
-       _rc;                                                            \
-})
-
-/* ----------------------------------------------------------- */
-/* saa7134-core.c                                              */
-
-extern struct list_head  saa7134_devlist;
-extern struct mutex saa7134_devlist_lock;
-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);
-
-#define SAA7134_PGTABLE_SIZE 4096
-
-int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt);
-int  saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
-                          struct scatterlist *list, unsigned int length,
-                          unsigned int startpage);
-void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt);
-
-int saa7134_buffer_count(unsigned int size, unsigned int count);
-int saa7134_buffer_startpage(struct saa7134_buf *buf);
-unsigned long saa7134_buffer_base(struct saa7134_buf *buf);
-
-int saa7134_buffer_queue(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
-                        struct saa7134_buf *buf);
-void saa7134_buffer_finish(struct saa7134_dev *dev, struct saa7134_dmaqueue *q,
-                          unsigned int state);
-void saa7134_buffer_next(struct saa7134_dev *dev, struct saa7134_dmaqueue *q);
-void saa7134_buffer_timeout(unsigned long data);
-void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf);
-
-int saa7134_set_dmabits(struct saa7134_dev *dev);
-
-extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
-extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
-
-
-/* ----------------------------------------------------------- */
-/* saa7134-cards.c                                             */
-
-extern struct saa7134_board saa7134_boards[];
-extern const unsigned int saa7134_bcount;
-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 component, int command, int arg);
-
-
-/* ----------------------------------------------------------- */
-/* saa7134-i2c.c                                               */
-
-int saa7134_i2c_register(struct saa7134_dev *dev);
-int saa7134_i2c_unregister(struct saa7134_dev *dev);
-
-
-/* ----------------------------------------------------------- */
-/* saa7134-video.c                                             */
-
-extern unsigned int video_debug;
-extern struct video_device saa7134_video_template;
-extern struct video_device saa7134_radio_template;
-
-int saa7134_s_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
-int saa7134_g_ctrl_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, struct v4l2_control *c);
-int saa7134_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *c);
-int saa7134_s_std_internal(struct saa7134_dev *dev,  struct saa7134_fh *fh, v4l2_std_id *id);
-
-int saa7134_videoport_init(struct saa7134_dev *dev);
-void saa7134_set_tvnorm_hw(struct saa7134_dev *dev);
-
-int saa7134_video_init1(struct saa7134_dev *dev);
-int saa7134_video_init2(struct saa7134_dev *dev);
-void saa7134_irq_video_signalchange(struct saa7134_dev *dev);
-void saa7134_irq_video_done(struct saa7134_dev *dev, unsigned long status);
-
-
-/* ----------------------------------------------------------- */
-/* saa7134-ts.c                                                */
-
-#define TS_PACKET_SIZE 188 /* TS packets 188 bytes */
-
-extern struct videobuf_queue_ops saa7134_ts_qops;
-
-int saa7134_ts_init1(struct saa7134_dev *dev);
-int saa7134_ts_fini(struct saa7134_dev *dev);
-void saa7134_irq_ts_done(struct saa7134_dev *dev, unsigned long status);
-
-int saa7134_ts_register(struct saa7134_mpeg_ops *ops);
-void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops);
-
-int saa7134_ts_init_hw(struct saa7134_dev *dev);
-
-int saa7134_ts_start(struct saa7134_dev *dev);
-int saa7134_ts_stop(struct saa7134_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* saa7134-vbi.c                                               */
-
-extern struct videobuf_queue_ops saa7134_vbi_qops;
-extern struct video_device saa7134_vbi_template;
-
-int saa7134_vbi_init1(struct saa7134_dev *dev);
-int saa7134_vbi_fini(struct saa7134_dev *dev);
-void saa7134_irq_vbi_done(struct saa7134_dev *dev, unsigned long status);
-
-
-/* ----------------------------------------------------------- */
-/* saa7134-tvaudio.c                                           */
-
-int saa7134_tvaudio_rx2mode(u32 rx);
-
-void saa7134_tvaudio_setmute(struct saa7134_dev *dev);
-void saa7134_tvaudio_setinput(struct saa7134_dev *dev,
-                             struct saa7134_input *in);
-void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level);
-int saa7134_tvaudio_getstereo(struct saa7134_dev *dev);
-
-void saa7134_tvaudio_init(struct saa7134_dev *dev);
-int saa7134_tvaudio_init2(struct saa7134_dev *dev);
-int saa7134_tvaudio_fini(struct saa7134_dev *dev);
-int saa7134_tvaudio_do_scan(struct saa7134_dev *dev);
-int saa7134_tvaudio_close(struct saa7134_dev *dev);
-
-int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value);
-
-void saa7134_enable_i2s(struct saa7134_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* saa7134-oss.c                                               */
-
-extern const struct file_operations saa7134_dsp_fops;
-extern const struct file_operations saa7134_mixer_fops;
-
-int saa7134_oss_init1(struct saa7134_dev *dev);
-int saa7134_oss_fini(struct saa7134_dev *dev);
-void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status);
-
-/* ----------------------------------------------------------- */
-/* saa7134-input.c                                             */
-
-#if defined(CONFIG_VIDEO_SAA7134_RC)
-int  saa7134_input_init1(struct saa7134_dev *dev);
-void saa7134_input_fini(struct saa7134_dev *dev);
-void saa7134_input_irq(struct saa7134_dev *dev);
-void saa7134_probe_i2c_ir(struct saa7134_dev *dev);
-int saa7134_ir_start(struct saa7134_dev *dev);
-void saa7134_ir_stop(struct saa7134_dev *dev);
-#else
-#define saa7134_input_init1(dev)       ((void)0)
-#define saa7134_input_fini(dev)                ((void)0)
-#define saa7134_input_irq(dev)         ((void)0)
-#define saa7134_probe_i2c_ir(dev)      ((void)0)
-#define saa7134_ir_start(dev)          ((void)0)
-#define saa7134_ir_stop(dev)           ((void)0)
-#endif
diff --git a/drivers/media/video/saa7164/Kconfig b/drivers/media/video/saa7164/Kconfig
deleted file mode 100644 (file)
index 3532637..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-config VIDEO_SAA7164
-       tristate "NXP SAA7164 support"
-       depends on DVB_CORE && PCI && I2C
-       select I2C_ALGOBIT
-       select FW_LOADER
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEOBUF_DVB
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         This is a video4linux driver for NXP SAA7164 based
-         TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7164
-
diff --git a/drivers/media/video/saa7164/Makefile b/drivers/media/video/saa7164/Makefile
deleted file mode 100644 (file)
index 847110c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-saa7164-objs   := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \
-                       saa7164-fw.o saa7164-bus.o saa7164-cmd.o saa7164-api.o \
-                       saa7164-buffer.o saa7164-encoder.o saa7164-vbi.o
-
-obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
-
-ccflags-y += -I$(srctree)/drivers/media/video
-ccflags-y += -I$(srctree)/drivers/media/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
-
-ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/saa7164/saa7164-api.c b/drivers/media/video/saa7164/saa7164-api.c
deleted file mode 100644 (file)
index eff7135..0000000
+++ /dev/null
@@ -1,1524 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/wait.h>
-#include <linux/slab.h>
-
-#include "saa7164.h"
-
-int saa7164_api_get_load_info(struct saa7164_dev *dev, struct tmFwInfoStruct *i)
-{
-       int ret;
-
-       if (!(saa_debug & DBGLVL_CPU))
-               return 0;
-
-       dprintk(DBGLVL_API, "%s()\n", __func__);
-
-       i->deviceinst = 0;
-       i->devicespec = 0;
-       i->mode = 0;
-       i->status = 0;
-
-       ret = saa7164_cmd_send(dev, 0, GET_CUR,
-               GET_FW_STATUS_CONTROL, sizeof(struct tmFwInfoStruct), i);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       printk(KERN_INFO "saa7164[%d]-CPU: %d percent", dev->nr, i->CPULoad);
-
-       return ret;
-}
-
-int saa7164_api_collect_debug(struct saa7164_dev *dev)
-{
-       struct tmComResDebugGetData d;
-       u8 more = 255;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s()\n", __func__);
-
-       while (more--) {
-
-               memset(&d, 0, sizeof(d));
-
-               ret = saa7164_cmd_send(dev, 0, GET_CUR,
-                       GET_DEBUG_DATA_CONTROL, sizeof(d), &d);
-               if (ret != SAA_OK)
-                       printk(KERN_ERR "%s() error, ret = 0x%x\n",
-                               __func__, ret);
-
-               if (d.dwResult != SAA_OK)
-                       break;
-
-               printk(KERN_INFO "saa7164[%d]-FWMSG: %s", dev->nr,
-                       d.ucDebugData);
-       }
-
-       return 0;
-}
-
-int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level)
-{
-       struct tmComResDebugSetLevel lvl;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s(level=%d)\n", __func__, level);
-
-       /* Retrieve current state */
-       ret = saa7164_cmd_send(dev, 0, GET_CUR,
-               SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       dprintk(DBGLVL_API, "%s() Was %d\n", __func__, lvl.dwDebugLevel);
-
-       lvl.dwDebugLevel = level;
-
-       /* set new state */
-       ret = saa7164_cmd_send(dev, 0, SET_CUR,
-               SET_DEBUG_LEVEL_CONTROL, sizeof(lvl), &lvl);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_set_vbi_format(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResProbeCommit fmt, rsp;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s(nr=%d, unitid=0x%x)\n", __func__,
-               port->nr, port->hwcfg.unitid);
-
-       fmt.bmHint = 0;
-       fmt.bFormatIndex = 1;
-       fmt.bFrameIndex = 1;
-
-       /* Probe, see if it can support this format */
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
-               SET_CUR, SAA_PROBE_CONTROL, sizeof(fmt), &fmt);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() set error, ret = 0x%x\n", __func__, ret);
-
-       /* See of the format change was successful */
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
-               GET_CUR, SAA_PROBE_CONTROL, sizeof(rsp), &rsp);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() get error, ret = 0x%x\n", __func__, ret);
-       } else {
-               /* Compare requested vs received, should be same */
-               if (memcmp(&fmt, &rsp, sizeof(rsp)) == 0) {
-                       dprintk(DBGLVL_API, "SET/PROBE Verified\n");
-
-                       /* Ask the device to select the negotiated format */
-                       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
-                               SET_CUR, SAA_COMMIT_CONTROL, sizeof(fmt), &fmt);
-                       if (ret != SAA_OK)
-                               printk(KERN_ERR "%s() commit error, ret = 0x%x\n",
-                                       __func__, ret);
-
-                       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid,
-                               GET_CUR, SAA_COMMIT_CONTROL, sizeof(rsp), &rsp);
-                       if (ret != SAA_OK)
-                               printk(KERN_ERR "%s() GET commit error, ret = 0x%x\n",
-                                       __func__, ret);
-
-                       if (memcmp(&fmt, &rsp, sizeof(rsp)) != 0) {
-                               printk(KERN_ERR "%s() memcmp error, ret = 0x%x\n",
-                                       __func__, ret);
-                       } else
-                               dprintk(DBGLVL_API, "SET/COMMIT Verified\n");
-
-                       dprintk(DBGLVL_API, "rsp.bmHint = 0x%x\n", rsp.bmHint);
-                       dprintk(DBGLVL_API, "rsp.bFormatIndex = 0x%x\n",
-                               rsp.bFormatIndex);
-                       dprintk(DBGLVL_API, "rsp.bFrameIndex = 0x%x\n",
-                               rsp.bFrameIndex);
-               } else
-                       printk(KERN_ERR "%s() compare failed\n", __func__);
-       }
-
-       if (ret == SAA_OK)
-               dprintk(DBGLVL_API, "%s(nr=%d) Success\n", __func__, port->nr);
-
-       return ret;
-}
-
-int saa7164_api_set_gop_size(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResEncVideoGopStructure gs;
-       int ret;
-
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       gs.ucRefFrameDist = port->encoder_params.refdist;
-       gs.ucGOPSize = port->encoder_params.gop_size;
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-               EU_VIDEO_GOP_STRUCTURE_CONTROL,
-               sizeof(gs), &gs);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_set_encoder(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResEncVideoBitRate vb;
-       struct tmComResEncAudioBitRate ab;
-       int ret;
-
-       dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
-               port->hwcfg.sourceid);
-
-       if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
-               port->encoder_profile = EU_PROFILE_PS_DVD;
-       else
-               port->encoder_profile = EU_PROFILE_TS_HQ;
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-               EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Resolution */
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-               EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Establish video bitrates */
-       if (port->encoder_params.bitrate_mode ==
-               V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
-               vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_CONSTANT;
-       else
-               vb.ucVideoBitRateMode = EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK;
-       vb.dwVideoBitRate = port->encoder_params.bitrate;
-       vb.dwVideoBitRatePeak = port->encoder_params.bitrate_peak;
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-               EU_VIDEO_BIT_RATE_CONTROL,
-               sizeof(struct tmComResEncVideoBitRate),
-               &vb);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Establish audio bitrates */
-       ab.ucAudioBitRateMode = 0;
-       ab.dwAudioBitRate = 384000;
-       ab.dwAudioBitRatePeak = ab.dwAudioBitRate;
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-               EU_AUDIO_BIT_RATE_CONTROL,
-               sizeof(struct tmComResEncAudioBitRate),
-               &ab);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
-                       ret);
-
-       saa7164_api_set_aspect_ratio(port);
-       saa7164_api_set_gop_size(port);
-
-       return ret;
-}
-
-int saa7164_api_get_encoder(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResEncVideoBitRate v;
-       struct tmComResEncAudioBitRate a;
-       struct tmComResEncVideoInputAspectRatio ar;
-       int ret;
-
-       dprintk(DBGLVL_ENC, "%s() unitid=0x%x\n", __func__,
-               port->hwcfg.sourceid);
-
-       port->encoder_profile = 0;
-       port->video_format = 0;
-       port->video_resolution = 0;
-       port->audio_format = 0;
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_PROFILE_CONTROL, sizeof(u8), &port->encoder_profile);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_VIDEO_RESOLUTION_CONTROL, sizeof(u8),
-               &port->video_resolution);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_VIDEO_FORMAT_CONTROL, sizeof(u8), &port->video_format);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_VIDEO_BIT_RATE_CONTROL, sizeof(v), &v);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_AUDIO_FORMAT_CONTROL, sizeof(u8), &port->audio_format);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_AUDIO_BIT_RATE_CONTROL, sizeof(a), &a);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Aspect Ratio */
-       ar.width = 0;
-       ar.height = 0;
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, GET_CUR,
-               EU_VIDEO_INPUT_ASPECT_CONTROL,
-               sizeof(struct tmComResEncVideoInputAspectRatio), &ar);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       dprintk(DBGLVL_ENC, "encoder_profile = %d\n", port->encoder_profile);
-       dprintk(DBGLVL_ENC, "video_format    = %d\n", port->video_format);
-       dprintk(DBGLVL_ENC, "audio_format    = %d\n", port->audio_format);
-       dprintk(DBGLVL_ENC, "video_resolution= %d\n", port->video_resolution);
-       dprintk(DBGLVL_ENC, "v.ucVideoBitRateMode = %d\n",
-               v.ucVideoBitRateMode);
-       dprintk(DBGLVL_ENC, "v.dwVideoBitRate     = %d\n",
-               v.dwVideoBitRate);
-       dprintk(DBGLVL_ENC, "v.dwVideoBitRatePeak = %d\n",
-               v.dwVideoBitRatePeak);
-       dprintk(DBGLVL_ENC, "a.ucVideoBitRateMode = %d\n",
-               a.ucAudioBitRateMode);
-       dprintk(DBGLVL_ENC, "a.dwVideoBitRate     = %d\n",
-               a.dwAudioBitRate);
-       dprintk(DBGLVL_ENC, "a.dwVideoBitRatePeak = %d\n",
-               a.dwAudioBitRatePeak);
-       dprintk(DBGLVL_ENC, "aspect.width / height = %d:%d\n",
-               ar.width, ar.height);
-
-       return ret;
-}
-
-int saa7164_api_set_aspect_ratio(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResEncVideoInputAspectRatio ar;
-       int ret;
-
-       dprintk(DBGLVL_ENC, "%s(%d)\n", __func__,
-               port->encoder_params.ctl_aspect);
-
-       switch (port->encoder_params.ctl_aspect) {
-       case V4L2_MPEG_VIDEO_ASPECT_1x1:
-               ar.width = 1;
-               ar.height = 1;
-               break;
-       case V4L2_MPEG_VIDEO_ASPECT_4x3:
-               ar.width = 4;
-               ar.height = 3;
-               break;
-       case V4L2_MPEG_VIDEO_ASPECT_16x9:
-               ar.width = 16;
-               ar.height = 9;
-               break;
-       case V4L2_MPEG_VIDEO_ASPECT_221x100:
-               ar.width = 221;
-               ar.height = 100;
-               break;
-       default:
-               BUG();
-       }
-
-       dprintk(DBGLVL_ENC, "%s(%d) now %d:%d\n", __func__,
-               port->encoder_params.ctl_aspect,
-               ar.width, ar.height);
-
-       /* Aspect Ratio */
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.sourceid, SET_CUR,
-               EU_VIDEO_INPUT_ASPECT_CONTROL,
-               sizeof(struct tmComResEncVideoInputAspectRatio), &ar);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-       u16 val;
-
-       if (ctl == PU_BRIGHTNESS_CONTROL)
-               val = port->ctl_brightness;
-       else
-       if (ctl == PU_CONTRAST_CONTROL)
-               val = port->ctl_contrast;
-       else
-       if (ctl == PU_HUE_CONTROL)
-               val = port->ctl_hue;
-       else
-       if (ctl == PU_SATURATION_CONTROL)
-               val = port->ctl_saturation;
-       else
-       if (ctl == PU_SHARPNESS_CONTROL)
-               val = port->ctl_sharpness;
-       else
-               return -EINVAL;
-
-       dprintk(DBGLVL_ENC, "%s() unitid=0x%x ctl=%d, val=%d\n",
-               __func__, port->encunit.vsourceid, ctl, val);
-
-       ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, SET_CUR,
-               ctl, sizeof(u16), &val);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-       u16 val;
-
-       ret = saa7164_cmd_send(port->dev, port->encunit.vsourceid, GET_CUR,
-               ctl, sizeof(u16), &val);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-               return ret;
-       }
-
-       dprintk(DBGLVL_ENC, "%s() ctl=%d, val=%d\n",
-               __func__, ctl, val);
-
-       if (ctl == PU_BRIGHTNESS_CONTROL)
-               port->ctl_brightness = val;
-       else
-       if (ctl == PU_CONTRAST_CONTROL)
-               port->ctl_contrast = val;
-       else
-       if (ctl == PU_HUE_CONTROL)
-               port->ctl_hue = val;
-       else
-       if (ctl == PU_SATURATION_CONTROL)
-               port->ctl_saturation = val;
-       else
-       if (ctl == PU_SHARPNESS_CONTROL)
-               port->ctl_sharpness = val;
-
-       return ret;
-}
-
-int saa7164_api_set_videomux(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       u8 inputs[] = { 1, 2, 2, 2, 5, 5, 5 };
-       int ret;
-
-       dprintk(DBGLVL_ENC, "%s() v_mux=%d a_mux=%d\n",
-               __func__, port->mux_input, inputs[port->mux_input - 1]);
-
-       /* Audio Mute */
-       ret = saa7164_api_audio_mute(port, 1);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Video Mux */
-       ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, SET_CUR,
-               SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Audio Mux */
-       ret = saa7164_cmd_send(port->dev, port->audfeat.sourceid, SET_CUR,
-               SU_INPUT_SELECT_CONTROL, sizeof(u8),
-               &inputs[port->mux_input - 1]);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Audio UnMute */
-       ret = saa7164_api_audio_mute(port, 0);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_audio_mute(struct saa7164_port *port, int mute)
-{
-       struct saa7164_dev *dev = port->dev;
-       u8 v = mute;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s(%d)\n", __func__, mute);
-
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
-               MUTE_CONTROL, sizeof(u8), &v);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-/* 0 = silence, 0xff = full */
-int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level)
-{
-       struct saa7164_dev *dev = port->dev;
-       s16 v, min, max;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s(%d)\n", __func__, level);
-
-       /* Obtain the min/max ranges */
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MIN,
-               VOLUME_CONTROL, sizeof(u16), &min);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_MAX,
-               VOLUME_CONTROL, sizeof(u16), &max);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
-               (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,
-               level, min, max, v);
-
-       v = level;
-       if (v < min)
-               v = min;
-       if (v > max)
-               v = max;
-
-       /* Left */
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
-               (0x01 << 8) | VOLUME_CONTROL, sizeof(s16), &v);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Right */
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
-               (0x02 << 8) | VOLUME_CONTROL, sizeof(s16), &v);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, GET_CUR,
-               (0x01 << 8) | VOLUME_CONTROL, sizeof(u16), &v);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       dprintk(DBGLVL_API, "%s(%d) min=%d max=%d cur=%d\n", __func__,
-               level, min, max, v);
-
-       return ret;
-}
-
-int saa7164_api_set_audio_std(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResAudioDefaults lvl;
-       struct tmComResTunerStandard tvaudio;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s()\n", __func__);
-
-       /* Establish default levels */
-       lvl.ucDecoderLevel = TMHW_LEV_ADJ_DECLEV_DEFAULT;
-       lvl.ucDecoderFM_Level = TMHW_LEV_ADJ_DECLEV_DEFAULT;
-       lvl.ucMonoLevel = TMHW_LEV_ADJ_MONOLEV_DEFAULT;
-       lvl.ucNICAM_Level = TMHW_LEV_ADJ_NICLEV_DEFAULT;
-       lvl.ucSAP_Level = TMHW_LEV_ADJ_SAPLEV_DEFAULT;
-       lvl.ucADC_Level = TMHW_LEV_ADJ_ADCLEV_DEFAULT;
-       ret = saa7164_cmd_send(port->dev, port->audfeat.unitid, SET_CUR,
-               AUDIO_DEFAULT_CONTROL, sizeof(struct tmComResAudioDefaults),
-               &lvl);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       /* Manually select the appropriate TV audio standard */
-       if (port->encodernorm.id & V4L2_STD_NTSC) {
-               tvaudio.std = TU_STANDARD_NTSC_M;
-               tvaudio.country = 1;
-       } else {
-               tvaudio.std = TU_STANDARD_PAL_I;
-               tvaudio.country = 44;
-       }
-
-       ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
-               TU_STANDARD_CONTROL, sizeof(tvaudio), &tvaudio);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() TU_STANDARD_CONTROL error, ret = 0x%x\n",
-                       __func__, ret);
-       return ret;
-}
-
-int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct tmComResTunerStandardAuto p;
-       int ret;
-
-       dprintk(DBGLVL_API, "%s(%d)\n", __func__, autodetect);
-
-       /* Disable TV Audio autodetect if not already set (buggy) */
-       if (autodetect)
-               p.mode = TU_STANDARD_AUTO;
-       else
-               p.mode = TU_STANDARD_MANUAL;
-       ret = saa7164_cmd_send(port->dev, port->tunerunit.unitid, SET_CUR,
-               TU_STANDARD_AUTO_CONTROL, sizeof(p), &p);
-       if (ret != SAA_OK)
-               printk(KERN_ERR
-                       "%s() TU_STANDARD_AUTO_CONTROL error, ret = 0x%x\n",
-                       __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_get_videomux(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_cmd_send(port->dev, port->vidproc.sourceid, GET_CUR,
-               SU_INPUT_SELECT_CONTROL, sizeof(u8), &port->mux_input);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       dprintk(DBGLVL_ENC, "%s() v_mux=%d\n",
-               __func__, port->mux_input);
-
-       return ret;
-}
-
-int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       u16 len = 0;
-       u8 buf[256];
-       int ret;
-       u8 mas;
-
-       dprintk(DBGLVL_API, "%s(nr=%d type=%d val=%x)\n", __func__,
-               port->nr, port->type, val);
-
-       if (port->nr == 0)
-               mas = 0xd0;
-       else
-               mas = 0xe0;
-
-       memset(buf, 0, sizeof(buf));
-
-       buf[0x00] = 0x04;
-       buf[0x01] = 0x00;
-       buf[0x02] = 0x00;
-       buf[0x03] = 0x00;
-
-       buf[0x04] = 0x04;
-       buf[0x05] = 0x00;
-       buf[0x06] = 0x00;
-       buf[0x07] = 0x00;
-
-       buf[0x08] = reg;
-       buf[0x09] = 0x26;
-       buf[0x0a] = mas;
-       buf[0x0b] = 0xb0;
-
-       buf[0x0c] = val;
-       buf[0x0d] = 0x00;
-       buf[0x0e] = 0x00;
-       buf[0x0f] = 0x00;
-
-       ret = saa7164_cmd_send(dev, port->ifunit.unitid, GET_LEN,
-               EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
-               return -EIO;
-       }
-
-       ret = saa7164_cmd_send(dev, port->ifunit.unitid, SET_CUR,
-               EXU_REGISTER_ACCESS_CONTROL, len, &buf);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
-#if 0
-       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, 16,
-                      false);
-#endif
-       return ret == SAA_OK ? 0 : -EIO;
-}
-
-/* Disable the IF block AGC controls */
-int saa7164_api_configure_dif(struct saa7164_port *port, u32 std)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-       u8 agc_disable;
-
-       dprintk(DBGLVL_API, "%s(nr=%d, 0x%x)\n", __func__, port->nr, std);
-
-       if (std & V4L2_STD_NTSC) {
-               dprintk(DBGLVL_API, " NTSC\n");
-               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_PAL_I) {
-               dprintk(DBGLVL_API, " PAL-I\n");
-               saa7164_api_set_dif(port, 0x00, 0x08); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_PAL_M) {
-               dprintk(DBGLVL_API, " PAL-M\n");
-               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_PAL_N) {
-               dprintk(DBGLVL_API, " PAL-N\n");
-               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_PAL_Nc) {
-               dprintk(DBGLVL_API, " PAL-Nc\n");
-               saa7164_api_set_dif(port, 0x00, 0x01); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_PAL_B) {
-               dprintk(DBGLVL_API, " PAL-B\n");
-               saa7164_api_set_dif(port, 0x00, 0x02); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_PAL_DK) {
-               dprintk(DBGLVL_API, " PAL-DK\n");
-               saa7164_api_set_dif(port, 0x00, 0x10); /* Video Standard */
-               agc_disable = 0;
-       } else if (std & V4L2_STD_SECAM_L) {
-               dprintk(DBGLVL_API, " SECAM-L\n");
-               saa7164_api_set_dif(port, 0x00, 0x20); /* Video Standard */
-               agc_disable = 0;
-       } else {
-               /* Unknown standard, assume DTV */
-               dprintk(DBGLVL_API, " Unknown (assuming DTV)\n");
-               /* Undefinded Video Standard */
-               saa7164_api_set_dif(port, 0x00, 0x80);
-               agc_disable = 1;
-       }
-
-       saa7164_api_set_dif(port, 0x48, 0xa0); /* AGC Functions 1 */
-       saa7164_api_set_dif(port, 0xc0, agc_disable); /* AGC Output Disable */
-       saa7164_api_set_dif(port, 0x7c, 0x04); /* CVBS EQ */
-       saa7164_api_set_dif(port, 0x04, 0x01); /* Active */
-       msleep(100);
-       saa7164_api_set_dif(port, 0x04, 0x00); /* Active (again) */
-       msleep(100);
-
-       return ret;
-}
-
-/* Ensure the dif is in the correct state for the operating mode
- * (analog / dtv). We only configure the diff through the analog encoder
- * so when we're in digital mode we need to find the appropriate encoder
- * and use it to configure the DIF.
- */
-int saa7164_api_initialize_dif(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_port *p = NULL;
-       int ret = -EINVAL;
-       u32 std = 0;
-
-       dprintk(DBGLVL_API, "%s(nr=%d type=%d)\n", __func__,
-               port->nr, port->type);
-
-       if (port->type == SAA7164_MPEG_ENCODER) {
-               /* Pick any analog standard to init the diff.
-                * we'll come back during encoder_init'
-                * and set the correct standard if requried.
-                */
-               std = V4L2_STD_NTSC;
-       } else
-       if (port->type == SAA7164_MPEG_DVB) {
-               if (port->nr == SAA7164_PORT_TS1)
-                       p = &dev->ports[SAA7164_PORT_ENC1];
-               else
-                       p = &dev->ports[SAA7164_PORT_ENC2];
-       } else
-       if (port->type == SAA7164_MPEG_VBI) {
-               std = V4L2_STD_NTSC;
-               if (port->nr == SAA7164_PORT_VBI1)
-                       p = &dev->ports[SAA7164_PORT_ENC1];
-               else
-                       p = &dev->ports[SAA7164_PORT_ENC2];
-       } else
-               BUG();
-
-       if (p)
-               ret = saa7164_api_configure_dif(p, std);
-
-       return ret;
-}
-
-int saa7164_api_transition_port(struct saa7164_port *port, u8 mode)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       int ret;
-
-       dprintk(DBGLVL_API, "%s(nr=%d unitid=0x%x,%d)\n",
-               __func__, port->nr, port->hwcfg.unitid, mode);
-
-       ret = saa7164_cmd_send(port->dev, port->hwcfg.unitid, SET_CUR,
-               SAA_STATE_CONTROL, sizeof(mode), &mode);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s(portnr %d unitid 0x%x) error, ret = 0x%x\n",
-                       __func__, port->nr, port->hwcfg.unitid, ret);
-
-       return ret;
-}
-
-int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version)
-{
-       int ret;
-
-       ret = saa7164_cmd_send(dev, 0, GET_CUR,
-               GET_FW_VERSION_CONTROL, sizeof(u32), version);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen)
-{
-       u8 reg[] = { 0x0f, 0x00 };
-
-       if (buflen < 128)
-               return -ENOMEM;
-
-       /* Assumption: Hauppauge eeprom is at 0xa0 on on bus 0 */
-       /* TODO: Pull the details from the boards struct */
-       return saa7164_api_i2c_read(&dev->i2c_bus[0], 0xa0 >> 1, sizeof(reg),
-               &reg[0], 128, buf);
-}
-
-int saa7164_api_configure_port_vbi(struct saa7164_dev *dev,
-       struct saa7164_port *port)
-{
-       struct tmComResVBIFormatDescrHeader *fmt = &port->vbi_fmt_ntsc;
-
-       dprintk(DBGLVL_API, "    bFormatIndex  = 0x%x\n", fmt->bFormatIndex);
-       dprintk(DBGLVL_API, "    VideoStandard = 0x%x\n", fmt->VideoStandard);
-       dprintk(DBGLVL_API, "    StartLine     = %d\n", fmt->StartLine);
-       dprintk(DBGLVL_API, "    EndLine       = %d\n", fmt->EndLine);
-       dprintk(DBGLVL_API, "    FieldRate     = %d\n", fmt->FieldRate);
-       dprintk(DBGLVL_API, "    bNumLines     = %d\n", fmt->bNumLines);
-
-       /* Cache the hardware configuration in the port */
-
-       port->bufcounter = port->hwcfg.BARLocation;
-       port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
-       port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
-       port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
-       port->bufptr32l = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
-       port->bufptr32h = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount);
-       port->bufptr64 = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount);
-       dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",
-               port->hwcfg.BARLocation);
-
-       dprintk(DBGLVL_API, "   = VS_FORMAT_VBI (becomes dev->en[%d])\n",
-               port->nr);
-
-       return 0;
-}
-
-int saa7164_api_configure_port_mpeg2ts(struct saa7164_dev *dev,
-       struct saa7164_port *port,
-       struct tmComResTSFormatDescrHeader *tsfmt)
-{
-       dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", tsfmt->bFormatIndex);
-       dprintk(DBGLVL_API, "    bDataOffset  = 0x%x\n", tsfmt->bDataOffset);
-       dprintk(DBGLVL_API, "    bPacketLength= 0x%x\n", tsfmt->bPacketLength);
-       dprintk(DBGLVL_API, "    bStrideLength= 0x%x\n", tsfmt->bStrideLength);
-       dprintk(DBGLVL_API, "    bguid        = (....)\n");
-
-       /* Cache the hardware configuration in the port */
-
-       port->bufcounter = port->hwcfg.BARLocation;
-       port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
-       port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
-       port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
-       port->bufptr32l = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
-       port->bufptr32h = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount);
-       port->bufptr64 = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount);
-       dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",
-               port->hwcfg.BARLocation);
-
-       dprintk(DBGLVL_API, "   = VS_FORMAT_MPEGTS (becomes dev->ts[%d])\n",
-               port->nr);
-
-       return 0;
-}
-
-int saa7164_api_configure_port_mpeg2ps(struct saa7164_dev *dev,
-       struct saa7164_port *port,
-       struct tmComResPSFormatDescrHeader *fmt)
-{
-       dprintk(DBGLVL_API, "    bFormatIndex = 0x%x\n", fmt->bFormatIndex);
-       dprintk(DBGLVL_API, "    wPacketLength= 0x%x\n", fmt->wPacketLength);
-       dprintk(DBGLVL_API, "    wPackLength=   0x%x\n", fmt->wPackLength);
-       dprintk(DBGLVL_API, "    bPackDataType= 0x%x\n", fmt->bPackDataType);
-
-       /* Cache the hardware configuration in the port */
-       /* TODO: CHECK THIS in the port config */
-       port->bufcounter = port->hwcfg.BARLocation;
-       port->pitch = port->hwcfg.BARLocation + (2 * sizeof(u32));
-       port->bufsize = port->hwcfg.BARLocation + (3 * sizeof(u32));
-       port->bufoffset = port->hwcfg.BARLocation + (4 * sizeof(u32));
-       port->bufptr32l = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount) + sizeof(u32);
-       port->bufptr32h = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount);
-       port->bufptr64 = port->hwcfg.BARLocation +
-               (4 * sizeof(u32)) +
-               (sizeof(u32) * port->hwcfg.buffercount);
-       dprintk(DBGLVL_API, "   = port->hwcfg.BARLocation = 0x%x\n",
-               port->hwcfg.BARLocation);
-
-       dprintk(DBGLVL_API, "   = VS_FORMAT_MPEGPS (becomes dev->enc[%d])\n",
-               port->nr);
-
-       return 0;
-}
-
-int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
-{
-       struct saa7164_port *tsport = NULL;
-       struct saa7164_port *encport = NULL;
-       struct saa7164_port *vbiport = NULL;
-       u32 idx, next_offset;
-       int i;
-       struct tmComResDescrHeader *hdr, *t;
-       struct tmComResExtDevDescrHeader *exthdr;
-       struct tmComResPathDescrHeader *pathhdr;
-       struct tmComResAntTermDescrHeader *anttermhdr;
-       struct tmComResTunerDescrHeader *tunerunithdr;
-       struct tmComResDMATermDescrHeader *vcoutputtermhdr;
-       struct tmComResTSFormatDescrHeader *tsfmt;
-       struct tmComResPSFormatDescrHeader *psfmt;
-       struct tmComResSelDescrHeader *psel;
-       struct tmComResProcDescrHeader *pdh;
-       struct tmComResAFeatureDescrHeader *afd;
-       struct tmComResEncoderDescrHeader *edh;
-       struct tmComResVBIFormatDescrHeader *vbifmt;
-       u32 currpath = 0;
-
-       dprintk(DBGLVL_API,
-               "%s(?,?,%d) sizeof(struct tmComResDescrHeader) = %d bytes\n",
-               __func__, len, (u32)sizeof(struct tmComResDescrHeader));
-
-       for (idx = 0; idx < (len - sizeof(struct tmComResDescrHeader));) {
-
-               hdr = (struct tmComResDescrHeader *)(buf + idx);
-
-               if (hdr->type != CS_INTERFACE)
-                       return SAA_ERR_NOT_SUPPORTED;
-
-               dprintk(DBGLVL_API, "@ 0x%x =\n", idx);
-               switch (hdr->subtype) {
-               case GENERAL_REQUEST:
-                       dprintk(DBGLVL_API, " GENERAL_REQUEST\n");
-                       break;
-               case VC_TUNER_PATH:
-                       dprintk(DBGLVL_API, " VC_TUNER_PATH\n");
-                       pathhdr = (struct tmComResPathDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, "  pathid = 0x%x\n",
-                               pathhdr->pathid);
-                       currpath = pathhdr->pathid;
-                       break;
-               case VC_INPUT_TERMINAL:
-                       dprintk(DBGLVL_API, " VC_INPUT_TERMINAL\n");
-                       anttermhdr =
-                               (struct tmComResAntTermDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, "  terminalid   = 0x%x\n",
-                               anttermhdr->terminalid);
-                       dprintk(DBGLVL_API, "  terminaltype = 0x%x\n",
-                               anttermhdr->terminaltype);
-                       switch (anttermhdr->terminaltype) {
-                       case ITT_ANTENNA:
-                               dprintk(DBGLVL_API, "   = ITT_ANTENNA\n");
-                               break;
-                       case LINE_CONNECTOR:
-                               dprintk(DBGLVL_API, "   = LINE_CONNECTOR\n");
-                               break;
-                       case SPDIF_CONNECTOR:
-                               dprintk(DBGLVL_API, "   = SPDIF_CONNECTOR\n");
-                               break;
-                       case COMPOSITE_CONNECTOR:
-                               dprintk(DBGLVL_API,
-                                       "   = COMPOSITE_CONNECTOR\n");
-                               break;
-                       case SVIDEO_CONNECTOR:
-                               dprintk(DBGLVL_API, "   = SVIDEO_CONNECTOR\n");
-                               break;
-                       case COMPONENT_CONNECTOR:
-                               dprintk(DBGLVL_API,
-                                       "   = COMPONENT_CONNECTOR\n");
-                               break;
-                       case STANDARD_DMA:
-                               dprintk(DBGLVL_API, "   = STANDARD_DMA\n");
-                               break;
-                       default:
-                               dprintk(DBGLVL_API, "   = undefined (0x%x)\n",
-                                       anttermhdr->terminaltype);
-                       }
-                       dprintk(DBGLVL_API, "  assocterminal= 0x%x\n",
-                               anttermhdr->assocterminal);
-                       dprintk(DBGLVL_API, "  iterminal    = 0x%x\n",
-                               anttermhdr->iterminal);
-                       dprintk(DBGLVL_API, "  controlsize  = 0x%x\n",
-                               anttermhdr->controlsize);
-                       break;
-               case VC_OUTPUT_TERMINAL:
-                       dprintk(DBGLVL_API, " VC_OUTPUT_TERMINAL\n");
-                       vcoutputtermhdr =
-                               (struct tmComResDMATermDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
-                               vcoutputtermhdr->unitid);
-                       dprintk(DBGLVL_API, "  terminaltype = 0x%x\n",
-                               vcoutputtermhdr->terminaltype);
-                       switch (vcoutputtermhdr->terminaltype) {
-                       case ITT_ANTENNA:
-                               dprintk(DBGLVL_API, "   = ITT_ANTENNA\n");
-                               break;
-                       case LINE_CONNECTOR:
-                               dprintk(DBGLVL_API, "   = LINE_CONNECTOR\n");
-                               break;
-                       case SPDIF_CONNECTOR:
-                               dprintk(DBGLVL_API, "   = SPDIF_CONNECTOR\n");
-                               break;
-                       case COMPOSITE_CONNECTOR:
-                               dprintk(DBGLVL_API,
-                                       "   = COMPOSITE_CONNECTOR\n");
-                               break;
-                       case SVIDEO_CONNECTOR:
-                               dprintk(DBGLVL_API, "   = SVIDEO_CONNECTOR\n");
-                               break;
-                       case COMPONENT_CONNECTOR:
-                               dprintk(DBGLVL_API,
-                                       "   = COMPONENT_CONNECTOR\n");
-                               break;
-                       case STANDARD_DMA:
-                               dprintk(DBGLVL_API, "   = STANDARD_DMA\n");
-                               break;
-                       default:
-                               dprintk(DBGLVL_API, "   = undefined (0x%x)\n",
-                                       vcoutputtermhdr->terminaltype);
-                       }
-                       dprintk(DBGLVL_API, "  assocterminal= 0x%x\n",
-                               vcoutputtermhdr->assocterminal);
-                       dprintk(DBGLVL_API, "  sourceid     = 0x%x\n",
-                               vcoutputtermhdr->sourceid);
-                       dprintk(DBGLVL_API, "  iterminal    = 0x%x\n",
-                               vcoutputtermhdr->iterminal);
-                       dprintk(DBGLVL_API, "  BARLocation  = 0x%x\n",
-                               vcoutputtermhdr->BARLocation);
-                       dprintk(DBGLVL_API, "  flags        = 0x%x\n",
-                               vcoutputtermhdr->flags);
-                       dprintk(DBGLVL_API, "  interruptid  = 0x%x\n",
-                               vcoutputtermhdr->interruptid);
-                       dprintk(DBGLVL_API, "  buffercount  = 0x%x\n",
-                               vcoutputtermhdr->buffercount);
-                       dprintk(DBGLVL_API, "  metadatasize = 0x%x\n",
-                               vcoutputtermhdr->metadatasize);
-                       dprintk(DBGLVL_API, "  controlsize  = 0x%x\n",
-                               vcoutputtermhdr->controlsize);
-                       dprintk(DBGLVL_API, "  numformats   = 0x%x\n",
-                               vcoutputtermhdr->numformats);
-
-                       t = (struct tmComResDescrHeader *)
-                               ((struct tmComResDMATermDescrHeader *)(buf + idx));
-                       next_offset = idx + (vcoutputtermhdr->len);
-                       for (i = 0; i < vcoutputtermhdr->numformats; i++) {
-                               t = (struct tmComResDescrHeader *)
-                                       (buf + next_offset);
-                               switch (t->subtype) {
-                               case VS_FORMAT_MPEG2TS:
-                                       tsfmt =
-                                       (struct tmComResTSFormatDescrHeader *)t;
-                                       if (currpath == 1)
-                                               tsport = &dev->ports[SAA7164_PORT_TS1];
-                                       else
-                                               tsport = &dev->ports[SAA7164_PORT_TS2];
-                                       memcpy(&tsport->hwcfg, vcoutputtermhdr,
-                                               sizeof(*vcoutputtermhdr));
-                                       saa7164_api_configure_port_mpeg2ts(dev,
-                                               tsport, tsfmt);
-                                       break;
-                               case VS_FORMAT_MPEG2PS:
-                                       psfmt =
-                                       (struct tmComResPSFormatDescrHeader *)t;
-                                       if (currpath == 1)
-                                               encport = &dev->ports[SAA7164_PORT_ENC1];
-                                       else
-                                               encport = &dev->ports[SAA7164_PORT_ENC2];
-                                       memcpy(&encport->hwcfg, vcoutputtermhdr,
-                                               sizeof(*vcoutputtermhdr));
-                                       saa7164_api_configure_port_mpeg2ps(dev,
-                                               encport, psfmt);
-                                       break;
-                               case VS_FORMAT_VBI:
-                                       vbifmt =
-                                       (struct tmComResVBIFormatDescrHeader *)t;
-                                       if (currpath == 1)
-                                               vbiport = &dev->ports[SAA7164_PORT_VBI1];
-                                       else
-                                               vbiport = &dev->ports[SAA7164_PORT_VBI2];
-                                       memcpy(&vbiport->hwcfg, vcoutputtermhdr,
-                                               sizeof(*vcoutputtermhdr));
-                                       memcpy(&vbiport->vbi_fmt_ntsc, vbifmt,
-                                               sizeof(*vbifmt));
-                                       saa7164_api_configure_port_vbi(dev,
-                                               vbiport);
-                                       break;
-                               case VS_FORMAT_RDS:
-                                       dprintk(DBGLVL_API,
-                                               "   = VS_FORMAT_RDS\n");
-                                       break;
-                               case VS_FORMAT_UNCOMPRESSED:
-                                       dprintk(DBGLVL_API,
-                                       "   = VS_FORMAT_UNCOMPRESSED\n");
-                                       break;
-                               case VS_FORMAT_TYPE:
-                                       dprintk(DBGLVL_API,
-                                               "   = VS_FORMAT_TYPE\n");
-                                       break;
-                               default:
-                                       dprintk(DBGLVL_API,
-                                               "   = undefined (0x%x)\n",
-                                               t->subtype);
-                               }
-                               next_offset += t->len;
-                       }
-
-                       break;
-               case TUNER_UNIT:
-                       dprintk(DBGLVL_API, " TUNER_UNIT\n");
-                       tunerunithdr =
-                               (struct tmComResTunerDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
-                               tunerunithdr->unitid);
-                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
-                               tunerunithdr->sourceid);
-                       dprintk(DBGLVL_API, "  iunit = 0x%x\n",
-                               tunerunithdr->iunit);
-                       dprintk(DBGLVL_API, "  tuningstandards = 0x%x\n",
-                               tunerunithdr->tuningstandards);
-                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
-                               tunerunithdr->controlsize);
-                       dprintk(DBGLVL_API, "  controls = 0x%x\n",
-                               tunerunithdr->controls);
-
-                       if (tunerunithdr->unitid == tunerunithdr->iunit) {
-                               if (currpath == 1)
-                                       encport = &dev->ports[SAA7164_PORT_ENC1];
-                               else
-                                       encport = &dev->ports[SAA7164_PORT_ENC2];
-                               memcpy(&encport->tunerunit, tunerunithdr,
-                                       sizeof(struct tmComResTunerDescrHeader));
-                               dprintk(DBGLVL_API,
-                                       "  (becomes dev->enc[%d] tuner)\n",
-                                       encport->nr);
-                       }
-                       break;
-               case VC_SELECTOR_UNIT:
-                       psel = (struct tmComResSelDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, " VC_SELECTOR_UNIT\n");
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
-                               psel->unitid);
-                       dprintk(DBGLVL_API, "  nrinpins = 0x%x\n",
-                               psel->nrinpins);
-                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
-                               psel->sourceid);
-                       break;
-               case VC_PROCESSING_UNIT:
-                       pdh = (struct tmComResProcDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, " VC_PROCESSING_UNIT\n");
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
-                               pdh->unitid);
-                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
-                               pdh->sourceid);
-                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
-                               pdh->controlsize);
-                       if (pdh->controlsize == 0x04) {
-                               if (currpath == 1)
-                                       encport = &dev->ports[SAA7164_PORT_ENC1];
-                               else
-                                       encport = &dev->ports[SAA7164_PORT_ENC2];
-                               memcpy(&encport->vidproc, pdh,
-                                       sizeof(struct tmComResProcDescrHeader));
-                               dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",
-                                       encport->nr);
-                       }
-                       break;
-               case FEATURE_UNIT:
-                       afd = (struct tmComResAFeatureDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, " FEATURE_UNIT\n");
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
-                               afd->unitid);
-                       dprintk(DBGLVL_API, "  sourceid = 0x%x\n",
-                               afd->sourceid);
-                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
-                               afd->controlsize);
-                       if (currpath == 1)
-                               encport = &dev->ports[SAA7164_PORT_ENC1];
-                       else
-                               encport = &dev->ports[SAA7164_PORT_ENC2];
-                       memcpy(&encport->audfeat, afd,
-                               sizeof(struct tmComResAFeatureDescrHeader));
-                       dprintk(DBGLVL_API, "  (becomes dev->enc[%d])\n",
-                               encport->nr);
-                       break;
-               case ENCODER_UNIT:
-                       edh = (struct tmComResEncoderDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, " ENCODER_UNIT\n");
-                       dprintk(DBGLVL_API, "  subtype = 0x%x\n", edh->subtype);
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n", edh->unitid);
-                       dprintk(DBGLVL_API, "  vsourceid = 0x%x\n",
-                       edh->vsourceid);
-                       dprintk(DBGLVL_API, "  asourceid = 0x%x\n",
-                               edh->asourceid);
-                       dprintk(DBGLVL_API, "  iunit = 0x%x\n", edh->iunit);
-                       if (edh->iunit == edh->unitid) {
-                               if (currpath == 1)
-                                       encport = &dev->ports[SAA7164_PORT_ENC1];
-                               else
-                                       encport = &dev->ports[SAA7164_PORT_ENC2];
-                               memcpy(&encport->encunit, edh,
-                                       sizeof(struct tmComResEncoderDescrHeader));
-                               dprintk(DBGLVL_API,
-                                       "  (becomes dev->enc[%d])\n",
-                                       encport->nr);
-                       }
-                       break;
-               case EXTENSION_UNIT:
-                       dprintk(DBGLVL_API, " EXTENSION_UNIT\n");
-                       exthdr = (struct tmComResExtDevDescrHeader *)(buf + idx);
-                       dprintk(DBGLVL_API, "  unitid = 0x%x\n",
-                               exthdr->unitid);
-                       dprintk(DBGLVL_API, "  deviceid = 0x%x\n",
-                               exthdr->deviceid);
-                       dprintk(DBGLVL_API, "  devicetype = 0x%x\n",
-                               exthdr->devicetype);
-                       if (exthdr->devicetype & 0x1)
-                               dprintk(DBGLVL_API, "   = Decoder Device\n");
-                       if (exthdr->devicetype & 0x2)
-                               dprintk(DBGLVL_API, "   = GPIO Source\n");
-                       if (exthdr->devicetype & 0x4)
-                               dprintk(DBGLVL_API, "   = Video Decoder\n");
-                       if (exthdr->devicetype & 0x8)
-                               dprintk(DBGLVL_API, "   = Audio Decoder\n");
-                       if (exthdr->devicetype & 0x20)
-                               dprintk(DBGLVL_API, "   = Crossbar\n");
-                       if (exthdr->devicetype & 0x40)
-                               dprintk(DBGLVL_API, "   = Tuner\n");
-                       if (exthdr->devicetype & 0x80)
-                               dprintk(DBGLVL_API, "   = IF PLL\n");
-                       if (exthdr->devicetype & 0x100)
-                               dprintk(DBGLVL_API, "   = Demodulator\n");
-                       if (exthdr->devicetype & 0x200)
-                               dprintk(DBGLVL_API, "   = RDS Decoder\n");
-                       if (exthdr->devicetype & 0x400)
-                               dprintk(DBGLVL_API, "   = Encoder\n");
-                       if (exthdr->devicetype & 0x800)
-                               dprintk(DBGLVL_API, "   = IR Decoder\n");
-                       if (exthdr->devicetype & 0x1000)
-                               dprintk(DBGLVL_API, "   = EEPROM\n");
-                       if (exthdr->devicetype & 0x2000)
-                               dprintk(DBGLVL_API,
-                                       "   = VBI Decoder\n");
-                       if (exthdr->devicetype & 0x10000)
-                               dprintk(DBGLVL_API,
-                                       "   = Streaming Device\n");
-                       if (exthdr->devicetype & 0x20000)
-                               dprintk(DBGLVL_API,
-                                       "   = DRM Device\n");
-                       if (exthdr->devicetype & 0x40000000)
-                               dprintk(DBGLVL_API,
-                                       "   = Generic Device\n");
-                       if (exthdr->devicetype & 0x80000000)
-                               dprintk(DBGLVL_API,
-                                       "   = Config Space Device\n");
-                       dprintk(DBGLVL_API, "  numgpiopins = 0x%x\n",
-                               exthdr->numgpiopins);
-                       dprintk(DBGLVL_API, "  numgpiogroups = 0x%x\n",
-                               exthdr->numgpiogroups);
-                       dprintk(DBGLVL_API, "  controlsize = 0x%x\n",
-                               exthdr->controlsize);
-                       if (exthdr->devicetype & 0x80) {
-                               if (currpath == 1)
-                                       encport = &dev->ports[SAA7164_PORT_ENC1];
-                               else
-                                       encport = &dev->ports[SAA7164_PORT_ENC2];
-                               memcpy(&encport->ifunit, exthdr,
-                                       sizeof(struct tmComResExtDevDescrHeader));
-                               dprintk(DBGLVL_API,
-                                       "  (becomes dev->enc[%d])\n",
-                                       encport->nr);
-                       }
-                       break;
-               case PVC_INFRARED_UNIT:
-                       dprintk(DBGLVL_API, " PVC_INFRARED_UNIT\n");
-                       break;
-               case DRM_UNIT:
-                       dprintk(DBGLVL_API, " DRM_UNIT\n");
-                       break;
-               default:
-                       dprintk(DBGLVL_API, "default %d\n", hdr->subtype);
-               }
-
-               dprintk(DBGLVL_API, " 1.%x\n", hdr->len);
-               dprintk(DBGLVL_API, " 2.%x\n", hdr->type);
-               dprintk(DBGLVL_API, " 3.%x\n", hdr->subtype);
-               dprintk(DBGLVL_API, " 4.%x\n", hdr->unitid);
-
-               idx += hdr->len;
-       }
-
-       return 0;
-}
-
-int saa7164_api_enum_subdevs(struct saa7164_dev *dev)
-{
-       int ret;
-       u32 buflen = 0;
-       u8 *buf;
-
-       dprintk(DBGLVL_API, "%s()\n", __func__);
-
-       /* Get the total descriptor length */
-       ret = saa7164_cmd_send(dev, 0, GET_LEN,
-               GET_DESCRIPTORS_CONTROL, sizeof(buflen), &buflen);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-
-       dprintk(DBGLVL_API, "%s() total descriptor size = %d bytes.\n",
-               __func__, buflen);
-
-       /* Allocate enough storage for all of the descs */
-       buf = kzalloc(buflen, GFP_KERNEL);
-       if (!buf)
-               return SAA_ERR_NO_RESOURCES;
-
-       /* Retrieve them */
-       ret = saa7164_cmd_send(dev, 0, GET_CUR,
-               GET_DESCRIPTORS_CONTROL, buflen, buf);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__, ret);
-               goto out;
-       }
-
-       if (saa_debug & DBGLVL_API)
-               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,
-                              buflen & ~15, false);
-
-       saa7164_api_dump_subdevs(dev, buf, buflen);
-
-out:
-       kfree(buf);
-       return ret;
-}
-
-int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
-       u32 datalen, u8 *data)
-{
-       struct saa7164_dev *dev = bus->dev;
-       u16 len = 0;
-       int unitid;
-       u8 buf[256];
-       int ret;
-
-       dprintk(DBGLVL_API, "%s()\n", __func__);
-
-       if (reglen > 4)
-               return -EIO;
-
-       /* Prepare the send buffer */
-       /* Bytes 00-03 source register length
-        *       04-07 source bytes to read
-        *       08... register address
-        */
-       memset(buf, 0, sizeof(buf));
-       memcpy((buf + 2 * sizeof(u32) + 0), reg, reglen);
-       *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
-       *((u32 *)(buf + 1 * sizeof(u32))) = datalen;
-
-       unitid = saa7164_i2caddr_to_unitid(bus, addr);
-       if (unitid < 0) {
-               printk(KERN_ERR
-                       "%s() error, cannot translate regaddr 0x%x to unitid\n",
-                       __func__, addr);
-               return -EIO;
-       }
-
-       ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
-               EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
-               return -EIO;
-       }
-
-       dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
-
-       if (saa_debug & DBGLVL_I2C)
-               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,
-                              32, false);
-
-       ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR,
-               EXU_REGISTER_ACCESS_CONTROL, len, &buf);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
-       else {
-               if (saa_debug & DBGLVL_I2C)
-                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
-                                      buf, sizeof(buf), false);
-               memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen);
-       }
-
-       return ret == SAA_OK ? 0 : -EIO;
-}
-
-/* For a given 8 bit i2c address device, write the buffer */
-int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
-       u8 *data)
-{
-       struct saa7164_dev *dev = bus->dev;
-       u16 len = 0;
-       int unitid;
-       int reglen;
-       u8 buf[256];
-       int ret;
-
-       dprintk(DBGLVL_API, "%s()\n", __func__);
-
-       if ((datalen == 0) || (datalen > 232))
-               return -EIO;
-
-       memset(buf, 0, sizeof(buf));
-
-       unitid = saa7164_i2caddr_to_unitid(bus, addr);
-       if (unitid < 0) {
-               printk(KERN_ERR
-                       "%s() error, cannot translate regaddr 0x%x to unitid\n",
-                       __func__, addr);
-               return -EIO;
-       }
-
-       reglen = saa7164_i2caddr_to_reglen(bus, addr);
-       if (reglen < 0) {
-               printk(KERN_ERR
-                       "%s() error, cannot translate regaddr to reglen\n",
-                       __func__);
-               return -EIO;
-       }
-
-       ret = saa7164_cmd_send(bus->dev, unitid, GET_LEN,
-               EXU_REGISTER_ACCESS_CONTROL, sizeof(len), &len);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() error, ret(1) = 0x%x\n", __func__, ret);
-               return -EIO;
-       }
-
-       dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
-
-       /* Prepare the send buffer */
-       /* Bytes 00-03 dest register length
-        *       04-07 dest bytes to write
-        *       08... register address
-        */
-       *((u32 *)(buf + 0 * sizeof(u32))) = reglen;
-       *((u32 *)(buf + 1 * sizeof(u32))) = datalen - reglen;
-       memcpy((buf + 2 * sizeof(u32)), data, datalen);
-
-       if (saa_debug & DBGLVL_I2C)
-               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
-                              buf, sizeof(buf), false);
-
-       ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR,
-               EXU_REGISTER_ACCESS_CONTROL, len, &buf);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
-
-       return ret == SAA_OK ? 0 : -EIO;
-}
-
-int saa7164_api_modify_gpio(struct saa7164_dev *dev, u8 unitid,
-       u8 pin, u8 state)
-{
-       int ret;
-       struct tmComResGPIO t;
-
-       dprintk(DBGLVL_API, "%s(0x%x, %d, %d)\n",
-               __func__, unitid, pin, state);
-
-       if ((pin > 7) || (state > 2))
-               return SAA_ERR_BAD_PARAMETER;
-
-       t.pin = pin;
-       t.state = state;
-
-       ret = saa7164_cmd_send(dev, unitid, SET_CUR,
-               EXU_GPIO_CONTROL, sizeof(t), &t);
-       if (ret != SAA_OK)
-               printk(KERN_ERR "%s() error, ret = 0x%x\n",
-                       __func__, ret);
-
-       return ret;
-}
-
-int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid,
-       u8 pin)
-{
-       return saa7164_api_modify_gpio(dev, unitid, pin, 1);
-}
-
-int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid,
-       u8 pin)
-{
-       return saa7164_api_modify_gpio(dev, unitid, pin, 0);
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c
deleted file mode 100644 (file)
index 66696fa..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 "saa7164.h"
-
-/* The PCI address space for buffer handling looks like this:
- *
- * +-u32 wide-------------+
- * |                      +
- * +-u64 wide------------------------------------+
- * +                                             +
- * +----------------------+
- * | CurrentBufferPtr     + Pointer to current PCI buffer >-+
- * +----------------------+                                 |
- * | Unused               +                                 |
- * +----------------------+                                 |
- * | Pitch                + = 188 (bytes)                   |
- * +----------------------+                                 |
- * | PCI buffer size      + = pitch * number of lines (312) |
- * +----------------------+                                 |
- * |0| Buf0 Write Offset  +                                 |
- * +----------------------+                                 v
- * |1| Buf1 Write Offset  +                                 |
- * +----------------------+                                 |
- * |2| Buf2 Write Offset  +                                 |
- * +----------------------+                                 |
- * |3| Buf3 Write Offset  +                                 |
- * +----------------------+                                 |
- * ... More write offsets                                   |
- * +---------------------------------------------+          |
- * +0| set of ptrs to PCI pagetables             +          |
- * +---------------------------------------------+          |
- * +1| set of ptrs to PCI pagetables             + <--------+
- * +---------------------------------------------+
- * +2| set of ptrs to PCI pagetables             +
- * +---------------------------------------------+
- * +3| set of ptrs to PCI pagetables             + >--+
- * +---------------------------------------------+    |
- * ... More buffer pointers                           |  +----------------+
- *                                                 +->| pt[0] TS data  |
- *                                                 |  +----------------+
- *                                                 |
- *                                                 |  +----------------+
- *                                                 +->| pt[1] TS data  |
- *                                                 |  +----------------+
- *                                                 | etc
- */
-
-void saa7164_buffer_display(struct saa7164_buffer *buf)
-{
-       struct saa7164_dev *dev = buf->port->dev;
-       int i;
-
-       dprintk(DBGLVL_BUF, "%s()   buffer @ 0x%p nr=%d\n",
-               __func__, buf, buf->idx);
-       dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08llx len = 0x%x\n",
-               buf->cpu, (long long)buf->dma, buf->pci_size);
-       dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08llx len = 0x%x\n",
-               buf->pt_cpu, (long long)buf->pt_dma, buf->pt_size);
-
-       /* Format the Page Table Entries to point into the data buffer */
-       for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) {
-
-               dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
-                       i, buf->pt_cpu, (u64)*(buf->pt_cpu));
-
-       }
-}
-/* Allocate a new buffer structure and associated PCI space in bytes.
- * len must be a multiple of sizeof(u64)
- */
-struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
-       u32 len)
-{
-       struct tmHWStreamParameters *params = &port->hw_streamingparams;
-       struct saa7164_buffer *buf = NULL;
-       struct saa7164_dev *dev = port->dev;
-       int i;
-
-       if ((len == 0) || (len >= 65536) || (len % sizeof(u64))) {
-               log_warn("%s() SAA_ERR_BAD_PARAMETER\n", __func__);
-               goto ret;
-       }
-
-       buf = kzalloc(sizeof(struct saa7164_buffer), GFP_KERNEL);
-       if (!buf) {
-               log_warn("%s() SAA_ERR_NO_RESOURCES\n", __func__);
-               goto ret;
-       }
-
-       buf->idx = -1;
-       buf->port = port;
-       buf->flags = SAA7164_BUFFER_FREE;
-       buf->pos = 0;
-       buf->actual_size = params->pitch * params->numberoflines;
-       buf->crc = 0;
-       /* TODO: arg len is being ignored */
-       buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
-       buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
-
-       /* Allocate contiguous memory */
-       buf->cpu = pci_alloc_consistent(port->dev->pci, buf->pci_size,
-               &buf->dma);
-       if (!buf->cpu)
-               goto fail1;
-
-       buf->pt_cpu = pci_alloc_consistent(port->dev->pci, buf->pt_size,
-               &buf->pt_dma);
-       if (!buf->pt_cpu)
-               goto fail2;
-
-       /* init the buffers to a known pattern, easier during debugging */
-       memset_io(buf->cpu, 0xff, buf->pci_size);
-       buf->crc = crc32(0, buf->cpu, buf->actual_size);
-       memset_io(buf->pt_cpu, 0xff, buf->pt_size);
-
-       dprintk(DBGLVL_BUF, "%s()   allocated buffer @ 0x%p (%d pageptrs)\n",
-               __func__, buf, params->numpagetables);
-       dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08lx len = 0x%x\n",
-               buf->cpu, (long)buf->dma, buf->pci_size);
-       dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n",
-               buf->pt_cpu, (long)buf->pt_dma, buf->pt_size);
-
-       /* Format the Page Table Entries to point into the data buffer */
-       for (i = 0 ; i < params->numpagetables; i++) {
-
-               *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */
-               dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
-                       i, buf->pt_cpu, (u64)*(buf->pt_cpu));
-
-       }
-
-       goto ret;
-
-fail2:
-       pci_free_consistent(port->dev->pci, buf->pci_size, buf->cpu, buf->dma);
-fail1:
-       kfree(buf);
-
-       buf = NULL;
-ret:
-       return buf;
-}
-
-int saa7164_buffer_dealloc(struct saa7164_buffer *buf)
-{
-       struct saa7164_dev *dev;
-
-       if (!buf || !buf->port)
-               return SAA_ERR_BAD_PARAMETER;
-       dev = buf->port->dev;
-
-       dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n",
-               __func__, buf);
-
-       if (buf->flags != SAA7164_BUFFER_FREE)
-               log_warn(" freeing a non-free buffer\n");
-
-       pci_free_consistent(dev->pci, buf->pci_size, buf->cpu, buf->dma);
-       pci_free_consistent(dev->pci, buf->pt_size, buf->pt_cpu, buf->pt_dma);
-
-       kfree(buf);
-
-       return SAA_OK;
-}
-
-int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       if ((i < 0) || (i >= port->hwcfg.buffercount))
-               return -EINVAL;
-
-       dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
-
-       saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
-
-       return 0;
-}
-
-/* Write a buffer into the hardware */
-int saa7164_buffer_activate(struct saa7164_buffer *buf, int i)
-{
-       struct saa7164_port *port = buf->port;
-       struct saa7164_dev *dev = port->dev;
-
-       if ((i < 0) || (i >= port->hwcfg.buffercount))
-               return -EINVAL;
-
-       dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
-
-       buf->idx = i; /* Note of which buffer list index position we occupy */
-       buf->flags = SAA7164_BUFFER_BUSY;
-       buf->pos = 0;
-
-       /* TODO: Review this in light of 32v64 assignments */
-       saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
-       saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma);
-       saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
-
-       dprintk(DBGLVL_BUF, "   buf[%d] offset 0x%llx (0x%x) "
-               "buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
-               buf->idx,
-               (u64)port->bufoffset + (i * sizeof(u32)),
-               saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
-               (u64)port->bufptr32h + ((sizeof(u32) * 2) * i),
-               (u64)port->bufptr32l + ((sizeof(u32) * 2) * i),
-               saa7164_readl(port->bufptr32h + ((sizeof(u32) * i) * 2)),
-               saa7164_readl(port->bufptr32l + ((sizeof(u32) * i) * 2)),
-               buf->idx);
-
-       return 0;
-}
-
-int saa7164_buffer_cfg_port(struct saa7164_port *port)
-{
-       struct tmHWStreamParameters *params = &port->hw_streamingparams;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct list_head *c, *n;
-       int i = 0;
-
-       dprintk(DBGLVL_BUF, "%s(port=%d)\n", __func__, port->nr);
-
-       saa7164_writel(port->bufcounter, 0);
-       saa7164_writel(port->pitch, params->pitch);
-       saa7164_writel(port->bufsize, params->pitch * params->numberoflines);
-
-       dprintk(DBGLVL_BUF, " configured:\n");
-       dprintk(DBGLVL_BUF, "   lmmio       0x%p\n", dev->lmmio);
-       dprintk(DBGLVL_BUF, "   bufcounter  0x%x = 0x%x\n", port->bufcounter,
-               saa7164_readl(port->bufcounter));
-
-       dprintk(DBGLVL_BUF, "   pitch       0x%x = %d\n", port->pitch,
-               saa7164_readl(port->pitch));
-
-       dprintk(DBGLVL_BUF, "   bufsize     0x%x = %d\n", port->bufsize,
-               saa7164_readl(port->bufsize));
-
-       dprintk(DBGLVL_BUF, "   buffercount = %d\n", port->hwcfg.buffercount);
-       dprintk(DBGLVL_BUF, "   bufoffset = 0x%x\n", port->bufoffset);
-       dprintk(DBGLVL_BUF, "   bufptr32h = 0x%x\n", port->bufptr32h);
-       dprintk(DBGLVL_BUF, "   bufptr32l = 0x%x\n", port->bufptr32l);
-
-       /* Poke the buffers and offsets into PCI space */
-       mutex_lock(&port->dmaqueue_lock);
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               buf = list_entry(c, struct saa7164_buffer, list);
-
-               if (buf->flags != SAA7164_BUFFER_FREE)
-                       BUG();
-
-               /* Place the buffer in the h/w queue */
-               saa7164_buffer_activate(buf, i);
-
-               /* Don't exceed the device maximum # bufs */
-               if (i++ > port->hwcfg.buffercount)
-                       BUG();
-
-       }
-       mutex_unlock(&port->dmaqueue_lock);
-
-       return 0;
-}
-
-struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev,
-       u32 len)
-{
-       struct saa7164_user_buffer *buf;
-
-       buf = kzalloc(sizeof(struct saa7164_user_buffer), GFP_KERNEL);
-       if (!buf)
-               return NULL;
-
-       buf->data = kzalloc(len, GFP_KERNEL);
-
-       if (!buf->data) {
-               kfree(buf);
-               return NULL;
-       }
-
-       buf->actual_size = len;
-       buf->pos = 0;
-       buf->crc = 0;
-
-       dprintk(DBGLVL_BUF, "%s()   allocated user buffer @ 0x%p\n",
-               __func__, buf);
-
-       return buf;
-}
-
-void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf)
-{
-       if (!buf)
-               return;
-
-       kfree(buf->data);
-       buf->data = NULL;
-
-       kfree(buf);
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c
deleted file mode 100644 (file)
index a7f58a9..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 "saa7164.h"
-
-/* The message bus to/from the firmware is a ring buffer in PCI address
- * space. Establish the defaults.
- */
-int saa7164_bus_setup(struct saa7164_dev *dev)
-{
-       struct tmComResBusInfo *b       = &dev->bus;
-
-       mutex_init(&b->lock);
-
-       b->Type                 = TYPE_BUS_PCIe;
-       b->m_wMaxReqSize        = SAA_DEVICE_MAXREQUESTSIZE;
-
-       b->m_pdwSetRing         = (u8 *)(dev->bmmio +
-               ((u32)dev->busdesc.CommandRing));
-
-       b->m_dwSizeSetRing      = SAA_DEVICE_BUFFERBLOCKSIZE;
-
-       b->m_pdwGetRing         = (u8 *)(dev->bmmio +
-               ((u32)dev->busdesc.ResponseRing));
-
-       b->m_dwSizeGetRing      = SAA_DEVICE_BUFFERBLOCKSIZE;
-
-       b->m_dwSetWritePos      = ((u32)dev->intfdesc.BARLocation) +
-               (2 * sizeof(u64));
-       b->m_dwSetReadPos       = b->m_dwSetWritePos + (1 * sizeof(u32));
-
-       b->m_dwGetWritePos      = b->m_dwSetWritePos + (2 * sizeof(u32));
-       b->m_dwGetReadPos       = b->m_dwSetWritePos + (3 * sizeof(u32));
-
-       return 0;
-}
-
-void saa7164_bus_dump(struct saa7164_dev *dev)
-{
-       struct tmComResBusInfo *b = &dev->bus;
-
-       dprintk(DBGLVL_BUS, "Dumping the bus structure:\n");
-       dprintk(DBGLVL_BUS, " .type             = %d\n", b->Type);
-       dprintk(DBGLVL_BUS, " .dev->bmmio       = 0x%p\n", dev->bmmio);
-       dprintk(DBGLVL_BUS, " .m_wMaxReqSize    = 0x%x\n", b->m_wMaxReqSize);
-       dprintk(DBGLVL_BUS, " .m_pdwSetRing     = 0x%p\n", b->m_pdwSetRing);
-       dprintk(DBGLVL_BUS, " .m_dwSizeSetRing  = 0x%x\n", b->m_dwSizeSetRing);
-       dprintk(DBGLVL_BUS, " .m_pdwGetRing     = 0x%p\n", b->m_pdwGetRing);
-       dprintk(DBGLVL_BUS, " .m_dwSizeGetRing  = 0x%x\n", b->m_dwSizeGetRing);
-
-       dprintk(DBGLVL_BUS, " .m_dwSetReadPos   = 0x%x (0x%08x)\n",
-               b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
-
-       dprintk(DBGLVL_BUS, " .m_dwSetWritePos  = 0x%x (0x%08x)\n",
-               b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
-
-       dprintk(DBGLVL_BUS, " .m_dwGetReadPos   = 0x%x (0x%08x)\n",
-               b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
-
-       dprintk(DBGLVL_BUS, " .m_dwGetWritePos  = 0x%x (0x%08x)\n",
-               b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
-
-}
-
-/* Intensionally throw a BUG() if the state of the message bus looks corrupt */
-void saa7164_bus_verify(struct saa7164_dev *dev)
-{
-       struct tmComResBusInfo *b = &dev->bus;
-       int bug = 0;
-
-       if (saa7164_readl(b->m_dwSetReadPos) > b->m_dwSizeSetRing)
-               bug++;
-
-       if (saa7164_readl(b->m_dwSetWritePos) > b->m_dwSizeSetRing)
-               bug++;
-
-       if (saa7164_readl(b->m_dwGetReadPos) > b->m_dwSizeGetRing)
-               bug++;
-
-       if (saa7164_readl(b->m_dwGetWritePos) > b->m_dwSizeGetRing)
-               bug++;
-
-       if (bug) {
-               saa_debug = 0xffff; /* Ensure we get the bus dump */
-               saa7164_bus_dump(dev);
-               saa_debug = 1024; /* Ensure we get the bus dump */
-               BUG();
-       }
-}
-
-void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo* m,
-       void *buf)
-{
-       dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
-       dprintk(DBGLVL_BUS, " .id               = %d\n",   m->id);
-       dprintk(DBGLVL_BUS, " .flags            = 0x%x\n", m->flags);
-       dprintk(DBGLVL_BUS, " .size             = 0x%x\n", m->size);
-       dprintk(DBGLVL_BUS, " .command          = 0x%x\n", m->command);
-       dprintk(DBGLVL_BUS, " .controlselector  = 0x%x\n", m->controlselector);
-       dprintk(DBGLVL_BUS, " .seqno            = %d\n",   m->seqno);
-       if (buf)
-               dprintk(DBGLVL_BUS, " .buffer (ignored)\n");
-}
-
-/*
- * Places a command or a response on the bus. The implementation does not
- * know if it is a command or a response it just places the data on the
- * bus depending on the bus information given in the struct tmComResBusInfo
- * structure. If the command or response does not fit into the bus ring
- * buffer it will be refused.
- *
- * Return Value:
- *  SAA_OK     The function executed successfully.
- *  < 0        One or more members are not initialized.
- */
-int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
-       void *buf)
-{
-       struct tmComResBusInfo *bus = &dev->bus;
-       u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
-       u32 new_swp, space_rem;
-       int ret = SAA_ERR_BAD_PARAMETER;
-
-       if (!msg) {
-               printk(KERN_ERR "%s() !msg\n", __func__);
-               return SAA_ERR_BAD_PARAMETER;
-       }
-
-       dprintk(DBGLVL_BUS, "%s()\n", __func__);
-
-       saa7164_bus_verify(dev);
-
-       msg->size = cpu_to_le16(msg->size);
-       msg->command = cpu_to_le32(msg->command);
-       msg->controlselector = cpu_to_le16(msg->controlselector);
-
-       if (msg->size > dev->bus.m_wMaxReqSize) {
-               printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
-                       __func__);
-               return SAA_ERR_BAD_PARAMETER;
-       }
-
-       if ((msg->size > 0) && (buf == NULL)) {
-               printk(KERN_ERR "%s() Missing message buffer\n", __func__);
-               return SAA_ERR_BAD_PARAMETER;
-       }
-
-       /* Lock the bus from any other access */
-       mutex_lock(&bus->lock);
-
-       bytes_to_write = sizeof(*msg) + msg->size;
-       free_write_space = 0;
-       timeout = SAA_BUS_TIMEOUT;
-       curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
-       curr_swp = le32_to_cpu(saa7164_readl(bus->m_dwSetWritePos));
-
-       /* Deal with ring wrapping issues */
-       if (curr_srp > curr_swp)
-               /* Deal with the wrapped ring */
-               free_write_space = curr_srp - curr_swp;
-       else
-               /* The ring has not wrapped yet */
-               free_write_space = (curr_srp + bus->m_dwSizeSetRing) - curr_swp;
-
-       dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__,
-               bytes_to_write);
-
-       dprintk(DBGLVL_BUS, "%s() free_write_space = %d\n", __func__,
-               free_write_space);
-
-       dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp);
-       dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp);
-
-       /* Process the msg and write the content onto the bus */
-       while (bytes_to_write >= free_write_space) {
-
-               if (timeout-- == 0) {
-                       printk(KERN_ERR "%s() bus timeout\n", __func__);
-                       ret = SAA_ERR_NO_RESOURCES;
-                       goto out;
-               }
-
-               /* TODO: Review this delay, efficient? */
-               /* Wait, allowing the hardware fetch time */
-               mdelay(1);
-
-               /* Check the space usage again */
-               curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
-
-               /* Deal with ring wrapping issues */
-               if (curr_srp > curr_swp)
-                       /* Deal with the wrapped ring */
-                       free_write_space = curr_srp - curr_swp;
-               else
-                       /* Read didn't wrap around the buffer */
-                       free_write_space = (curr_srp + bus->m_dwSizeSetRing) -
-                               curr_swp;
-
-       }
-
-       /* Calculate the new write position */
-       new_swp = curr_swp + bytes_to_write;
-
-       dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
-       dprintk(DBGLVL_BUS, "%s() bus->m_dwSizeSetRing = %x\n", __func__,
-               bus->m_dwSizeSetRing);
-
-       /* Mental Note: line 462 tmmhComResBusPCIe.cpp */
-
-       /* Check if we're going to wrap again */
-       if (new_swp > bus->m_dwSizeSetRing) {
-
-               /* Ring wraps */
-               new_swp -= bus->m_dwSizeSetRing;
-
-               space_rem = bus->m_dwSizeSetRing - curr_swp;
-
-               dprintk(DBGLVL_BUS, "%s() space_rem = %x\n", __func__,
-                       space_rem);
-
-               dprintk(DBGLVL_BUS, "%s() sizeof(*msg) = %d\n", __func__,
-                       (u32)sizeof(*msg));
-
-               if (space_rem < sizeof(*msg)) {
-                       dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
-
-                       /* Split the msg into pieces as the ring wraps */
-                       memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem);
-                       memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem,
-                               sizeof(*msg) - space_rem);
-
-                       memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
-                               buf, msg->size);
-
-               } else if (space_rem == sizeof(*msg)) {
-                       dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
-
-                       /* Additional data at the beginning of the ring */
-                       memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-                       memcpy(bus->m_pdwSetRing, buf, msg->size);
-
-               } else {
-                       /* Additional data wraps around the ring */
-                       memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-                       if (msg->size > 0) {
-                               memcpy(bus->m_pdwSetRing + curr_swp +
-                                       sizeof(*msg), buf, space_rem -
-                                       sizeof(*msg));
-                               memcpy(bus->m_pdwSetRing, (u8 *)buf +
-                                       space_rem - sizeof(*msg),
-                                       bytes_to_write - space_rem);
-                       }
-
-               }
-
-       } /* (new_swp > bus->m_dwSizeSetRing) */
-       else {
-               dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
-
-               /* The ring buffer doesn't wrap, two simple copies */
-               memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
-               memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
-                       msg->size);
-       }
-
-       dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
-
-       /* Update the bus write position */
-       saa7164_writel(bus->m_dwSetWritePos, cpu_to_le32(new_swp));
-       ret = SAA_OK;
-
-out:
-       saa7164_bus_dump(dev);
-       mutex_unlock(&bus->lock);
-       saa7164_bus_verify(dev);
-       return ret;
-}
-
-/*
- * Receive a command or a response from the bus. The implementation does not
- * know if it is a command or a response it simply dequeues the data,
- * depending on the bus information given in the struct tmComResBusInfo
- * structure.
- *
- * Return Value:
- *  0          The function executed successfully.
- *  < 0        One or more members are not initialized.
- */
-int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
-       void *buf, int peekonly)
-{
-       struct tmComResBusInfo *bus = &dev->bus;
-       u32 bytes_to_read, write_distance, curr_grp, curr_gwp,
-               new_grp, buf_size, space_rem;
-       struct tmComResInfo msg_tmp;
-       int ret = SAA_ERR_BAD_PARAMETER;
-
-       saa7164_bus_verify(dev);
-
-       if (msg == NULL)
-               return ret;
-
-       if (msg->size > dev->bus.m_wMaxReqSize) {
-               printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
-                       __func__);
-               return ret;
-       }
-
-       if ((peekonly == 0) && (msg->size > 0) && (buf == NULL)) {
-               printk(KERN_ERR
-                       "%s() Missing msg buf, size should be %d bytes\n",
-                       __func__, msg->size);
-               return ret;
-       }
-
-       mutex_lock(&bus->lock);
-
-       /* Peek the bus to see if a msg exists, if it's not what we're expecting
-        * then return cleanly else read the message from the bus.
-        */
-       curr_gwp = le32_to_cpu(saa7164_readl(bus->m_dwGetWritePos));
-       curr_grp = le32_to_cpu(saa7164_readl(bus->m_dwGetReadPos));
-
-       if (curr_gwp == curr_grp) {
-               ret = SAA_ERR_EMPTY;
-               goto out;
-       }
-
-       bytes_to_read = sizeof(*msg);
-
-       /* Calculate write distance to current read position */
-       write_distance = 0;
-       if (curr_gwp >= curr_grp)
-               /* Write doesn't wrap around the ring */
-               write_distance = curr_gwp - curr_grp;
-       else
-               /* Write wraps around the ring */
-               write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
-
-       if (bytes_to_read > write_distance) {
-               printk(KERN_ERR "%s() No message/response found\n", __func__);
-               ret = SAA_ERR_INVALID_COMMAND;
-               goto out;
-       }
-
-       /* Calculate the new read position */
-       new_grp = curr_grp + bytes_to_read;
-       if (new_grp > bus->m_dwSizeGetRing) {
-
-               /* Ring wraps */
-               new_grp -= bus->m_dwSizeGetRing;
-               space_rem = bus->m_dwSizeGetRing - curr_grp;
-
-               memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
-               memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
-                       bytes_to_read - space_rem);
-
-       } else {
-               /* No wrapping */
-               memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
-       }
-
-       /* No need to update the read positions, because this was a peek */
-       /* If the caller specifically want to peek, return */
-       if (peekonly) {
-               memcpy(msg, &msg_tmp, sizeof(*msg));
-               goto peekout;
-       }
-
-       /* Check if the command/response matches what is expected */
-       if ((msg_tmp.id != msg->id) || (msg_tmp.command != msg->command) ||
-               (msg_tmp.controlselector != msg->controlselector) ||
-               (msg_tmp.seqno != msg->seqno) || (msg_tmp.size != msg->size)) {
-
-               printk(KERN_ERR "%s() Unexpected msg miss-match\n", __func__);
-               saa7164_bus_dumpmsg(dev, msg, buf);
-               saa7164_bus_dumpmsg(dev, &msg_tmp, NULL);
-               ret = SAA_ERR_INVALID_COMMAND;
-               goto out;
-       }
-
-       /* Get the actual command and response from the bus */
-       buf_size = msg->size;
-
-       bytes_to_read = sizeof(*msg) + msg->size;
-       /* Calculate write distance to current read position */
-       write_distance = 0;
-       if (curr_gwp >= curr_grp)
-               /* Write doesn't wrap around the ring */
-               write_distance = curr_gwp - curr_grp;
-       else
-               /* Write wraps around the ring */
-               write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
-
-       if (bytes_to_read > write_distance) {
-               printk(KERN_ERR "%s() Invalid bus state, missing msg "
-                       "or mangled ring, faulty H/W / bad code?\n", __func__);
-               ret = SAA_ERR_INVALID_COMMAND;
-               goto out;
-       }
-
-       /* Calculate the new read position */
-       new_grp = curr_grp + bytes_to_read;
-       if (new_grp > bus->m_dwSizeGetRing) {
-
-               /* Ring wraps */
-               new_grp -= bus->m_dwSizeGetRing;
-               space_rem = bus->m_dwSizeGetRing - curr_grp;
-
-               if (space_rem < sizeof(*msg)) {
-                       /* msg wraps around the ring */
-                       memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem);
-                       memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing,
-                               sizeof(*msg) - space_rem);
-                       if (buf)
-                               memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) -
-                                       space_rem, buf_size);
-
-               } else if (space_rem == sizeof(*msg)) {
-                       memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
-                       if (buf)
-                               memcpy(buf, bus->m_pdwGetRing, buf_size);
-               } else {
-                       /* Additional data wraps around the ring */
-                       memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
-                       if (buf) {
-                               memcpy(buf, bus->m_pdwGetRing + curr_grp +
-                                       sizeof(*msg), space_rem - sizeof(*msg));
-                               memcpy(buf + space_rem - sizeof(*msg),
-                                       bus->m_pdwGetRing, bytes_to_read -
-                                       space_rem);
-                       }
-
-               }
-
-       } else {
-               /* No wrapping */
-               memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
-               if (buf)
-                       memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
-                               buf_size);
-       }
-
-       /* Update the read positions, adjusting the ring */
-       saa7164_writel(bus->m_dwGetReadPos, cpu_to_le32(new_grp));
-
-peekout:
-       msg->size = le16_to_cpu(msg->size);
-       msg->command = le32_to_cpu(msg->command);
-       msg->controlselector = le16_to_cpu(msg->controlselector);
-       ret = SAA_OK;
-out:
-       mutex_unlock(&bus->lock);
-       saa7164_bus_verify(dev);
-       return ret;
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-cards.c b/drivers/media/video/saa7164/saa7164-cards.c
deleted file mode 100644 (file)
index 5b72da5..0000000
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-#include "saa7164.h"
-
-/* The Bridge API needs to understand register widths (in bytes) for the
- * attached I2C devices, so we can simplify the virtual i2c mechansms
- * and keep the -i2c.c implementation clean.
- */
-#define REGLEN_8bit    1
-#define REGLEN_16bit   2
-
-struct saa7164_board saa7164_boards[] = {
-       [SAA7164_BOARD_UNKNOWN] = {
-               /* Bridge will not load any firmware, without knowing
-                * the rev this would be fatal. */
-               .name           = "Unknown",
-       },
-       [SAA7164_BOARD_UNKNOWN_REV2] = {
-               /* Bridge will load the v2 f/w and dump descriptors */
-               /* Required during new board bringup */
-               .name           = "Generic Rev2",
-               .chiprev        = SAA7164_CHIP_REV2,
-       },
-       [SAA7164_BOARD_UNKNOWN_REV3] = {
-               /* Bridge will load the v2 f/w and dump descriptors */
-               /* Required during new board bringup */
-               .name           = "Generic Rev3",
-               .chiprev        = SAA7164_CHIP_REV3,
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2200] = {
-               .name           = "Hauppauge WinTV-HVR2200",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV3,
-               .unit           = {{
-                       .id             = 0x1d,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1b,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1e,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x10 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1f,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x12 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2200_2] = {
-               .name           = "Hauppauge WinTV-HVR2200",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV2,
-               .unit           = {{
-                       .id             = 0x06,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x05,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x10 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1e,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1f,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x12 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2200_3] = {
-               .name           = "Hauppauge WinTV-HVR2200",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV2,
-               .unit           = {{
-                       .id             = 0x1d,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x05,
-                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
-                       .name           = "TDA8290-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x84 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1b,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1c,
-                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
-                       .name           = "TDA8290-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x84 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1e,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x10 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1f,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x12 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2200_4] = {
-               .name           = "Hauppauge WinTV-HVR2200",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV3,
-               .unit           = {{
-                       .id             = 0x1d,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x05,
-                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
-                       .name           = "TDA8290-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x84 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1b,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1c,
-                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
-                       .name           = "TDA8290-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x84 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1e,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x10 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1f,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x12 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2250] = {
-               .name           = "Hauppauge WinTV-HVR2250",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV3,
-               .unit           = {{
-                       .id             = 0x22,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x07,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-1 (TOP)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x32 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x08,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-1 (QAM)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x34 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x1e,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x20,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-2 (TOP)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x32 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x23,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-2 (QAM)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x34 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2250_2] = {
-               .name           = "Hauppauge WinTV-HVR2250",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV3,
-               .unit           = {{
-                       .id             = 0x28,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x07,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-1 (TOP)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x32 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x08,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-1 (QAM)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x34 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x24,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x26,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-2 (TOP)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x32 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x29,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-2 (QAM)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x34 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2250_3] = {
-               .name           = "Hauppauge WinTV-HVR2250",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .portc          = SAA7164_MPEG_ENCODER,
-               .portd          = SAA7164_MPEG_ENCODER,
-               .porte          = SAA7164_MPEG_VBI,
-               .portf          = SAA7164_MPEG_VBI,
-               .chiprev        = SAA7164_CHIP_REV3,
-               .unit           = {{
-                       .id             = 0x26,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x07,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-1 (TOP)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x32 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x08,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-1 (QAM)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x34 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x22,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x24,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-2 (TOP)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x32 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x27,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "CX24228/S5H1411-2 (QAM)",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x34 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-       [SAA7164_BOARD_HAUPPAUGE_HVR2200_5] = {
-               .name           = "Hauppauge WinTV-HVR2200",
-               .porta          = SAA7164_MPEG_DVB,
-               .portb          = SAA7164_MPEG_DVB,
-               .chiprev        = SAA7164_CHIP_REV3,
-               .unit           = {{
-                       .id             = 0x23,
-                       .type           = SAA7164_UNIT_EEPROM,
-                       .name           = "4K EEPROM",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_0,
-                       .i2c_bus_addr   = 0xa0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x04,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x05,
-                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
-                       .name           = "TDA8290-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x84 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x21,
-                       .type           = SAA7164_UNIT_TUNER,
-                       .name           = "TDA18271-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0xc0 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x22,
-                       .type           = SAA7164_UNIT_ANALOG_DEMODULATOR,
-                       .name           = "TDA8290-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x84 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x24,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-1",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_1,
-                       .i2c_bus_addr   = 0x10 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               }, {
-                       .id             = 0x25,
-                       .type           = SAA7164_UNIT_DIGITAL_DEMODULATOR,
-                       .name           = "TDA10048-2",
-                       .i2c_bus_nr     = SAA7164_I2C_BUS_2,
-                       .i2c_bus_addr   = 0x12 >> 1,
-                       .i2c_reg_len    = REGLEN_8bit,
-               } },
-       },
-};
-const unsigned int saa7164_bcount = ARRAY_SIZE(saa7164_boards);
-
-/* ------------------------------------------------------------------ */
-/* PCI subsystem IDs                                                  */
-
-struct saa7164_subid saa7164_subids[] = {
-       {
-               .subvendor = 0x0070,
-               .subdevice = 0x8880,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8810,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8980,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8900,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_2,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8901,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_3,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x88A1,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_3,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8891,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8851,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2250_2,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8940,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_4,
-       }, {
-               .subvendor = 0x0070,
-               .subdevice = 0x8953,
-               .card      = SAA7164_BOARD_HAUPPAUGE_HVR2200_5,
-       },
-};
-const unsigned int saa7164_idcount = ARRAY_SIZE(saa7164_subids);
-
-void saa7164_card_list(struct saa7164_dev *dev)
-{
-       int i;
-
-       if (0 == dev->pci->subsystem_vendor &&
-           0 == dev->pci->subsystem_device) {
-               printk(KERN_ERR
-                       "%s: Board has no valid PCIe Subsystem ID and can't\n"
-                       "%s: be autodetected. Pass card=<n> insmod option to\n"
-                       "%s: workaround that. Send complaints to the vendor\n"
-                       "%s: of the TV card. Best regards,\n"
-                       "%s:         -- tux\n",
-                       dev->name, dev->name, dev->name, dev->name, dev->name);
-       } else {
-               printk(KERN_ERR
-                       "%s: Your board isn't known (yet) to the driver.\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",
-                       dev->name, dev->name, dev->name, dev->name);
-       }
-
-       printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod "
-               "option:\n", dev->name);
-
-       for (i = 0; i < saa7164_bcount; i++)
-               printk(KERN_ERR "%s:    card=%d -> %s\n",
-                      dev->name, i, saa7164_boards[i].name);
-}
-
-/* TODO: clean this define up into the -cards.c structs */
-#define PCIEBRIDGE_UNITID 2
-
-void saa7164_gpio_setup(struct saa7164_dev *dev)
-{
-       switch (dev->board) {
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
-               /*
-               GPIO 2: s5h1411 / tda10048-1 demod reset
-               GPIO 3: s5h1411 / tda10048-2 demod reset
-               GPIO 7: IRBlaster Zilog reset
-                */
-
-               /* Reset parts by going in and out of reset */
-               saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
-               saa7164_api_clear_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
-
-               msleep(20);
-
-               saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 2);
-               saa7164_api_set_gpiobit(dev, PCIEBRIDGE_UNITID, 3);
-               break;
-       }
-}
-
-static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data)
-{
-       struct tveeprom tv;
-
-       /* TODO: Assumption: eeprom on bus 0 */
-       tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
-               eeprom_data);
-
-       /* Make sure we support the board model */
-       switch (tv.model) {
-       case 88001:
-               /* Development board - Limit circulation */
-               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
-                * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
-       case 88021:
-               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
-                * ATSC/QAM (TDA18271/S5H1411) and basic analog, MCE CIR, FM */
-               break;
-       case 88041:
-               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
-                * ATSC/QAM (TDA18271/S5H1411) and basic analog, no IR, FM */
-               break;
-       case 88061:
-               /* WinTV-HVR2250 (PCIe, Retail, full-height bracket)
-                * ATSC/QAM (TDA18271/S5H1411) and basic analog, FM */
-               break;
-       case 89519:
-       case 89609:
-               /* WinTV-HVR2200 (PCIe, Retail, full-height)
-                * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
-               break;
-       case 89619:
-               /* WinTV-HVR2200 (PCIe, Retail, half-height)
-                * DVB-T (TDA18271/TDA10048) and basic analog, no IR */
-               break;
-       default:
-               printk(KERN_ERR "%s: Warning: Unknown Hauppauge model #%d\n",
-                       dev->name, tv.model);
-               break;
-       }
-
-       printk(KERN_INFO "%s: Hauppauge eeprom: model=%d\n", dev->name,
-               tv.model);
-}
-
-void saa7164_card_setup(struct saa7164_dev *dev)
-{
-       static u8 eeprom[256];
-
-       if (dev->i2c_bus[0].i2c_rc == 0) {
-               if (saa7164_api_read_eeprom(dev, &eeprom[0],
-                       sizeof(eeprom)) < 0)
-                       return;
-       }
-
-       switch (dev->board) {
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
-               hauppauge_eeprom(dev, &eeprom[0]);
-               break;
-       }
-}
-
-/* With most other drivers, the kernel expects to communicate with subdrivers
- * through i2c. This bridge does not allow that, it does not expose any direct
- * access to I2C. Instead we have to communicate through the device f/w for
- * register access to 'processing units'. Each unit has a unique
- * id, regardless of how the physical implementation occurs across
- * the three physical i2c busses. The being said if we want leverge of
- * the existing kernel drivers for tuners and demods we have to 'speak i2c',
- * to this bridge implements 3 virtual i2c buses. This is a helper function
- * for those.
- *
- * Description: Translate the kernels notion of an i2c address and bus into
- * the appropriate unitid.
- */
-int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr)
-{
-       /* For a given bus and i2c device address, return the saa7164 unique
-        * unitid. < 0 on error */
-
-       struct saa7164_dev *dev = bus->dev;
-       struct saa7164_unit *unit;
-       int i;
-
-       for (i = 0; i < SAA7164_MAX_UNITS; i++) {
-               unit = &saa7164_boards[dev->board].unit[i];
-
-               if (unit->type == SAA7164_UNIT_UNDEFINED)
-                       continue;
-               if ((bus->nr == unit->i2c_bus_nr) &&
-                       (addr == unit->i2c_bus_addr))
-                       return unit->id;
-       }
-
-       return -1;
-}
-
-/* The 7164 API needs to know the i2c register length in advance.
- * this is a helper function. Based on a specific chip addr and bus return the
- * reg length.
- */
-int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr)
-{
-       /* For a given bus and i2c device address, return the
-        * saa7164 registry address width. < 0 on error
-        */
-
-       struct saa7164_dev *dev = bus->dev;
-       struct saa7164_unit *unit;
-       int i;
-
-       for (i = 0; i < SAA7164_MAX_UNITS; i++) {
-               unit = &saa7164_boards[dev->board].unit[i];
-
-               if (unit->type == SAA7164_UNIT_UNDEFINED)
-                       continue;
-
-               if ((bus->nr == unit->i2c_bus_nr) &&
-                       (addr == unit->i2c_bus_addr))
-                       return unit->i2c_reg_len;
-       }
-
-       return -1;
-}
-/* TODO: implement a 'findeeprom' functio like the above and fix any other
- * eeprom related todo's in -api.c.
- */
-
-/* Translate a unitid into a x readable device name, for display purposes.  */
-char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid)
-{
-       char *undefed = "UNDEFINED";
-       char *bridge = "BRIDGE";
-       struct saa7164_unit *unit;
-       int i;
-
-       if (unitid == 0)
-               return bridge;
-
-       for (i = 0; i < SAA7164_MAX_UNITS; i++) {
-               unit = &saa7164_boards[dev->board].unit[i];
-
-               if (unit->type == SAA7164_UNIT_UNDEFINED)
-                       continue;
-
-               if (unitid == unit->id)
-                               return unit->name;
-       }
-
-       return undefed;
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-cmd.c b/drivers/media/video/saa7164/saa7164-cmd.c
deleted file mode 100644 (file)
index 62fac7f..0000000
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/wait.h>
-
-#include "saa7164.h"
-
-int saa7164_cmd_alloc_seqno(struct saa7164_dev *dev)
-{
-       int i, ret = -1;
-
-       mutex_lock(&dev->lock);
-       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
-               if (dev->cmds[i].inuse == 0) {
-                       dev->cmds[i].inuse = 1;
-                       dev->cmds[i].signalled = 0;
-                       dev->cmds[i].timeout = 0;
-                       ret = dev->cmds[i].seqno;
-                       break;
-               }
-       }
-       mutex_unlock(&dev->lock);
-
-       return ret;
-}
-
-void saa7164_cmd_free_seqno(struct saa7164_dev *dev, u8 seqno)
-{
-       mutex_lock(&dev->lock);
-       if ((dev->cmds[seqno].inuse == 1) &&
-               (dev->cmds[seqno].seqno == seqno)) {
-               dev->cmds[seqno].inuse = 0;
-               dev->cmds[seqno].signalled = 0;
-               dev->cmds[seqno].timeout = 0;
-       }
-       mutex_unlock(&dev->lock);
-}
-
-void saa7164_cmd_timeout_seqno(struct saa7164_dev *dev, u8 seqno)
-{
-       mutex_lock(&dev->lock);
-       if ((dev->cmds[seqno].inuse == 1) &&
-               (dev->cmds[seqno].seqno == seqno)) {
-               dev->cmds[seqno].timeout = 1;
-       }
-       mutex_unlock(&dev->lock);
-}
-
-u32 saa7164_cmd_timeout_get(struct saa7164_dev *dev, u8 seqno)
-{
-       int ret = 0;
-
-       mutex_lock(&dev->lock);
-       if ((dev->cmds[seqno].inuse == 1) &&
-               (dev->cmds[seqno].seqno == seqno)) {
-               ret = dev->cmds[seqno].timeout;
-       }
-       mutex_unlock(&dev->lock);
-
-       return ret;
-}
-
-/* Commands to the f/w get marshelled to/from this code then onto the PCI
- * -bus/c running buffer. */
-int saa7164_irq_dequeue(struct saa7164_dev *dev)
-{
-       int ret = SAA_OK, i = 0;
-       u32 timeout;
-       wait_queue_head_t *q = NULL;
-       u8 tmp[512];
-       dprintk(DBGLVL_CMD, "%s()\n", __func__);
-
-       /* While any outstand message on the bus exists... */
-       do {
-
-               /* Peek the msg bus */
-               struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
-               ret = saa7164_bus_get(dev, &tRsp, NULL, 1);
-               if (ret != SAA_OK)
-                       break;
-
-               q = &dev->cmds[tRsp.seqno].wait;
-               timeout = saa7164_cmd_timeout_get(dev, tRsp.seqno);
-               dprintk(DBGLVL_CMD, "%s() timeout = %d\n", __func__, timeout);
-               if (!timeout) {
-                       dprintk(DBGLVL_CMD,
-                               "%s() signalled seqno(%d) (for dequeue)\n",
-                               __func__, tRsp.seqno);
-                       dev->cmds[tRsp.seqno].signalled = 1;
-                       wake_up(q);
-               } else {
-                       printk(KERN_ERR
-                               "%s() found timed out command on the bus\n",
-                                       __func__);
-
-                       /* Clean the bus */
-                       ret = saa7164_bus_get(dev, &tRsp, &tmp, 0);
-                       printk(KERN_ERR "%s() ret = %x\n", __func__, ret);
-                       if (ret == SAA_ERR_EMPTY)
-                               /* Someone else already fetched the response */
-                               return SAA_OK;
-
-                       if (ret != SAA_OK)
-                               return ret;
-               }
-
-               /* It's unlikely to have more than 4 or 5 pending messages,
-                * ensure we exit at some point regardless.
-                */
-       } while (i++ < 32);
-
-       return ret;
-}
-
-/* Commands to the f/w get marshelled to/from this code then onto the PCI
- * -bus/c running buffer. */
-int saa7164_cmd_dequeue(struct saa7164_dev *dev)
-{
-       int loop = 1;
-       int ret;
-       u32 timeout;
-       wait_queue_head_t *q = NULL;
-       u8 tmp[512];
-       dprintk(DBGLVL_CMD, "%s()\n", __func__);
-
-       while (loop) {
-
-               struct tmComResInfo tRsp = { 0, 0, 0, 0, 0, 0 };
-               ret = saa7164_bus_get(dev, &tRsp, NULL, 1);
-               if (ret == SAA_ERR_EMPTY)
-                       return SAA_OK;
-
-               if (ret != SAA_OK)
-                       return ret;
-
-               q = &dev->cmds[tRsp.seqno].wait;
-               timeout = saa7164_cmd_timeout_get(dev, tRsp.seqno);
-               dprintk(DBGLVL_CMD, "%s() timeout = %d\n", __func__, timeout);
-               if (timeout) {
-                       printk(KERN_ERR "found timed out command on the bus\n");
-
-                       /* Clean the bus */
-                       ret = saa7164_bus_get(dev, &tRsp, &tmp, 0);
-                       printk(KERN_ERR "ret = %x\n", ret);
-                       if (ret == SAA_ERR_EMPTY)
-                               /* Someone else already fetched the response */
-                               return SAA_OK;
-
-                       if (ret != SAA_OK)
-                               return ret;
-
-                       if (tRsp.flags & PVC_CMDFLAG_CONTINUE)
-                               printk(KERN_ERR "split response\n");
-                       else
-                               saa7164_cmd_free_seqno(dev, tRsp.seqno);
-
-                       printk(KERN_ERR " timeout continue\n");
-                       continue;
-               }
-
-               dprintk(DBGLVL_CMD, "%s() signalled seqno(%d) (for dequeue)\n",
-                       __func__, tRsp.seqno);
-               dev->cmds[tRsp.seqno].signalled = 1;
-               wake_up(q);
-               return SAA_OK;
-       }
-
-       return SAA_OK;
-}
-
-int saa7164_cmd_set(struct saa7164_dev *dev, struct tmComResInfo *msg,
-       void *buf)
-{
-       struct tmComResBusInfo *bus = &dev->bus;
-       u8 cmd_sent;
-       u16 size, idx;
-       u32 cmds;
-       void *tmp;
-       int ret = -1;
-
-       if (!msg) {
-               printk(KERN_ERR "%s() !msg\n", __func__);
-               return SAA_ERR_BAD_PARAMETER;
-       }
-
-       mutex_lock(&dev->cmds[msg->id].lock);
-
-       size = msg->size;
-       idx = 0;
-       cmds = size / bus->m_wMaxReqSize;
-       if (size % bus->m_wMaxReqSize == 0)
-               cmds -= 1;
-
-       cmd_sent = 0;
-
-       /* Split the request into smaller chunks */
-       for (idx = 0; idx < cmds; idx++) {
-
-               msg->flags |= SAA_CMDFLAG_CONTINUE;
-               msg->size = bus->m_wMaxReqSize;
-               tmp = buf + idx * bus->m_wMaxReqSize;
-
-               ret = saa7164_bus_set(dev, msg, tmp);
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "%s() set failed %d\n", __func__, ret);
-
-                       if (cmd_sent) {
-                               ret = SAA_ERR_BUSY;
-                               goto out;
-                       }
-                       ret = SAA_ERR_OVERFLOW;
-                       goto out;
-               }
-               cmd_sent = 1;
-       }
-
-       /* If not the last command... */
-       if (idx != 0)
-               msg->flags &= ~SAA_CMDFLAG_CONTINUE;
-
-       msg->size = size - idx * bus->m_wMaxReqSize;
-
-       ret = saa7164_bus_set(dev, msg, buf + idx * bus->m_wMaxReqSize);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() set last failed %d\n", __func__, ret);
-
-               if (cmd_sent) {
-                       ret = SAA_ERR_BUSY;
-                       goto out;
-               }
-               ret = SAA_ERR_OVERFLOW;
-               goto out;
-       }
-       ret = SAA_OK;
-
-out:
-       mutex_unlock(&dev->cmds[msg->id].lock);
-       return ret;
-}
-
-/* Wait for a signal event, without holding a mutex. Either return TIMEOUT if
- * the event never occurred, or SAA_OK if it was signaled during the wait.
- */
-int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
-{
-       wait_queue_head_t *q = NULL;
-       int ret = SAA_BUS_TIMEOUT;
-       unsigned long stamp;
-       int r;
-
-       if (saa_debug >= 4)
-               saa7164_bus_dump(dev);
-
-       dprintk(DBGLVL_CMD, "%s(seqno=%d)\n", __func__, seqno);
-
-       mutex_lock(&dev->lock);
-       if ((dev->cmds[seqno].inuse == 1) &&
-               (dev->cmds[seqno].seqno == seqno)) {
-               q = &dev->cmds[seqno].wait;
-       }
-       mutex_unlock(&dev->lock);
-
-       if (q) {
-               /* If we haven't been signalled we need to wait */
-               if (dev->cmds[seqno].signalled == 0) {
-                       stamp = jiffies;
-                       dprintk(DBGLVL_CMD,
-                               "%s(seqno=%d) Waiting (signalled=%d)\n",
-                               __func__, seqno, dev->cmds[seqno].signalled);
-
-                       /* Wait for signalled to be flagged or timeout */
-                       /* In a highly stressed system this can easily extend
-                        * into multiple seconds before the deferred worker
-                        * is scheduled, and we're woken up via signal.
-                        * We typically are signalled in < 50ms but it can
-                        * take MUCH longer.
-                        */
-                       wait_event_timeout(*q, dev->cmds[seqno].signalled,
-                               (HZ * waitsecs));
-                       r = time_before(jiffies, stamp + (HZ * waitsecs));
-                       if (r)
-                               ret = SAA_OK;
-                       else
-                               saa7164_cmd_timeout_seqno(dev, seqno);
-
-                       dprintk(DBGLVL_CMD, "%s(seqno=%d) Waiting res = %d "
-                               "(signalled=%d)\n", __func__, seqno, r,
-                               dev->cmds[seqno].signalled);
-               } else
-                       ret = SAA_OK;
-       } else
-               printk(KERN_ERR "%s(seqno=%d) seqno is invalid\n",
-                       __func__, seqno);
-
-       return ret;
-}
-
-void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno)
-{
-       int i;
-       dprintk(DBGLVL_CMD, "%s()\n", __func__);
-
-       mutex_lock(&dev->lock);
-       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
-               if (dev->cmds[i].inuse == 1) {
-                       dprintk(DBGLVL_CMD,
-                               "seqno %d inuse, sig = %d, t/out = %d\n",
-                               dev->cmds[i].seqno,
-                               dev->cmds[i].signalled,
-                               dev->cmds[i].timeout);
-               }
-       }
-
-       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
-               if ((dev->cmds[i].inuse == 1) && ((i == 0) ||
-                       (dev->cmds[i].signalled) || (dev->cmds[i].timeout))) {
-                       dprintk(DBGLVL_CMD, "%s(seqno=%d) calling wake_up\n",
-                               __func__, i);
-                       dev->cmds[i].signalled = 1;
-                       wake_up(&dev->cmds[i].wait);
-               }
-       }
-       mutex_unlock(&dev->lock);
-}
-
-int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command,
-       u16 controlselector, u16 size, void *buf)
-{
-       struct tmComResInfo command_t, *pcommand_t;
-       struct tmComResInfo response_t, *presponse_t;
-       u8 errdata[256];
-       u16 resp_dsize;
-       u16 data_recd;
-       u32 loop;
-       int ret;
-       int safety = 0;
-
-       dprintk(DBGLVL_CMD, "%s(unitid = %s (%d) , command = 0x%x, "
-               "sel = 0x%x)\n", __func__, saa7164_unitid_name(dev, id), id,
-               command, controlselector);
-
-       if ((size == 0) || (buf == NULL)) {
-               printk(KERN_ERR "%s() Invalid param\n", __func__);
-               return SAA_ERR_BAD_PARAMETER;
-       }
-
-       /* Prepare some basic command/response structures */
-       memset(&command_t, 0, sizeof(command_t));
-       memset(&response_t, 0, sizeof(response_t));
-       pcommand_t = &command_t;
-       presponse_t = &response_t;
-       command_t.id = id;
-       command_t.command = command;
-       command_t.controlselector = controlselector;
-       command_t.size = size;
-
-       /* Allocate a unique sequence number */
-       ret = saa7164_cmd_alloc_seqno(dev);
-       if (ret < 0) {
-               printk(KERN_ERR "%s() No free sequences\n", __func__);
-               ret = SAA_ERR_NO_RESOURCES;
-               goto out;
-       }
-
-       command_t.seqno = (u8)ret;
-
-       /* Send Command */
-       resp_dsize = size;
-       pcommand_t->size = size;
-
-       dprintk(DBGLVL_CMD, "%s() pcommand_t.seqno = %d\n",
-               __func__, pcommand_t->seqno);
-
-       dprintk(DBGLVL_CMD, "%s() pcommand_t.size = %d\n",
-               __func__, pcommand_t->size);
-
-       ret = saa7164_cmd_set(dev, pcommand_t, buf);
-       if (ret != SAA_OK) {
-               printk(KERN_ERR "%s() set command failed %d\n", __func__, ret);
-
-               if (ret != SAA_ERR_BUSY)
-                       saa7164_cmd_free_seqno(dev, pcommand_t->seqno);
-               else
-                       /* Flag a timeout, because at least one
-                        * command was sent */
-                       saa7164_cmd_timeout_seqno(dev, pcommand_t->seqno);
-
-               goto out;
-       }
-
-       /* With split responses we have to collect the msgs piece by piece */
-       data_recd = 0;
-       loop = 1;
-       while (loop) {
-               dprintk(DBGLVL_CMD, "%s() loop\n", __func__);
-
-               ret = saa7164_cmd_wait(dev, pcommand_t->seqno);
-               dprintk(DBGLVL_CMD, "%s() loop ret = %d\n", __func__, ret);
-
-               /* if power is down and this is not a power command ... */
-
-               if (ret == SAA_BUS_TIMEOUT) {
-                       printk(KERN_ERR "Event timed out\n");
-                       saa7164_cmd_timeout_seqno(dev, pcommand_t->seqno);
-                       return ret;
-               }
-
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "spurious error\n");
-                       return ret;
-               }
-
-               /* Peek response */
-               ret = saa7164_bus_get(dev, presponse_t, NULL, 1);
-               if (ret == SAA_ERR_EMPTY) {
-                       dprintk(4, "%s() SAA_ERR_EMPTY\n", __func__);
-                       continue;
-               }
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "peek failed\n");
-                       return ret;
-               }
-
-               dprintk(DBGLVL_CMD, "%s() presponse_t->seqno = %d\n",
-                       __func__, presponse_t->seqno);
-
-               dprintk(DBGLVL_CMD, "%s() presponse_t->flags = 0x%x\n",
-                       __func__, presponse_t->flags);
-
-               dprintk(DBGLVL_CMD, "%s() presponse_t->size = %d\n",
-                       __func__, presponse_t->size);
-
-               /* Check if the response was for our command */
-               if (presponse_t->seqno != pcommand_t->seqno) {
-
-                       dprintk(DBGLVL_CMD,
-                               "wrong event: seqno = %d, "
-                               "expected seqno = %d, "
-                               "will dequeue regardless\n",
-                               presponse_t->seqno, pcommand_t->seqno);
-
-                       ret = saa7164_cmd_dequeue(dev);
-                       if (ret != SAA_OK) {
-                               printk(KERN_ERR "dequeue failed, ret = %d\n",
-                                       ret);
-                               if (safety++ > 16) {
-                                       printk(KERN_ERR
-                                       "dequeue exceeded, safety exit\n");
-                                       return SAA_ERR_BUSY;
-                               }
-                       }
-
-                       continue;
-               }
-
-               if ((presponse_t->flags & PVC_RESPONSEFLAG_ERROR) != 0) {
-
-                       memset(&errdata[0], 0, sizeof(errdata));
-
-                       ret = saa7164_bus_get(dev, presponse_t, &errdata[0], 0);
-                       if (ret != SAA_OK) {
-                               printk(KERN_ERR "get error(2)\n");
-                               return ret;
-                       }
-
-                       saa7164_cmd_free_seqno(dev, pcommand_t->seqno);
-
-                       dprintk(DBGLVL_CMD, "%s() errdata %02x%02x%02x%02x\n",
-                               __func__, errdata[0], errdata[1], errdata[2],
-                               errdata[3]);
-
-                       /* Map error codes */
-                       dprintk(DBGLVL_CMD, "%s() cmd, error code  = 0x%x\n",
-                               __func__, errdata[0]);
-
-                       switch (errdata[0]) {
-                       case PVC_ERRORCODE_INVALID_COMMAND:
-                               dprintk(DBGLVL_CMD, "%s() INVALID_COMMAND\n",
-                                       __func__);
-                               ret = SAA_ERR_INVALID_COMMAND;
-                               break;
-                       case PVC_ERRORCODE_INVALID_DATA:
-                               dprintk(DBGLVL_CMD, "%s() INVALID_DATA\n",
-                                       __func__);
-                               ret = SAA_ERR_BAD_PARAMETER;
-                               break;
-                       case PVC_ERRORCODE_TIMEOUT:
-                               dprintk(DBGLVL_CMD, "%s() TIMEOUT\n", __func__);
-                               ret = SAA_ERR_TIMEOUT;
-                               break;
-                       case PVC_ERRORCODE_NAK:
-                               dprintk(DBGLVL_CMD, "%s() NAK\n", __func__);
-                               ret = SAA_ERR_NULL_PACKET;
-                               break;
-                       case PVC_ERRORCODE_UNKNOWN:
-                       case PVC_ERRORCODE_INVALID_CONTROL:
-                               dprintk(DBGLVL_CMD,
-                                       "%s() UNKNOWN OR INVALID CONTROL\n",
-                                       __func__);
-                       default:
-                               dprintk(DBGLVL_CMD, "%s() UNKNOWN\n", __func__);
-                               ret = SAA_ERR_NOT_SUPPORTED;
-                       }
-
-                       /* See of other commands are on the bus */
-                       if (saa7164_cmd_dequeue(dev) != SAA_OK)
-                               printk(KERN_ERR "dequeue(2) failed\n");
-
-                       return ret;
-               }
-
-               /* If response is invalid */
-               if ((presponse_t->id != pcommand_t->id) ||
-                       (presponse_t->command != pcommand_t->command) ||
-                       (presponse_t->controlselector !=
-                               pcommand_t->controlselector) ||
-                       (((resp_dsize - data_recd) != presponse_t->size) &&
-                               !(presponse_t->flags & PVC_CMDFLAG_CONTINUE)) ||
-                       ((resp_dsize - data_recd) < presponse_t->size)) {
-
-                       /* Invalid */
-                       dprintk(DBGLVL_CMD, "%s() Invalid\n", __func__);
-                       ret = saa7164_bus_get(dev, presponse_t, NULL, 0);
-                       if (ret != SAA_OK) {
-                               printk(KERN_ERR "get failed\n");
-                               return ret;
-                       }
-
-                       /* See of other commands are on the bus */
-                       if (saa7164_cmd_dequeue(dev) != SAA_OK)
-                               printk(KERN_ERR "dequeue(3) failed\n");
-                       continue;
-               }
-
-               /* OK, now we're actually getting out correct response */
-               ret = saa7164_bus_get(dev, presponse_t, buf + data_recd, 0);
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "get failed\n");
-                       return ret;
-               }
-
-               data_recd = presponse_t->size + data_recd;
-               if (resp_dsize == data_recd) {
-                       dprintk(DBGLVL_CMD, "%s() Resp recd\n", __func__);
-                       break;
-               }
-
-               /* See of other commands are on the bus */
-               if (saa7164_cmd_dequeue(dev) != SAA_OK)
-                       printk(KERN_ERR "dequeue(3) failed\n");
-
-               continue;
-
-       } /* (loop) */
-
-       /* Release the sequence number allocation */
-       saa7164_cmd_free_seqno(dev, pcommand_t->seqno);
-
-       /* if powerdown signal all pending commands */
-
-       dprintk(DBGLVL_CMD, "%s() Calling dequeue then exit\n", __func__);
-
-       /* See of other commands are on the bus */
-       if (saa7164_cmd_dequeue(dev) != SAA_OK)
-               printk(KERN_ERR "dequeue(4) failed\n");
-
-       ret = SAA_OK;
-out:
-       return ret;
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-core.c b/drivers/media/video/saa7164/saa7164-core.c
deleted file mode 100644 (file)
index 2c9ad87..0000000
+++ /dev/null
@@ -1,1488 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kmod.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/div64.h>
-
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#endif
-#include "saa7164.h"
-
-MODULE_DESCRIPTION("Driver for NXP SAA7164 based TV cards");
-MODULE_AUTHOR("Steven Toth <stoth@kernellabs.com>");
-MODULE_LICENSE("GPL");
-
-/*
- *  1 Basic
- *  2
- *  4 i2c
- *  8 api
- * 16 cmd
- * 32 bus
- */
-
-unsigned int saa_debug;
-module_param_named(debug, saa_debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-unsigned int fw_debug;
-module_param(fw_debug, int, 0644);
-MODULE_PARM_DESC(fw_debug, "Firware debug level def:2");
-
-unsigned int encoder_buffers = SAA7164_MAX_ENCODER_BUFFERS;
-module_param(encoder_buffers, int, 0644);
-MODULE_PARM_DESC(encoder_buffers, "Total buffers in read queue 16-512 def:64");
-
-unsigned int vbi_buffers = SAA7164_MAX_VBI_BUFFERS;
-module_param(vbi_buffers, int, 0644);
-MODULE_PARM_DESC(vbi_buffers, "Total buffers in read queue 16-512 def:64");
-
-unsigned int waitsecs = 10;
-module_param(waitsecs, int, 0644);
-MODULE_PARM_DESC(waitsecs, "timeout on firmware messages");
-
-static unsigned int card[]  = {[0 ... (SAA7164_MAXBOARDS - 1)] = UNSET };
-module_param_array(card,  int, NULL, 0444);
-MODULE_PARM_DESC(card, "card type");
-
-unsigned int print_histogram = 64;
-module_param(print_histogram, int, 0644);
-MODULE_PARM_DESC(print_histogram, "print histogram values once");
-
-unsigned int crc_checking = 1;
-module_param(crc_checking, int, 0644);
-MODULE_PARM_DESC(crc_checking, "enable crc sanity checking on buffers");
-
-unsigned int guard_checking = 1;
-module_param(guard_checking, int, 0644);
-MODULE_PARM_DESC(guard_checking,
-       "enable dma sanity checking for buffer overruns");
-
-static unsigned int saa7164_devcount;
-
-static DEFINE_MUTEX(devlist);
-LIST_HEAD(saa7164_devlist);
-
-#define INT_SIZE 16
-
-static void saa7164_pack_verifier(struct saa7164_buffer *buf)
-{
-       u8 *p = (u8 *)buf->cpu;
-       int i;
-
-       for (i = 0; i < buf->actual_size; i += 2048) {
-
-               if ((*(p + i + 0) != 0x00) || (*(p + i + 1) != 0x00) ||
-                       (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) {
-                       printk(KERN_ERR "No pack at 0x%x\n", i);
-#if 0
-                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
-                                      p + 1, 32, false);
-#endif
-               }
-       }
-}
-
-#define FIXED_VIDEO_PID 0xf1
-#define FIXED_AUDIO_PID 0xf2
-
-static void saa7164_ts_verifier(struct saa7164_buffer *buf)
-{
-       struct saa7164_port *port = buf->port;
-       u32 i;
-       u8 cc, a;
-       u16 pid;
-       u8 __iomem *bufcpu = (u8 *)buf->cpu;
-
-       port->sync_errors = 0;
-       port->v_cc_errors = 0;
-       port->a_cc_errors = 0;
-
-       for (i = 0; i < buf->actual_size; i += 188) {
-               if (*(bufcpu + i) != 0x47)
-                       port->sync_errors++;
-
-               /* TODO: Query pid lower 8 bits, ignoring upper bits intensionally */
-               pid = ((*(bufcpu + i + 1) & 0x1f) << 8) | *(bufcpu + i + 2);
-               cc = *(bufcpu + i + 3) & 0x0f;
-
-               if (pid == FIXED_VIDEO_PID) {
-                       a = ((port->last_v_cc + 1) & 0x0f);
-                       if (a != cc) {
-                               printk(KERN_ERR "video cc last = %x current = %x i = %d\n",
-                                       port->last_v_cc, cc, i);
-                               port->v_cc_errors++;
-                       }
-
-                       port->last_v_cc = cc;
-               } else
-               if (pid == FIXED_AUDIO_PID) {
-                       a = ((port->last_a_cc + 1) & 0x0f);
-                       if (a != cc) {
-                               printk(KERN_ERR "audio cc last = %x current = %x i = %d\n",
-                                       port->last_a_cc, cc, i);
-                               port->a_cc_errors++;
-                       }
-
-                       port->last_a_cc = cc;
-               }
-
-       }
-
-       /* Only report errors if we've been through this function atleast
-        * once already and the cached cc values are primed. First time through
-        * always generates errors.
-        */
-       if (port->v_cc_errors && (port->done_first_interrupt > 1))
-               printk(KERN_ERR "video pid cc, %d errors\n", port->v_cc_errors);
-
-       if (port->a_cc_errors && (port->done_first_interrupt > 1))
-               printk(KERN_ERR "audio pid cc, %d errors\n", port->a_cc_errors);
-
-       if (port->sync_errors && (port->done_first_interrupt > 1))
-               printk(KERN_ERR "sync_errors = %d\n", port->sync_errors);
-
-       if (port->done_first_interrupt == 1)
-               port->done_first_interrupt++;
-}
-
-static void saa7164_histogram_reset(struct saa7164_histogram *hg, char *name)
-{
-       int i;
-
-       memset(hg, 0, sizeof(struct saa7164_histogram));
-       strcpy(hg->name, name);
-
-       /* First 30ms x 1ms */
-       for (i = 0; i < 30; i++)
-               hg->counter1[0 + i].val = i;
-
-       /* 30 - 200ms x 10ms  */
-       for (i = 0; i < 18; i++)
-               hg->counter1[30 + i].val = 30 + (i * 10);
-
-       /* 200 - 2000ms x 100ms  */
-       for (i = 0; i < 15; i++)
-               hg->counter1[48 + i].val = 200 + (i * 200);
-
-       /* Catch all massive value (2secs) */
-       hg->counter1[55].val = 2000;
-
-       /* Catch all massive value (4secs) */
-       hg->counter1[56].val = 4000;
-
-       /* Catch all massive value (8secs) */
-       hg->counter1[57].val = 8000;
-
-       /* Catch all massive value (15secs) */
-       hg->counter1[58].val = 15000;
-
-       /* Catch all massive value (30secs) */
-       hg->counter1[59].val = 30000;
-
-       /* Catch all massive value (60secs) */
-       hg->counter1[60].val = 60000;
-
-       /* Catch all massive value (5mins) */
-       hg->counter1[61].val = 300000;
-
-       /* Catch all massive value (15mins) */
-       hg->counter1[62].val = 900000;
-
-       /* Catch all massive values (1hr) */
-       hg->counter1[63].val = 3600000;
-}
-
-void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val)
-{
-       int i;
-       for (i = 0; i < 64; i++) {
-               if (val <= hg->counter1[i].val) {
-                       hg->counter1[i].count++;
-                       hg->counter1[i].update_time = jiffies;
-                       break;
-               }
-       }
-}
-
-static void saa7164_histogram_print(struct saa7164_port *port,
-       struct saa7164_histogram *hg)
-{
-       u32 entries = 0;
-       int i;
-
-       printk(KERN_ERR "Histogram named %s (ms, count, last_update_jiffy)\n", hg->name);
-       for (i = 0; i < 64; i++) {
-               if (hg->counter1[i].count == 0)
-                       continue;
-
-               printk(KERN_ERR " %4d %12d %Ld\n",
-                       hg->counter1[i].val,
-                       hg->counter1[i].count,
-                       hg->counter1[i].update_time);
-
-               entries++;
-       }
-       printk(KERN_ERR "Total: %d\n", entries);
-}
-
-static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf = NULL;
-       struct saa7164_user_buffer *ubuf = NULL;
-       struct list_head *c, *n;
-       int i = 0;
-       u8 __iomem *p;
-
-       mutex_lock(&port->dmaqueue_lock);
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-
-               buf = list_entry(c, struct saa7164_buffer, list);
-               if (i++ > port->hwcfg.buffercount) {
-                       printk(KERN_ERR "%s() illegal i count %d\n",
-                               __func__, i);
-                       break;
-               }
-
-               if (buf->idx == bufnr) {
-
-                       /* Found the buffer, deal with it */
-                       dprintk(DBGLVL_IRQ, "%s() bufnr: %d\n", __func__, bufnr);
-
-                       if (crc_checking) {
-                               /* Throw a new checksum on the dma buffer */
-                               buf->crc = crc32(0, buf->cpu, buf->actual_size);
-                       }
-
-                       if (guard_checking) {
-                               p = (u8 *)buf->cpu;
-                               if ((*(p + buf->actual_size + 0) != 0xff) ||
-                                       (*(p + buf->actual_size + 1) != 0xff) ||
-                                       (*(p + buf->actual_size + 2) != 0xff) ||
-                                       (*(p + buf->actual_size + 3) != 0xff) ||
-                                       (*(p + buf->actual_size + 0x10) != 0xff) ||
-                                       (*(p + buf->actual_size + 0x11) != 0xff) ||
-                                       (*(p + buf->actual_size + 0x12) != 0xff) ||
-                                       (*(p + buf->actual_size + 0x13) != 0xff)) {
-                                               printk(KERN_ERR "%s() buf %p guard buffer breach\n",
-                                                       __func__, buf);
-#if 0
-                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
-                                      p + buf->actual_size - 32, 64, false);
-#endif
-                               }
-                       }
-
-                       if ((port->nr != SAA7164_PORT_VBI1) && (port->nr != SAA7164_PORT_VBI2)) {
-                               /* Validate the incoming buffer content */
-                               if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
-                                       saa7164_ts_verifier(buf);
-                               else if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS)
-                                       saa7164_pack_verifier(buf);
-                       }
-
-                       /* find a free user buffer and clone to it */
-                       if (!list_empty(&port->list_buf_free.list)) {
-
-                               /* Pull the first buffer from the used list */
-                               ubuf = list_first_entry(&port->list_buf_free.list,
-                                       struct saa7164_user_buffer, list);
-
-                               if (buf->actual_size <= ubuf->actual_size) {
-
-                                       memcpy_fromio(ubuf->data, buf->cpu,
-                                               ubuf->actual_size);
-
-                                       if (crc_checking) {
-                                               /* Throw a new checksum on the read buffer */
-                                               ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);
-                                       }
-
-                                       /* Requeue the buffer on the free list */
-                                       ubuf->pos = 0;
-
-                                       list_move_tail(&ubuf->list,
-                                               &port->list_buf_used.list);
-
-                                       /* Flag any userland waiters */
-                                       wake_up_interruptible(&port->wait_read);
-
-                               } else {
-                                       printk(KERN_ERR "buf %p bufsize fails match\n", buf);
-                               }
-
-                       } else
-                               printk(KERN_ERR "encirq no free buffers, increase param encoder_buffers\n");
-
-                       /* Ensure offset into buffer remains 0, fill buffer
-                        * with known bad data. We check for this data at a later point
-                        * in time. */
-                       saa7164_buffer_zero_offsets(port, bufnr);
-                       memset_io(buf->cpu, 0xff, buf->pci_size);
-                       if (crc_checking) {
-                               /* Throw yet aanother new checksum on the dma buffer */
-                               buf->crc = crc32(0, buf->cpu, buf->actual_size);
-                       }
-
-                       break;
-               }
-       }
-       mutex_unlock(&port->dmaqueue_lock);
-}
-
-static void saa7164_work_enchandler(struct work_struct *w)
-{
-       struct saa7164_port *port =
-               container_of(w, struct saa7164_port, workenc);
-       struct saa7164_dev *dev = port->dev;
-
-       u32 wp, mcb, rp, cnt = 0;
-
-       port->last_svc_msecs_diff = port->last_svc_msecs;
-       port->last_svc_msecs = jiffies_to_msecs(jiffies);
-
-       port->last_svc_msecs_diff = port->last_svc_msecs -
-               port->last_svc_msecs_diff;
-
-       saa7164_histogram_update(&port->svc_interval,
-               port->last_svc_msecs_diff);
-
-       port->last_irq_svc_msecs_diff = port->last_svc_msecs -
-               port->last_irq_msecs;
-
-       saa7164_histogram_update(&port->irq_svc_interval,
-               port->last_irq_svc_msecs_diff);
-
-       dprintk(DBGLVL_IRQ,
-               "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
-               __func__,
-               port->last_svc_msecs_diff,
-               port->last_irq_svc_msecs_diff,
-               port->last_svc_wp,
-               port->last_svc_rp
-               );
-
-       /* Current write position */
-       wp = saa7164_readl(port->bufcounter);
-       if (wp > (port->hwcfg.buffercount - 1)) {
-               printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
-               return;
-       }
-
-       /* Most current complete buffer */
-       if (wp == 0)
-               mcb = (port->hwcfg.buffercount - 1);
-       else
-               mcb = wp - 1;
-
-       while (1) {
-               if (port->done_first_interrupt == 0) {
-                       port->done_first_interrupt++;
-                       rp = mcb;
-               } else
-                       rp = (port->last_svc_rp + 1) % 8;
-
-               if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
-                       printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
-                       break;
-               }
-
-               saa7164_work_enchandler_helper(port, rp);
-               port->last_svc_rp = rp;
-               cnt++;
-
-               if (rp == mcb)
-                       break;
-       }
-
-       /* TODO: Convert this into a /proc/saa7164 style readable file */
-       if (print_histogram == port->nr) {
-               saa7164_histogram_print(port, &port->irq_interval);
-               saa7164_histogram_print(port, &port->svc_interval);
-               saa7164_histogram_print(port, &port->irq_svc_interval);
-               saa7164_histogram_print(port, &port->read_interval);
-               saa7164_histogram_print(port, &port->poll_interval);
-               /* TODO: fix this to preserve any previous state */
-               print_histogram = 64 + port->nr;
-       }
-}
-
-static void saa7164_work_vbihandler(struct work_struct *w)
-{
-       struct saa7164_port *port =
-               container_of(w, struct saa7164_port, workenc);
-       struct saa7164_dev *dev = port->dev;
-
-       u32 wp, mcb, rp, cnt = 0;
-
-       port->last_svc_msecs_diff = port->last_svc_msecs;
-       port->last_svc_msecs = jiffies_to_msecs(jiffies);
-       port->last_svc_msecs_diff = port->last_svc_msecs -
-               port->last_svc_msecs_diff;
-
-       saa7164_histogram_update(&port->svc_interval,
-               port->last_svc_msecs_diff);
-
-       port->last_irq_svc_msecs_diff = port->last_svc_msecs -
-               port->last_irq_msecs;
-
-       saa7164_histogram_update(&port->irq_svc_interval,
-               port->last_irq_svc_msecs_diff);
-
-       dprintk(DBGLVL_IRQ,
-               "%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
-               __func__,
-               port->last_svc_msecs_diff,
-               port->last_irq_svc_msecs_diff,
-               port->last_svc_wp,
-               port->last_svc_rp
-               );
-
-       /* Current write position */
-       wp = saa7164_readl(port->bufcounter);
-       if (wp > (port->hwcfg.buffercount - 1)) {
-               printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
-               return;
-       }
-
-       /* Most current complete buffer */
-       if (wp == 0)
-               mcb = (port->hwcfg.buffercount - 1);
-       else
-               mcb = wp - 1;
-
-       while (1) {
-               if (port->done_first_interrupt == 0) {
-                       port->done_first_interrupt++;
-                       rp = mcb;
-               } else
-                       rp = (port->last_svc_rp + 1) % 8;
-
-               if ((rp < 0) || (rp > (port->hwcfg.buffercount - 1))) {
-                       printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
-                       break;
-               }
-
-               saa7164_work_enchandler_helper(port, rp);
-               port->last_svc_rp = rp;
-               cnt++;
-
-               if (rp == mcb)
-                       break;
-       }
-
-       /* TODO: Convert this into a /proc/saa7164 style readable file */
-       if (print_histogram == port->nr) {
-               saa7164_histogram_print(port, &port->irq_interval);
-               saa7164_histogram_print(port, &port->svc_interval);
-               saa7164_histogram_print(port, &port->irq_svc_interval);
-               saa7164_histogram_print(port, &port->read_interval);
-               saa7164_histogram_print(port, &port->poll_interval);
-               /* TODO: fix this to preserve any previous state */
-               print_histogram = 64 + port->nr;
-       }
-}
-
-static void saa7164_work_cmdhandler(struct work_struct *w)
-{
-       struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
-
-       /* Wake up any complete commands */
-       saa7164_irq_dequeue(dev);
-}
-
-static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
-{
-       struct saa7164_port *port = buf->port;
-
-       /* Feed the transport payload into the kernel demux */
-       dvb_dmx_swfilter_packets(&port->dvb.demux, (u8 *)buf->cpu,
-               SAA7164_TS_NUMBER_OF_LINES);
-
-}
-
-static irqreturn_t saa7164_irq_vbi(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       /* Store old time */
-       port->last_irq_msecs_diff = port->last_irq_msecs;
-
-       /* Collect new stats */
-       port->last_irq_msecs = jiffies_to_msecs(jiffies);
-
-       /* Calculate stats */
-       port->last_irq_msecs_diff = port->last_irq_msecs -
-               port->last_irq_msecs_diff;
-
-       saa7164_histogram_update(&port->irq_interval,
-               port->last_irq_msecs_diff);
-
-       dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
-               port->last_irq_msecs_diff);
-
-       /* Tis calls the vbi irq handler */
-       schedule_work(&port->workenc);
-       return 0;
-}
-
-static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       /* Store old time */
-       port->last_irq_msecs_diff = port->last_irq_msecs;
-
-       /* Collect new stats */
-       port->last_irq_msecs = jiffies_to_msecs(jiffies);
-
-       /* Calculate stats */
-       port->last_irq_msecs_diff = port->last_irq_msecs -
-               port->last_irq_msecs_diff;
-
-       saa7164_histogram_update(&port->irq_interval,
-               port->last_irq_msecs_diff);
-
-       dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
-               port->last_irq_msecs_diff);
-
-       schedule_work(&port->workenc);
-       return 0;
-}
-
-static irqreturn_t saa7164_irq_ts(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct list_head *c, *n;
-       int wp, i = 0, rp;
-
-       /* Find the current write point from the hardware */
-       wp = saa7164_readl(port->bufcounter);
-       if (wp > (port->hwcfg.buffercount - 1))
-               BUG();
-
-       /* Find the previous buffer to the current write point */
-       if (wp == 0)
-               rp = (port->hwcfg.buffercount - 1);
-       else
-               rp = wp - 1;
-
-       /* Lookup the WP in the buffer list */
-       /* TODO: turn this into a worker thread */
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               buf = list_entry(c, struct saa7164_buffer, list);
-               if (i++ > port->hwcfg.buffercount)
-                       BUG();
-
-               if (buf->idx == rp) {
-                       /* Found the buffer, deal with it */
-                       dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d\n",
-                               __func__, wp, rp);
-                       saa7164_buffer_deliver(buf);
-                       break;
-               }
-
-       }
-       return 0;
-}
-
-/* Primary IRQ handler and dispatch mechanism */
-static irqreturn_t saa7164_irq(int irq, void *dev_id)
-{
-       struct saa7164_dev *dev = dev_id;
-       struct saa7164_port *porta = &dev->ports[SAA7164_PORT_TS1];
-       struct saa7164_port *portb = &dev->ports[SAA7164_PORT_TS2];
-       struct saa7164_port *portc = &dev->ports[SAA7164_PORT_ENC1];
-       struct saa7164_port *portd = &dev->ports[SAA7164_PORT_ENC2];
-       struct saa7164_port *porte = &dev->ports[SAA7164_PORT_VBI1];
-       struct saa7164_port *portf = &dev->ports[SAA7164_PORT_VBI2];
-
-       u32 intid, intstat[INT_SIZE/4];
-       int i, handled = 0, bit;
-
-       if (dev == NULL) {
-               printk(KERN_ERR "%s() No device specified\n", __func__);
-               handled = 0;
-               goto out;
-       }
-
-       /* Check that the hardware is accessible. If the status bytes are
-        * 0xFF then the device is not accessible, the the IRQ belongs
-        * to another driver.
-        * 4 x u32 interrupt registers.
-        */
-       for (i = 0; i < INT_SIZE/4; i++) {
-
-               /* TODO: Convert into saa7164_readl() */
-               /* Read the 4 hardware interrupt registers */
-               intstat[i] = saa7164_readl(dev->int_status + (i * 4));
-
-               if (intstat[i])
-                       handled = 1;
-       }
-       if (handled == 0)
-               goto out;
-
-       /* For each of the HW interrupt registers */
-       for (i = 0; i < INT_SIZE/4; i++) {
-
-               if (intstat[i]) {
-                       /* Each function of the board has it's own interruptid.
-                        * Find the function that triggered then call
-                        * it's handler.
-                        */
-                       for (bit = 0; bit < 32; bit++) {
-
-                               if (((intstat[i] >> bit) & 0x00000001) == 0)
-                                       continue;
-
-                               /* Calculate the interrupt id (0x00 to 0x7f) */
-
-                               intid = (i * 32) + bit;
-                               if (intid == dev->intfdesc.bInterruptId) {
-                                       /* A response to an cmd/api call */
-                                       schedule_work(&dev->workcmd);
-                               } else if (intid == porta->hwcfg.interruptid) {
-
-                                       /* Transport path 1 */
-                                       saa7164_irq_ts(porta);
-
-                               } else if (intid == portb->hwcfg.interruptid) {
-
-                                       /* Transport path 2 */
-                                       saa7164_irq_ts(portb);
-
-                               } else if (intid == portc->hwcfg.interruptid) {
-
-                                       /* Encoder path 1 */
-                                       saa7164_irq_encoder(portc);
-
-                               } else if (intid == portd->hwcfg.interruptid) {
-
-                                       /* Encoder path 2 */
-                                       saa7164_irq_encoder(portd);
-
-                               } else if (intid == porte->hwcfg.interruptid) {
-
-                                       /* VBI path 1 */
-                                       saa7164_irq_vbi(porte);
-
-                               } else if (intid == portf->hwcfg.interruptid) {
-
-                                       /* VBI path 2 */
-                                       saa7164_irq_vbi(portf);
-
-                               } else {
-                                       /* Find the function */
-                                       dprintk(DBGLVL_IRQ,
-                                               "%s() unhandled interrupt "
-                                               "reg 0x%x bit 0x%x "
-                                               "intid = 0x%x\n",
-                                               __func__, i, bit, intid);
-                               }
-                       }
-
-                       /* Ack it */
-                       saa7164_writel(dev->int_ack + (i * 4), intstat[i]);
-
-               }
-       }
-out:
-       return IRQ_RETVAL(handled);
-}
-
-void saa7164_getfirmwarestatus(struct saa7164_dev *dev)
-{
-       struct saa7164_fw_status *s = &dev->fw_status;
-
-       dev->fw_status.status = saa7164_readl(SAA_DEVICE_SYSINIT_STATUS);
-       dev->fw_status.mode = saa7164_readl(SAA_DEVICE_SYSINIT_MODE);
-       dev->fw_status.spec = saa7164_readl(SAA_DEVICE_SYSINIT_SPEC);
-       dev->fw_status.inst = saa7164_readl(SAA_DEVICE_SYSINIT_INST);
-       dev->fw_status.cpuload = saa7164_readl(SAA_DEVICE_SYSINIT_CPULOAD);
-       dev->fw_status.remainheap =
-               saa7164_readl(SAA_DEVICE_SYSINIT_REMAINHEAP);
-
-       dprintk(1, "Firmware status:\n");
-       dprintk(1, " .status     = 0x%08x\n", s->status);
-       dprintk(1, " .mode       = 0x%08x\n", s->mode);
-       dprintk(1, " .spec       = 0x%08x\n", s->spec);
-       dprintk(1, " .inst       = 0x%08x\n", s->inst);
-       dprintk(1, " .cpuload    = 0x%08x\n", s->cpuload);
-       dprintk(1, " .remainheap = 0x%08x\n", s->remainheap);
-}
-
-u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev)
-{
-       u32 reg;
-
-       reg = saa7164_readl(SAA_DEVICE_VERSION);
-       dprintk(1, "Device running firmware version %d.%d.%d.%d (0x%x)\n",
-               (reg & 0x0000fc00) >> 10,
-               (reg & 0x000003e0) >> 5,
-               (reg & 0x0000001f),
-               (reg & 0xffff0000) >> 16,
-               reg);
-
-       return reg;
-}
-
-/* TODO: Debugging func, remove */
-void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr)
-{
-       int i;
-
-       dprintk(1, "--------------------> "
-               "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
-
-       for (i = 0; i < 0x100; i += 16)
-               dprintk(1, "region0[0x%08x] = "
-                       "%02x %02x %02x %02x %02x %02x %02x %02x"
-                       " %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
-                       (u8)saa7164_readb(addr + i + 0),
-                       (u8)saa7164_readb(addr + i + 1),
-                       (u8)saa7164_readb(addr + i + 2),
-                       (u8)saa7164_readb(addr + i + 3),
-                       (u8)saa7164_readb(addr + i + 4),
-                       (u8)saa7164_readb(addr + i + 5),
-                       (u8)saa7164_readb(addr + i + 6),
-                       (u8)saa7164_readb(addr + i + 7),
-                       (u8)saa7164_readb(addr + i + 8),
-                       (u8)saa7164_readb(addr + i + 9),
-                       (u8)saa7164_readb(addr + i + 10),
-                       (u8)saa7164_readb(addr + i + 11),
-                       (u8)saa7164_readb(addr + i + 12),
-                       (u8)saa7164_readb(addr + i + 13),
-                       (u8)saa7164_readb(addr + i + 14),
-                       (u8)saa7164_readb(addr + i + 15)
-                       );
-}
-
-static void saa7164_dump_hwdesc(struct saa7164_dev *dev)
-{
-       dprintk(1, "@0x%p hwdesc sizeof(struct tmComResHWDescr) = %d bytes\n",
-               &dev->hwdesc, (u32)sizeof(struct tmComResHWDescr));
-
-       dprintk(1, " .bLength = 0x%x\n", dev->hwdesc.bLength);
-       dprintk(1, " .bDescriptorType = 0x%x\n", dev->hwdesc.bDescriptorType);
-       dprintk(1, " .bDescriptorSubtype = 0x%x\n",
-               dev->hwdesc.bDescriptorSubtype);
-
-       dprintk(1, " .bcdSpecVersion = 0x%x\n", dev->hwdesc.bcdSpecVersion);
-       dprintk(1, " .dwClockFrequency = 0x%x\n", dev->hwdesc.dwClockFrequency);
-       dprintk(1, " .dwClockUpdateRes = 0x%x\n", dev->hwdesc.dwClockUpdateRes);
-       dprintk(1, " .bCapabilities = 0x%x\n", dev->hwdesc.bCapabilities);
-       dprintk(1, " .dwDeviceRegistersLocation = 0x%x\n",
-               dev->hwdesc.dwDeviceRegistersLocation);
-
-       dprintk(1, " .dwHostMemoryRegion = 0x%x\n",
-               dev->hwdesc.dwHostMemoryRegion);
-
-       dprintk(1, " .dwHostMemoryRegionSize = 0x%x\n",
-               dev->hwdesc.dwHostMemoryRegionSize);
-
-       dprintk(1, " .dwHostHibernatMemRegion = 0x%x\n",
-               dev->hwdesc.dwHostHibernatMemRegion);
-
-       dprintk(1, " .dwHostHibernatMemRegionSize = 0x%x\n",
-               dev->hwdesc.dwHostHibernatMemRegionSize);
-}
-
-static void saa7164_dump_intfdesc(struct saa7164_dev *dev)
-{
-       dprintk(1, "@0x%p intfdesc "
-               "sizeof(struct tmComResInterfaceDescr) = %d bytes\n",
-               &dev->intfdesc, (u32)sizeof(struct tmComResInterfaceDescr));
-
-       dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength);
-       dprintk(1, " .bDescriptorType = 0x%x\n", dev->intfdesc.bDescriptorType);
-       dprintk(1, " .bDescriptorSubtype = 0x%x\n",
-               dev->intfdesc.bDescriptorSubtype);
-
-       dprintk(1, " .bFlags = 0x%x\n", dev->intfdesc.bFlags);
-       dprintk(1, " .bInterfaceType = 0x%x\n", dev->intfdesc.bInterfaceType);
-       dprintk(1, " .bInterfaceId = 0x%x\n", dev->intfdesc.bInterfaceId);
-       dprintk(1, " .bBaseInterface = 0x%x\n", dev->intfdesc.bBaseInterface);
-       dprintk(1, " .bInterruptId = 0x%x\n", dev->intfdesc.bInterruptId);
-       dprintk(1, " .bDebugInterruptId = 0x%x\n",
-               dev->intfdesc.bDebugInterruptId);
-
-       dprintk(1, " .BARLocation = 0x%x\n", dev->intfdesc.BARLocation);
-}
-
-static void saa7164_dump_busdesc(struct saa7164_dev *dev)
-{
-       dprintk(1, "@0x%p busdesc sizeof(struct tmComResBusDescr) = %d bytes\n",
-               &dev->busdesc, (u32)sizeof(struct tmComResBusDescr));
-
-       dprintk(1, " .CommandRing   = 0x%016Lx\n", dev->busdesc.CommandRing);
-       dprintk(1, " .ResponseRing  = 0x%016Lx\n", dev->busdesc.ResponseRing);
-       dprintk(1, " .CommandWrite  = 0x%x\n", dev->busdesc.CommandWrite);
-       dprintk(1, " .CommandRead   = 0x%x\n", dev->busdesc.CommandRead);
-       dprintk(1, " .ResponseWrite = 0x%x\n", dev->busdesc.ResponseWrite);
-       dprintk(1, " .ResponseRead  = 0x%x\n", dev->busdesc.ResponseRead);
-}
-
-/* Much of the hardware configuration and PCI registers are configured
- * dynamically depending on firmware. We have to cache some initial
- * structures then use these to locate other important structures
- * from PCI space.
- */
-static void saa7164_get_descriptors(struct saa7164_dev *dev)
-{
-       memcpy_fromio(&dev->hwdesc, dev->bmmio, sizeof(struct tmComResHWDescr));
-       memcpy_fromio(&dev->intfdesc, dev->bmmio + sizeof(struct tmComResHWDescr),
-               sizeof(struct tmComResInterfaceDescr));
-       memcpy_fromio(&dev->busdesc, dev->bmmio + dev->intfdesc.BARLocation,
-               sizeof(struct tmComResBusDescr));
-
-       if (dev->hwdesc.bLength != sizeof(struct tmComResHWDescr)) {
-               printk(KERN_ERR "Structure struct tmComResHWDescr is mangled\n");
-               printk(KERN_ERR "Need %x got %d\n", dev->hwdesc.bLength,
-                       (u32)sizeof(struct tmComResHWDescr));
-       } else
-               saa7164_dump_hwdesc(dev);
-
-       if (dev->intfdesc.bLength != sizeof(struct tmComResInterfaceDescr)) {
-               printk(KERN_ERR "struct struct tmComResInterfaceDescr is mangled\n");
-               printk(KERN_ERR "Need %x got %d\n", dev->intfdesc.bLength,
-                       (u32)sizeof(struct tmComResInterfaceDescr));
-       } else
-               saa7164_dump_intfdesc(dev);
-
-       saa7164_dump_busdesc(dev);
-}
-
-static int saa7164_pci_quirks(struct saa7164_dev *dev)
-{
-       return 0;
-}
-
-static int get_resources(struct saa7164_dev *dev)
-{
-       if (request_mem_region(pci_resource_start(dev->pci, 0),
-               pci_resource_len(dev->pci, 0), dev->name)) {
-
-               if (request_mem_region(pci_resource_start(dev->pci, 2),
-                       pci_resource_len(dev->pci, 2), dev->name))
-                       return 0;
-       }
-
-       printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx or 0x%llx\n",
-               dev->name,
-               (u64)pci_resource_start(dev->pci, 0),
-               (u64)pci_resource_start(dev->pci, 2));
-
-       return -EBUSY;
-}
-
-static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
-{
-       struct saa7164_port *port = NULL;
-
-       if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
-               BUG();
-
-       port = &dev->ports[portnr];
-
-       port->dev = dev;
-       port->nr = portnr;
-
-       if ((portnr == SAA7164_PORT_TS1) || (portnr == SAA7164_PORT_TS2))
-               port->type = SAA7164_MPEG_DVB;
-       else
-       if ((portnr == SAA7164_PORT_ENC1) || (portnr == SAA7164_PORT_ENC2)) {
-               port->type = SAA7164_MPEG_ENCODER;
-
-               /* We need a deferred interrupt handler for cmd handling */
-               INIT_WORK(&port->workenc, saa7164_work_enchandler);
-       } else if ((portnr == SAA7164_PORT_VBI1) || (portnr == SAA7164_PORT_VBI2)) {
-               port->type = SAA7164_MPEG_VBI;
-
-               /* We need a deferred interrupt handler for cmd handling */
-               INIT_WORK(&port->workenc, saa7164_work_vbihandler);
-       } else
-               BUG();
-
-       /* Init all the critical resources */
-       mutex_init(&port->dvb.lock);
-       INIT_LIST_HEAD(&port->dmaqueue.list);
-       mutex_init(&port->dmaqueue_lock);
-
-       INIT_LIST_HEAD(&port->list_buf_used.list);
-       INIT_LIST_HEAD(&port->list_buf_free.list);
-       init_waitqueue_head(&port->wait_read);
-
-
-       saa7164_histogram_reset(&port->irq_interval, "irq intervals");
-       saa7164_histogram_reset(&port->svc_interval, "deferred intervals");
-       saa7164_histogram_reset(&port->irq_svc_interval,
-               "irq to deferred intervals");
-       saa7164_histogram_reset(&port->read_interval,
-               "encoder/vbi read() intervals");
-       saa7164_histogram_reset(&port->poll_interval,
-               "encoder/vbi poll() intervals");
-
-       return 0;
-}
-
-static int saa7164_dev_setup(struct saa7164_dev *dev)
-{
-       int i;
-
-       mutex_init(&dev->lock);
-       atomic_inc(&dev->refcount);
-       dev->nr = saa7164_devcount++;
-
-       snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr);
-
-       mutex_lock(&devlist);
-       list_add_tail(&dev->devlist, &saa7164_devlist);
-       mutex_unlock(&devlist);
-
-       /* board config */
-       dev->board = UNSET;
-       if (card[dev->nr] < saa7164_bcount)
-               dev->board = card[dev->nr];
-
-       for (i = 0; UNSET == dev->board  &&  i < saa7164_idcount; i++)
-               if (dev->pci->subsystem_vendor == saa7164_subids[i].subvendor &&
-                       dev->pci->subsystem_device ==
-                               saa7164_subids[i].subdevice)
-                               dev->board = saa7164_subids[i].card;
-
-       if (UNSET == dev->board) {
-               dev->board = SAA7164_BOARD_UNKNOWN;
-               saa7164_card_list(dev);
-       }
-
-       dev->pci_bus  = dev->pci->bus->number;
-       dev->pci_slot = PCI_SLOT(dev->pci->devfn);
-
-       /* I2C Defaults / setup */
-       dev->i2c_bus[0].dev = dev;
-       dev->i2c_bus[0].nr = 0;
-       dev->i2c_bus[1].dev = dev;
-       dev->i2c_bus[1].nr = 1;
-       dev->i2c_bus[2].dev = dev;
-       dev->i2c_bus[2].nr = 2;
-
-       /* Transport + Encoder ports 1, 2, 3, 4 - Defaults / setup */
-       saa7164_port_init(dev, SAA7164_PORT_TS1);
-       saa7164_port_init(dev, SAA7164_PORT_TS2);
-       saa7164_port_init(dev, SAA7164_PORT_ENC1);
-       saa7164_port_init(dev, SAA7164_PORT_ENC2);
-       saa7164_port_init(dev, SAA7164_PORT_VBI1);
-       saa7164_port_init(dev, SAA7164_PORT_VBI2);
-
-       if (get_resources(dev) < 0) {
-               printk(KERN_ERR "CORE %s No more PCIe resources for "
-                      "subsystem: %04x:%04x\n",
-                      dev->name, dev->pci->subsystem_vendor,
-                      dev->pci->subsystem_device);
-
-               saa7164_devcount--;
-               return -ENODEV;
-       }
-
-       /* PCI/e allocations */
-       dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
-                            pci_resource_len(dev->pci, 0));
-
-       dev->lmmio2 = ioremap(pci_resource_start(dev->pci, 2),
-                            pci_resource_len(dev->pci, 2));
-
-       dev->bmmio = (u8 __iomem *)dev->lmmio;
-       dev->bmmio2 = (u8 __iomem *)dev->lmmio2;
-
-       /* Inerrupt and ack register locations offset of bmmio */
-       dev->int_status = 0x183000 + 0xf80;
-       dev->int_ack = 0x183000 + 0xf90;
-
-       printk(KERN_INFO
-               "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-              dev->name, dev->pci->subsystem_vendor,
-              dev->pci->subsystem_device, saa7164_boards[dev->board].name,
-              dev->board, card[dev->nr] == dev->board ?
-              "insmod option" : "autodetected");
-
-       saa7164_pci_quirks(dev);
-
-       return 0;
-}
-
-static void saa7164_dev_unregister(struct saa7164_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       release_mem_region(pci_resource_start(dev->pci, 0),
-               pci_resource_len(dev->pci, 0));
-
-       release_mem_region(pci_resource_start(dev->pci, 2),
-               pci_resource_len(dev->pci, 2));
-
-       if (!atomic_dec_and_test(&dev->refcount))
-               return;
-
-       iounmap(dev->lmmio);
-       iounmap(dev->lmmio2);
-
-       return;
-}
-
-#ifdef CONFIG_PROC_FS
-static int saa7164_proc_show(struct seq_file *m, void *v)
-{
-       struct saa7164_dev *dev;
-       struct tmComResBusInfo *b;
-       struct list_head *list;
-       int i, c;
-
-       if (saa7164_devcount == 0)
-               return 0;
-
-       list_for_each(list, &saa7164_devlist) {
-               dev = list_entry(list, struct saa7164_dev, devlist);
-               seq_printf(m, "%s = %p\n", dev->name, dev);
-
-               /* Lock the bus from any other access */
-               b = &dev->bus;
-               mutex_lock(&b->lock);
-
-               seq_printf(m, " .m_pdwSetWritePos = 0x%x (0x%08x)\n",
-                       b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
-
-               seq_printf(m, " .m_pdwSetReadPos  = 0x%x (0x%08x)\n",
-                       b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
-
-               seq_printf(m, " .m_pdwGetWritePos = 0x%x (0x%08x)\n",
-                       b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
-
-               seq_printf(m, " .m_pdwGetReadPos  = 0x%x (0x%08x)\n",
-                       b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
-               c = 0;
-               seq_printf(m, "\n  Set Ring:\n");
-               seq_printf(m, "\n addr  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
-               for (i = 0; i < b->m_dwSizeSetRing; i++) {
-                       if (c == 0)
-                               seq_printf(m, " %04x:", i);
-
-                       seq_printf(m, " %02x", *(b->m_pdwSetRing + i));
-
-                       if (++c == 16) {
-                               seq_printf(m, "\n");
-                               c = 0;
-                       }
-               }
-
-               c = 0;
-               seq_printf(m, "\n  Get Ring:\n");
-               seq_printf(m, "\n addr  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
-               for (i = 0; i < b->m_dwSizeGetRing; i++) {
-                       if (c == 0)
-                               seq_printf(m, " %04x:", i);
-
-                       seq_printf(m, " %02x", *(b->m_pdwGetRing + i));
-
-                       if (++c == 16) {
-                               seq_printf(m, "\n");
-                               c = 0;
-                       }
-               }
-
-               mutex_unlock(&b->lock);
-
-       }
-
-       return 0;
-}
-
-static int saa7164_proc_open(struct inode *inode, struct file *filp)
-{
-       return single_open(filp, saa7164_proc_show, NULL);
-}
-
-static const struct file_operations saa7164_proc_fops = {
-       .open           = saa7164_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int saa7164_proc_create(void)
-{
-       struct proc_dir_entry *pe;
-
-       pe = proc_create("saa7164", S_IRUGO, NULL, &saa7164_proc_fops);
-       if (!pe)
-               return -ENOMEM;
-
-       return 0;
-}
-#endif
-
-static int saa7164_thread_function(void *data)
-{
-       struct saa7164_dev *dev = data;
-       struct tmFwInfoStruct fwinfo;
-       u64 last_poll_time = 0;
-
-       dprintk(DBGLVL_THR, "thread started\n");
-
-       set_freezable();
-
-       while (1) {
-               msleep_interruptible(100);
-               if (kthread_should_stop())
-                       break;
-               try_to_freeze();
-
-               dprintk(DBGLVL_THR, "thread running\n");
-
-               /* Dump the firmware debug message to console */
-               /* Polling this costs us 1-2% of the arm CPU */
-               /* convert this into a respnde to interrupt 0x7a */
-               saa7164_api_collect_debug(dev);
-
-               /* Monitor CPU load every 1 second */
-               if ((last_poll_time + 1000 /* ms */) < jiffies_to_msecs(jiffies)) {
-                       saa7164_api_get_load_info(dev, &fwinfo);
-                       last_poll_time = jiffies_to_msecs(jiffies);
-               }
-
-       }
-
-       dprintk(DBGLVL_THR, "thread exiting\n");
-       return 0;
-}
-
-static int __devinit saa7164_initdev(struct pci_dev *pci_dev,
-                                    const struct pci_device_id *pci_id)
-{
-       struct saa7164_dev *dev;
-       int err, i;
-       u32 version;
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (NULL == dev)
-               return -ENOMEM;
-
-       /* pci init */
-       dev->pci = pci_dev;
-       if (pci_enable_device(pci_dev)) {
-               err = -EIO;
-               goto fail_free;
-       }
-
-       if (saa7164_dev_setup(dev) < 0) {
-               err = -EINVAL;
-               goto fail_free;
-       }
-
-       /* print pci info */
-       dev->pci_rev = pci_dev->revision;
-       pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-       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));
-
-       pci_set_master(pci_dev);
-       /* TODO */
-       if (!pci_dma_supported(pci_dev, 0xffffffff)) {
-               printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
-               err = -EIO;
-               goto fail_irq;
-       }
-
-       err = request_irq(pci_dev->irq, saa7164_irq,
-               IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
-       if (err < 0) {
-               printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name,
-                       pci_dev->irq);
-               err = -EIO;
-               goto fail_irq;
-       }
-
-       pci_set_drvdata(pci_dev, dev);
-
-       /* Init the internal command list */
-       for (i = 0; i < SAA_CMD_MAX_MSG_UNITS; i++) {
-               dev->cmds[i].seqno = i;
-               dev->cmds[i].inuse = 0;
-               mutex_init(&dev->cmds[i].lock);
-               init_waitqueue_head(&dev->cmds[i].wait);
-       }
-
-       /* We need a deferred interrupt handler for cmd handling */
-       INIT_WORK(&dev->workcmd, saa7164_work_cmdhandler);
-
-       /* Only load the firmware if we know the board */
-       if (dev->board != SAA7164_BOARD_UNKNOWN) {
-
-               err = saa7164_downloadfirmware(dev);
-               if (err < 0) {
-                       printk(KERN_ERR
-                               "Failed to boot firmware, no features "
-                               "registered\n");
-                       goto fail_fw;
-               }
-
-               saa7164_get_descriptors(dev);
-               saa7164_dumpregs(dev, 0);
-               saa7164_getcurrentfirmwareversion(dev);
-               saa7164_getfirmwarestatus(dev);
-               err = saa7164_bus_setup(dev);
-               if (err < 0)
-                       printk(KERN_ERR
-                               "Failed to setup the bus, will continue\n");
-               saa7164_bus_dump(dev);
-
-               /* Ping the running firmware via the command bus and get the
-                * firmware version, this checks the bus is running OK.
-                */
-               version = 0;
-               if (saa7164_api_get_fw_version(dev, &version) == SAA_OK)
-                       dprintk(1, "Bus is operating correctly using "
-                               "version %d.%d.%d.%d (0x%x)\n",
-                               (version & 0x0000fc00) >> 10,
-                               (version & 0x000003e0) >> 5,
-                               (version & 0x0000001f),
-                               (version & 0xffff0000) >> 16,
-                               version);
-               else
-                       printk(KERN_ERR
-                               "Failed to communicate with the firmware\n");
-
-               /* Bring up the I2C buses */
-               saa7164_i2c_register(&dev->i2c_bus[0]);
-               saa7164_i2c_register(&dev->i2c_bus[1]);
-               saa7164_i2c_register(&dev->i2c_bus[2]);
-               saa7164_gpio_setup(dev);
-               saa7164_card_setup(dev);
-
-               /* Parse the dynamic device configuration, find various
-                * media endpoints (MPEG, WMV, PS, TS) and cache their
-                * configuration details into the driver, so we can
-                * reference them later during simething_register() func,
-                * interrupt handlers, deferred work handlers etc.
-                */
-               saa7164_api_enum_subdevs(dev);
-
-               /* Begin to create the video sub-systems and register funcs */
-               if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) {
-                       if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS1]) < 0) {
-                               printk(KERN_ERR "%s() Failed to register "
-                                       "dvb adapters on porta\n",
-                                       __func__);
-                       }
-               }
-
-               if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) {
-                       if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS2]) < 0) {
-                               printk(KERN_ERR"%s() Failed to register "
-                                       "dvb adapters on portb\n",
-                                       __func__);
-                       }
-               }
-
-               if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) {
-                       if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC1]) < 0) {
-                               printk(KERN_ERR"%s() Failed to register "
-                                       "mpeg encoder\n", __func__);
-                       }
-               }
-
-               if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) {
-                       if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC2]) < 0) {
-                               printk(KERN_ERR"%s() Failed to register "
-                                       "mpeg encoder\n", __func__);
-                       }
-               }
-
-               if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI) {
-                       if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI1]) < 0) {
-                               printk(KERN_ERR"%s() Failed to register "
-                                       "vbi device\n", __func__);
-                       }
-               }
-
-               if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI) {
-                       if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI2]) < 0) {
-                               printk(KERN_ERR"%s() Failed to register "
-                                       "vbi device\n", __func__);
-                       }
-               }
-               saa7164_api_set_debug(dev, fw_debug);
-
-               if (fw_debug) {
-                       dev->kthread = kthread_run(saa7164_thread_function, dev,
-                               "saa7164 debug");
-                       if (!dev->kthread)
-                               printk(KERN_ERR "%s() Failed to create "
-                                       "debug kernel thread\n", __func__);
-               }
-
-       } /* != BOARD_UNKNOWN */
-       else
-               printk(KERN_ERR "%s() Unsupported board detected, "
-                       "registering without firmware\n", __func__);
-
-       dprintk(1, "%s() parameter debug = %d\n", __func__, saa_debug);
-       dprintk(1, "%s() parameter waitsecs = %d\n", __func__, waitsecs);
-
-fail_fw:
-       return 0;
-
-fail_irq:
-       saa7164_dev_unregister(dev);
-fail_free:
-       kfree(dev);
-       return err;
-}
-
-static void saa7164_shutdown(struct saa7164_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-}
-
-static void __devexit saa7164_finidev(struct pci_dev *pci_dev)
-{
-       struct saa7164_dev *dev = pci_get_drvdata(pci_dev);
-
-       if (dev->board != SAA7164_BOARD_UNKNOWN) {
-               if (fw_debug && dev->kthread) {
-                       kthread_stop(dev->kthread);
-                       dev->kthread = NULL;
-               }
-               if (dev->firmwareloaded)
-                       saa7164_api_set_debug(dev, 0x00);
-       }
-
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
-               &dev->ports[SAA7164_PORT_ENC1].irq_interval);
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
-               &dev->ports[SAA7164_PORT_ENC1].svc_interval);
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
-               &dev->ports[SAA7164_PORT_ENC1].irq_svc_interval);
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
-               &dev->ports[SAA7164_PORT_ENC1].read_interval);
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_ENC1],
-               &dev->ports[SAA7164_PORT_ENC1].poll_interval);
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI1],
-               &dev->ports[SAA7164_PORT_VBI1].read_interval);
-       saa7164_histogram_print(&dev->ports[SAA7164_PORT_VBI2],
-               &dev->ports[SAA7164_PORT_VBI2].poll_interval);
-
-       saa7164_shutdown(dev);
-
-       if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB)
-               saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS1]);
-
-       if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB)
-               saa7164_dvb_unregister(&dev->ports[SAA7164_PORT_TS2]);
-
-       if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER)
-               saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC1]);
-
-       if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER)
-               saa7164_encoder_unregister(&dev->ports[SAA7164_PORT_ENC2]);
-
-       if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI)
-               saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI1]);
-
-       if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI)
-               saa7164_vbi_unregister(&dev->ports[SAA7164_PORT_VBI2]);
-
-       saa7164_i2c_unregister(&dev->i2c_bus[0]);
-       saa7164_i2c_unregister(&dev->i2c_bus[1]);
-       saa7164_i2c_unregister(&dev->i2c_bus[2]);
-
-       pci_disable_device(pci_dev);
-
-       /* unregister stuff */
-       free_irq(pci_dev->irq, dev);
-       pci_set_drvdata(pci_dev, NULL);
-
-       mutex_lock(&devlist);
-       list_del(&dev->devlist);
-       mutex_unlock(&devlist);
-
-       saa7164_dev_unregister(dev);
-       kfree(dev);
-}
-
-static struct pci_device_id saa7164_pci_tbl[] = {
-       {
-               /* SAA7164 */
-               .vendor       = 0x1131,
-               .device       = 0x7164,
-               .subvendor    = PCI_ANY_ID,
-               .subdevice    = PCI_ANY_ID,
-       }, {
-               /* --- end of list --- */
-       }
-};
-MODULE_DEVICE_TABLE(pci, saa7164_pci_tbl);
-
-static struct pci_driver saa7164_pci_driver = {
-       .name     = "saa7164",
-       .id_table = saa7164_pci_tbl,
-       .probe    = saa7164_initdev,
-       .remove   = __devexit_p(saa7164_finidev),
-       /* TODO */
-       .suspend  = NULL,
-       .resume   = NULL,
-};
-
-static int __init saa7164_init(void)
-{
-       printk(KERN_INFO "saa7164 driver loaded\n");
-
-#ifdef CONFIG_PROC_FS
-       saa7164_proc_create();
-#endif
-       return pci_register_driver(&saa7164_pci_driver);
-}
-
-static void __exit saa7164_fini(void)
-{
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("saa7164", NULL);
-#endif
-       pci_unregister_driver(&saa7164_pci_driver);
-}
-
-module_init(saa7164_init);
-module_exit(saa7164_fini);
-
diff --git a/drivers/media/video/saa7164/saa7164-dvb.c b/drivers/media/video/saa7164/saa7164-dvb.c
deleted file mode 100644 (file)
index 5c5cc3e..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 "saa7164.h"
-
-#include "tda10048.h"
-#include "tda18271.h"
-#include "s5h1411.h"
-
-#define DRIVER_NAME "saa7164"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* addr is in the card struct, get it from there */
-static struct tda10048_config hauppauge_hvr2200_1_config = {
-       .demod_address    = 0x10 >> 1,
-       .output_mode      = TDA10048_SERIAL_OUTPUT,
-       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
-       .inversion        = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3500,
-       .dtv8_if_freq_khz = TDA10048_IF_4000,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-};
-static struct tda10048_config hauppauge_hvr2200_2_config = {
-       .demod_address    = 0x12 >> 1,
-       .output_mode      = TDA10048_SERIAL_OUTPUT,
-       .fwbulkwritelen   = TDA10048_BULKWRITE_200,
-       .inversion        = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3500,
-       .dtv8_if_freq_khz = TDA10048_IF_4000,
-       .clk_freq_khz     = TDA10048_CLK_16000,
-};
-
-static struct tda18271_std_map hauppauge_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 3250, .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_hvr22x0_tuner_config = {
-       .std_map        = &hauppauge_tda18271_std_map,
-       .gate           = TDA18271_GATE_ANALOG,
-       .role           = TDA18271_MASTER,
-};
-
-static struct tda18271_config hauppauge_hvr22x0s_tuner_config = {
-       .std_map        = &hauppauge_tda18271_std_map,
-       .gate           = TDA18271_GATE_ANALOG,
-       .role           = TDA18271_SLAVE,
-       .output_opt     = TDA18271_OUTPUT_LT_OFF,
-       .rf_cal_on_startup = 1
-};
-
-static struct s5h1411_config hauppauge_s5h1411_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_ON,
-       .qam_if        = S5H1411_IF_4000,
-       .vsb_if        = S5H1411_IF_3250,
-       .inversion     = S5H1411_INVERSION_ON,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static int saa7164_dvb_stop_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_DVB, "%s()    Stopped\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int saa7164_dvb_acquire_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_DVB, "%s() Acquired\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int saa7164_dvb_pause_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-/* Firmware is very windows centric, meaning you have to transition
- * the part through AVStream / KS Windows stages, forwards or backwards.
- * States are: stopped, acquired (h/w), paused, started.
- */
-static int saa7164_dvb_stop_streaming(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct list_head *p, *q;
-       int ret;
-
-       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
-
-       ret = saa7164_dvb_pause_port(port);
-       ret = saa7164_dvb_acquire_port(port);
-       ret = saa7164_dvb_stop_port(port);
-
-       /* Mark the hardware buffers as free */
-       mutex_lock(&port->dmaqueue_lock);
-       list_for_each_safe(p, q, &port->dmaqueue.list) {
-               buf = list_entry(p, struct saa7164_buffer, list);
-               buf->flags = SAA7164_BUFFER_FREE;
-       }
-       mutex_unlock(&port->dmaqueue_lock);
-
-       return ret;
-}
-
-static int saa7164_dvb_start_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0, result;
-
-       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
-
-       saa7164_buffer_cfg_port(port);
-
-       /* Acquire the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
-                       __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-                       printk(KERN_ERR "%s() acquire/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-               ret = -EIO;
-               goto out;
-       } else
-               dprintk(DBGLVL_DVB, "%s()   Acquired\n", __func__);
-
-       /* Pause the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
-                               __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-                       printk(KERN_ERR "%s() pause/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-
-               ret = -EIO;
-               goto out;
-       } else
-               dprintk(DBGLVL_DVB, "%s()   Paused\n", __func__);
-
-       /* Start the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
-                               __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-                       printk(KERN_ERR "%s() run/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-
-               ret = -EIO;
-       } else
-               dprintk(DBGLVL_DVB, "%s()   Running\n", __func__);
-
-out:
-       return ret;
-}
-
-static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct saa7164_port *port = (struct saa7164_port *) demux->priv;
-       struct saa7164_dvb *dvb = &port->dvb;
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-
-       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
-
-       if (!demux->dmx.frontend)
-               return -EINVAL;
-
-       if (dvb) {
-               mutex_lock(&dvb->lock);
-               if (dvb->feeding++ == 0) {
-                       /* Start transport */
-                       ret = saa7164_dvb_start_port(port);
-               }
-               mutex_unlock(&dvb->lock);
-               dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
-                       __func__, port->nr, dvb->feeding);
-       }
-
-       return ret;
-}
-
-static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct saa7164_port *port = (struct saa7164_port *) demux->priv;
-       struct saa7164_dvb *dvb = &port->dvb;
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-
-       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
-
-       if (dvb) {
-               mutex_lock(&dvb->lock);
-               if (--dvb->feeding == 0) {
-                       /* Stop transport */
-                       ret = saa7164_dvb_stop_streaming(port);
-               }
-               mutex_unlock(&dvb->lock);
-               dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
-                       __func__, port->nr, dvb->feeding);
-       }
-
-       return ret;
-}
-
-static int dvb_register(struct saa7164_port *port)
-{
-       struct saa7164_dvb *dvb = &port->dvb;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       int result, i;
-
-       dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
-
-       if (port->type != SAA7164_MPEG_DVB)
-               BUG();
-
-       /* Sanity check that the PCI configuration space is active */
-       if (port->hwcfg.BARLocation == 0) {
-               result = -ENOMEM;
-               printk(KERN_ERR "%s: dvb_register_adapter failed "
-                      "(errno = %d), NO PCI configuration\n",
-                       DRIVER_NAME, result);
-               goto fail_adapter;
-       }
-
-       /* Init and establish defaults */
-       port->hw_streamingparams.bitspersample = 8;
-       port->hw_streamingparams.samplesperline = 188;
-       port->hw_streamingparams.numberoflines =
-               (SAA7164_TS_NUMBER_OF_LINES * 188) / 188;
-
-       port->hw_streamingparams.pitch = 188;
-       port->hw_streamingparams.linethreshold = 0;
-       port->hw_streamingparams.pagetablelistvirt = NULL;
-       port->hw_streamingparams.pagetablelistphys = NULL;
-       port->hw_streamingparams.numpagetables = 2 +
-               ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
-
-       port->hw_streamingparams.numpagetableentries = port->hwcfg.buffercount;
-
-       /* Allocate the PCI resources */
-       for (i = 0; i < port->hwcfg.buffercount; i++) {
-               buf = saa7164_buffer_alloc(port,
-                       port->hw_streamingparams.numberoflines *
-                       port->hw_streamingparams.pitch);
-
-               if (!buf) {
-                       result = -ENOMEM;
-                       printk(KERN_ERR "%s: dvb_register_adapter failed "
-                              "(errno = %d), unable to allocate buffers\n",
-                               DRIVER_NAME, result);
-                       goto fail_adapter;
-               }
-
-               mutex_lock(&port->dmaqueue_lock);
-               list_add_tail(&buf->list, &port->dmaqueue.list);
-               mutex_unlock(&port->dmaqueue_lock);
-       }
-
-       /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
-                       &dev->pci->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 = port;
-
-       /* 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       = port;
-       dvb->demux.filternum  = 256;
-       dvb->demux.feednum    = 256;
-       dvb->demux.start_feed = saa7164_dvb_start_feed;
-       dvb->demux.stop_feed  = saa7164_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;
-}
-
-int saa7164_dvb_unregister(struct saa7164_port *port)
-{
-       struct saa7164_dvb *dvb = &port->dvb;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *b;
-       struct list_head *c, *n;
-
-       dprintk(DBGLVL_DVB, "%s()\n", __func__);
-
-       if (port->type != SAA7164_MPEG_DVB)
-               BUG();
-
-       /* Remove any allocated buffers */
-       mutex_lock(&port->dmaqueue_lock);
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               b = list_entry(c, struct saa7164_buffer, list);
-               list_del(c);
-               saa7164_buffer_dealloc(b);
-       }
-       mutex_unlock(&port->dmaqueue_lock);
-
-       if (dvb->frontend == NULL)
-               return 0;
-
-       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);
-       return 0;
-}
-
-/* All the DVB attach calls go here, this function get's modified
- * for each new card.
- */
-int saa7164_dvb_register(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_dvb *dvb = &port->dvb;
-       struct saa7164_i2c *i2c_bus = NULL;
-       int ret;
-
-       dprintk(DBGLVL_DVB, "%s()\n", __func__);
-
-       /* init frontend */
-       switch (dev->board) {
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_2:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_3:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_4:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2200_5:
-               i2c_bus = &dev->i2c_bus[port->nr + 1];
-               switch (port->nr) {
-               case 0:
-                       port->dvb.frontend = dvb_attach(tda10048_attach,
-                               &hauppauge_hvr2200_1_config,
-                               &i2c_bus->i2c_adap);
-
-                       if (port->dvb.frontend != NULL) {
-                               /* TODO: addr is in the card struct */
-                               dvb_attach(tda18271_attach, port->dvb.frontend,
-                                       0xc0 >> 1, &i2c_bus->i2c_adap,
-                                       &hauppauge_hvr22x0_tuner_config);
-                       }
-
-                       break;
-               case 1:
-                       port->dvb.frontend = dvb_attach(tda10048_attach,
-                               &hauppauge_hvr2200_2_config,
-                               &i2c_bus->i2c_adap);
-
-                       if (port->dvb.frontend != NULL) {
-                               /* TODO: addr is in the card struct */
-                               dvb_attach(tda18271_attach, port->dvb.frontend,
-                                       0xc0 >> 1, &i2c_bus->i2c_adap,
-                                       &hauppauge_hvr22x0s_tuner_config);
-                       }
-
-                       break;
-               }
-               break;
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250_2:
-       case SAA7164_BOARD_HAUPPAUGE_HVR2250_3:
-               i2c_bus = &dev->i2c_bus[port->nr + 1];
-
-               port->dvb.frontend = dvb_attach(s5h1411_attach,
-                       &hauppauge_s5h1411_config,
-                       &i2c_bus->i2c_adap);
-
-               if (port->dvb.frontend != NULL) {
-                       if (port->nr == 0) {
-                               /* Master TDA18271 */
-                               /* TODO: addr is in the card struct */
-                               dvb_attach(tda18271_attach, port->dvb.frontend,
-                                       0xc0 >> 1, &i2c_bus->i2c_adap,
-                                       &hauppauge_hvr22x0_tuner_config);
-                       } else {
-                               /* Slave TDA18271 */
-                               dvb_attach(tda18271_attach, port->dvb.frontend,
-                                       0xc0 >> 1, &i2c_bus->i2c_adap,
-                                       &hauppauge_hvr22x0s_tuner_config);
-                       }
-               }
-
-               break;
-       default:
-               printk(KERN_ERR "%s: The frontend isn't supported\n",
-                      dev->name);
-               break;
-       }
-       if (NULL == dvb->frontend) {
-               printk(KERN_ERR "%s() Frontend initialization failed\n",
-                      __func__);
-               return -1;
-       }
-
-       /* register everything */
-       ret = dvb_register(port);
-       if (ret < 0) {
-               if (dvb->frontend->ops.release)
-                       dvb->frontend->ops.release(dvb->frontend);
-               return ret;
-       }
-
-       return 0;
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-encoder.c b/drivers/media/video/saa7164/saa7164-encoder.c
deleted file mode 100644 (file)
index a9ed686..0000000
+++ /dev/null
@@ -1,1500 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 "saa7164.h"
-
-#define ENCODER_MAX_BITRATE 6500000
-#define ENCODER_MIN_BITRATE 1000000
-#define ENCODER_DEF_BITRATE 5000000
-
-static struct saa7164_tvnorm saa7164_tvnorms[] = {
-       {
-               .name      = "NTSC-M",
-               .id        = V4L2_STD_NTSC_M,
-       }, {
-               .name      = "NTSC-JP",
-               .id        = V4L2_STD_NTSC_M_JP,
-       }
-};
-
-static const u32 saa7164_v4l2_ctrls[] = {
-       V4L2_CID_BRIGHTNESS,
-       V4L2_CID_CONTRAST,
-       V4L2_CID_SATURATION,
-       V4L2_CID_HUE,
-       V4L2_CID_AUDIO_VOLUME,
-       V4L2_CID_SHARPNESS,
-       V4L2_CID_MPEG_STREAM_TYPE,
-       V4L2_CID_MPEG_VIDEO_ASPECT,
-       V4L2_CID_MPEG_VIDEO_B_FRAMES,
-       V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-       V4L2_CID_MPEG_AUDIO_MUTE,
-       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-       V4L2_CID_MPEG_VIDEO_BITRATE,
-       V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
-       0
-};
-
-/* Take the encoder configuration form the port struct and
- * flush it to the hardware.
- */
-static void saa7164_encoder_configure(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       port->encoder_params.width = port->width;
-       port->encoder_params.height = port->height;
-       port->encoder_params.is_50hz =
-               (port->encodernorm.id & V4L2_STD_625_50) != 0;
-
-       /* Set up the DIF (enable it) for analog mode by default */
-       saa7164_api_initialize_dif(port);
-
-       /* Configure the correct video standard */
-       saa7164_api_configure_dif(port, port->encodernorm.id);
-
-       /* Ensure the audio decoder is correct configured */
-       saa7164_api_set_audio_std(port);
-}
-
-static int saa7164_encoder_buffers_dealloc(struct saa7164_port *port)
-{
-       struct list_head *c, *n, *p, *q, *l, *v;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct saa7164_user_buffer *ubuf;
-
-       /* Remove any allocated buffers */
-       mutex_lock(&port->dmaqueue_lock);
-
-       dprintk(DBGLVL_ENC, "%s(port=%d) dmaqueue\n", __func__, port->nr);
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               buf = list_entry(c, struct saa7164_buffer, list);
-               list_del(c);
-               saa7164_buffer_dealloc(buf);
-       }
-
-       dprintk(DBGLVL_ENC, "%s(port=%d) used\n", __func__, port->nr);
-       list_for_each_safe(p, q, &port->list_buf_used.list) {
-               ubuf = list_entry(p, struct saa7164_user_buffer, list);
-               list_del(p);
-               saa7164_buffer_dealloc_user(ubuf);
-       }
-
-       dprintk(DBGLVL_ENC, "%s(port=%d) free\n", __func__, port->nr);
-       list_for_each_safe(l, v, &port->list_buf_free.list) {
-               ubuf = list_entry(l, struct saa7164_user_buffer, list);
-               list_del(l);
-               saa7164_buffer_dealloc_user(ubuf);
-       }
-
-       mutex_unlock(&port->dmaqueue_lock);
-       dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
-
-       return 0;
-}
-
-/* Dynamic buffer switch at encoder start time */
-static int saa7164_encoder_buffers_alloc(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct saa7164_user_buffer *ubuf;
-       struct tmHWStreamParameters *params = &port->hw_streamingparams;
-       int result = -ENODEV, i;
-       int len = 0;
-
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       if (port->encoder_params.stream_type ==
-               V4L2_MPEG_STREAM_TYPE_MPEG2_PS) {
-               dprintk(DBGLVL_ENC,
-                       "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_PS\n",
-                       __func__);
-               params->samplesperline = 128;
-               params->numberoflines = 256;
-               params->pitch = 128;
-               params->numpagetables = 2 +
-                       ((SAA7164_PS_NUMBER_OF_LINES * 128) / PAGE_SIZE);
-       } else
-       if (port->encoder_params.stream_type ==
-               V4L2_MPEG_STREAM_TYPE_MPEG2_TS) {
-               dprintk(DBGLVL_ENC,
-                       "%s() type=V4L2_MPEG_STREAM_TYPE_MPEG2_TS\n",
-                       __func__);
-               params->samplesperline = 188;
-               params->numberoflines = 312;
-               params->pitch = 188;
-               params->numpagetables = 2 +
-                       ((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
-       } else
-               BUG();
-
-       /* Init and establish defaults */
-       params->bitspersample = 8;
-       params->linethreshold = 0;
-       params->pagetablelistvirt = NULL;
-       params->pagetablelistphys = NULL;
-       params->numpagetableentries = port->hwcfg.buffercount;
-
-       /* Allocate the PCI resources, buffers (hard) */
-       for (i = 0; i < port->hwcfg.buffercount; i++) {
-               buf = saa7164_buffer_alloc(port,
-                       params->numberoflines *
-                       params->pitch);
-
-               if (!buf) {
-                       printk(KERN_ERR "%s() failed "
-                              "(errno = %d), unable to allocate buffer\n",
-                               __func__, result);
-                       result = -ENOMEM;
-                       goto failed;
-               } else {
-
-                       mutex_lock(&port->dmaqueue_lock);
-                       list_add_tail(&buf->list, &port->dmaqueue.list);
-                       mutex_unlock(&port->dmaqueue_lock);
-
-               }
-       }
-
-       /* Allocate some kernel buffers for copying
-        * to userpsace.
-        */
-       len = params->numberoflines * params->pitch;
-
-       if (encoder_buffers < 16)
-               encoder_buffers = 16;
-       if (encoder_buffers > 512)
-               encoder_buffers = 512;
-
-       for (i = 0; i < encoder_buffers; i++) {
-
-               ubuf = saa7164_buffer_alloc_user(dev, len);
-               if (ubuf) {
-                       mutex_lock(&port->dmaqueue_lock);
-                       list_add_tail(&ubuf->list, &port->list_buf_free.list);
-                       mutex_unlock(&port->dmaqueue_lock);
-               }
-
-       }
-
-       result = 0;
-
-failed:
-       return result;
-}
-
-static int saa7164_encoder_initialize(struct saa7164_port *port)
-{
-       saa7164_encoder_configure(port);
-       return 0;
-}
-
-/* -- V4L2 --------------------------------------------------------- */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-       unsigned int i;
-
-       dprintk(DBGLVL_ENC, "%s(id=0x%x)\n", __func__, (u32)*id);
-
-       for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
-               if (*id & saa7164_tvnorms[i].id)
-                       break;
-       }
-       if (i == ARRAY_SIZE(saa7164_tvnorms))
-               return -EINVAL;
-
-       port->encodernorm = saa7164_tvnorms[i];
-
-       /* Update the audio decoder while is not running in
-        * auto detect mode.
-        */
-       saa7164_api_set_audio_std(port);
-
-       dprintk(DBGLVL_ENC, "%s(id=0x%x) OK\n", __func__, (u32)*id);
-
-       return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-       struct v4l2_input *i)
-{
-       int n;
-
-       char *inputs[] = { "tuner", "composite", "svideo", "aux",
-               "composite 2", "svideo 2", "aux 2" };
-
-       if (i->index >= 7)
-               return -EINVAL;
-
-       strcpy(i->name, inputs[i->index]);
-
-       if (i->index == 0)
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       else
-               i->type  = V4L2_INPUT_TYPE_CAMERA;
-
-       for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
-               i->std |= saa7164_tvnorms[n].id;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       if (saa7164_api_get_videomux(port) != SAA_OK)
-               return -EIO;
-
-       *i = (port->mux_input - 1);
-
-       dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, *i);
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_ENC, "%s() input=%d\n", __func__, i);
-
-       if (i >= 7)
-               return -EINVAL;
-
-       port->mux_input = i + 1;
-
-       if (saa7164_api_set_videomux(port) != SAA_OK)
-               return -EIO;
-
-       return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-       struct v4l2_tuner *t)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "tuner");
-       t->type = V4L2_TUNER_ANALOG_TV;
-       t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
-
-       dprintk(DBGLVL_ENC, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-       struct v4l2_tuner *t)
-{
-       /* Update the A/V core */
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-
-       f->type = V4L2_TUNER_ANALOG_TV;
-       f->frequency = port->freq;
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_port *tsport;
-       struct dvb_frontend *fe;
-
-       /* TODO: Pull this for the std */
-       struct analog_parameters params = {
-               .mode      = V4L2_TUNER_ANALOG_TV,
-               .audmode   = V4L2_TUNER_MODE_STEREO,
-               .std       = port->encodernorm.id,
-               .frequency = f->frequency
-       };
-
-       /* Stop the encoder */
-       dprintk(DBGLVL_ENC, "%s() frequency=%d tuner=%d\n", __func__,
-               f->frequency, f->tuner);
-
-       if (f->tuner != 0)
-               return -EINVAL;
-
-       if (f->type != V4L2_TUNER_ANALOG_TV)
-               return -EINVAL;
-
-       port->freq = f->frequency;
-
-       /* Update the hardware */
-       if (port->nr == SAA7164_PORT_ENC1)
-               tsport = &dev->ports[SAA7164_PORT_TS1];
-       else
-       if (port->nr == SAA7164_PORT_ENC2)
-               tsport = &dev->ports[SAA7164_PORT_TS2];
-       else
-               BUG();
-
-       fe = tsport->dvb.frontend;
-
-       if (fe && fe->ops.tuner_ops.set_analog_params)
-               fe->ops.tuner_ops.set_analog_params(fe, &params);
-       else
-               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
-
-       saa7164_encoder_initialize(port);
-
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-       struct v4l2_control *ctl)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
-               ctl->id, ctl->value);
-
-       switch (ctl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               ctl->value = port->ctl_brightness;
-               break;
-       case V4L2_CID_CONTRAST:
-               ctl->value = port->ctl_contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               ctl->value = port->ctl_saturation;
-               break;
-       case V4L2_CID_HUE:
-               ctl->value = port->ctl_hue;
-               break;
-       case V4L2_CID_SHARPNESS:
-               ctl->value = port->ctl_sharpness;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               ctl->value = port->ctl_volume;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-       struct v4l2_control *ctl)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-
-       dprintk(DBGLVL_ENC, "%s(id=%d, value=%d)\n", __func__,
-               ctl->id, ctl->value);
-
-       switch (ctl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_brightness = ctl->value;
-                       saa7164_api_set_usercontrol(port,
-                               PU_BRIGHTNESS_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_CONTRAST:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_contrast = ctl->value;
-                       saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_SATURATION:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_saturation = ctl->value;
-                       saa7164_api_set_usercontrol(port,
-                               PU_SATURATION_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_HUE:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_hue = ctl->value;
-                       saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_SHARPNESS:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_sharpness = ctl->value;
-                       saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               if ((ctl->value >= -83) && (ctl->value <= 24)) {
-                       port->ctl_volume = ctl->value;
-                       saa7164_api_set_audio_volume(port, port->ctl_volume);
-               } else
-                       ret = -EINVAL;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static int saa7164_get_ctrl(struct saa7164_port *port,
-       struct v4l2_ext_control *ctrl)
-{
-       struct saa7164_encoder_params *params = &port->encoder_params;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               ctrl->value = params->bitrate;
-               break;
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               ctrl->value = params->stream_type;
-               break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               ctrl->value = params->ctl_mute;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               ctrl->value = params->ctl_aspect;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               ctrl->value = params->bitrate_mode;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               ctrl->value = params->refdist;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               ctrl->value = params->bitrate_peak;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               ctrl->value = params->gop_size;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-       struct v4l2_ext_controls *ctrls)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = saa7164_get_ctrl(port, ctrl);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-
-       }
-
-       return -EINVAL;
-}
-
-static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
-       int ret = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
-                       (ctrl->value <= ENCODER_MAX_BITRATE))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
-                       (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               if ((ctrl->value >= 0) &&
-                       (ctrl->value <= 1))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
-                       (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               if ((ctrl->value >= 0) &&
-                       (ctrl->value <= 255))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               if ((ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ||
-                       (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               if ((ctrl->value >= 1) &&
-                       (ctrl->value <= 3))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               if ((ctrl->value >= ENCODER_MIN_BITRATE) &&
-                       (ctrl->value <= ENCODER_MAX_BITRATE))
-                       ret = 0;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-       struct v4l2_ext_controls *ctrls)
-{
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = saa7164_try_ctrl(ctrl, 0);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-       }
-
-       return -EINVAL;
-}
-
-static int saa7164_set_ctrl(struct saa7164_port *port,
-       struct v4l2_ext_control *ctrl)
-{
-       struct saa7164_encoder_params *params = &port->encoder_params;
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               params->bitrate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               params->stream_type = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               params->ctl_mute = ctrl->value;
-               ret = saa7164_api_audio_mute(port, params->ctl_mute);
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
-                               ret);
-                       ret = -EIO;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               params->ctl_aspect = ctrl->value;
-               ret = saa7164_api_set_aspect_ratio(port);
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
-                               ret);
-                       ret = -EIO;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               params->bitrate_mode = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               params->refdist = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               params->bitrate_peak = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               params->gop_size = ctrl->value;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* TODO: Update the hardware */
-
-       return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-       struct v4l2_ext_controls *ctrls)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = saa7164_try_ctrl(ctrl, 0);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-                       err = saa7164_set_ctrl(port, ctrl);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-       struct v4l2_capability *cap)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       strcpy(cap->driver, dev->name);
-       strlcpy(cap->card, saa7164_boards[dev->board].name,
-               sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-
-       cap->capabilities =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_READWRITE     |
-               0;
-
-       cap->capabilities |= V4L2_CAP_TUNER;
-       cap->version = 0;
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-       struct v4l2_fmtdesc *f)
-{
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, "MPEG", sizeof(f->description));
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               port->ts_packet_size * port->ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-       f->fmt.pix.width        = port->width;
-       f->fmt.pix.height       = port->height;
-
-       dprintk(DBGLVL_ENC, "VIDIOC_G_FMT: w: %d, h: %d\n",
-               port->width, port->height);
-
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               port->ts_packet_size * port->ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-       dprintk(DBGLVL_ENC, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
-               port->width, port->height);
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               port->ts_packet_size * port->ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-
-       dprintk(DBGLVL_ENC, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
-               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-
-       return 0;
-}
-
-static int fill_queryctrl(struct saa7164_encoder_params *params,
-       struct v4l2_queryctrl *c)
-{
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
-       case V4L2_CID_CONTRAST:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
-       case V4L2_CID_SATURATION:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
-       case V4L2_CID_HUE:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
-       case V4L2_CID_SHARPNESS:
-               return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
-       case V4L2_CID_AUDIO_VOLUME:
-               return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               return v4l2_ctrl_query_fill(c,
-                       ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
-                       100000, ENCODER_DEF_BITRATE);
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               return v4l2_ctrl_query_fill(c,
-                       V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
-                       V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
-                       1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               return v4l2_ctrl_query_fill(c,
-                       V4L2_MPEG_VIDEO_ASPECT_1x1,
-                       V4L2_MPEG_VIDEO_ASPECT_221x100,
-                       1, V4L2_MPEG_VIDEO_ASPECT_4x3);
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               return v4l2_ctrl_query_fill(c,
-                       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
-                       1, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               return v4l2_ctrl_query_fill(c,
-                       1, 3, 1, 1);
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               return v4l2_ctrl_query_fill(c,
-                       ENCODER_MIN_BITRATE, ENCODER_MAX_BITRATE,
-                       100000, ENCODER_DEF_BITRATE);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-       struct v4l2_queryctrl *c)
-{
-       struct saa7164_encoder_fh *fh = priv;
-       struct saa7164_port *port = fh->port;
-       int i, next;
-       u32 id = c->id;
-
-       memset(c, 0, sizeof(*c));
-
-       next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
-       c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
-       for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
-               if (next) {
-                       if (c->id < saa7164_v4l2_ctrls[i])
-                               c->id = saa7164_v4l2_ctrls[i];
-                       else
-                               continue;
-               }
-
-               if (c->id == saa7164_v4l2_ctrls[i])
-                       return fill_queryctrl(&port->encoder_params, c);
-
-               if (c->id < saa7164_v4l2_ctrls[i])
-                       break;
-       }
-
-       return -EINVAL;
-}
-
-static int saa7164_encoder_stop_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_ENC, "%s()    Stopped\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int saa7164_encoder_acquire_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_ENC, "%s() Acquired\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int saa7164_encoder_pause_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_ENC, "%s()   Paused\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-/* Firmware is very windows centric, meaning you have to transition
- * the part through AVStream / KS Windows stages, forwards or backwards.
- * States are: stopped, acquired (h/w), paused, started.
- * We have to leave here will all of the soft buffers on the free list,
- * else the cfg_post() func won't have soft buffers to correctly configure.
- */
-static int saa7164_encoder_stop_streaming(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct saa7164_user_buffer *ubuf;
-       struct list_head *c, *n;
-       int ret;
-
-       dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
-
-       ret = saa7164_encoder_pause_port(port);
-       ret = saa7164_encoder_acquire_port(port);
-       ret = saa7164_encoder_stop_port(port);
-
-       dprintk(DBGLVL_ENC, "%s(port=%d) Hardware stopped\n", __func__,
-               port->nr);
-
-       /* Reset the state of any allocated buffer resources */
-       mutex_lock(&port->dmaqueue_lock);
-
-       /* Reset the hard and soft buffer state */
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               buf = list_entry(c, struct saa7164_buffer, list);
-               buf->flags = SAA7164_BUFFER_FREE;
-               buf->pos = 0;
-       }
-
-       list_for_each_safe(c, n, &port->list_buf_used.list) {
-               ubuf = list_entry(c, struct saa7164_user_buffer, list);
-               ubuf->pos = 0;
-               list_move_tail(&ubuf->list, &port->list_buf_free.list);
-       }
-
-       mutex_unlock(&port->dmaqueue_lock);
-
-       /* Free any allocated resources */
-       saa7164_encoder_buffers_dealloc(port);
-
-       dprintk(DBGLVL_ENC, "%s(port=%d) Released\n", __func__, port->nr);
-
-       return ret;
-}
-
-static int saa7164_encoder_start_streaming(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int result, ret = 0;
-
-       dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
-
-       port->done_first_interrupt = 0;
-
-       /* allocate all of the PCIe DMA buffer resources on the fly,
-        * allowing switching between TS and PS payloads without
-        * requiring a complete driver reload.
-        */
-       saa7164_encoder_buffers_alloc(port);
-
-       /* Configure the encoder with any cache values */
-       saa7164_api_set_encoder(port);
-       saa7164_api_get_encoder(port);
-
-       /* Place the empty buffers on the hardware */
-       saa7164_buffer_cfg_port(port);
-
-       /* Acquire the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
-                       __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-                       printk(KERN_ERR "%s() acquire/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-               ret = -EIO;
-               goto out;
-       } else
-               dprintk(DBGLVL_ENC, "%s()   Acquired\n", __func__);
-
-       /* Pause the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
-                               __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-                       printk(KERN_ERR "%s() pause/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-
-               ret = -EIO;
-               goto out;
-       } else
-               dprintk(DBGLVL_ENC, "%s()   Paused\n", __func__);
-
-       /* Start the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
-                               __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-               if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-                       printk(KERN_ERR "%s() run/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-
-               ret = -EIO;
-       } else
-               dprintk(DBGLVL_ENC, "%s()   Running\n", __func__);
-
-out:
-       return ret;
-}
-
-static int fops_open(struct file *file)
-{
-       struct saa7164_dev *dev;
-       struct saa7164_port *port;
-       struct saa7164_encoder_fh *fh;
-
-       port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
-       if (!port)
-               return -ENODEV;
-
-       dev = port->dev;
-
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
-               return -ENOMEM;
-
-       file->private_data = fh;
-       fh->port = port;
-
-       return 0;
-}
-
-static int fops_release(struct file *file)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       /* Shut device down on last close */
-       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
-               if (atomic_dec_return(&port->v4l_reader_count) == 0) {
-                       /* stop mpeg capture then cancel buffers */
-                       saa7164_encoder_stop_streaming(port);
-               }
-       }
-
-       file->private_data = NULL;
-       kfree(fh);
-
-       return 0;
-}
-
-struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
-{
-       struct saa7164_user_buffer *ubuf = NULL;
-       struct saa7164_dev *dev = port->dev;
-       u32 crc;
-
-       mutex_lock(&port->dmaqueue_lock);
-       if (!list_empty(&port->list_buf_used.list)) {
-               ubuf = list_first_entry(&port->list_buf_used.list,
-                       struct saa7164_user_buffer, list);
-
-               if (crc_checking) {
-                       crc = crc32(0, ubuf->data, ubuf->actual_size);
-                       if (crc != ubuf->crc) {
-                               printk(KERN_ERR
-               "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
-                                       __func__,
-                                       ubuf, ubuf->crc, crc);
-                       }
-               }
-
-       }
-       mutex_unlock(&port->dmaqueue_lock);
-
-       dprintk(DBGLVL_ENC, "%s() returns %p\n", __func__, ubuf);
-
-       return ubuf;
-}
-
-static ssize_t fops_read(struct file *file, char __user *buffer,
-       size_t count, loff_t *pos)
-{
-       struct saa7164_encoder_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_user_buffer *ubuf = NULL;
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-       int rem, cnt;
-       u8 *p;
-
-       port->last_read_msecs_diff = port->last_read_msecs;
-       port->last_read_msecs = jiffies_to_msecs(jiffies);
-       port->last_read_msecs_diff = port->last_read_msecs -
-               port->last_read_msecs_diff;
-
-       saa7164_histogram_update(&port->read_interval,
-               port->last_read_msecs_diff);
-
-       if (*pos) {
-               printk(KERN_ERR "%s() ESPIPE\n", __func__);
-               return -ESPIPE;
-       }
-
-       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
-               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
-
-                       if (saa7164_encoder_initialize(port) < 0) {
-                               printk(KERN_ERR "%s() EINVAL\n", __func__);
-                               return -EINVAL;
-                       }
-
-                       saa7164_encoder_start_streaming(port);
-                       msleep(200);
-               }
-       }
-
-       /* blocking wait for buffer */
-       if ((file->f_flags & O_NONBLOCK) == 0) {
-               if (wait_event_interruptible(port->wait_read,
-                       saa7164_enc_next_buf(port))) {
-                               printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
-                               return -ERESTARTSYS;
-               }
-       }
-
-       /* Pull the first buffer from the used list */
-       ubuf = saa7164_enc_next_buf(port);
-
-       while ((count > 0) && ubuf) {
-
-               /* set remaining bytes to copy */
-               rem = ubuf->actual_size - ubuf->pos;
-               cnt = rem > count ? count : rem;
-
-               p = ubuf->data + ubuf->pos;
-
-               dprintk(DBGLVL_ENC,
-                       "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
-                       __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
-
-               if (copy_to_user(buffer, p, cnt)) {
-                       printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
-                       if (!ret) {
-                               printk(KERN_ERR "%s() EFAULT\n", __func__);
-                               ret = -EFAULT;
-                       }
-                       goto err;
-               }
-
-               ubuf->pos += cnt;
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               if (ubuf->pos > ubuf->actual_size)
-                       printk(KERN_ERR "read() pos > actual, huh?\n");
-
-               if (ubuf->pos == ubuf->actual_size) {
-
-                       /* finished with current buffer, take next buffer */
-
-                       /* Requeue the buffer on the free list */
-                       ubuf->pos = 0;
-
-                       mutex_lock(&port->dmaqueue_lock);
-                       list_move_tail(&ubuf->list, &port->list_buf_free.list);
-                       mutex_unlock(&port->dmaqueue_lock);
-
-                       /* Dequeue next */
-                       if ((file->f_flags & O_NONBLOCK) == 0) {
-                               if (wait_event_interruptible(port->wait_read,
-                                       saa7164_enc_next_buf(port))) {
-                                               break;
-                               }
-                       }
-                       ubuf = saa7164_enc_next_buf(port);
-               }
-       }
-err:
-       if (!ret && !ubuf)
-               ret = -EAGAIN;
-
-       return ret;
-}
-
-static unsigned int fops_poll(struct file *file, poll_table *wait)
-{
-       struct saa7164_encoder_fh *fh =
-               (struct saa7164_encoder_fh *)file->private_data;
-       struct saa7164_port *port = fh->port;
-       unsigned int mask = 0;
-
-       port->last_poll_msecs_diff = port->last_poll_msecs;
-       port->last_poll_msecs = jiffies_to_msecs(jiffies);
-       port->last_poll_msecs_diff = port->last_poll_msecs -
-               port->last_poll_msecs_diff;
-
-       saa7164_histogram_update(&port->poll_interval,
-               port->last_poll_msecs_diff);
-
-       if (!video_is_registered(port->v4l_device))
-               return -EIO;
-
-       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
-               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
-                       if (saa7164_encoder_initialize(port) < 0)
-                               return -EINVAL;
-                       saa7164_encoder_start_streaming(port);
-                       msleep(200);
-               }
-       }
-
-       /* blocking wait for buffer */
-       if ((file->f_flags & O_NONBLOCK) == 0) {
-               if (wait_event_interruptible(port->wait_read,
-                       saa7164_enc_next_buf(port))) {
-                               return -ERESTARTSYS;
-               }
-       }
-
-       /* Pull the first buffer from the used list */
-       if (!list_empty(&port->list_buf_used.list))
-               mask |= POLLIN | POLLRDNORM;
-
-       return mask;
-}
-
-static const struct v4l2_file_operations mpeg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = fops_open,
-       .release        = fops_release,
-       .read           = fops_read,
-       .poll           = fops_poll,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-int saa7164_g_chip_ident(struct file *file, void *fh,
-       struct v4l2_dbg_chip_ident *chip)
-{
-       struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
-       struct saa7164_dev *dev = port->dev;
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       return 0;
-}
-
-int saa7164_g_register(struct file *file, void *fh,
-       struct v4l2_dbg_register *reg)
-{
-       struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
-       struct saa7164_dev *dev = port->dev;
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       return 0;
-}
-
-int saa7164_s_register(struct file *file, void *fh,
-       struct v4l2_dbg_register *reg)
-{
-       struct saa7164_port *port = ((struct saa7164_encoder_fh *)fh)->port;
-       struct saa7164_dev *dev = port->dev;
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       if (!capable(CAP_SYS_ADMIN))
-               return -EPERM;
-
-       return 0;
-}
-
-static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
-       .vidioc_s_std            = vidioc_s_std,
-       .vidioc_enum_input       = vidioc_enum_input,
-       .vidioc_g_input          = vidioc_g_input,
-       .vidioc_s_input          = vidioc_s_input,
-       .vidioc_g_tuner          = vidioc_g_tuner,
-       .vidioc_s_tuner          = vidioc_s_tuner,
-       .vidioc_g_frequency      = vidioc_g_frequency,
-       .vidioc_s_frequency      = vidioc_s_frequency,
-       .vidioc_s_ctrl           = vidioc_s_ctrl,
-       .vidioc_g_ctrl           = vidioc_g_ctrl,
-       .vidioc_querycap         = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
-       .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
-       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
-       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
-       .vidioc_queryctrl        = vidioc_queryctrl,
-       .vidioc_g_chip_ident     = saa7164_g_chip_ident,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register       = saa7164_g_register,
-       .vidioc_s_register       = saa7164_s_register,
-#endif
-};
-
-static struct video_device saa7164_mpeg_template = {
-       .name          = "saa7164",
-       .fops          = &mpeg_fops,
-       .ioctl_ops     = &mpeg_ioctl_ops,
-       .minor         = -1,
-       .tvnorms       = SAA7164_NORMS,
-       .current_norm  = V4L2_STD_NTSC_M,
-};
-
-static struct video_device *saa7164_encoder_alloc(
-       struct saa7164_port *port,
-       struct pci_dev *pci,
-       struct video_device *template,
-       char *type)
-{
-       struct video_device *vfd;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
-       *vfd = *template;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
-               type, saa7164_boards[dev->board].name);
-
-       vfd->parent  = &pci->dev;
-       vfd->release = video_device_release;
-       return vfd;
-}
-
-int saa7164_encoder_register(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int result = -ENODEV;
-
-       dprintk(DBGLVL_ENC, "%s()\n", __func__);
-
-       if (port->type != SAA7164_MPEG_ENCODER)
-               BUG();
-
-       /* Sanity check that the PCI configuration space is active */
-       if (port->hwcfg.BARLocation == 0) {
-               printk(KERN_ERR "%s() failed "
-                      "(errno = %d), NO PCI configuration\n",
-                       __func__, result);
-               result = -ENOMEM;
-               goto failed;
-       }
-
-       /* Establish encoder defaults here */
-       /* Set default TV standard */
-       port->encodernorm = saa7164_tvnorms[0];
-       port->width = 720;
-       port->mux_input = 1; /* Composite */
-       port->video_format = EU_VIDEO_FORMAT_MPEG_2;
-       port->audio_format = 0;
-       port->video_resolution = 0;
-       port->ctl_brightness = 127;
-       port->ctl_contrast = 66;
-       port->ctl_hue = 128;
-       port->ctl_saturation = 62;
-       port->ctl_sharpness = 8;
-       port->encoder_params.bitrate = ENCODER_DEF_BITRATE;
-       port->encoder_params.bitrate_peak = ENCODER_DEF_BITRATE;
-       port->encoder_params.bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
-       port->encoder_params.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;
-       port->encoder_params.ctl_mute = 0;
-       port->encoder_params.ctl_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
-       port->encoder_params.refdist = 1;
-       port->encoder_params.gop_size = SAA7164_ENCODER_DEFAULT_GOP_SIZE;
-
-       if (port->encodernorm.id & V4L2_STD_525_60)
-               port->height = 480;
-       else
-               port->height = 576;
-
-       /* Allocate and register the video device node */
-       port->v4l_device = saa7164_encoder_alloc(port,
-               dev->pci, &saa7164_mpeg_template, "mpeg");
-
-       if (!port->v4l_device) {
-               printk(KERN_INFO "%s: can't allocate mpeg device\n",
-                       dev->name);
-               result = -ENOMEM;
-               goto failed;
-       }
-
-       video_set_drvdata(port->v4l_device, port);
-       result = video_register_device(port->v4l_device,
-               VFL_TYPE_GRABBER, -1);
-       if (result < 0) {
-               printk(KERN_INFO "%s: can't register mpeg device\n",
-                       dev->name);
-               /* TODO: We're going to leak here if we don't dealloc
-                The buffers above. The unreg function can't deal wit it.
-               */
-               goto failed;
-       }
-
-       printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
-               dev->name, port->v4l_device->num);
-
-       /* Configure the hardware defaults */
-       saa7164_api_set_videomux(port);
-       saa7164_api_set_usercontrol(port, PU_BRIGHTNESS_CONTROL);
-       saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
-       saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
-       saa7164_api_set_usercontrol(port, PU_SATURATION_CONTROL);
-       saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
-       saa7164_api_audio_mute(port, 0);
-       saa7164_api_set_audio_volume(port, 20);
-       saa7164_api_set_aspect_ratio(port);
-
-       /* Disable audio standard detection, it's buggy */
-       saa7164_api_set_audio_detection(port, 0);
-
-       saa7164_api_set_encoder(port);
-       saa7164_api_get_encoder(port);
-
-       result = 0;
-failed:
-       return result;
-}
-
-void saa7164_encoder_unregister(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_ENC, "%s(port=%d)\n", __func__, port->nr);
-
-       if (port->type != SAA7164_MPEG_ENCODER)
-               BUG();
-
-       if (port->v4l_device) {
-               if (port->v4l_device->minor != -1)
-                       video_unregister_device(port->v4l_device);
-               else
-                       video_device_release(port->v4l_device);
-
-               port->v4l_device = NULL;
-       }
-
-       dprintk(DBGLVL_ENC, "%s(port=%d) done\n", __func__, port->nr);
-}
-
diff --git a/drivers/media/video/saa7164/saa7164-fw.c b/drivers/media/video/saa7164/saa7164-fw.c
deleted file mode 100644 (file)
index a266bf0..0000000
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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/firmware.h>
-#include <linux/slab.h>
-
-#include "saa7164.h"
-
-#define SAA7164_REV2_FIRMWARE          "NXP7164-2010-03-10.1.fw"
-#define SAA7164_REV2_FIRMWARE_SIZE     4019072
-
-#define SAA7164_REV3_FIRMWARE          "NXP7164-2010-03-10.1.fw"
-#define SAA7164_REV3_FIRMWARE_SIZE     4019072
-
-struct fw_header {
-       u32     firmwaresize;
-       u32     bslsize;
-       u32     reserved;
-       u32     version;
-};
-
-int saa7164_dl_wait_ack(struct saa7164_dev *dev, u32 reg)
-{
-       u32 timeout = SAA_DEVICE_TIMEOUT;
-       while ((saa7164_readl(reg) & 0x01) == 0) {
-               timeout -= 10;
-               if (timeout == 0) {
-                       printk(KERN_ERR "%s() timeout (no d/l ack)\n",
-                               __func__);
-                       return -EBUSY;
-               }
-               msleep(100);
-       }
-
-       return 0;
-}
-
-int saa7164_dl_wait_clr(struct saa7164_dev *dev, u32 reg)
-{
-       u32 timeout = SAA_DEVICE_TIMEOUT;
-       while (saa7164_readl(reg) & 0x01) {
-               timeout -= 10;
-               if (timeout == 0) {
-                       printk(KERN_ERR "%s() timeout (no d/l clr)\n",
-                               __func__);
-                       return -EBUSY;
-               }
-               msleep(100);
-       }
-
-       return 0;
-}
-
-/* TODO: move dlflags into dev-> and change to write/readl/b */
-/* TODO: Excessive levels of debug */
-int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
-       u32 dlflags, u8 *dst, u32 dstsize)
-{
-       u32 reg, timeout, offset;
-       u8 *srcbuf = NULL;
-       int ret;
-
-       u32 dlflag = dlflags;
-       u32 dlflag_ack = dlflag + 4;
-       u32 drflag = dlflag_ack + 4;
-       u32 drflag_ack = drflag + 4;
-       u32 bleflag = drflag_ack + 4;
-
-       dprintk(DBGLVL_FW,
-               "%s(image=%p, size=%d, flags=0x%x, dst=%p, dstsize=0x%x)\n",
-               __func__, src, srcsize, dlflags, dst, dstsize);
-
-       if ((src == NULL) || (dst == NULL)) {
-               ret = -EIO;
-               goto out;
-       }
-
-       srcbuf = kzalloc(4 * 1048576, GFP_KERNEL);
-       if (NULL == srcbuf) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       if (srcsize > (4*1048576)) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       memcpy(srcbuf, src, srcsize);
-
-       dprintk(DBGLVL_FW, "%s() dlflag = 0x%x\n", __func__, dlflag);
-       dprintk(DBGLVL_FW, "%s() dlflag_ack = 0x%x\n", __func__, dlflag_ack);
-       dprintk(DBGLVL_FW, "%s() drflag = 0x%x\n", __func__, drflag);
-       dprintk(DBGLVL_FW, "%s() drflag_ack = 0x%x\n", __func__, drflag_ack);
-       dprintk(DBGLVL_FW, "%s() bleflag = 0x%x\n", __func__, bleflag);
-
-       reg = saa7164_readl(dlflag);
-       dprintk(DBGLVL_FW, "%s() dlflag (0x%x)= 0x%x\n", __func__, dlflag, reg);
-       if (reg == 1)
-               dprintk(DBGLVL_FW,
-                       "%s() Download flag already set, please reboot\n",
-                       __func__);
-
-       /* Indicate download start */
-       saa7164_writel(dlflag, 1);
-       ret = saa7164_dl_wait_ack(dev, dlflag_ack);
-       if (ret < 0)
-               goto out;
-
-       /* Ack download start, then wait for wait */
-       saa7164_writel(dlflag, 0);
-       ret = saa7164_dl_wait_clr(dev, dlflag_ack);
-       if (ret < 0)
-               goto out;
-
-       /* Deal with the raw firmware, in the appropriate chunk size */
-       for (offset = 0; srcsize > dstsize;
-               srcsize -= dstsize, offset += dstsize) {
-
-               dprintk(DBGLVL_FW, "%s() memcpy %d\n", __func__, dstsize);
-               memcpy(dst, srcbuf + offset, dstsize);
-
-               /* Flag the data as ready */
-               saa7164_writel(drflag, 1);
-               ret = saa7164_dl_wait_ack(dev, drflag_ack);
-               if (ret < 0)
-                       goto out;
-
-               /* Wait for indication data was received */
-               saa7164_writel(drflag, 0);
-               ret = saa7164_dl_wait_clr(dev, drflag_ack);
-               if (ret < 0)
-                       goto out;
-
-       }
-
-       dprintk(DBGLVL_FW, "%s() memcpy(l) %d\n", __func__, dstsize);
-       /* Write last block to the device */
-       memcpy(dst, srcbuf+offset, srcsize);
-
-       /* Flag the data as ready */
-       saa7164_writel(drflag, 1);
-       ret = saa7164_dl_wait_ack(dev, drflag_ack);
-       if (ret < 0)
-               goto out;
-
-       saa7164_writel(drflag, 0);
-       timeout = 0;
-       while (saa7164_readl(bleflag) != SAA_DEVICE_IMAGE_BOOTING) {
-               if (saa7164_readl(bleflag) & SAA_DEVICE_IMAGE_CORRUPT) {
-                       printk(KERN_ERR "%s() image corrupt\n", __func__);
-                       ret = -EBUSY;
-                       goto out;
-               }
-
-               if (saa7164_readl(bleflag) & SAA_DEVICE_MEMORY_CORRUPT) {
-                       printk(KERN_ERR "%s() device memory corrupt\n",
-                               __func__);
-                       ret = -EBUSY;
-                       goto out;
-               }
-
-               msleep(10); /* Checkpatch throws a < 20ms warning */
-               if (timeout++ > 60)
-                       break;
-       }
-
-       printk(KERN_INFO "%s() Image downloaded, booting...\n", __func__);
-
-       ret = saa7164_dl_wait_clr(dev, drflag_ack);
-       if (ret < 0)
-               goto out;
-
-       printk(KERN_INFO "%s() Image booted successfully.\n", __func__);
-       ret = 0;
-
-out:
-       kfree(srcbuf);
-       return ret;
-}
-
-/* TODO: Excessive debug */
-/* Load the firmware. Optionally it can be in ROM or newer versions
- * can be on disk, saving the expense of the ROM hardware. */
-int saa7164_downloadfirmware(struct saa7164_dev *dev)
-{
-       /* u32 second_timeout = 60 * SAA_DEVICE_TIMEOUT; */
-       u32 tmp, filesize, version, err_flags, first_timeout, fwlength;
-       u32 second_timeout, updatebootloader = 1, bootloadersize = 0;
-       const struct firmware *fw = NULL;
-       struct fw_header *hdr, *boothdr = NULL, *fwhdr;
-       u32 bootloaderversion = 0, fwloadersize;
-       u8 *bootloaderoffset = NULL, *fwloaderoffset;
-       char *fwname;
-       int ret;
-
-       dprintk(DBGLVL_FW, "%s()\n", __func__);
-
-       if (saa7164_boards[dev->board].chiprev == SAA7164_CHIP_REV2) {
-               fwname = SAA7164_REV2_FIRMWARE;
-               fwlength = SAA7164_REV2_FIRMWARE_SIZE;
-       } else {
-               fwname = SAA7164_REV3_FIRMWARE;
-               fwlength = SAA7164_REV3_FIRMWARE_SIZE;
-       }
-
-       version = saa7164_getcurrentfirmwareversion(dev);
-
-       if (version == 0x00) {
-
-               second_timeout = 100;
-               first_timeout = 100;
-               err_flags = saa7164_readl(SAA_BOOTLOADERERROR_FLAGS);
-               dprintk(DBGLVL_FW, "%s() err_flags = %x\n",
-                       __func__, err_flags);
-
-               while (err_flags != SAA_DEVICE_IMAGE_BOOTING) {
-                       dprintk(DBGLVL_FW, "%s() err_flags = %x\n",
-                               __func__, err_flags);
-                       msleep(10); /* Checkpatch throws a < 20ms warning */
-
-                       if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) {
-                               printk(KERN_ERR "%s() firmware corrupt\n",
-                                       __func__);
-                               break;
-                       }
-                       if (err_flags & SAA_DEVICE_MEMORY_CORRUPT) {
-                               printk(KERN_ERR "%s() device memory corrupt\n",
-                                       __func__);
-                               break;
-                       }
-                       if (err_flags & SAA_DEVICE_NO_IMAGE) {
-                               printk(KERN_ERR "%s() no first image\n",
-                               __func__);
-                               break;
-                       }
-                       if (err_flags & SAA_DEVICE_IMAGE_SEARCHING) {
-                               first_timeout -= 10;
-                               if (first_timeout == 0) {
-                                       printk(KERN_ERR
-                                               "%s() no first image\n",
-                                               __func__);
-                                       break;
-                               }
-                       } else if (err_flags & SAA_DEVICE_IMAGE_LOADING) {
-                               second_timeout -= 10;
-                               if (second_timeout == 0) {
-                                       printk(KERN_ERR
-                                       "%s() FW load time exceeded\n",
-                                               __func__);
-                                       break;
-                               }
-                       } else {
-                               second_timeout -= 10;
-                               if (second_timeout == 0) {
-                                       printk(KERN_ERR
-                                       "%s() Unknown bootloader flags 0x%x\n",
-                                               __func__, err_flags);
-                                       break;
-                               }
-                       }
-
-                       err_flags = saa7164_readl(SAA_BOOTLOADERERROR_FLAGS);
-               } /* While != Booting */
-
-               if (err_flags == SAA_DEVICE_IMAGE_BOOTING) {
-                       dprintk(DBGLVL_FW, "%s() Loader 1 has loaded.\n",
-                               __func__);
-                       first_timeout = SAA_DEVICE_TIMEOUT;
-                       second_timeout = 60 * SAA_DEVICE_TIMEOUT;
-                       second_timeout = 100;
-
-                       err_flags = saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS);
-                       dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n",
-                               __func__, err_flags);
-                       while (err_flags != SAA_DEVICE_IMAGE_BOOTING) {
-                               dprintk(DBGLVL_FW, "%s() err_flags2 = %x\n",
-                                       __func__, err_flags);
-                               msleep(10); /* Checkpatch throws a < 20ms warning */
-
-                               if (err_flags & SAA_DEVICE_IMAGE_CORRUPT) {
-                                       printk(KERN_ERR
-                                               "%s() firmware corrupt\n",
-                                               __func__);
-                                       break;
-                               }
-                               if (err_flags & SAA_DEVICE_MEMORY_CORRUPT) {
-                                       printk(KERN_ERR
-                                               "%s() device memory corrupt\n",
-                                               __func__);
-                                       break;
-                               }
-                               if (err_flags & SAA_DEVICE_NO_IMAGE) {
-                                       printk(KERN_ERR "%s() no first image\n",
-                                               __func__);
-                                       break;
-                               }
-                               if (err_flags & SAA_DEVICE_IMAGE_SEARCHING) {
-                                       first_timeout -= 10;
-                                       if (first_timeout == 0) {
-                                               printk(KERN_ERR
-                                               "%s() no second image\n",
-                                                       __func__);
-                                               break;
-                                       }
-                               } else if (err_flags &
-                                       SAA_DEVICE_IMAGE_LOADING) {
-                                       second_timeout -= 10;
-                                       if (second_timeout == 0) {
-                                               printk(KERN_ERR
-                                               "%s() FW load time exceeded\n",
-                                                       __func__);
-                                               break;
-                                       }
-                               } else {
-                                       second_timeout -= 10;
-                                       if (second_timeout == 0) {
-                                               printk(KERN_ERR
-                                       "%s() Unknown bootloader flags 0x%x\n",
-                                                       __func__, err_flags);
-                                               break;
-                                       }
-                               }
-
-                               err_flags =
-                               saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS);
-                       } /* err_flags != SAA_DEVICE_IMAGE_BOOTING */
-
-                       dprintk(DBGLVL_FW, "%s() Loader flags 1:0x%x 2:0x%x.\n",
-                               __func__,
-                               saa7164_readl(SAA_BOOTLOADERERROR_FLAGS),
-                               saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS));
-
-               } /* err_flags == SAA_DEVICE_IMAGE_BOOTING */
-
-               /* It's possible for both firmwares to have booted,
-                * but that doesn't mean they've finished booting yet.
-                */
-               if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) ==
-                       SAA_DEVICE_IMAGE_BOOTING) &&
-                       (saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS) ==
-                       SAA_DEVICE_IMAGE_BOOTING)) {
-
-
-                       dprintk(DBGLVL_FW, "%s() Loader 2 has loaded.\n",
-                               __func__);
-
-                       first_timeout = SAA_DEVICE_TIMEOUT;
-                       while (first_timeout) {
-                               msleep(10); /* Checkpatch throws a < 20ms warning */
-
-                               version =
-                                       saa7164_getcurrentfirmwareversion(dev);
-                               if (version) {
-                                       dprintk(DBGLVL_FW,
-                                       "%s() All f/w loaded successfully\n",
-                                               __func__);
-                                       break;
-                               } else {
-                                       first_timeout -= 10;
-                                       if (first_timeout == 0) {
-                                               printk(KERN_ERR
-                                               "%s() FW did not boot\n",
-                                                       __func__);
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               version = saa7164_getcurrentfirmwareversion(dev);
-       } /* version == 0 */
-
-       /* Has the firmware really booted? */
-       if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) ==
-               SAA_DEVICE_IMAGE_BOOTING) &&
-               (saa7164_readl(SAA_SECONDSTAGEERROR_FLAGS) ==
-               SAA_DEVICE_IMAGE_BOOTING) && (version == 0)) {
-
-               printk(KERN_ERR
-                       "%s() The firmware hung, probably bad firmware\n",
-                       __func__);
-
-               /* Tell the second stage loader we have a deadlock */
-               saa7164_writel(SAA_DEVICE_DEADLOCK_DETECTED_OFFSET,
-                       SAA_DEVICE_DEADLOCK_DETECTED);
-
-               saa7164_getfirmwarestatus(dev);
-
-               return -ENOMEM;
-       }
-
-       dprintk(DBGLVL_FW, "Device has Firmware Version %d.%d.%d.%d\n",
-               (version & 0x0000fc00) >> 10,
-               (version & 0x000003e0) >> 5,
-               (version & 0x0000001f),
-               (version & 0xffff0000) >> 16);
-
-       /* Load the firmwware from the disk if required */
-       if (version == 0) {
-
-               printk(KERN_INFO "%s() Waiting for firmware upload (%s)\n",
-                       __func__, fwname);
-
-               ret = request_firmware(&fw, fwname, &dev->pci->dev);
-               if (ret) {
-                       printk(KERN_ERR "%s() Upload failed. "
-                               "(file not found?)\n", __func__);
-                       return -ENOMEM;
-               }
-
-               printk(KERN_INFO "%s() firmware read %Zu bytes.\n",
-                       __func__, fw->size);
-
-               if (fw->size != fwlength) {
-                       printk(KERN_ERR "xc5000: firmware incorrect size\n");
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               printk(KERN_INFO "%s() firmware loaded.\n", __func__);
-
-               hdr = (struct fw_header *)fw->data;
-               printk(KERN_INFO "Firmware file header part 1:\n");
-               printk(KERN_INFO " .FirmwareSize = 0x%x\n", hdr->firmwaresize);
-               printk(KERN_INFO " .BSLSize = 0x%x\n", hdr->bslsize);
-               printk(KERN_INFO " .Reserved = 0x%x\n", hdr->reserved);
-               printk(KERN_INFO " .Version = 0x%x\n", hdr->version);
-
-               /* Retrieve bootloader if reqd */
-               if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0))
-                       /* Second bootloader in the firmware file */
-                       filesize = hdr->reserved * 16;
-               else
-                       filesize = (hdr->firmwaresize + hdr->bslsize) *
-                               16 + sizeof(struct fw_header);
-
-               printk(KERN_INFO "%s() SecBootLoader.FileSize = %d\n",
-                       __func__, filesize);
-
-               /* Get bootloader (if reqd) and firmware header */
-               if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) {
-                       /* Second boot loader is required */
-
-                       /* Get the loader header */
-                       boothdr = (struct fw_header *)(fw->data +
-                               sizeof(struct fw_header));
-
-                       bootloaderversion =
-                               saa7164_readl(SAA_DEVICE_2ND_VERSION);
-                       dprintk(DBGLVL_FW, "Onboard BootLoader:\n");
-                       dprintk(DBGLVL_FW, "->Flag 0x%x\n",
-                               saa7164_readl(SAA_BOOTLOADERERROR_FLAGS));
-                       dprintk(DBGLVL_FW, "->Ack 0x%x\n",
-                               saa7164_readl(SAA_DATAREADY_FLAG_ACK));
-                       dprintk(DBGLVL_FW, "->FW Version 0x%x\n", version);
-                       dprintk(DBGLVL_FW, "->Loader Version 0x%x\n",
-                               bootloaderversion);
-
-                       if ((saa7164_readl(SAA_BOOTLOADERERROR_FLAGS) ==
-                               0x03) && (saa7164_readl(SAA_DATAREADY_FLAG_ACK)
-                               == 0x00) && (version == 0x00)) {
-
-                               dprintk(DBGLVL_FW, "BootLoader version in  "
-                                       "rom %d.%d.%d.%d\n",
-                                       (bootloaderversion & 0x0000fc00) >> 10,
-                                       (bootloaderversion & 0x000003e0) >> 5,
-                                       (bootloaderversion & 0x0000001f),
-                                       (bootloaderversion & 0xffff0000) >> 16
-                                       );
-                               dprintk(DBGLVL_FW, "BootLoader version "
-                                       "in file %d.%d.%d.%d\n",
-                                       (boothdr->version & 0x0000fc00) >> 10,
-                                       (boothdr->version & 0x000003e0) >> 5,
-                                       (boothdr->version & 0x0000001f),
-                                       (boothdr->version & 0xffff0000) >> 16
-                                       );
-
-                               if (bootloaderversion == boothdr->version)
-                                       updatebootloader = 0;
-                       }
-
-                       /* Calculate offset to firmware header */
-                       tmp = (boothdr->firmwaresize + boothdr->bslsize) * 16 +
-                               (sizeof(struct fw_header) +
-                               sizeof(struct fw_header));
-
-                       fwhdr = (struct fw_header *)(fw->data+tmp);
-               } else {
-                       /* No second boot loader */
-                       fwhdr = hdr;
-               }
-
-               dprintk(DBGLVL_FW, "Firmware version in file %d.%d.%d.%d\n",
-                       (fwhdr->version & 0x0000fc00) >> 10,
-                       (fwhdr->version & 0x000003e0) >> 5,
-                       (fwhdr->version & 0x0000001f),
-                       (fwhdr->version & 0xffff0000) >> 16
-                       );
-
-               if (version == fwhdr->version) {
-                       /* No download, firmware already on board */
-                       ret = 0;
-                       goto out;
-               }
-
-               if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0)) {
-                       if (updatebootloader) {
-                               /* Get ready to upload the bootloader */
-                               bootloadersize = (boothdr->firmwaresize +
-                                       boothdr->bslsize) * 16 +
-                                       sizeof(struct fw_header);
-
-                               bootloaderoffset = (u8 *)(fw->data +
-                                       sizeof(struct fw_header));
-
-                               dprintk(DBGLVL_FW, "bootloader d/l starts.\n");
-                               printk(KERN_INFO "%s() FirmwareSize = 0x%x\n",
-                                       __func__, boothdr->firmwaresize);
-                               printk(KERN_INFO "%s() BSLSize = 0x%x\n",
-                                       __func__, boothdr->bslsize);
-                               printk(KERN_INFO "%s() Reserved = 0x%x\n",
-                                       __func__, boothdr->reserved);
-                               printk(KERN_INFO "%s() Version = 0x%x\n",
-                                       __func__, boothdr->version);
-                               ret = saa7164_downloadimage(
-                                       dev,
-                                       bootloaderoffset,
-                                       bootloadersize,
-                                       SAA_DOWNLOAD_FLAGS,
-                                       dev->bmmio + SAA_DEVICE_DOWNLOAD_OFFSET,
-                                       SAA_DEVICE_BUFFERBLOCKSIZE);
-                               if (ret < 0) {
-                                       printk(KERN_ERR
-                                               "bootloader d/l has failed\n");
-                                       goto out;
-                               }
-                               dprintk(DBGLVL_FW,
-                                       "bootloader download complete.\n");
-
-                       }
-
-                       printk(KERN_ERR "starting firmware download(2)\n");
-                       bootloadersize = (boothdr->firmwaresize +
-                               boothdr->bslsize) * 16 +
-                               sizeof(struct fw_header);
-
-                       bootloaderoffset =
-                               (u8 *)(fw->data + sizeof(struct fw_header));
-
-                       fwloaderoffset = bootloaderoffset + bootloadersize;
-
-                       /* TODO: fix this bounds overrun here with old f/ws */
-                       fwloadersize = (fwhdr->firmwaresize + fwhdr->bslsize) *
-                               16 + sizeof(struct fw_header);
-
-                       ret = saa7164_downloadimage(
-                               dev,
-                               fwloaderoffset,
-                               fwloadersize,
-                               SAA_DEVICE_2ND_DOWNLOADFLAG_OFFSET,
-                               dev->bmmio + SAA_DEVICE_2ND_DOWNLOAD_OFFSET,
-                               SAA_DEVICE_2ND_BUFFERBLOCKSIZE);
-                       if (ret < 0) {
-                               printk(KERN_ERR "firmware download failed\n");
-                               goto out;
-                       }
-                       printk(KERN_ERR "firmware download complete.\n");
-
-               } else {
-
-                       /* No bootloader update reqd, download firmware only */
-                       printk(KERN_ERR "starting firmware download(3)\n");
-
-                       ret = saa7164_downloadimage(
-                               dev,
-                               (u8 *)fw->data,
-                               fw->size,
-                               SAA_DOWNLOAD_FLAGS,
-                               dev->bmmio + SAA_DEVICE_DOWNLOAD_OFFSET,
-                               SAA_DEVICE_BUFFERBLOCKSIZE);
-                       if (ret < 0) {
-                               printk(KERN_ERR "firmware download failed\n");
-                               goto out;
-                       }
-                       printk(KERN_ERR "firmware download complete.\n");
-               }
-       }
-
-       dev->firmwareloaded = 1;
-       ret = 0;
-
-out:
-       release_firmware(fw);
-       return ret;
-}
diff --git a/drivers/media/video/saa7164/saa7164-i2c.c b/drivers/media/video/saa7164/saa7164-i2c.c
deleted file mode 100644 (file)
index 4f7e3b4..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 "saa7164.h"
-
-static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
-{
-       struct saa7164_i2c *bus = i2c_adap->algo_data;
-       struct saa7164_dev *dev = bus->dev;
-       int i, retval = 0;
-
-       dprintk(DBGLVL_I2C, "%s(num = %d)\n", __func__, num);
-
-       for (i = 0 ; i < num; i++) {
-               dprintk(DBGLVL_I2C, "%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) {
-                       /* Unsupported - Yet*/
-                       printk(KERN_ERR "%s() Unsupported - Yet\n", __func__);
-                       continue;
-               } 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 = saa7164_api_i2c_read(bus, msgs[i].addr,
-                               msgs[i].len, msgs[i].buf,
-                               msgs[i+1].len, msgs[i+1].buf
-                               );
-
-                       i++;
-
-                       if (retval < 0)
-                               goto err;
-               } else {
-                       /* write */
-                       retval = saa7164_api_i2c_write(bus, msgs[i].addr,
-                               msgs[i].len, msgs[i].buf);
-               }
-               if (retval < 0)
-                       goto err;
-       }
-       return num;
-
-err:
-       return retval;
-}
-
-static u32 saa7164_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm saa7164_i2c_algo_template = {
-       .master_xfer    = i2c_xfer,
-       .functionality  = saa7164_functionality,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_adapter saa7164_i2c_adap_template = {
-       .name              = "saa7164",
-       .owner             = THIS_MODULE,
-       .algo              = &saa7164_i2c_algo_template,
-};
-
-static struct i2c_client saa7164_i2c_client_template = {
-       .name   = "saa7164 internal",
-};
-
-int saa7164_i2c_register(struct saa7164_i2c *bus)
-{
-       struct saa7164_dev *dev = bus->dev;
-
-       dprintk(DBGLVL_I2C, "%s(bus = %d)\n", __func__, bus->nr);
-
-       bus->i2c_adap = saa7164_i2c_adap_template;
-       bus->i2c_client = saa7164_i2c_client_template;
-
-       bus->i2c_adap.dev.parent = &dev->pci->dev;
-
-       strlcpy(bus->i2c_adap.name, bus->dev->name,
-               sizeof(bus->i2c_adap.name));
-
-       bus->i2c_adap.algo_data = bus;
-       i2c_set_adapdata(&bus->i2c_adap, bus);
-       i2c_add_adapter(&bus->i2c_adap);
-
-       bus->i2c_client.adapter = &bus->i2c_adap;
-
-       if (0 != bus->i2c_rc)
-               printk(KERN_ERR "%s: i2c bus %d register FAILED\n",
-                       dev->name, bus->nr);
-
-       return bus->i2c_rc;
-}
-
-int saa7164_i2c_unregister(struct saa7164_i2c *bus)
-{
-       i2c_del_adapter(&bus->i2c_adap);
-       return 0;
-}
diff --git a/drivers/media/video/saa7164/saa7164-reg.h b/drivers/media/video/saa7164/saa7164-reg.h
deleted file mode 100644 (file)
index 2bbf815..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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.
- */
-
-/* TODO: Retest the driver with errors expressed as negatives */
-
-/* Result codes */
-#define SAA_OK                         0
-#define SAA_ERR_BAD_PARAMETER          0x09
-#define SAA_ERR_NO_RESOURCES           0x0c
-#define SAA_ERR_NOT_SUPPORTED          0x13
-#define SAA_ERR_BUSY                   0x15
-#define SAA_ERR_READ                   0x17
-#define SAA_ERR_TIMEOUT                        0x1f
-#define SAA_ERR_OVERFLOW               0x20
-#define SAA_ERR_EMPTY                  0x22
-#define SAA_ERR_NOT_STARTED            0x23
-#define SAA_ERR_ALREADY_STARTED                0x24
-#define SAA_ERR_NOT_STOPPED            0x25
-#define SAA_ERR_ALREADY_STOPPED                0x26
-#define SAA_ERR_INVALID_COMMAND                0x3e
-#define SAA_ERR_NULL_PACKET            0x59
-
-/* Errors and flags from the silicon */
-#define PVC_ERRORCODE_UNKNOWN          0x00
-#define PVC_ERRORCODE_INVALID_COMMAND  0x01
-#define PVC_ERRORCODE_INVALID_CONTROL  0x02
-#define PVC_ERRORCODE_INVALID_DATA     0x03
-#define PVC_ERRORCODE_TIMEOUT          0x04
-#define PVC_ERRORCODE_NAK              0x05
-#define PVC_RESPONSEFLAG_ERROR         0x01
-#define PVC_RESPONSEFLAG_OVERFLOW      0x02
-#define PVC_RESPONSEFLAG_RESET         0x04
-#define PVC_RESPONSEFLAG_INTERFACE     0x08
-#define PVC_RESPONSEFLAG_CONTINUED     0x10
-#define PVC_CMDFLAG_INTERRUPT          0x02
-#define PVC_CMDFLAG_INTERFACE          0x04
-#define PVC_CMDFLAG_SERIALIZE          0x08
-#define PVC_CMDFLAG_CONTINUE           0x10
-
-/* Silicon Commands */
-#define GET_DESCRIPTORS_CONTROL                0x01
-#define GET_STRING_CONTROL             0x03
-#define GET_LANGUAGE_CONTROL           0x05
-#define SET_POWER_CONTROL              0x07
-#define GET_FW_STATUS_CONTROL          0x08
-#define GET_FW_VERSION_CONTROL         0x09
-#define SET_DEBUG_LEVEL_CONTROL                0x0B
-#define GET_DEBUG_DATA_CONTROL         0x0C
-#define GET_PRODUCTION_INFO_CONTROL    0x0D
-
-/* cmd defines */
-#define SAA_CMDFLAG_CONTINUE           0x10
-#define SAA_CMD_MAX_MSG_UNITS          256
-
-/* Some defines */
-#define SAA_BUS_TIMEOUT                        50
-#define SAA_DEVICE_TIMEOUT             5000
-#define SAA_DEVICE_MAXREQUESTSIZE      256
-
-/* Register addresses */
-#define SAA_DEVICE_VERSION             0x30
-#define SAA_DOWNLOAD_FLAGS             0x34
-#define SAA_DOWNLOAD_FLAG              0x34
-#define SAA_DOWNLOAD_FLAG_ACK          0x38
-#define SAA_DATAREADY_FLAG             0x3C
-#define SAA_DATAREADY_FLAG_ACK         0x40
-
-/* Boot loader register and bit definitions */
-#define SAA_BOOTLOADERERROR_FLAGS      0x44
-#define SAA_DEVICE_IMAGE_SEARCHING     0x01
-#define SAA_DEVICE_IMAGE_LOADING       0x02
-#define SAA_DEVICE_IMAGE_BOOTING       0x03
-#define SAA_DEVICE_IMAGE_CORRUPT       0x04
-#define SAA_DEVICE_MEMORY_CORRUPT      0x08
-#define SAA_DEVICE_NO_IMAGE            0x10
-
-/* Register addresses */
-#define SAA_DEVICE_2ND_VERSION                 0x50
-#define SAA_DEVICE_2ND_DOWNLOADFLAG_OFFSET     0x54
-
-/* Register addresses */
-#define SAA_SECONDSTAGEERROR_FLAGS             0x64
-
-/* Bootloader regs and flags */
-#define SAA_DEVICE_DEADLOCK_DETECTED_OFFSET    0x6C
-#define SAA_DEVICE_DEADLOCK_DETECTED           0xDEADDEAD
-
-/* Basic firmware status registers */
-#define SAA_DEVICE_SYSINIT_STATUS_OFFSET       0x70
-#define SAA_DEVICE_SYSINIT_STATUS              0x70
-#define SAA_DEVICE_SYSINIT_MODE                        0x74
-#define SAA_DEVICE_SYSINIT_SPEC                        0x78
-#define SAA_DEVICE_SYSINIT_INST                        0x7C
-#define SAA_DEVICE_SYSINIT_CPULOAD             0x80
-#define SAA_DEVICE_SYSINIT_REMAINHEAP          0x84
-
-#define SAA_DEVICE_DOWNLOAD_OFFSET             0x1000
-#define SAA_DEVICE_BUFFERBLOCKSIZE             0x1000
-
-#define SAA_DEVICE_2ND_BUFFERBLOCKSIZE         0x100000
-#define SAA_DEVICE_2ND_DOWNLOAD_OFFSET         0x200000
-
-/* Descriptors */
-#define CS_INTERFACE   0x24
-
-/* Descriptor subtypes */
-#define VC_INPUT_TERMINAL              0x02
-#define VC_OUTPUT_TERMINAL             0x03
-#define VC_SELECTOR_UNIT               0x04
-#define VC_PROCESSING_UNIT             0x05
-#define FEATURE_UNIT                   0x06
-#define TUNER_UNIT                     0x09
-#define ENCODER_UNIT                   0x0A
-#define EXTENSION_UNIT                 0x0B
-#define VC_TUNER_PATH                  0xF0
-#define PVC_HARDWARE_DESCRIPTOR                0xF1
-#define PVC_INTERFACE_DESCRIPTOR       0xF2
-#define PVC_INFRARED_UNIT              0xF3
-#define DRM_UNIT                       0xF4
-#define GENERAL_REQUEST                        0xF5
-
-/* Format Types */
-#define VS_FORMAT_TYPE         0x02
-#define VS_FORMAT_TYPE_I       0x01
-#define VS_FORMAT_UNCOMPRESSED 0x04
-#define VS_FRAME_UNCOMPRESSED  0x05
-#define VS_FORMAT_MPEG2PS      0x09
-#define VS_FORMAT_MPEG2TS      0x0A
-#define VS_FORMAT_MPEG4SL      0x0B
-#define VS_FORMAT_WM9          0x0C
-#define VS_FORMAT_DIVX         0x0D
-#define VS_FORMAT_VBI          0x0E
-#define VS_FORMAT_RDS          0x0F
-
-/* Device extension commands */
-#define EXU_REGISTER_ACCESS_CONTROL    0x00
-#define EXU_GPIO_CONTROL               0x01
-#define EXU_GPIO_GROUP_CONTROL         0x02
-#define EXU_INTERRUPT_CONTROL          0x03
-
-/* State Transition and args */
-#define SAA_PROBE_CONTROL      0x01
-#define SAA_COMMIT_CONTROL     0x02
-#define SAA_STATE_CONTROL      0x03
-#define SAA_DMASTATE_STOP      0x00
-#define SAA_DMASTATE_ACQUIRE   0x01
-#define SAA_DMASTATE_PAUSE     0x02
-#define SAA_DMASTATE_RUN       0x03
-
-/* A/V Mux Input Selector */
-#define SU_INPUT_SELECT_CONTROL 0x01
-
-/* Encoder Profiles */
-#define EU_PROFILE_PS_DVD      0x06
-#define EU_PROFILE_TS_HQ       0x09
-#define EU_VIDEO_FORMAT_MPEG_2 0x02
-
-/* Tuner */
-#define TU_AUDIO_MODE_CONTROL  0x17
-
-/* Video Formats */
-#define TU_STANDARD_CONTROL            0x00
-#define TU_STANDARD_AUTO_CONTROL       0x01
-#define TU_STANDARD_NONE               0x00
-#define TU_STANDARD_NTSC_M             0x01
-#define TU_STANDARD_PAL_I              0x08
-#define TU_STANDARD_MANUAL             0x00
-#define TU_STANDARD_AUTO               0x01
-
-/* Video Controls */
-#define PU_BRIGHTNESS_CONTROL  0x02
-#define PU_CONTRAST_CONTROL    0x03
-#define PU_HUE_CONTROL         0x06
-#define PU_SATURATION_CONTROL  0x07
-#define PU_SHARPNESS_CONTROL   0x08
-
-/* Audio Controls */
-#define MUTE_CONTROL           0x01
-#define VOLUME_CONTROL         0x02
-#define AUDIO_DEFAULT_CONTROL  0x0D
-
-/* Default Volume Levels */
-#define TMHW_LEV_ADJ_DECLEV_DEFAULT     0x00
-#define TMHW_LEV_ADJ_MONOLEV_DEFAULT    0x00
-#define TMHW_LEV_ADJ_NICLEV_DEFAULT     0x00
-#define TMHW_LEV_ADJ_SAPLEV_DEFAULT     0x00
-#define TMHW_LEV_ADJ_ADCLEV_DEFAULT     0x00
-
-/* Encoder Related Commands */
-#define EU_PROFILE_CONTROL             0x00
-#define EU_VIDEO_FORMAT_CONTROL                0x01
-#define EU_VIDEO_BIT_RATE_CONTROL      0x02
-#define EU_VIDEO_RESOLUTION_CONTROL    0x03
-#define EU_VIDEO_GOP_STRUCTURE_CONTROL 0x04
-#define EU_VIDEO_INPUT_ASPECT_CONTROL  0x0A
-#define EU_AUDIO_FORMAT_CONTROL                0x0C
-#define EU_AUDIO_BIT_RATE_CONTROL      0x0D
-
-/* Firmware Debugging */
-#define SET_DEBUG_LEVEL_CONTROL        0x0B
-#define GET_DEBUG_DATA_CONTROL 0x0C
diff --git a/drivers/media/video/saa7164/saa7164-types.h b/drivers/media/video/saa7164/saa7164-types.h
deleted file mode 100644 (file)
index 1d2140a..0000000
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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.
- */
-
-/* TODO: Cleanup and shorten the namespace */
-
-/* Some structues are passed directly to/from the firmware and
- * have strict alignment requirements. This is one of them.
- */
-struct tmComResHWDescr {
-       u8      bLength;
-       u8      bDescriptorType;
-       u8      bDescriptorSubtype;
-       u16     bcdSpecVersion;
-       u32     dwClockFrequency;
-       u32     dwClockUpdateRes;
-       u8      bCapabilities;
-       u32     dwDeviceRegistersLocation;
-       u32     dwHostMemoryRegion;
-       u32     dwHostMemoryRegionSize;
-       u32     dwHostHibernatMemRegion;
-       u32     dwHostHibernatMemRegionSize;
-} __attribute__((packed));
-
-/* This is DWORD aligned on windows but I can't find the right
- * gcc syntax to match the binary data from the device.
- * I've manually padded with Reserved[3] bytes to match the hardware,
- * but this could break if GCC decies to pack in a different way.
- */
-struct tmComResInterfaceDescr {
-       u8      bLength;
-       u8      bDescriptorType;
-       u8      bDescriptorSubtype;
-       u8      bFlags;
-       u8      bInterfaceType;
-       u8      bInterfaceId;
-       u8      bBaseInterface;
-       u8      bInterruptId;
-       u8      bDebugInterruptId;
-       u8      BARLocation;
-       u8      Reserved[3];
-};
-
-struct tmComResBusDescr {
-       u64     CommandRing;
-       u64     ResponseRing;
-       u32     CommandWrite;
-       u32     CommandRead;
-       u32     ResponseWrite;
-       u32     ResponseRead;
-};
-
-enum tmBusType {
-       NONE            = 0,
-       TYPE_BUS_PCI    = 1,
-       TYPE_BUS_PCIe   = 2,
-       TYPE_BUS_USB    = 3,
-       TYPE_BUS_I2C    = 4
-};
-
-struct tmComResBusInfo {
-       enum tmBusType Type;
-       u16     m_wMaxReqSize;
-       u8      *m_pdwSetRing;
-       u32     m_dwSizeSetRing;
-       u8      *m_pdwGetRing;
-       u32     m_dwSizeGetRing;
-       u32     m_dwSetWritePos;
-       u32     m_dwSetReadPos;
-       u32     m_dwGetWritePos;
-       u32     m_dwGetReadPos;
-
-       /* All access is protected */
-       struct mutex lock;
-
-};
-
-struct tmComResInfo {
-       u8      id;
-       u8      flags;
-       u16     size;
-       u32     command;
-       u16     controlselector;
-       u8      seqno;
-} __attribute__((packed));
-
-enum tmComResCmd {
-       SET_CUR  = 0x01,
-       GET_CUR  = 0x81,
-       GET_MIN  = 0x82,
-       GET_MAX  = 0x83,
-       GET_RES  = 0x84,
-       GET_LEN  = 0x85,
-       GET_INFO = 0x86,
-       GET_DEF  = 0x87
-};
-
-struct cmd {
-       u8 seqno;
-       u32 inuse;
-       u32 timeout;
-       u32 signalled;
-       struct mutex lock;
-       wait_queue_head_t wait;
-};
-
-struct tmDescriptor {
-       u32     pathid;
-       u32     size;
-       void    *descriptor;
-};
-
-struct tmComResDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-} __attribute__((packed));
-
-struct tmComResExtDevDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-       u32     devicetype;
-       u16     deviceid;
-       u32     numgpiopins;
-       u8      numgpiogroups;
-       u8      controlsize;
-} __attribute__((packed));
-
-struct tmComResGPIO {
-       u32     pin;
-       u8      state;
-} __attribute__((packed));
-
-struct tmComResPathDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      pathid;
-} __attribute__((packed));
-
-/* terminaltype */
-enum tmComResTermType {
-       ITT_ANTENNA              = 0x0203,
-       LINE_CONNECTOR           = 0x0603,
-       SPDIF_CONNECTOR          = 0x0605,
-       COMPOSITE_CONNECTOR      = 0x0401,
-       SVIDEO_CONNECTOR         = 0x0402,
-       COMPONENT_CONNECTOR      = 0x0403,
-       STANDARD_DMA             = 0xF101
-};
-
-struct tmComResAntTermDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      terminalid;
-       u16     terminaltype;
-       u8      assocterminal;
-       u8      iterminal;
-       u8      controlsize;
-} __attribute__((packed));
-
-struct tmComResTunerDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-       u8      sourceid;
-       u8      iunit;
-       u32     tuningstandards;
-       u8      controlsize;
-       u32     controls;
-} __attribute__((packed));
-
-enum tmBufferFlag {
-       /* the buffer does not contain any valid data */
-       TM_BUFFER_FLAG_EMPTY,
-
-       /* the buffer is filled with valid data */
-       TM_BUFFER_FLAG_DONE,
-
-       /* the buffer is the dummy buffer - TODO??? */
-       TM_BUFFER_FLAG_DUMMY_BUFFER
-};
-
-struct tmBuffer {
-       u64             *pagetablevirt;
-       u64             pagetablephys;
-       u16             offset;
-       u8              *context;
-       u64             timestamp;
-       enum tmBufferFlag BufferFlag;
-       u32             lostbuffers;
-       u32             validbuffers;
-       u64             *dummypagevirt;
-       u64             dummypagephys;
-       u64             *addressvirt;
-};
-
-struct tmHWStreamParameters {
-       u32     bitspersample;
-       u32     samplesperline;
-       u32     numberoflines;
-       u32     pitch;
-       u32     linethreshold;
-       u64     **pagetablelistvirt;
-       u64     *pagetablelistphys;
-       u32     numpagetables;
-       u32     numpagetableentries;
-};
-
-struct tmStreamParameters {
-       struct tmHWStreamParameters     HWStreamParameters;
-       u64                             qwDummyPageTablePhys;
-       u64                             *pDummyPageTableVirt;
-};
-
-struct tmComResDMATermDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtyle;
-       u8      unitid;
-       u16     terminaltype;
-       u8      assocterminal;
-       u8      sourceid;
-       u8      iterminal;
-       u32     BARLocation;
-       u8      flags;
-       u8      interruptid;
-       u8      buffercount;
-       u8      metadatasize;
-       u8      numformats;
-       u8      controlsize;
-} __attribute__((packed));
-
-/*
- *
- * Description:
- *  This is the transport stream format header.
- *
- * Settings:
- *  bLength                 - The size of this descriptor in bytes.
- *  bDescriptorType         - CS_INTERFACE.
- *  bDescriptorSubtype      - VS_FORMAT_MPEG2TS descriptor subtype.
- *  bFormatIndex            - A non-zero constant that uniquely identifies the
- *                            format.
- *  bDataOffset             - Offset to TSP packet within MPEG-2 TS transport
- *                            stride, in bytes.
- *  bPacketLength           - Length of TSP packet, in bytes (typically 188).
- *  bStrideLength           - Length of MPEG-2 TS transport stride.
- *  guidStrideFormat        - A Globally Unique Identifier indicating the
- *                            format of the stride data (if any). Set to zeros
- *                            if there is no Stride Data, or if the Stride
- *                            Data is to be ignored by the application.
- *
- */
-struct tmComResTSFormatDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      bFormatIndex;
-       u8      bDataOffset;
-       u8      bPacketLength;
-       u8      bStrideLength;
-       u8      guidStrideFormat[16];
-} __attribute__((packed));
-
-/* Encoder related structures */
-
-/* A/V Mux Selector */
-struct tmComResSelDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-       u8      nrinpins;
-       u8      sourceid;
-} __attribute__((packed));
-
-/* A/V Audio processor definitions */
-struct tmComResProcDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-       u8      sourceid;
-       u16     wreserved;
-       u8      controlsize;
-} __attribute__((packed));
-
-/* Video bitrate control message */
-#define EU_VIDEO_BIT_RATE_MODE_CONSTANT                (0)
-#define EU_VIDEO_BIT_RATE_MODE_VARIABLE_AVERAGE (1)
-#define EU_VIDEO_BIT_RATE_MODE_VARIABLE_PEAK   (2)
-struct tmComResEncVideoBitRate {
-       u8      ucVideoBitRateMode;
-       u32     dwVideoBitRate;
-       u32     dwVideoBitRatePeak;
-} __attribute__((packed));
-
-/* Video Encoder Aspect Ratio message */
-struct tmComResEncVideoInputAspectRatio {
-       u8      width;
-       u8      height;
-} __attribute__((packed));
-
-/* Video Encoder GOP IBP message */
-/* 1. IPPPPPPPPPPPPPP */
-/* 2. IBPBPBPBPBPBPBP */
-/* 3. IBBPBBPBBPBBP   */
-#define SAA7164_ENCODER_DEFAULT_GOP_DIST (1)
-#define SAA7164_ENCODER_DEFAULT_GOP_SIZE (15)
-struct tmComResEncVideoGopStructure {
-       u8      ucGOPSize;      /* GOP Size 12, 15 */
-       u8      ucRefFrameDist; /* Reference Frame Distance */
-} __attribute__((packed));
-
-/* Encoder processor definition */
-struct tmComResEncoderDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-       u8      vsourceid;
-       u8      asourceid;
-       u8      iunit;
-       u32     dwmControlCap;
-       u32     dwmProfileCap;
-       u32     dwmVidFormatCap;
-       u8      bmVidBitrateCap;
-       u16     wmVidResolutionsCap;
-       u16     wmVidFrmRateCap;
-       u32     dwmAudFormatCap;
-       u8      bmAudBitrateCap;
-} __attribute__((packed));
-
-/* Audio processor definition */
-struct tmComResAFeatureDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      unitid;
-       u8      sourceid;
-       u8      controlsize;
-} __attribute__((packed));
-
-/* Audio control messages */
-struct tmComResAudioDefaults {
-       u8      ucDecoderLevel;
-       u8      ucDecoderFM_Level;
-       u8      ucMonoLevel;
-       u8      ucNICAM_Level;
-       u8      ucSAP_Level;
-       u8      ucADC_Level;
-} __attribute__((packed));
-
-/* Audio bitrate control message */
-struct tmComResEncAudioBitRate {
-       u8      ucAudioBitRateMode;
-       u32     dwAudioBitRate;
-       u32     dwAudioBitRatePeak;
-} __attribute__((packed));
-
-/* Tuner / AV Decoder messages */
-struct tmComResTunerStandard {
-       u8      std;
-       u32     country;
-} __attribute__((packed));
-
-struct tmComResTunerStandardAuto {
-       u8      mode;
-} __attribute__((packed));
-
-/* EEPROM definition for PS stream types */
-struct tmComResPSFormatDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype;
-       u8      bFormatIndex;
-       u16     wPacketLength;
-       u16     wPackLength;
-       u8      bPackDataType;
-} __attribute__((packed));
-
-/* VBI control structure */
-struct tmComResVBIFormatDescrHeader {
-       u8      len;
-       u8      type;
-       u8      subtype; /* VS_FORMAT_VBI */
-       u8      bFormatIndex;
-       u32     VideoStandard; /* See KS_AnalogVideoStandard, NTSC = 1 */
-       u8      StartLine; /* NTSC Start = 10 */
-       u8      EndLine; /* NTSC = 21 */
-       u8      FieldRate; /* 60 for NTSC */
-       u8      bNumLines; /* Unused - scheduled for removal */
-} __attribute__((packed));
-
-struct tmComResProbeCommit {
-       u16     bmHint;
-       u8      bFormatIndex;
-       u8      bFrameIndex;
-} __attribute__((packed));
-
-struct tmComResDebugSetLevel {
-       u32     dwDebugLevel;
-} __attribute__((packed));
-
-struct tmComResDebugGetData {
-       u32     dwResult;
-       u8      ucDebugData[256];
-} __attribute__((packed));
-
-struct tmFwInfoStruct {
-       u32     status;
-       u32     mode;
-       u32     devicespec;
-       u32     deviceinst;
-       u32     CPULoad;
-       u32     RemainHeap;
-       u32     CPUClock;
-       u32     RAMSpeed;
-} __attribute__((packed));
diff --git a/drivers/media/video/saa7164/saa7164-vbi.c b/drivers/media/video/saa7164/saa7164-vbi.c
deleted file mode 100644 (file)
index d8e6c8f..0000000
+++ /dev/null
@@ -1,1374 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 "saa7164.h"
-
-static struct saa7164_tvnorm saa7164_tvnorms[] = {
-       {
-               .name      = "NTSC-M",
-               .id        = V4L2_STD_NTSC_M,
-       }, {
-               .name      = "NTSC-JP",
-               .id        = V4L2_STD_NTSC_M_JP,
-       }
-};
-
-static const u32 saa7164_v4l2_ctrls[] = {
-       0
-};
-
-/* Take the encoder configuration from the port struct and
- * flush it to the hardware.
- */
-static void saa7164_vbi_configure(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       dprintk(DBGLVL_VBI, "%s()\n", __func__);
-
-       port->vbi_params.width = port->width;
-       port->vbi_params.height = port->height;
-       port->vbi_params.is_50hz =
-               (port->encodernorm.id & V4L2_STD_625_50) != 0;
-
-       /* Set up the DIF (enable it) for analog mode by default */
-       saa7164_api_initialize_dif(port);
-
-       /* Configure the correct video standard */
-#if 0
-       saa7164_api_configure_dif(port, port->encodernorm.id);
-#endif
-
-#if 0
-       /* Ensure the audio decoder is correct configured */
-       saa7164_api_set_audio_std(port);
-#endif
-       dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
-}
-
-static int saa7164_vbi_buffers_dealloc(struct saa7164_port *port)
-{
-       struct list_head *c, *n, *p, *q, *l, *v;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct saa7164_user_buffer *ubuf;
-
-       /* Remove any allocated buffers */
-       mutex_lock(&port->dmaqueue_lock);
-
-       dprintk(DBGLVL_VBI, "%s(port=%d) dmaqueue\n", __func__, port->nr);
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               buf = list_entry(c, struct saa7164_buffer, list);
-               list_del(c);
-               saa7164_buffer_dealloc(buf);
-       }
-
-       dprintk(DBGLVL_VBI, "%s(port=%d) used\n", __func__, port->nr);
-       list_for_each_safe(p, q, &port->list_buf_used.list) {
-               ubuf = list_entry(p, struct saa7164_user_buffer, list);
-               list_del(p);
-               saa7164_buffer_dealloc_user(ubuf);
-       }
-
-       dprintk(DBGLVL_VBI, "%s(port=%d) free\n", __func__, port->nr);
-       list_for_each_safe(l, v, &port->list_buf_free.list) {
-               ubuf = list_entry(l, struct saa7164_user_buffer, list);
-               list_del(l);
-               saa7164_buffer_dealloc_user(ubuf);
-       }
-
-       mutex_unlock(&port->dmaqueue_lock);
-       dprintk(DBGLVL_VBI, "%s(port=%d) done\n", __func__, port->nr);
-
-       return 0;
-}
-
-/* Dynamic buffer switch at vbi start time */
-static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct saa7164_user_buffer *ubuf;
-       struct tmHWStreamParameters *params = &port->hw_streamingparams;
-       int result = -ENODEV, i;
-       int len = 0;
-
-       dprintk(DBGLVL_VBI, "%s()\n", __func__);
-
-       /* TODO: NTSC SPECIFIC */
-       /* Init and establish defaults */
-       params->samplesperline = 1440;
-       params->numberoflines = 12;
-       params->numberoflines = 18;
-       params->pitch = 1600;
-       params->pitch = 1440;
-       params->numpagetables = 2 +
-               ((params->numberoflines * params->pitch) / PAGE_SIZE);
-       params->bitspersample = 8;
-       params->linethreshold = 0;
-       params->pagetablelistvirt = NULL;
-       params->pagetablelistphys = NULL;
-       params->numpagetableentries = port->hwcfg.buffercount;
-
-       /* Allocate the PCI resources, buffers (hard) */
-       for (i = 0; i < port->hwcfg.buffercount; i++) {
-               buf = saa7164_buffer_alloc(port,
-                       params->numberoflines *
-                       params->pitch);
-
-               if (!buf) {
-                       printk(KERN_ERR "%s() failed "
-                              "(errno = %d), unable to allocate buffer\n",
-                               __func__, result);
-                       result = -ENOMEM;
-                       goto failed;
-               } else {
-
-                       mutex_lock(&port->dmaqueue_lock);
-                       list_add_tail(&buf->list, &port->dmaqueue.list);
-                       mutex_unlock(&port->dmaqueue_lock);
-
-               }
-       }
-
-       /* Allocate some kernel buffers for copying
-        * to userpsace.
-        */
-       len = params->numberoflines * params->pitch;
-
-       if (vbi_buffers < 16)
-               vbi_buffers = 16;
-       if (vbi_buffers > 512)
-               vbi_buffers = 512;
-
-       for (i = 0; i < vbi_buffers; i++) {
-
-               ubuf = saa7164_buffer_alloc_user(dev, len);
-               if (ubuf) {
-                       mutex_lock(&port->dmaqueue_lock);
-                       list_add_tail(&ubuf->list, &port->list_buf_free.list);
-                       mutex_unlock(&port->dmaqueue_lock);
-               }
-
-       }
-
-       result = 0;
-
-failed:
-       return result;
-}
-
-
-static int saa7164_vbi_initialize(struct saa7164_port *port)
-{
-       saa7164_vbi_configure(port);
-       return 0;
-}
-
-/* -- V4L2 --------------------------------------------------------- */
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-       unsigned int i;
-
-       dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)*id);
-
-       for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
-               if (*id & saa7164_tvnorms[i].id)
-                       break;
-       }
-       if (i == ARRAY_SIZE(saa7164_tvnorms))
-               return -EINVAL;
-
-       port->encodernorm = saa7164_tvnorms[i];
-
-       /* Update the audio decoder while is not running in
-        * auto detect mode.
-        */
-       saa7164_api_set_audio_std(port);
-
-       dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)*id);
-
-       return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-       struct v4l2_input *i)
-{
-       int n;
-
-       char *inputs[] = { "tuner", "composite", "svideo", "aux",
-               "composite 2", "svideo 2", "aux 2" };
-
-       if (i->index >= 7)
-               return -EINVAL;
-
-       strcpy(i->name, inputs[i->index]);
-
-       if (i->index == 0)
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       else
-               i->type  = V4L2_INPUT_TYPE_CAMERA;
-
-       for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
-               i->std |= saa7164_tvnorms[n].id;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       if (saa7164_api_get_videomux(port) != SAA_OK)
-               return -EIO;
-
-       *i = (port->mux_input - 1);
-
-       dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i);
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i);
-
-       if (i >= 7)
-               return -EINVAL;
-
-       port->mux_input = i + 1;
-
-       if (saa7164_api_set_videomux(port) != SAA_OK)
-               return -EIO;
-
-       return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-       struct v4l2_tuner *t)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "tuner");
-       t->type = V4L2_TUNER_ANALOG_TV;
-       t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
-
-       dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-       struct v4l2_tuner *t)
-{
-       /* Update the A/V core */
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-
-       f->type = V4L2_TUNER_ANALOG_TV;
-       f->frequency = port->freq;
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-       struct v4l2_frequency *f)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_port *tsport;
-       struct dvb_frontend *fe;
-
-       /* TODO: Pull this for the std */
-       struct analog_parameters params = {
-               .mode      = V4L2_TUNER_ANALOG_TV,
-               .audmode   = V4L2_TUNER_MODE_STEREO,
-               .std       = port->encodernorm.id,
-               .frequency = f->frequency
-       };
-
-       /* Stop the encoder */
-       dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__,
-               f->frequency, f->tuner);
-
-       if (f->tuner != 0)
-               return -EINVAL;
-
-       if (f->type != V4L2_TUNER_ANALOG_TV)
-               return -EINVAL;
-
-       port->freq = f->frequency;
-
-       /* Update the hardware */
-       if (port->nr == SAA7164_PORT_VBI1)
-               tsport = &dev->ports[SAA7164_PORT_TS1];
-       else
-       if (port->nr == SAA7164_PORT_VBI2)
-               tsport = &dev->ports[SAA7164_PORT_TS2];
-       else
-               BUG();
-
-       fe = tsport->dvb.frontend;
-
-       if (fe && fe->ops.tuner_ops.set_analog_params)
-               fe->ops.tuner_ops.set_analog_params(fe, &params);
-       else
-               printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
-
-       saa7164_vbi_initialize(port);
-
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-       struct v4l2_control *ctl)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
-               ctl->id, ctl->value);
-
-       switch (ctl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               ctl->value = port->ctl_brightness;
-               break;
-       case V4L2_CID_CONTRAST:
-               ctl->value = port->ctl_contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               ctl->value = port->ctl_saturation;
-               break;
-       case V4L2_CID_HUE:
-               ctl->value = port->ctl_hue;
-               break;
-       case V4L2_CID_SHARPNESS:
-               ctl->value = port->ctl_sharpness;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               ctl->value = port->ctl_volume;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-       struct v4l2_control *ctl)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-
-       dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
-               ctl->id, ctl->value);
-
-       switch (ctl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_brightness = ctl->value;
-                       saa7164_api_set_usercontrol(port,
-                               PU_BRIGHTNESS_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_CONTRAST:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_contrast = ctl->value;
-                       saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_SATURATION:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_saturation = ctl->value;
-                       saa7164_api_set_usercontrol(port,
-                               PU_SATURATION_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_HUE:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_hue = ctl->value;
-                       saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_SHARPNESS:
-               if ((ctl->value >= 0) && (ctl->value <= 255)) {
-                       port->ctl_sharpness = ctl->value;
-                       saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
-               } else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               if ((ctl->value >= -83) && (ctl->value <= 24)) {
-                       port->ctl_volume = ctl->value;
-                       saa7164_api_set_audio_volume(port, port->ctl_volume);
-               } else
-                       ret = -EINVAL;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static int saa7164_get_ctrl(struct saa7164_port *port,
-       struct v4l2_ext_control *ctrl)
-{
-       struct saa7164_vbi_params *params = &port->vbi_params;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               ctrl->value = params->stream_type;
-               break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               ctrl->value = params->ctl_mute;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               ctrl->value = params->ctl_aspect;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               ctrl->value = params->refdist;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               ctrl->value = params->gop_size;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-       struct v4l2_ext_controls *ctrls)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = saa7164_get_ctrl(port, ctrl);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-
-       }
-
-       return -EINVAL;
-}
-
-static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
-       int ret = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
-                       (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               if ((ctrl->value >= 0) &&
-                       (ctrl->value <= 1))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
-                       (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               if ((ctrl->value >= 0) &&
-                       (ctrl->value <= 255))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               if ((ctrl->value >= 1) &&
-                       (ctrl->value <= 3))
-                       ret = 0;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-       struct v4l2_ext_controls *ctrls)
-{
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = saa7164_try_ctrl(ctrl, 0);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-       }
-
-       return -EINVAL;
-}
-
-static int saa7164_set_ctrl(struct saa7164_port *port,
-       struct v4l2_ext_control *ctrl)
-{
-       struct saa7164_vbi_params *params = &port->vbi_params;
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               params->stream_type = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               params->ctl_mute = ctrl->value;
-               ret = saa7164_api_audio_mute(port, params->ctl_mute);
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
-                               ret);
-                       ret = -EIO;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               params->ctl_aspect = ctrl->value;
-               ret = saa7164_api_set_aspect_ratio(port);
-               if (ret != SAA_OK) {
-                       printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
-                               ret);
-                       ret = -EIO;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               params->refdist = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               params->gop_size = ctrl->value;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* TODO: Update the hardware */
-
-       return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-       struct v4l2_ext_controls *ctrls)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = saa7164_try_ctrl(ctrl, 0);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-                       err = saa7164_set_ctrl(port, ctrl);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-       struct v4l2_capability *cap)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       strcpy(cap->driver, dev->name);
-       strlcpy(cap->card, saa7164_boards[dev->board].name,
-               sizeof(cap->card));
-       sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
-
-       cap->capabilities =
-               V4L2_CAP_VBI_CAPTURE |
-               V4L2_CAP_READWRITE     |
-               0;
-
-       cap->capabilities |= V4L2_CAP_TUNER;
-       cap->version = 0;
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-       struct v4l2_fmtdesc *f)
-{
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, "VBI", sizeof(f->description));
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               port->ts_packet_size * port->ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-       f->fmt.pix.width        = port->width;
-       f->fmt.pix.height       = port->height;
-
-       dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n",
-               port->width, port->height);
-
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               port->ts_packet_size * port->ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-       dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
-               port->width, port->height);
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               port->ts_packet_size * port->ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-
-       dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
-               f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
-
-       return 0;
-}
-
-static int fill_queryctrl(struct saa7164_vbi_params *params,
-       struct v4l2_queryctrl *c)
-{
-       switch (c->id) {
-       case V4L2_CID_BRIGHTNESS:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
-       case V4L2_CID_CONTRAST:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
-       case V4L2_CID_SATURATION:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
-       case V4L2_CID_HUE:
-               return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
-       case V4L2_CID_SHARPNESS:
-               return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
-       case V4L2_CID_MPEG_AUDIO_MUTE:
-               return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
-       case V4L2_CID_AUDIO_VOLUME:
-               return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               return v4l2_ctrl_query_fill(c,
-                       V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
-                       V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
-                       1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
-       case V4L2_CID_MPEG_VIDEO_ASPECT:
-               return v4l2_ctrl_query_fill(c,
-                       V4L2_MPEG_VIDEO_ASPECT_1x1,
-                       V4L2_MPEG_VIDEO_ASPECT_221x100,
-                       1, V4L2_MPEG_VIDEO_ASPECT_4x3);
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               return v4l2_ctrl_query_fill(c,
-                       1, 3, 1, 1);
-       default:
-               return -EINVAL;
-       }
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-       struct v4l2_queryctrl *c)
-{
-       struct saa7164_vbi_fh *fh = priv;
-       struct saa7164_port *port = fh->port;
-       int i, next;
-       u32 id = c->id;
-
-       memset(c, 0, sizeof(*c));
-
-       next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
-       c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
-       for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
-               if (next) {
-                       if (c->id < saa7164_v4l2_ctrls[i])
-                               c->id = saa7164_v4l2_ctrls[i];
-                       else
-                               continue;
-               }
-
-               if (c->id == saa7164_v4l2_ctrls[i])
-                       return fill_queryctrl(&port->vbi_params, c);
-
-               if (c->id < saa7164_v4l2_ctrls[i])
-                       break;
-       }
-
-       return -EINVAL;
-}
-
-static int saa7164_vbi_stop_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_VBI, "%s()    Stopped\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int saa7164_vbi_acquire_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-static int saa7164_vbi_pause_port(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int ret;
-
-       ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
-       if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
-                       __func__, ret);
-               ret = -EIO;
-       } else {
-               dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
-               ret = 0;
-       }
-
-       return ret;
-}
-
-/* Firmware is very windows centric, meaning you have to transition
- * the part through AVStream / KS Windows stages, forwards or backwards.
- * States are: stopped, acquired (h/w), paused, started.
- * We have to leave here will all of the soft buffers on the free list,
- * else the cfg_post() func won't have soft buffers to correctly configure.
- */
-static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       struct saa7164_buffer *buf;
-       struct saa7164_user_buffer *ubuf;
-       struct list_head *c, *n;
-       int ret;
-
-       dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
-
-       ret = saa7164_vbi_pause_port(port);
-       ret = saa7164_vbi_acquire_port(port);
-       ret = saa7164_vbi_stop_port(port);
-
-       dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
-               port->nr);
-
-       /* Reset the state of any allocated buffer resources */
-       mutex_lock(&port->dmaqueue_lock);
-
-       /* Reset the hard and soft buffer state */
-       list_for_each_safe(c, n, &port->dmaqueue.list) {
-               buf = list_entry(c, struct saa7164_buffer, list);
-               buf->flags = SAA7164_BUFFER_FREE;
-               buf->pos = 0;
-       }
-
-       list_for_each_safe(c, n, &port->list_buf_used.list) {
-               ubuf = list_entry(c, struct saa7164_user_buffer, list);
-               ubuf->pos = 0;
-               list_move_tail(&ubuf->list, &port->list_buf_free.list);
-       }
-
-       mutex_unlock(&port->dmaqueue_lock);
-
-       /* Free any allocated resources */
-       saa7164_vbi_buffers_dealloc(port);
-
-       dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
-
-       return ret;
-}
-
-static int saa7164_vbi_start_streaming(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int result, ret = 0;
-
-       dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
-
-       port->done_first_interrupt = 0;
-
-       /* allocate all of the PCIe DMA buffer resources on the fly,
-        * allowing switching between TS and PS payloads without
-        * requiring a complete driver reload.
-        */
-       saa7164_vbi_buffers_alloc(port);
-
-       /* Configure the encoder with any cache values */
-#if 0
-       saa7164_api_set_encoder(port);
-       saa7164_api_get_encoder(port);
-#endif
-
-       /* Place the empty buffers on the hardware */
-       saa7164_buffer_cfg_port(port);
-
-       /* Negotiate format */
-       if (saa7164_api_set_vbi_format(port) != SAA_OK) {
-               printk(KERN_ERR "%s() No supported VBI format\n", __func__);
-               ret = -EIO;
-               goto out;
-       }
-
-       /* Acquire the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
-                       __func__, result);
-
-               ret = -EIO;
-               goto out;
-       } else
-               dprintk(DBGLVL_VBI, "%s()   Acquired\n", __func__);
-
-       /* Pause the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
-                               __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_vbi_stop_port(port);
-               if (result != SAA_OK) {
-                       printk(KERN_ERR "%s() pause/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-
-               ret = -EIO;
-               goto out;
-       } else
-               dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
-
-       /* Start the hardware */
-       result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
-       if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-               printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
-                               __func__, result);
-
-               /* Stop the hardware, regardless */
-               result = saa7164_vbi_acquire_port(port);
-               result = saa7164_vbi_stop_port(port);
-               if (result != SAA_OK) {
-                       printk(KERN_ERR "%s() run/forced stop transition "
-                               "failed, res = 0x%x\n", __func__, result);
-               }
-
-               ret = -EIO;
-       } else
-               dprintk(DBGLVL_VBI, "%s()   Running\n", __func__);
-
-out:
-       return ret;
-}
-
-int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       /* ntsc */
-       f->fmt.vbi.samples_per_line = 1600;
-       f->fmt.vbi.samples_per_line = 1440;
-       f->fmt.vbi.sampling_rate = 27000000;
-       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset = 0;
-       f->fmt.vbi.flags = 0;
-       f->fmt.vbi.start[0] = 10;
-       f->fmt.vbi.count[0] = 18;
-       f->fmt.vbi.start[1] = 263 + 10 + 1;
-       f->fmt.vbi.count[1] = 18;
-       return 0;
-}
-
-static int fops_open(struct file *file)
-{
-       struct saa7164_dev *dev;
-       struct saa7164_port *port;
-       struct saa7164_vbi_fh *fh;
-
-       port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
-       if (!port)
-               return -ENODEV;
-
-       dev = port->dev;
-
-       dprintk(DBGLVL_VBI, "%s()\n", __func__);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh)
-               return -ENOMEM;
-
-       file->private_data = fh;
-       fh->port = port;
-
-       return 0;
-}
-
-static int fops_release(struct file *file)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_VBI, "%s()\n", __func__);
-
-       /* Shut device down on last close */
-       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
-               if (atomic_dec_return(&port->v4l_reader_count) == 0) {
-                       /* stop vbi capture then cancel buffers */
-                       saa7164_vbi_stop_streaming(port);
-               }
-       }
-
-       file->private_data = NULL;
-       kfree(fh);
-
-       return 0;
-}
-
-struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
-{
-       struct saa7164_user_buffer *ubuf = NULL;
-       struct saa7164_dev *dev = port->dev;
-       u32 crc;
-
-       mutex_lock(&port->dmaqueue_lock);
-       if (!list_empty(&port->list_buf_used.list)) {
-               ubuf = list_first_entry(&port->list_buf_used.list,
-                       struct saa7164_user_buffer, list);
-
-               if (crc_checking) {
-                       crc = crc32(0, ubuf->data, ubuf->actual_size);
-                       if (crc != ubuf->crc) {
-                               printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
-                                       __func__,
-                                       ubuf, ubuf->crc, crc);
-                       }
-               }
-
-       }
-       mutex_unlock(&port->dmaqueue_lock);
-
-       dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
-
-       return ubuf;
-}
-
-static ssize_t fops_read(struct file *file, char __user *buffer,
-       size_t count, loff_t *pos)
-{
-       struct saa7164_vbi_fh *fh = file->private_data;
-       struct saa7164_port *port = fh->port;
-       struct saa7164_user_buffer *ubuf = NULL;
-       struct saa7164_dev *dev = port->dev;
-       int ret = 0;
-       int rem, cnt;
-       u8 *p;
-
-       port->last_read_msecs_diff = port->last_read_msecs;
-       port->last_read_msecs = jiffies_to_msecs(jiffies);
-       port->last_read_msecs_diff = port->last_read_msecs -
-               port->last_read_msecs_diff;
-
-       saa7164_histogram_update(&port->read_interval,
-               port->last_read_msecs_diff);
-
-       if (*pos) {
-               printk(KERN_ERR "%s() ESPIPE\n", __func__);
-               return -ESPIPE;
-       }
-
-       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
-               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
-
-                       if (saa7164_vbi_initialize(port) < 0) {
-                               printk(KERN_ERR "%s() EINVAL\n", __func__);
-                               return -EINVAL;
-                       }
-
-                       saa7164_vbi_start_streaming(port);
-                       msleep(200);
-               }
-       }
-
-       /* blocking wait for buffer */
-       if ((file->f_flags & O_NONBLOCK) == 0) {
-               if (wait_event_interruptible(port->wait_read,
-                       saa7164_vbi_next_buf(port))) {
-                               printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
-                               return -ERESTARTSYS;
-               }
-       }
-
-       /* Pull the first buffer from the used list */
-       ubuf = saa7164_vbi_next_buf(port);
-
-       while ((count > 0) && ubuf) {
-
-               /* set remaining bytes to copy */
-               rem = ubuf->actual_size - ubuf->pos;
-               cnt = rem > count ? count : rem;
-
-               p = ubuf->data + ubuf->pos;
-
-               dprintk(DBGLVL_VBI,
-                       "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
-                       __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
-
-               if (copy_to_user(buffer, p, cnt)) {
-                       printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
-                       if (!ret) {
-                               printk(KERN_ERR "%s() EFAULT\n", __func__);
-                               ret = -EFAULT;
-                       }
-                       goto err;
-               }
-
-               ubuf->pos += cnt;
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               if (ubuf->pos > ubuf->actual_size)
-                       printk(KERN_ERR "read() pos > actual, huh?\n");
-
-               if (ubuf->pos == ubuf->actual_size) {
-
-                       /* finished with current buffer, take next buffer */
-
-                       /* Requeue the buffer on the free list */
-                       ubuf->pos = 0;
-
-                       mutex_lock(&port->dmaqueue_lock);
-                       list_move_tail(&ubuf->list, &port->list_buf_free.list);
-                       mutex_unlock(&port->dmaqueue_lock);
-
-                       /* Dequeue next */
-                       if ((file->f_flags & O_NONBLOCK) == 0) {
-                               if (wait_event_interruptible(port->wait_read,
-                                       saa7164_vbi_next_buf(port))) {
-                                               break;
-                               }
-                       }
-                       ubuf = saa7164_vbi_next_buf(port);
-               }
-       }
-err:
-       if (!ret && !ubuf) {
-               printk(KERN_ERR "%s() EAGAIN\n", __func__);
-               ret = -EAGAIN;
-       }
-
-       return ret;
-}
-
-static unsigned int fops_poll(struct file *file, poll_table *wait)
-{
-       struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
-       struct saa7164_port *port = fh->port;
-       unsigned int mask = 0;
-
-       port->last_poll_msecs_diff = port->last_poll_msecs;
-       port->last_poll_msecs = jiffies_to_msecs(jiffies);
-       port->last_poll_msecs_diff = port->last_poll_msecs -
-               port->last_poll_msecs_diff;
-
-       saa7164_histogram_update(&port->poll_interval,
-               port->last_poll_msecs_diff);
-
-       if (!video_is_registered(port->v4l_device))
-               return -EIO;
-
-       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
-               if (atomic_inc_return(&port->v4l_reader_count) == 1) {
-                       if (saa7164_vbi_initialize(port) < 0)
-                               return -EINVAL;
-                       saa7164_vbi_start_streaming(port);
-                       msleep(200);
-               }
-       }
-
-       /* blocking wait for buffer */
-       if ((file->f_flags & O_NONBLOCK) == 0) {
-               if (wait_event_interruptible(port->wait_read,
-                       saa7164_vbi_next_buf(port))) {
-                               return -ERESTARTSYS;
-               }
-       }
-
-       /* Pull the first buffer from the used list */
-       if (!list_empty(&port->list_buf_used.list))
-               mask |= POLLIN | POLLRDNORM;
-
-       return mask;
-}
-static const struct v4l2_file_operations vbi_fops = {
-       .owner          = THIS_MODULE,
-       .open           = fops_open,
-       .release        = fops_release,
-       .read           = fops_read,
-       .poll           = fops_poll,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
-       .vidioc_s_std            = vidioc_s_std,
-       .vidioc_enum_input       = vidioc_enum_input,
-       .vidioc_g_input          = vidioc_g_input,
-       .vidioc_s_input          = vidioc_s_input,
-       .vidioc_g_tuner          = vidioc_g_tuner,
-       .vidioc_s_tuner          = vidioc_s_tuner,
-       .vidioc_g_frequency      = vidioc_g_frequency,
-       .vidioc_s_frequency      = vidioc_s_frequency,
-       .vidioc_s_ctrl           = vidioc_s_ctrl,
-       .vidioc_g_ctrl           = vidioc_g_ctrl,
-       .vidioc_querycap         = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
-       .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
-       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
-       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
-       .vidioc_queryctrl        = vidioc_queryctrl,
-#if 0
-       .vidioc_g_chip_ident     = saa7164_g_chip_ident,
-#endif
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-#if 0
-       .vidioc_g_register       = saa7164_g_register,
-       .vidioc_s_register       = saa7164_s_register,
-#endif
-#endif
-       .vidioc_g_fmt_vbi_cap    = saa7164_vbi_fmt,
-       .vidioc_try_fmt_vbi_cap  = saa7164_vbi_fmt,
-       .vidioc_s_fmt_vbi_cap    = saa7164_vbi_fmt,
-};
-
-static struct video_device saa7164_vbi_template = {
-       .name          = "saa7164",
-       .fops          = &vbi_fops,
-       .ioctl_ops     = &vbi_ioctl_ops,
-       .minor         = -1,
-       .tvnorms       = SAA7164_NORMS,
-       .current_norm  = V4L2_STD_NTSC_M,
-};
-
-static struct video_device *saa7164_vbi_alloc(
-       struct saa7164_port *port,
-       struct pci_dev *pci,
-       struct video_device *template,
-       char *type)
-{
-       struct video_device *vfd;
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_VBI, "%s()\n", __func__);
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
-       *vfd = *template;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
-               type, saa7164_boards[dev->board].name);
-
-       vfd->parent  = &pci->dev;
-       vfd->release = video_device_release;
-       return vfd;
-}
-
-int saa7164_vbi_register(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-       int result = -ENODEV;
-
-       dprintk(DBGLVL_VBI, "%s()\n", __func__);
-
-       if (port->type != SAA7164_MPEG_VBI)
-               BUG();
-
-       /* Sanity check that the PCI configuration space is active */
-       if (port->hwcfg.BARLocation == 0) {
-               printk(KERN_ERR "%s() failed "
-                      "(errno = %d), NO PCI configuration\n",
-                       __func__, result);
-               result = -ENOMEM;
-               goto failed;
-       }
-
-       /* Establish VBI defaults here */
-
-       /* Allocate and register the video device node */
-       port->v4l_device = saa7164_vbi_alloc(port,
-               dev->pci, &saa7164_vbi_template, "vbi");
-
-       if (!port->v4l_device) {
-               printk(KERN_INFO "%s: can't allocate vbi device\n",
-                       dev->name);
-               result = -ENOMEM;
-               goto failed;
-       }
-
-       video_set_drvdata(port->v4l_device, port);
-       result = video_register_device(port->v4l_device,
-               VFL_TYPE_VBI, -1);
-       if (result < 0) {
-               printk(KERN_INFO "%s: can't register vbi device\n",
-                       dev->name);
-               /* TODO: We're going to leak here if we don't dealloc
-                The buffers above. The unreg function can't deal wit it.
-               */
-               goto failed;
-       }
-
-       printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
-               dev->name, port->v4l_device->num);
-
-       /* Configure the hardware defaults */
-
-       result = 0;
-failed:
-       return result;
-}
-
-void saa7164_vbi_unregister(struct saa7164_port *port)
-{
-       struct saa7164_dev *dev = port->dev;
-
-       dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
-
-       if (port->type != SAA7164_MPEG_VBI)
-               BUG();
-
-       if (port->v4l_device) {
-               if (port->v4l_device->minor != -1)
-                       video_unregister_device(port->v4l_device);
-               else
-                       video_device_release(port->v4l_device);
-
-               port->v4l_device = NULL;
-       }
-
-}
diff --git a/drivers/media/video/saa7164/saa7164.h b/drivers/media/video/saa7164/saa7164.h
deleted file mode 100644 (file)
index 437284e..0000000
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- *  Driver for the NXP SAA7164 PCIe bridge
- *
- *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 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 architecture
-       *******************
-
-       saa7164_core.c/buffer.c/cards.c/i2c.c/dvb.c
-               |       : Standard Linux driver framework for creating
-               |       : exposing and managing interfaces to the rest
-               |       : of the kernel or userland. Also uses _fw.c to load
-               |       : firmware direct into the PCIe bus, bypassing layers.
-               V
-       saa7164_api..() : Translate kernel specific functions/features
-               |       : into command buffers.
-               V
-       saa7164_cmd..() : Manages the flow of command packets on/off,
-               |       : the bus. Deal with bus errors, timeouts etc.
-               V
-       saa7164_bus..() : Manage a read/write memory ring buffer in the
-               |       : PCIe Address space.
-               |
-               |               saa7164_fw...() : Load any frimware
-               |                       |       : direct into the device
-               V                       V
-       <- ----------------- PCIe address space -------------------- ->
-*/
-
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/kdev_t.h>
-#include <linux/mutex.h>
-#include <linux/crc32.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-
-#include <media/tuner.h>
-#include <media/tveeprom.h>
-#include <media/videobuf-dma-sg.h>
-#include <media/videobuf-dvb.h>
-#include <dvb_demux.h>
-#include <dvb_frontend.h>
-#include <dvb_net.h>
-#include <dvbdev.h>
-#include <dmxdev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-
-#include "saa7164-reg.h"
-#include "saa7164-types.h"
-
-#define SAA7164_MAXBOARDS 8
-
-#define UNSET (-1U)
-#define SAA7164_BOARD_NOAUTO                   UNSET
-#define SAA7164_BOARD_UNKNOWN                  0
-#define SAA7164_BOARD_UNKNOWN_REV2             1
-#define SAA7164_BOARD_UNKNOWN_REV3             2
-#define SAA7164_BOARD_HAUPPAUGE_HVR2250                3
-#define SAA7164_BOARD_HAUPPAUGE_HVR2200                4
-#define SAA7164_BOARD_HAUPPAUGE_HVR2200_2      5
-#define SAA7164_BOARD_HAUPPAUGE_HVR2200_3      6
-#define SAA7164_BOARD_HAUPPAUGE_HVR2250_2      7
-#define SAA7164_BOARD_HAUPPAUGE_HVR2250_3      8
-#define SAA7164_BOARD_HAUPPAUGE_HVR2200_4      9
-#define SAA7164_BOARD_HAUPPAUGE_HVR2200_5      10
-
-#define SAA7164_MAX_UNITS              8
-#define SAA7164_TS_NUMBER_OF_LINES     312
-#define SAA7164_PS_NUMBER_OF_LINES     256
-#define SAA7164_PT_ENTRIES             16 /* (312 * 188) / 4096 */
-#define SAA7164_MAX_ENCODER_BUFFERS    64 /* max 5secs of latency at 6Mbps */
-#define SAA7164_MAX_VBI_BUFFERS                64
-
-/* Port related defines */
-#define SAA7164_PORT_TS1       (0)
-#define SAA7164_PORT_TS2       (SAA7164_PORT_TS1 + 1)
-#define SAA7164_PORT_ENC1      (SAA7164_PORT_TS2 + 1)
-#define SAA7164_PORT_ENC2      (SAA7164_PORT_ENC1 + 1)
-#define SAA7164_PORT_VBI1      (SAA7164_PORT_ENC2 + 1)
-#define SAA7164_PORT_VBI2      (SAA7164_PORT_VBI1 + 1)
-#define SAA7164_MAX_PORTS      (SAA7164_PORT_VBI2 + 1)
-
-#define DBGLVL_FW    4
-#define DBGLVL_DVB   8
-#define DBGLVL_I2C  16
-#define DBGLVL_API  32
-#define DBGLVL_CMD  64
-#define DBGLVL_BUS 128
-#define DBGLVL_IRQ 256
-#define DBGLVL_BUF 512
-#define DBGLVL_ENC 1024
-#define DBGLVL_VBI 2048
-#define DBGLVL_THR 4096
-#define DBGLVL_CPU 8192
-
-#define SAA7164_NORMS \
-       (V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443)
-
-enum port_t {
-       SAA7164_MPEG_UNDEFINED = 0,
-       SAA7164_MPEG_DVB,
-       SAA7164_MPEG_ENCODER,
-       SAA7164_MPEG_VBI,
-};
-
-enum saa7164_i2c_bus_nr {
-       SAA7164_I2C_BUS_0 = 0,
-       SAA7164_I2C_BUS_1,
-       SAA7164_I2C_BUS_2,
-};
-
-enum saa7164_buffer_flags {
-       SAA7164_BUFFER_UNDEFINED = 0,
-       SAA7164_BUFFER_FREE,
-       SAA7164_BUFFER_BUSY,
-       SAA7164_BUFFER_FULL
-};
-
-enum saa7164_unit_type {
-       SAA7164_UNIT_UNDEFINED = 0,
-       SAA7164_UNIT_DIGITAL_DEMODULATOR,
-       SAA7164_UNIT_ANALOG_DEMODULATOR,
-       SAA7164_UNIT_TUNER,
-       SAA7164_UNIT_EEPROM,
-       SAA7164_UNIT_ZILOG_IRBLASTER,
-       SAA7164_UNIT_ENCODER,
-};
-
-/* The PCIe bridge doesn't grant direct access to i2c.
- * Instead, you address i2c devices using a uniqely
- * allocated 'unitid' value via a messaging API. This
- * is a problem. The kernel and existing demod/tuner
- * drivers expect to talk 'i2c', so we have to maintain
- * a translation layer, and a series of functions to
- * convert i2c bus + device address into a unit id.
- */
-struct saa7164_unit {
-       enum saa7164_unit_type type;
-       u8      id;
-       char    *name;
-       enum saa7164_i2c_bus_nr i2c_bus_nr;
-       u8      i2c_bus_addr;
-       u8      i2c_reg_len;
-};
-
-struct saa7164_board {
-       char    *name;
-       enum port_t porta, portb, portc,
-               portd, porte, portf;
-       enum {
-               SAA7164_CHIP_UNDEFINED = 0,
-               SAA7164_CHIP_REV2,
-               SAA7164_CHIP_REV3,
-       } chiprev;
-       struct  saa7164_unit unit[SAA7164_MAX_UNITS];
-};
-
-struct saa7164_subid {
-       u16     subvendor;
-       u16     subdevice;
-       u32     card;
-};
-
-struct saa7164_encoder_fh {
-       struct saa7164_port *port;
-       atomic_t v4l_reading;
-};
-
-struct saa7164_vbi_fh {
-       struct saa7164_port *port;
-       atomic_t v4l_reading;
-};
-
-struct saa7164_histogram_bucket {
-       u32 val;
-       u32 count;
-       u64 update_time;
-};
-
-struct saa7164_histogram {
-       char name[32];
-       struct saa7164_histogram_bucket counter1[64];
-};
-
-struct saa7164_user_buffer {
-       struct list_head list;
-
-       /* Attributes */
-       u8  *data;
-       u32 pos;
-       u32 actual_size;
-
-       u32 crc;
-};
-
-struct saa7164_fw_status {
-
-       /* RISC Core details */
-       u32     status;
-       u32     mode;
-       u32     spec;
-       u32     inst;
-       u32     cpuload;
-       u32     remainheap;
-
-       /* Firmware version */
-       u32     version;
-       u32     major;
-       u32     sub;
-       u32     rel;
-       u32     buildnr;
-};
-
-struct saa7164_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 saa7164_i2c {
-       struct saa7164_dev              *dev;
-
-       enum saa7164_i2c_bus_nr         nr;
-
-       /* I2C I/O */
-       struct i2c_adapter              i2c_adap;
-       struct i2c_client               i2c_client;
-       u32                             i2c_rc;
-};
-
-struct saa7164_ctrl {
-       struct v4l2_queryctrl v;
-};
-
-struct saa7164_tvnorm {
-       char            *name;
-       v4l2_std_id     id;
-};
-
-struct saa7164_encoder_params {
-       struct saa7164_tvnorm encodernorm;
-       u32 height;
-       u32 width;
-       u32 is_50hz;
-       u32 bitrate; /* bps */
-       u32 bitrate_peak; /* bps */
-       u32 bitrate_mode;
-       u32 stream_type; /* V4L2_MPEG_STREAM_TYPE_MPEG2_TS */
-
-       u32 audio_sampling_freq;
-       u32 ctl_mute;
-       u32 ctl_aspect;
-       u32 refdist;
-       u32 gop_size;
-};
-
-struct saa7164_vbi_params {
-       struct saa7164_tvnorm encodernorm;
-       u32 height;
-       u32 width;
-       u32 is_50hz;
-       u32 bitrate; /* bps */
-       u32 bitrate_peak; /* bps */
-       u32 bitrate_mode;
-       u32 stream_type; /* V4L2_MPEG_STREAM_TYPE_MPEG2_TS */
-
-       u32 audio_sampling_freq;
-       u32 ctl_mute;
-       u32 ctl_aspect;
-       u32 refdist;
-       u32 gop_size;
-};
-
-struct saa7164_port;
-
-struct saa7164_buffer {
-       struct list_head list;
-
-       /* Note of which h/w buffer list index position we occupy */
-       int idx;
-
-       struct saa7164_port *port;
-
-       /* Hardware Specific */
-       /* PCI Memory allocations */
-       enum saa7164_buffer_flags flags; /* Free, Busy, Full */
-
-       /* A block of page align PCI memory */
-       u32 pci_size;   /* PCI allocation size in bytes */
-       u64 __iomem *cpu;       /* Virtual address */
-       dma_addr_t dma; /* Physical address */
-       u32 crc;        /* Checksum for the entire buffer data */
-
-       /* A page table that splits the block into a number of entries */
-       u32 pt_size;            /* PCI allocation size in bytes */
-       u64 __iomem *pt_cpu;            /* Virtual address */
-       dma_addr_t pt_dma;      /* Physical address */
-
-       /* Encoder fops */
-       u32 pos;
-       u32 actual_size;
-};
-
-struct saa7164_port {
-
-       struct saa7164_dev *dev;
-       enum port_t type;
-       int nr;
-
-       /* --- Generic port attributes --- */
-
-       /* HW stream parameters */
-       struct tmHWStreamParameters hw_streamingparams;
-
-       /* DMA configuration values, is seeded during initialization */
-       struct tmComResDMATermDescrHeader hwcfg;
-
-       /* hardware specific registers */
-       u32 bufcounter;
-       u32 pitch;
-       u32 bufsize;
-       u32 bufoffset;
-       u32 bufptr32l;
-       u32 bufptr32h;
-       u64 bufptr64;
-
-       u32 numpte;     /* Number of entries in array, only valid in head */
-
-       struct mutex dmaqueue_lock;
-       struct saa7164_buffer dmaqueue;
-
-       u64 last_irq_msecs, last_svc_msecs;
-       u64 last_irq_msecs_diff, last_svc_msecs_diff;
-       u32 last_svc_wp;
-       u32 last_svc_rp;
-       u64 last_irq_svc_msecs_diff;
-       u64 last_read_msecs, last_read_msecs_diff;
-       u64 last_poll_msecs, last_poll_msecs_diff;
-
-       struct saa7164_histogram irq_interval;
-       struct saa7164_histogram svc_interval;
-       struct saa7164_histogram irq_svc_interval;
-       struct saa7164_histogram read_interval;
-       struct saa7164_histogram poll_interval;
-
-       /* --- DVB Transport Specific --- */
-       struct saa7164_dvb dvb;
-
-       /* --- Encoder/V4L related attributes --- */
-       /* Encoder */
-       /* Defaults established in saa7164-encoder.c */
-       struct saa7164_tvnorm encodernorm;
-       u32 height;
-       u32 width;
-       u32 freq;
-       u32 ts_packet_size;
-       u32 ts_packet_count;
-       u8 mux_input;
-       u8 encoder_profile;
-       u8 video_format;
-       u8 audio_format;
-       u8 video_resolution;
-       u16 ctl_brightness;
-       u16 ctl_contrast;
-       u16 ctl_hue;
-       u16 ctl_saturation;
-       u16 ctl_sharpness;
-       s8 ctl_volume;
-
-       struct tmComResAFeatureDescrHeader audfeat;
-       struct tmComResEncoderDescrHeader encunit;
-       struct tmComResProcDescrHeader vidproc;
-       struct tmComResExtDevDescrHeader ifunit;
-       struct tmComResTunerDescrHeader tunerunit;
-
-       struct work_struct workenc;
-
-       /* V4L Encoder Video */
-       struct saa7164_encoder_params encoder_params;
-       struct video_device *v4l_device;
-       atomic_t v4l_reader_count;
-
-       struct saa7164_buffer list_buf_used;
-       struct saa7164_buffer list_buf_free;
-       wait_queue_head_t wait_read;
-
-       /* V4L VBI */
-       struct tmComResVBIFormatDescrHeader vbi_fmt_ntsc;
-       struct saa7164_vbi_params vbi_params;
-
-       /* Debug */
-       u32 sync_errors;
-       u32 v_cc_errors;
-       u32 a_cc_errors;
-       u8 last_v_cc;
-       u8 last_a_cc;
-       u32 done_first_interrupt;
-};
-
-struct saa7164_dev {
-       struct list_head        devlist;
-       atomic_t                refcount;
-
-       /* pci stuff */
-       struct pci_dev  *pci;
-       unsigned char   pci_rev, pci_lat;
-       int             pci_bus, pci_slot;
-       u32             __iomem *lmmio;
-       u8              __iomem *bmmio;
-       u32             __iomem *lmmio2;
-       u8              __iomem *bmmio2;
-       int             pci_irqmask;
-
-       /* board details */
-       int     nr;
-       int     hwrevision;
-       u32     board;
-       char    name[16];
-
-       /* firmware status */
-       struct saa7164_fw_status        fw_status;
-       u32                             firmwareloaded;
-
-       struct tmComResHWDescr          hwdesc;
-       struct tmComResInterfaceDescr   intfdesc;
-       struct tmComResBusDescr         busdesc;
-
-       struct tmComResBusInfo          bus;
-
-       /* Interrupt status and ack registers */
-       u32 int_status;
-       u32 int_ack;
-
-       struct cmd                      cmds[SAA_CMD_MAX_MSG_UNITS];
-       struct mutex                    lock;
-
-       /* I2c related */
-       struct saa7164_i2c i2c_bus[3];
-
-       /* Transport related */
-       struct saa7164_port ports[SAA7164_MAX_PORTS];
-
-       /* Deferred command/api interrupts handling */
-       struct work_struct workcmd;
-
-       /* A kernel thread to monitor the firmware log, used
-        * only in debug mode.
-        */
-       struct task_struct *kthread;
-
-};
-
-extern struct list_head saa7164_devlist;
-extern unsigned int waitsecs;
-extern unsigned int encoder_buffers;
-extern unsigned int vbi_buffers;
-
-/* ----------------------------------------------------------- */
-/* saa7164-core.c                                              */
-void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr);
-void saa7164_getfirmwarestatus(struct saa7164_dev *dev);
-u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev);
-void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val);
-
-/* ----------------------------------------------------------- */
-/* saa7164-fw.c                                                */
-int saa7164_downloadfirmware(struct saa7164_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* saa7164-i2c.c                                               */
-extern int saa7164_i2c_register(struct saa7164_i2c *bus);
-extern int saa7164_i2c_unregister(struct saa7164_i2c *bus);
-extern void saa7164_call_i2c_clients(struct saa7164_i2c *bus,
-       unsigned int cmd, void *arg);
-
-/* ----------------------------------------------------------- */
-/* saa7164-bus.c                                               */
-int saa7164_bus_setup(struct saa7164_dev *dev);
-void saa7164_bus_dump(struct saa7164_dev *dev);
-int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
-       void *buf);
-int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
-       void *buf, int peekonly);
-
-/* ----------------------------------------------------------- */
-/* saa7164-cmd.c                                               */
-int saa7164_cmd_send(struct saa7164_dev *dev,
-       u8 id, enum tmComResCmd command, u16 controlselector,
-       u16 size, void *buf);
-void saa7164_cmd_signal(struct saa7164_dev *dev, u8 seqno);
-int saa7164_irq_dequeue(struct saa7164_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* saa7164-api.c                                               */
-int saa7164_api_get_fw_version(struct saa7164_dev *dev, u32 *version);
-int saa7164_api_enum_subdevs(struct saa7164_dev *dev);
-int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
-       u32 datalen, u8 *data);
-int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr,
-       u32 datalen, u8 *data);
-int saa7164_api_dif_write(struct saa7164_i2c *bus, u8 addr,
-       u32 datalen, u8 *data);
-int saa7164_api_read_eeprom(struct saa7164_dev *dev, u8 *buf, int buflen);
-int saa7164_api_set_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin);
-int saa7164_api_clear_gpiobit(struct saa7164_dev *dev, u8 unitid, u8 pin);
-int saa7164_api_transition_port(struct saa7164_port *port, u8 mode);
-int saa7164_api_initialize_dif(struct saa7164_port *port);
-int saa7164_api_configure_dif(struct saa7164_port *port, u32 std);
-int saa7164_api_set_encoder(struct saa7164_port *port);
-int saa7164_api_get_encoder(struct saa7164_port *port);
-int saa7164_api_set_aspect_ratio(struct saa7164_port *port);
-int saa7164_api_set_usercontrol(struct saa7164_port *port, u8 ctl);
-int saa7164_api_get_usercontrol(struct saa7164_port *port, u8 ctl);
-int saa7164_api_set_videomux(struct saa7164_port *port);
-int saa7164_api_audio_mute(struct saa7164_port *port, int mute);
-int saa7164_api_set_audio_volume(struct saa7164_port *port, s8 level);
-int saa7164_api_set_audio_std(struct saa7164_port *port);
-int saa7164_api_set_audio_detection(struct saa7164_port *port, int autodetect);
-int saa7164_api_get_videomux(struct saa7164_port *port);
-int saa7164_api_set_vbi_format(struct saa7164_port *port);
-int saa7164_api_set_debug(struct saa7164_dev *dev, u8 level);
-int saa7164_api_collect_debug(struct saa7164_dev *dev);
-int saa7164_api_get_load_info(struct saa7164_dev *dev,
-       struct tmFwInfoStruct *i);
-
-/* ----------------------------------------------------------- */
-/* saa7164-cards.c                                             */
-extern struct saa7164_board saa7164_boards[];
-extern const unsigned int saa7164_bcount;
-
-extern struct saa7164_subid saa7164_subids[];
-extern const unsigned int saa7164_idcount;
-
-extern void saa7164_card_list(struct saa7164_dev *dev);
-extern void saa7164_gpio_setup(struct saa7164_dev *dev);
-extern void saa7164_card_setup(struct saa7164_dev *dev);
-
-extern int saa7164_i2caddr_to_reglen(struct saa7164_i2c *bus, int addr);
-extern int saa7164_i2caddr_to_unitid(struct saa7164_i2c *bus, int addr);
-extern char *saa7164_unitid_name(struct saa7164_dev *dev, u8 unitid);
-
-/* ----------------------------------------------------------- */
-/* saa7164-dvb.c                                               */
-extern int saa7164_dvb_register(struct saa7164_port *port);
-extern int saa7164_dvb_unregister(struct saa7164_port *port);
-
-/* ----------------------------------------------------------- */
-/* saa7164-buffer.c                                            */
-extern struct saa7164_buffer *saa7164_buffer_alloc(
-       struct saa7164_port *port, u32 len);
-extern int saa7164_buffer_dealloc(struct saa7164_buffer *buf);
-extern void saa7164_buffer_display(struct saa7164_buffer *buf);
-extern int saa7164_buffer_activate(struct saa7164_buffer *buf, int i);
-extern int saa7164_buffer_cfg_port(struct saa7164_port *port);
-extern struct saa7164_user_buffer *saa7164_buffer_alloc_user(
-       struct saa7164_dev *dev, u32 len);
-extern void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf);
-extern int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i);
-
-/* ----------------------------------------------------------- */
-/* saa7164-encoder.c                                            */
-int saa7164_encoder_register(struct saa7164_port *port);
-void saa7164_encoder_unregister(struct saa7164_port *port);
-
-/* ----------------------------------------------------------- */
-/* saa7164-vbi.c                                            */
-int saa7164_vbi_register(struct saa7164_port *port);
-void saa7164_vbi_unregister(struct saa7164_port *port);
-
-/* ----------------------------------------------------------- */
-
-extern unsigned int crc_checking;
-
-extern unsigned int saa_debug;
-#define dprintk(level, fmt, arg...)\
-       do { if (saa_debug & level)\
-               printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
-       } while (0)
-
-#define log_warn(fmt, arg...)\
-       do { \
-               printk(KERN_WARNING "%s: " fmt, dev->name, ## arg);\
-       } while (0)
-
-#define saa7164_readl(reg) readl(dev->lmmio + ((reg) >> 2))
-#define saa7164_writel(reg, value) writel((value), dev->lmmio + ((reg) >> 2))
-
-#define saa7164_readb(reg)             readl(dev->bmmio + (reg))
-#define saa7164_writeb(reg, value)     writel((value), dev->bmmio + (reg))
-
diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig
deleted file mode 100644 (file)
index fd4120e..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-config VIDEO_ZORAN
-       tristate "Zoran ZR36057/36067 Video For Linux"
-       depends on PCI && I2C_ALGOBIT && VIDEO_V4L2 && VIRT_TO_BUS
-       help
-         Say Y for support for MJPEG capture cards based on the Zoran
-         36057/36067 PCI controller chipset. This includes the Iomega
-         Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
-         a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
-         more information, check <file:Documentation/video4linux/Zoran>.
-
-         To compile this driver as a module, choose M here: the
-         module will be called zr36067.
-
-config VIDEO_ZORAN_DC30
-       tristate "Pinnacle/Miro DC30(+) support"
-       depends on VIDEO_ZORAN
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
-         card. This also supports really old DC10 cards based on the
-         zr36050 MJPEG codec and zr36016 VFE.
-
-config VIDEO_ZORAN_ZR36060
-       tristate "Zoran ZR36060"
-       depends on VIDEO_ZORAN
-       help
-         Say Y to support Zoran boards based on 36060 chips.
-         This includes Iomega Buz, Pinnacle DC10, Linux media Labs 33
-         and 33 R10 and AverMedia 6 boards.
-
-config VIDEO_ZORAN_BUZ
-       tristate "Iomega Buz support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Iomega Buz MJPEG capture/playback card.
-
-config VIDEO_ZORAN_DC10
-       tristate "Pinnacle/Miro DC10(+) support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
-         card.
-
-config VIDEO_ZORAN_LML33
-       tristate "Linux Media Labs LML33 support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the Linux Media Labs LML33 MJPEG capture/playback
-         card.
-
-config VIDEO_ZORAN_LML33R10
-       tristate "Linux Media Labs LML33R10 support"
-       depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         support for the Linux Media Labs LML33R10 MJPEG capture/playback
-         card.
-
-config VIDEO_ZORAN_AVS6EYES
-       tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
-       depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL
-       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Support for the AverMedia 6 Eyes video surveillance card.
diff --git a/drivers/media/video/zoran/Makefile b/drivers/media/video/zoran/Makefile
deleted file mode 100644 (file)
index 44cc133..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-zr36067-objs   :=      zoran_procfs.o zoran_device.o \
-                       zoran_driver.o zoran_card.o
-
-obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
-obj-$(CONFIG_VIDEO_ZORAN_DC30) += zr36050.o zr36016.o
-obj-$(CONFIG_VIDEO_ZORAN_ZR36060) += zr36060.o
diff --git a/drivers/media/video/zoran/videocodec.c b/drivers/media/video/zoran/videocodec.c
deleted file mode 100644 (file)
index c010716..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * VIDEO MOTION CODECs internal API for video devices
- *
- * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
- * bound to a master device.
- *
- * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: videocodec.c,v 1.1.2.8 2003/03/29 07:16:04 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 VIDEOCODEC_VERSION "v0.2"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-
-// kernel config is here (procfs flag)
-
-#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;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-struct attached_list {
-       struct videocodec *codec;
-       struct attached_list *next;
-};
-
-struct codec_list {
-       const struct videocodec *codec;
-       int attached;
-       struct attached_list *list;
-       struct codec_list *next;
-};
-
-static struct codec_list *codeclist_top = NULL;
-
-/* ================================================= */
-/* function prototypes of the master/slave interface */
-/* ================================================= */
-
-struct videocodec *
-videocodec_attach (struct videocodec_master *master)
-{
-       struct codec_list *h = codeclist_top;
-       struct attached_list *a, *ptr;
-       struct videocodec *codec;
-       int res;
-
-       if (!master) {
-               dprintk(1, KERN_ERR "videocodec_attach: no data\n");
-               return NULL;
-       }
-
-       dprintk(2,
-               "videocodec_attach: '%s', flags %lx, magic %lx\n",
-               master->name, master->flags, master->magic);
-
-       if (!h) {
-               dprintk(1,
-                       KERN_ERR
-                       "videocodec_attach: no device available\n");
-               return NULL;
-       }
-
-       while (h) {
-               // attach only if the slave has at least the flags
-               // expected by the master
-               if ((master->flags & h->codec->flags) == master->flags) {
-                       dprintk(4, "videocodec_attach: try '%s'\n",
-                               h->codec->name);
-
-                       if (!try_module_get(h->codec->owner))
-                               return NULL;
-
-                       codec = kmemdup(h->codec, sizeof(struct videocodec),
-                                       GFP_KERNEL);
-                       if (!codec) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "videocodec_attach: no mem\n");
-                               goto out_module_put;
-                       }
-
-                       snprintf(codec->name, sizeof(codec->name),
-                                "%s[%d]", codec->name, h->attached);
-                       codec->master_data = master;
-                       res = codec->setup(codec);
-                       if (res == 0) {
-                               dprintk(3, "videocodec_attach '%s'\n",
-                                       codec->name);
-                               ptr = kzalloc(sizeof(struct attached_list), GFP_KERNEL);
-                               if (!ptr) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "videocodec_attach: no memory\n");
-                                       goto out_kfree;
-                               }
-                               ptr->codec = codec;
-
-                               a = h->list;
-                               if (!a) {
-                                       h->list = ptr;
-                                       dprintk(4,
-                                               "videocodec: first element\n");
-                               } else {
-                                       while (a->next)
-                                               a = a->next;    // find end
-                                       a->next = ptr;
-                                       dprintk(4,
-                                               "videocodec: in after '%s'\n",
-                                               h->codec->name);
-                               }
-
-                               h->attached += 1;
-                               return codec;
-                       } else {
-                               kfree(codec);
-                       }
-               }
-               h = h->next;
-       }
-
-       dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
-       return NULL;
-
- out_module_put:
-       module_put(h->codec->owner);
- out_kfree:
-       kfree(codec);
-       return NULL;
-}
-
-int
-videocodec_detach (struct videocodec *codec)
-{
-       struct codec_list *h = codeclist_top;
-       struct attached_list *a, *prev;
-       int res;
-
-       if (!codec) {
-               dprintk(1, KERN_ERR "videocodec_detach: no data\n");
-               return -EINVAL;
-       }
-
-       dprintk(2,
-               "videocodec_detach: '%s', type: %x, flags %lx, magic %lx\n",
-               codec->name, codec->type, codec->flags, codec->magic);
-
-       if (!h) {
-               dprintk(1,
-                       KERN_ERR "videocodec_detach: no device left...\n");
-               return -ENXIO;
-       }
-
-       while (h) {
-               a = h->list;
-               prev = NULL;
-               while (a) {
-                       if (codec == a->codec) {
-                               res = a->codec->unset(a->codec);
-                               if (res >= 0) {
-                                       dprintk(3,
-                                               "videocodec_detach: '%s'\n",
-                                               a->codec->name);
-                                       a->codec->master_data = NULL;
-                               } else {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "videocodec_detach: '%s'\n",
-                                               a->codec->name);
-                                       a->codec->master_data = NULL;
-                               }
-                               if (prev == NULL) {
-                                       h->list = a->next;
-                                       dprintk(4,
-                                               "videocodec: delete first\n");
-                               } else {
-                                       prev->next = a->next;
-                                       dprintk(4,
-                                               "videocodec: delete middle\n");
-                               }
-                               module_put(a->codec->owner);
-                               kfree(a->codec);
-                               kfree(a);
-                               h->attached -= 1;
-                               return 0;
-                       }
-                       prev = a;
-                       a = a->next;
-               }
-               h = h->next;
-       }
-
-       dprintk(1, KERN_ERR "videocodec_detach: given codec not found!\n");
-       return -EINVAL;
-}
-
-int
-videocodec_register (const struct videocodec *codec)
-{
-       struct codec_list *ptr, *h = codeclist_top;
-
-       if (!codec) {
-               dprintk(1, KERN_ERR "videocodec_register: no data!\n");
-               return -EINVAL;
-       }
-
-       dprintk(2,
-               "videocodec: register '%s', type: %x, flags %lx, magic %lx\n",
-               codec->name, codec->type, codec->flags, codec->magic);
-
-       ptr = kzalloc(sizeof(struct codec_list), GFP_KERNEL);
-       if (!ptr) {
-               dprintk(1, KERN_ERR "videocodec_register: no memory\n");
-               return -ENOMEM;
-       }
-       ptr->codec = codec;
-
-       if (!h) {
-               codeclist_top = ptr;
-               dprintk(4, "videocodec: hooked in as first element\n");
-       } else {
-               while (h->next)
-                       h = h->next;    // find the end
-               h->next = ptr;
-               dprintk(4, "videocodec: hooked in after '%s'\n",
-                       h->codec->name);
-       }
-
-       return 0;
-}
-
-int
-videocodec_unregister (const struct videocodec *codec)
-{
-       struct codec_list *prev = NULL, *h = codeclist_top;
-
-       if (!codec) {
-               dprintk(1, KERN_ERR "videocodec_unregister: no data!\n");
-               return -EINVAL;
-       }
-
-       dprintk(2,
-               "videocodec: unregister '%s', type: %x, flags %lx, magic %lx\n",
-               codec->name, codec->type, codec->flags, codec->magic);
-
-       if (!h) {
-               dprintk(1,
-                       KERN_ERR
-                       "videocodec_unregister: no device left...\n");
-               return -ENXIO;
-       }
-
-       while (h) {
-               if (codec == h->codec) {
-                       if (h->attached) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "videocodec: '%s' is used\n",
-                                       h->codec->name);
-                               return -EBUSY;
-                       }
-                       dprintk(3, "videocodec: unregister '%s' is ok.\n",
-                               h->codec->name);
-                       if (prev == NULL) {
-                               codeclist_top = h->next;
-                               dprintk(4,
-                                       "videocodec: delete first element\n");
-                       } else {
-                               prev->next = h->next;
-                               dprintk(4,
-                                       "videocodec: delete middle element\n");
-                       }
-                       kfree(h);
-                       return 0;
-               }
-               prev = h;
-               h = h->next;
-       }
-
-       dprintk(1,
-               KERN_ERR
-               "videocodec_unregister: given codec not found!\n");
-       return -EINVAL;
-}
-
-#ifdef CONFIG_PROC_FS
-static int proc_videocodecs_show(struct seq_file *m, void *v)
-{
-       struct codec_list *h = codeclist_top;
-       struct attached_list *a;
-
-       seq_printf(m, "<S>lave or attached <M>aster name  type flags    magic    ");
-       seq_printf(m, "(connected as)\n");
-
-       h = codeclist_top;
-       while (h) {
-               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) {
-                       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,
-                                     a->codec->master_data->magic,
-                                     a->codec->name);
-                       a = a->next;
-               }
-               h = h->next;
-       }
-
-       return 0;
-}
-
-static int proc_videocodecs_open(struct inode *inode, struct file *file)
-{
-       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
-
-/* ===================== */
-/* hook in driver module */
-/* ===================== */
-static int __init
-videocodec_init (void)
-{
-#ifdef CONFIG_PROC_FS
-       static struct proc_dir_entry *videocodec_proc_entry;
-#endif
-
-       printk(KERN_INFO "Linux video codec intermediate layer: %s\n",
-              VIDEOCODEC_VERSION);
-
-#ifdef CONFIG_PROC_FS
-       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
-       return 0;
-}
-
-static void __exit
-videocodec_exit (void)
-{
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("videocodecs", NULL);
-#endif
-}
-
-EXPORT_SYMBOL(videocodec_attach);
-EXPORT_SYMBOL(videocodec_detach);
-EXPORT_SYMBOL(videocodec_register);
-EXPORT_SYMBOL(videocodec_unregister);
-
-module_init(videocodec_init);
-module_exit(videocodec_exit);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Intermediate API module for video codecs "
-                  VIDEOCODEC_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/videocodec.h b/drivers/media/video/zoran/videocodec.h
deleted file mode 100644 (file)
index def5558..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * VIDEO MOTION CODECs internal API for video devices
- *
- * Interface for MJPEG (and maybe later MPEG/WAVELETS) codec's
- * bound to a master device.
- *
- * (c) 2002 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: videocodec.h,v 1.1.2.4 2003/01/14 21:15:03 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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.
- *
- * ------------------------------------------------------------------------
- */
-
-/* =================== */
-/* general description */
-/* =================== */
-
-/* Should ease the (re-)usage of drivers supporting cards with (different)
-   video codecs. The codecs register to this module their functionality,
-   and the processors (masters) can attach to them if they fit.
-
-   The codecs are typically have a "strong" binding to their master - so I
-   don't think it makes sense to have a full blown interfacing as with e.g.
-   i2c. If you have an other opinion, let's discuss & implement it :-)))
-
-   Usage:
-
-   The slave has just to setup the videocodec structure and use two functions:
-   videocodec_register(codecdata);
-   videocodec_unregister(codecdata);
-   The best is just calling them at module (de-)initialisation.
-
-   The master sets up the structure videocodec_master and calls:
-   codecdata=videocodec_attach(master_codecdata);
-   videocodec_detach(codecdata);
-
-   The slave is called during attach/detach via functions setup previously
-   during register. At that time, the master_data pointer is set up
-   and the slave can access any io registers of the master device (in the case
-   the slave is bound to it). Otherwise it doesn't need this functions and
-   therfor they may not be initialized.
-
-   The other functions are just for convenience, as they are for sure used by
-   most/all of the codecs. The last ones may be omitted, too.
-
-   See the structure declaration below for more information and which data has
-   to be set up for the master and the slave.
-
-   ----------------------------------------------------------------------------
-   The master should have "knowledge" of the slave and vice versa.  So the data
-   structures sent to/from slave via set_data/get_data set_image/get_image are
-   device dependent and vary between MJPEG/MPEG/WAVELET/... devices. (!!!!)
-   ----------------------------------------------------------------------------
-*/
-\f
-
-/* ========================================== */
-/* description of the videocodec_io structure */
-/* ========================================== */
-
-/*
-   ==== master setup ====
-   name -> name of the device structure for reference and debugging
-   master_data ->  data ref. for the master (e.g. the zr36055,57,67)
-   readreg -> ref. to read-fn from register (setup by master, used by slave)
-   writereg -> ref. to write-fn to register (setup by master, used by slave)
-              this two functions do the lowlevel I/O job
-
-   ==== slave functionality setup ====
-   slave_data -> data ref. for the slave (e.g. the zr36050,60)
-   check -> fn-ref. checks availability of an device, returns -EIO on failure or
-           the type on success
-           this makes espcecially sense if a driver module supports more than
-           one codec which may be quite similar to access, nevertheless it
-           is good for a first functionality check
-
-   -- main functions you always need for compression/decompression --
-
-   set_mode -> this fn-ref. resets the entire codec, and sets up the mode
-              with the last defined norm/size (or device default if not
-              available) - it returns 0 if the mode is possible
-   set_size -> this fn-ref. sets the norm and image size for
-              compression/decompression (returns 0 on success)
-              the norm param is defined in videodev2.h (V4L2_STD_*)
-
-   additional setup may be available, too - but the codec should work with
-   some default values even without this
-
-   set_data -> sets device-specific data (tables, quality etc.)
-   get_data -> query device-specific data (tables, quality etc.)
-
-   if the device delivers interrupts, they may be setup/handled here
-   setup_interrupt -> codec irq setup (not needed for 36050/60)
-   handle_interrupt -> codec irq handling (not needed for 36050/60)
-
-   if the device delivers pictures, they may be handled here
-   put_image -> puts image data to the codec (not needed for 36050/60)
-   get_image -> gets image data from the codec (not needed for 36050/60)
-               the calls include frame numbers and flags (even/odd/...)
-               if needed and a flag which allows blocking until its ready
-*/
-\f
-/* ============== */
-/* user interface */
-/* ============== */
-
-/*
-   Currently there is only a information display planned, as the layer
-   is not visible for the user space at all.
-
-   Information is available via procfs. The current entry is "/proc/videocodecs"
-   but it makes sense to "hide" it in the /proc/video tree of v4l(2) --TODO--.
-
-A example for such an output is:
-
-<S>lave or attached <M>aster name  type flags    magic    (connected as)
-S                          zr36050 0002 0000d001 00000000 (TEMPLATE)
-M                       zr36055[0] 0001 0000c001 00000000 (zr36050[0])
-M                       zr36055[1] 0001 0000c001 00000000 (zr36050[1])
-
-*/
-\f
-
-/* =============================================== */
-/* special defines for the videocodec_io structure */
-/* =============================================== */
-
-#ifndef __LINUX_VIDEOCODEC_H
-#define __LINUX_VIDEOCODEC_H
-
-#include <linux/videodev2.h>
-
-#define CODEC_DO_COMPRESSION 0
-#define CODEC_DO_EXPANSION   1
-
-/* this are the current codec flags I think they are needed */
-/*  -> type value in structure */
-#define CODEC_FLAG_JPEG      0x00000001L       // JPEG codec
-#define CODEC_FLAG_MPEG      0x00000002L       // MPEG1/2/4 codec
-#define CODEC_FLAG_DIVX      0x00000004L       // DIVX codec
-#define CODEC_FLAG_WAVELET   0x00000008L       // WAVELET codec
-                                         // room for other types
-
-#define CODEC_FLAG_MAGIC     0x00000800L       // magic key must match
-#define CODEC_FLAG_HARDWARE  0x00001000L       // is a hardware codec
-#define CODEC_FLAG_VFE       0x00002000L       // has direct video frontend
-#define CODEC_FLAG_ENCODER   0x00004000L       // compression capability
-#define CODEC_FLAG_DECODER   0x00008000L       // decompression capability
-#define CODEC_FLAG_NEEDIRQ   0x00010000L       // needs irq handling
-#define CODEC_FLAG_RDWRPIC   0x00020000L       // handles picture I/O
-
-/* a list of modes, some are just examples (is there any HW?) */
-#define CODEC_MODE_BJPG      0x0001    // Baseline JPEG
-#define CODEC_MODE_LJPG      0x0002    // Lossless JPEG
-#define CODEC_MODE_MPEG1     0x0003    // MPEG 1
-#define CODEC_MODE_MPEG2     0x0004    // MPEG 2
-#define CODEC_MODE_MPEG4     0x0005    // MPEG 4
-#define CODEC_MODE_MSDIVX    0x0006    // MS DivX
-#define CODEC_MODE_ODIVX     0x0007    // Open DivX
-#define CODEC_MODE_WAVELET   0x0008    // Wavelet
-
-/* this are the current codec types I want to implement */
-/*  -> type value in structure */
-#define CODEC_TYPE_NONE    0
-#define CODEC_TYPE_L64702  1
-#define CODEC_TYPE_ZR36050 2
-#define CODEC_TYPE_ZR36016 3
-#define CODEC_TYPE_ZR36060 4
-
-/* the type of data may be enhanced by future implementations (data-fn.'s) */
-/*  -> used in command                                                     */
-#define CODEC_G_STATUS         0x0000  /* codec status (query only) */
-#define CODEC_S_CODEC_MODE     0x0001  /* codec mode (baseline JPEG, MPEG1,... */
-#define CODEC_G_CODEC_MODE     0x8001
-#define CODEC_S_VFE            0x0002  /* additional video frontend setup */
-#define CODEC_G_VFE            0x8002
-#define CODEC_S_MMAP           0x0003  /* MMAP setup (if available) */
-
-#define CODEC_S_JPEG_TDS_BYTE  0x0010  /* target data size in bytes */
-#define CODEC_G_JPEG_TDS_BYTE  0x8010
-#define CODEC_S_JPEG_SCALE     0x0011  /* scaling factor for quant. tables */
-#define CODEC_G_JPEG_SCALE     0x8011
-#define CODEC_S_JPEG_HDT_DATA  0x0018  /* huffman-tables */
-#define CODEC_G_JPEG_HDT_DATA  0x8018
-#define CODEC_S_JPEG_QDT_DATA  0x0019  /* quantizing-tables */
-#define CODEC_G_JPEG_QDT_DATA  0x8019
-#define CODEC_S_JPEG_APP_DATA  0x001A  /* APP marker */
-#define CODEC_G_JPEG_APP_DATA  0x801A
-#define CODEC_S_JPEG_COM_DATA  0x001B  /* COM marker */
-#define CODEC_G_JPEG_COM_DATA  0x801B
-
-#define CODEC_S_PRIVATE        0x1000  /* "private" commands start here */
-#define CODEC_G_PRIVATE        0x9000
-
-#define CODEC_G_FLAG           0x8000  /* this is how 'get' is detected */
-
-/* types of transfer, directly user space or a kernel buffer (image-fn.'s) */
-/*  -> used in get_image, put_image                                        */
-#define CODEC_TRANSFER_KERNEL 0        /* use "memcopy" */
-#define CODEC_TRANSFER_USER   1        /* use "to/from_user" */
-\f
-
-/* ========================= */
-/* the structures itself ... */
-/* ========================= */
-
-struct vfe_polarity {
-       unsigned int vsync_pol:1;
-       unsigned int hsync_pol:1;
-       unsigned int field_pol:1;
-       unsigned int blank_pol:1;
-       unsigned int subimg_pol:1;
-       unsigned int poe_pol:1;
-       unsigned int pvalid_pol:1;
-       unsigned int vclk_pol:1;
-};
-
-struct vfe_settings {
-       __u32 x, y;             /* Offsets into image */
-       __u32 width, height;    /* Area to capture */
-       __u16 decimation;       /* Decimation divider */
-       __u16 flags;            /* Flags for capture */
-       __u16 quality;          /* quality of the video */
-};
-
-struct tvnorm {
-       u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
-};
-
-struct jpeg_com_marker {
-       int len; /* number of usable bytes in data */
-       char data[60];
-};
-
-struct jpeg_app_marker {
-       int appn; /* number app segment */
-       int len; /* number of usable bytes in data */
-       char data[60];
-};
-
-struct videocodec {
-       struct module *owner;
-       /* -- filled in by slave device during register -- */
-       char name[32];
-       unsigned long magic;    /* may be used for client<->master attaching */
-       unsigned long flags;    /* functionality flags */
-       unsigned int type;      /* codec type */
-
-       /* -- these is filled in later during master device attach -- */
-
-       struct videocodec_master *master_data;
-
-       /* -- these are filled in by the slave device during register -- */
-
-       void *data;             /* private slave data */
-
-       /* attach/detach client functions (indirect call) */
-       int (*setup) (struct videocodec * codec);
-       int (*unset) (struct videocodec * codec);
-
-       /* main functions, every client needs them for sure! */
-       // set compression or decompression (or freeze, stop, standby, etc)
-       int (*set_mode) (struct videocodec * codec,
-                        int mode);
-       // setup picture size and norm (for the codec's video frontend)
-       int (*set_video) (struct videocodec * codec,
-                         struct tvnorm * norm,
-                         struct vfe_settings * cap,
-                         struct vfe_polarity * pol);
-       // other control commands, also mmap setup etc.
-       int (*control) (struct videocodec * codec,
-                       int type,
-                       int size,
-                       void *data);
-
-       /* additional setup/query/processing (may be NULL pointer) */
-       // interrupt setup / handling (for irq's delivered by master)
-       int (*setup_interrupt) (struct videocodec * codec,
-                               long mode);
-       int (*handle_interrupt) (struct videocodec * codec,
-                                int source,
-                                long flag);
-       // picture interface (if any)
-       long (*put_image) (struct videocodec * codec,
-                          int tr_type,
-                          int block,
-                          long *fr_num,
-                          long *flag,
-                          long size,
-                          void *buf);
-       long (*get_image) (struct videocodec * codec,
-                          int tr_type,
-                          int block,
-                          long *fr_num,
-                          long *flag,
-                          long size,
-                          void *buf);
-};
-
-struct videocodec_master {
-       /* -- filled in by master device for registration -- */
-       char name[32];
-       unsigned long magic;    /* may be used for client<->master attaching */
-       unsigned long flags;    /* functionality flags */
-       unsigned int type;      /* master type */
-
-       void *data;             /* private master data */
-
-        __u32(*readreg) (struct videocodec * codec,
-                         __u16 reg);
-       void (*writereg) (struct videocodec * codec,
-                         __u16 reg,
-                         __u32 value);
-};
-\f
-
-/* ================================================= */
-/* function prototypes of the master/slave interface */
-/* ================================================= */
-
-/* attach and detach commands for the master */
-// * master structure needs to be kmalloc'ed before calling attach
-//   and free'd after calling detach
-// * returns pointer on success, NULL on failure
-extern struct videocodec *videocodec_attach(struct videocodec_master *);
-// * 0 on success, <0 (errno) on failure
-extern int videocodec_detach(struct videocodec *);
-
-/* register and unregister commands for the slaves */
-// * 0 on success, <0 (errno) on failure
-extern int videocodec_register(const struct videocodec *);
-// * 0 on success, <0 (errno) on failure
-extern int videocodec_unregister(const struct videocodec *);
-
-/* the other calls are directly done via the videocodec structure! */
-
-#endif                         /*ifndef __LINUX_VIDEOCODEC_H */
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h
deleted file mode 100644 (file)
index ca2754a..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * zoran - Iomega Buz driver
- *
- * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
- *
- * based on
- *
- * zoran.0.0.3 Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * and
- *
- * bttv - Bt848 frame grabber driver
- * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
- *                        & Marcus Metzler (mocm@thp.uni-koeln.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.
- *
- * 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 _BUZ_H_
-#define _BUZ_H_
-
-#include <media/v4l2-device.h>
-
-struct zoran_sync {
-       unsigned long frame;    /* number of buffer that has been free'd */
-       unsigned long length;   /* number of code bytes in buffer (capture only) */
-       unsigned long seq;      /* frame sequence number */
-       struct timeval timestamp;       /* timestamp */
-};
-
-
-#define ZORAN_NAME    "ZORAN"  /* name of the device */
-
-#define ZR_DEVNAME(zr) ((zr)->name)
-
-#define   BUZ_MAX_WIDTH   (zr->timing->Wa)
-#define   BUZ_MAX_HEIGHT  (zr->timing->Ha)
-#define   BUZ_MIN_WIDTH    32  /* never display less than 32 pixels */
-#define   BUZ_MIN_HEIGHT   24  /* never display less than 24 rows */
-
-#define BUZ_NUM_STAT_COM    4
-#define BUZ_MASK_STAT_COM   3
-
-#define BUZ_MAX_FRAME     256  /* Must be a power of 2 */
-#define BUZ_MASK_FRAME    255  /* Must be BUZ_MAX_FRAME-1 */
-
-#define BUZ_MAX_INPUT       16
-
-#if VIDEO_MAX_FRAME <= 32
-#   define   V4L_MAX_FRAME   32
-#elif VIDEO_MAX_FRAME <= 64
-#   define   V4L_MAX_FRAME   64
-#else
-#   error   "Too many video frame buffers to handle"
-#endif
-#define   V4L_MASK_FRAME   (V4L_MAX_FRAME - 1)
-
-#define MAX_FRAME (BUZ_MAX_FRAME > VIDEO_MAX_FRAME ? BUZ_MAX_FRAME : VIDEO_MAX_FRAME)
-
-#include "zr36057.h"
-
-enum card_type {
-       UNKNOWN = -1,
-
-       /* Pinnacle/Miro */
-       DC10_old,               /* DC30 like */
-       DC10_new,               /* DC10plus like */
-       DC10plus,
-       DC30,
-       DC30plus,
-
-       /* Linux Media Labs */
-       LML33,
-       LML33R10,
-
-       /* Iomega */
-       BUZ,
-
-       /* AverMedia */
-       AVS6EYES,
-
-       /* total number of cards */
-       NUM_CARDS
-};
-
-enum zoran_codec_mode {
-       BUZ_MODE_IDLE,          /* nothing going on */
-       BUZ_MODE_MOTION_COMPRESS,       /* grabbing frames */
-       BUZ_MODE_MOTION_DECOMPRESS,     /* playing frames */
-       BUZ_MODE_STILL_COMPRESS,        /* still frame conversion */
-       BUZ_MODE_STILL_DECOMPRESS       /* still frame conversion */
-};
-
-enum zoran_buffer_state {
-       BUZ_STATE_USER,         /* buffer is owned by application */
-       BUZ_STATE_PEND,         /* buffer is queued in pend[] ready to feed to I/O */
-       BUZ_STATE_DMA,          /* buffer is queued in dma[] for I/O */
-       BUZ_STATE_DONE          /* buffer is ready to return to application */
-};
-
-enum zoran_map_mode {
-       ZORAN_MAP_MODE_RAW,
-       ZORAN_MAP_MODE_JPG_REC,
-#define ZORAN_MAP_MODE_JPG ZORAN_MAP_MODE_JPG_REC
-       ZORAN_MAP_MODE_JPG_PLAY,
-};
-
-enum gpio_type {
-       ZR_GPIO_JPEG_SLEEP = 0,
-       ZR_GPIO_JPEG_RESET,
-       ZR_GPIO_JPEG_FRAME,
-       ZR_GPIO_VID_DIR,
-       ZR_GPIO_VID_EN,
-       ZR_GPIO_VID_RESET,
-       ZR_GPIO_CLK_SEL1,
-       ZR_GPIO_CLK_SEL2,
-       ZR_GPIO_MAX,
-};
-
-enum gpcs_type {
-       GPCS_JPEG_RESET = 0,
-       GPCS_JPEG_START,
-       GPCS_MAX,
-};
-
-struct zoran_format {
-       char *name;
-       __u32 fourcc;
-       int colorspace;
-       int depth;
-       __u32 flags;
-       __u32 vfespfr;
-};
-/* flags */
-#define ZORAN_FORMAT_COMPRESSED 1<<0
-#define ZORAN_FORMAT_OVERLAY    1<<1
-#define ZORAN_FORMAT_CAPTURE   1<<2
-#define ZORAN_FORMAT_PLAYBACK  1<<3
-
-/* overlay-settings */
-struct zoran_overlay_settings {
-       int is_set;
-       int x, y, width, height;        /* position */
-       int clipcount;          /* position and number of clips */
-       const struct zoran_format *format;      /* overlay format */
-};
-
-/* v4l-capture settings */
-struct zoran_v4l_settings {
-       int width, height, bytesperline;        /* capture size */
-       const struct zoran_format *format;      /* capture format */
-};
-
-/* jpg-capture/-playback settings */
-struct zoran_jpg_settings {
-       int decimation;         /* this bit is used to set everything to default */
-       int HorDcm, VerDcm, TmpDcm;     /* capture decimation settings (TmpDcm=1 means both fields) */
-       int field_per_buff, odd_even;   /* field-settings (odd_even=1 (+TmpDcm=1) means top-field-first) */
-       int img_x, img_y, img_width, img_height;        /* crop settings (subframe capture) */
-       struct v4l2_jpegcompression jpg_comp;   /* JPEG-specific capture settings */
-};
-
-struct zoran_fh;
-
-struct zoran_mapping {
-       struct zoran_fh *fh;
-       int count;
-};
-
-struct zoran_buffer {
-       struct zoran_mapping *map;
-       enum zoran_buffer_state state;  /* state: unused/pending/dma/done */
-       struct zoran_sync bs;           /* DONE: info to return to application */
-       union {
-               struct {
-                       __le32 *frag_tab;       /* addresses of frag table */
-                       u32 frag_tab_bus;       /* same value cached to save time in ISR */
-               } jpg;
-               struct {
-                       char *fbuffer;          /* virtual address of frame buffer */
-                       unsigned long fbuffer_phys;/* physical address of frame buffer */
-                       unsigned long fbuffer_bus;/* bus address of frame buffer */
-               } v4l;
-       };
-};
-
-enum zoran_lock_activity {
-       ZORAN_FREE,             /* free for use */
-       ZORAN_ACTIVE,           /* active but unlocked */
-       ZORAN_LOCKED,           /* locked */
-};
-
-/* buffer collections */
-struct zoran_buffer_col {
-       enum zoran_lock_activity active;        /* feature currently in use? */
-       unsigned int num_buffers, buffer_size;
-       struct zoran_buffer buffer[MAX_FRAME];  /* buffers */
-       u8 allocated;           /* Flag if buffers are allocated  */
-       u8 need_contiguous;     /* Flag if contiguous buffers are needed */
-       /* only applies to jpg buffers, raw buffers are always contiguous */
-};
-
-struct zoran;
-
-/* zoran_fh contains per-open() settings */
-struct zoran_fh {
-       struct zoran *zr;
-
-       enum zoran_map_mode map_mode;           /* Flag which bufferset will map by next mmap() */
-
-       struct zoran_overlay_settings overlay_settings;
-       u32 *overlay_mask;                      /* overlay mask */
-       enum zoran_lock_activity overlay_active;/* feature currently in use? */
-
-       struct zoran_buffer_col buffers;        /* buffers' info */
-
-       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
-       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
-};
-
-struct card_info {
-       enum card_type type;
-       char name[32];
-       const char *i2c_decoder;        /* i2c decoder device */
-       const unsigned short *addrs_decoder;
-       const char *i2c_encoder;        /* i2c encoder device */
-       const unsigned short *addrs_encoder;
-       u16 video_vfe, video_codec;                     /* videocodec types */
-       u16 audio_chip;                                 /* audio type */
-
-       int inputs;             /* number of video inputs */
-       struct input {
-               int muxsel;
-               char name[32];
-       } input[BUZ_MAX_INPUT];
-
-       v4l2_std_id norms;
-       struct tvnorm *tvn[3];  /* supported TV norms */
-
-       u32 jpeg_int;           /* JPEG interrupt */
-       u32 vsync_int;          /* VSYNC interrupt */
-       s8 gpio[ZR_GPIO_MAX];
-       u8 gpcs[GPCS_MAX];
-
-       struct vfe_polarity vfe_pol;
-       u8 gpio_pol[ZR_GPIO_MAX];
-
-       /* is the /GWS line connected? */
-       u8 gws_not_connected;
-
-       /* avs6eyes mux setting */
-       u8 input_mux;
-
-       void (*init) (struct zoran * zr);
-};
-
-struct zoran {
-       struct v4l2_device v4l2_dev;
-       struct video_device *video_dev;
-
-       struct i2c_adapter i2c_adapter; /* */
-       struct i2c_algo_bit_data i2c_algo;      /* */
-       u32 i2cbr;
-
-       struct v4l2_subdev *decoder;    /* video decoder sub-device */
-       struct v4l2_subdev *encoder;    /* video encoder sub-device */
-
-       struct videocodec *codec;       /* video codec */
-       struct videocodec *vfe; /* video front end */
-
-       struct mutex resource_lock;     /* prevent evil stuff */
-       struct mutex other_lock;        /* please merge with above */
-
-       u8 initialized;         /* flag if zoran has been correctly initialized */
-       int user;               /* number of current users */
-       struct card_info card;
-       struct tvnorm *timing;
-
-       unsigned short id;      /* number of this device */
-       char name[32];          /* name of this device */
-       struct pci_dev *pci_dev;        /* PCI device */
-       unsigned char revision; /* revision of zr36057 */
-       unsigned char __iomem *zr36057_mem;/* pointer to mapped IO memory */
-
-       spinlock_t spinlock;    /* Spinlock */
-
-       /* Video for Linux parameters */
-       int input;      /* card's norm and input */
-       v4l2_std_id norm;
-
-       /* Current buffer params */
-       void    *vbuf_base;
-       int     vbuf_height, vbuf_width;
-       int     vbuf_depth;
-       int     vbuf_bytesperline;
-
-       struct zoran_overlay_settings overlay_settings;
-       u32 *overlay_mask;      /* overlay mask */
-       enum zoran_lock_activity overlay_active;        /* feature currently in use? */
-
-       wait_queue_head_t v4l_capq;
-
-       int v4l_overlay_active; /* Overlay grab is activated */
-       int v4l_memgrab_active; /* Memory grab is activated */
-
-       int v4l_grab_frame;     /* Frame number being currently grabbed */
-#define NO_GRAB_ACTIVE (-1)
-       unsigned long v4l_grab_seq;     /* Number of frames grabbed */
-       struct zoran_v4l_settings v4l_settings; /* structure with a lot of things to play with */
-
-       /* V4L grab queue of frames pending */
-       unsigned long v4l_pend_head;
-       unsigned long v4l_pend_tail;
-       unsigned long v4l_sync_tail;
-       int v4l_pend[V4L_MAX_FRAME];
-       struct zoran_buffer_col v4l_buffers;    /* V4L buffers' info */
-
-       /* Buz MJPEG parameters */
-       enum zoran_codec_mode codec_mode;       /* status of codec */
-       struct zoran_jpg_settings jpg_settings; /* structure with a lot of things to play with */
-
-       wait_queue_head_t jpg_capq;     /* wait here for grab to finish */
-
-       /* grab queue counts/indices, mask with BUZ_MASK_STAT_COM before using as index */
-       /* (dma_head - dma_tail) is number active in DMA, must be <= BUZ_NUM_STAT_COM */
-       /* (value & BUZ_MASK_STAT_COM) corresponds to index in stat_com table */
-       unsigned long jpg_que_head;     /* Index where to put next buffer which is queued */
-       unsigned long jpg_dma_head;     /* Index of next buffer which goes into stat_com  */
-       unsigned long jpg_dma_tail;     /* Index of last buffer in stat_com               */
-       unsigned long jpg_que_tail;     /* Index of last buffer in queue                  */
-       unsigned long jpg_seq_num;      /* count of frames since grab/play started        */
-       unsigned long jpg_err_seq;      /* last seq_num before error                      */
-       unsigned long jpg_err_shift;
-       unsigned long jpg_queued_num;   /* count of frames queued since grab/play started */
-
-       /* zr36057's code buffer table */
-       __le32 *stat_com;               /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
-
-       /* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
-       int jpg_pend[BUZ_MAX_FRAME];
-
-       /* array indexed by frame number */
-       struct zoran_buffer_col jpg_buffers;    /* MJPEG buffers' info */
-
-       /* Additional stuff for testing */
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *zoran_proc;
-#else
-       void *zoran_proc;
-#endif
-       int testing;
-       int jpeg_error;
-       int intr_counter_GIRQ1;
-       int intr_counter_GIRQ0;
-       int intr_counter_CodRepIRQ;
-       int intr_counter_JPEGRepIRQ;
-       int field_counter;
-       int IRQ1_in;
-       int IRQ1_out;
-       int JPEG_in;
-       int JPEG_out;
-       int JPEG_0;
-       int JPEG_1;
-       int END_event_missed;
-       int JPEG_missed;
-       int JPEG_error;
-       int num_errors;
-       int JPEG_max_missed;
-       int JPEG_min_missed;
-
-       u32 last_isr;
-       unsigned long frame_num;
-
-       wait_queue_head_t test_q;
-};
-
-static inline struct zoran *to_zoran(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct zoran, v4l2_dev);
-}
-
-/* There was something called _ALPHA_BUZ that used the PCI address instead of
- * the kernel iomapped address for btread/btwrite.  */
-#define btwrite(dat,adr)    writel((dat), zr->zr36057_mem+(adr))
-#define btread(adr)         readl(zr->zr36057_mem+(adr))
-
-#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
-#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
-#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
-
-#endif
diff --git a/drivers/media/video/zoran/zoran_card.c b/drivers/media/video/zoran/zoran_card.c
deleted file mode 100644 (file)
index c3602d6..0000000
+++ /dev/null
@@ -1,1524 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.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/delay.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-
-#include <linux/proc_fs.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev2.h>
-#include <linux/spinlock.h>
-#include <linux/sem.h>
-#include <linux/kmod.h>
-#include <linux/wait.h>
-
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-#include <media/v4l2-common.h>
-#include <media/bt819.h>
-
-#include "videocodec.h"
-#include "zoran.h"
-#include "zoran_card.h"
-#include "zoran_device.h"
-#include "zoran_procfs.h"
-
-extern const struct zoran_format zoran_formats[];
-
-static int card[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
-module_param_array(card, int, NULL, 0444);
-MODULE_PARM_DESC(card, "Card type");
-
-/*
-   The video mem address of the video card.
-   The driver has a little database for some videocards
-   to determine it from there. If your video card is not in there
-   you have either to give it to the driver as a parameter
-   or set in in a VIDIOCSFBUF ioctl
- */
-
-static unsigned long vidmem;   /* default = 0 - Video memory base address */
-module_param(vidmem, ulong, 0444);
-MODULE_PARM_DESC(vidmem, "Default video memory base address");
-
-/*
-   Default input and video norm at startup of the driver.
-*/
-
-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)");
-
-static int default_mux = 1;    /* 6 Eyes input selection */
-module_param(default_mux, int, 0644);
-MODULE_PARM_DESC(default_mux,
-                "Default 6 Eyes mux setting (Input selection)");
-
-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)");
-
-/* /dev/videoN, -1 for autodetect */
-static int video_nr[BUZ_MAX] = { [0 ... (BUZ_MAX-1)] = -1 };
-module_param_array(video_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "Video device number (-1=Auto)");
-
-int v4l_nbufs = 4;
-int v4l_bufsize = 864;         /* Everybody should be able to work with this setting */
-module_param(v4l_nbufs, int, 0644);
-MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use");
-module_param(v4l_bufsize, int, 0644);
-MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)");
-
-int jpg_nbufs = 32;
-int jpg_bufsize = 512;         /* max size for 100% quality full-PAL frame */
-module_param(jpg_nbufs, int, 0644);
-MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use");
-module_param(jpg_bufsize, int, 0644);
-MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)");
-
-int pass_through = 0;          /* 1=Pass through TV signal when device is not used */
-                               /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */
-module_param(pass_through, int, 0644);
-MODULE_PARM_DESC(pass_through,
-                "Pass TV signal through to TV-out when idling");
-
-int zr36067_debug = 1;
-module_param_named(debug, zr36067_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-5)");
-
-#define ZORAN_VERSION "0.10.1"
-
-MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver");
-MODULE_AUTHOR("Serguei Miridonov");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(ZORAN_VERSION);
-
-#define ZR_DEVICE(subven, subdev, data)        { \
-       .vendor = PCI_VENDOR_ID_ZORAN, .device = PCI_DEVICE_ID_ZORAN_36057, \
-       .subvendor = (subven), .subdevice = (subdev), .driver_data = (data) }
-
-static struct pci_device_id zr36067_pci_tbl[] = {
-       ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC10PLUS, DC10plus),
-       ZR_DEVICE(PCI_VENDOR_ID_MIRO, PCI_DEVICE_ID_MIRO_DC30PLUS, DC30plus),
-       ZR_DEVICE(PCI_VENDOR_ID_ELECTRONICDESIGNGMBH, PCI_DEVICE_ID_LML_33R10, LML33R10),
-       ZR_DEVICE(PCI_VENDOR_ID_IOMEGA, PCI_DEVICE_ID_IOMEGA_BUZ, BUZ),
-       ZR_DEVICE(PCI_ANY_ID, PCI_ANY_ID, NUM_CARDS),
-       {0}
-};
-MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl);
-
-static unsigned int zoran_num;         /* number of cards found */
-
-/* videocodec bus functions ZR36060 */
-static u32
-zr36060_read (struct videocodec *codec,
-             u16                reg)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-       __u32 data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 0, 1, reg >> 8)
-           || post_office_write(zr, 0, 2, reg & 0xff)) {
-               return -1;
-       }
-
-       data = post_office_read(zr, 0, 3) & 0xff;
-       return data;
-}
-
-static void
-zr36060_write (struct videocodec *codec,
-              u16                reg,
-              u32                val)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 0, 1, reg >> 8)
-           || post_office_write(zr, 0, 2, reg & 0xff)) {
-               return;
-       }
-
-       post_office_write(zr, 0, 3, val & 0xff);
-}
-
-/* videocodec bus functions ZR36050 */
-static u32
-zr36050_read (struct videocodec *codec,
-             u16                reg)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-       __u32 data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
-               return -1;
-       }
-
-       data = post_office_read(zr, 0, reg & 0x03) & 0xff;      // reg. LOWBYTES + read
-       return data;
-}
-
-static void
-zr36050_write (struct videocodec *codec,
-              u16                reg,
-              u32                val)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-
-       if (post_office_wait(zr)
-           || post_office_write(zr, 1, 0, reg >> 2)) { // reg. HIGHBYTES
-               return;
-       }
-
-       post_office_write(zr, 0, reg & 0x03, val & 0xff);       // reg. LOWBYTES + wr. data
-}
-
-/* videocodec bus functions ZR36016 */
-static u32
-zr36016_read (struct videocodec *codec,
-             u16                reg)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-       __u32 data;
-
-       if (post_office_wait(zr)) {
-               return -1;
-       }
-
-       data = post_office_read(zr, 2, reg & 0x03) & 0xff;      // read
-       return data;
-}
-
-/* hack for in zoran_device.c */
-void
-zr36016_write (struct videocodec *codec,
-              u16                reg,
-              u32                val)
-{
-       struct zoran *zr = (struct zoran *) codec->master_data->data;
-
-       if (post_office_wait(zr)) {
-               return;
-       }
-
-       post_office_write(zr, 2, reg & 0x03, val & 0x0ff);      // wr. data
-}
-
-/*
- * Board specific information
- */
-
-static void
-dc10_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
-
-       /* Pixel clock selection */
-       GPIO(zr, 4, 0);
-       GPIO(zr, 5, 1);
-       /* Enable the video bus sync signals */
-       GPIO(zr, 7, 0);
-}
-
-static void
-dc10plus_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
-}
-
-static void
-buz_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
-
-       /* some stuff from Iomega */
-       pci_write_config_dword(zr->pci_dev, 0xfc, 0x90680f15);
-       pci_write_config_dword(zr->pci_dev, 0x0c, 0x00012020);
-       pci_write_config_dword(zr->pci_dev, 0xe8, 0xc0200000);
-}
-
-static void
-lml33_init (struct zoran *zr)
-{
-       dprintk(3, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
-
-       GPIO(zr, 2, 1);         // Set Composite input/output
-}
-
-static void
-avs6eyes_init (struct zoran *zr)
-{
-       // AverMedia 6-Eyes original driver by Christer Weinigel
-
-       // Lifted straight from Christer's old driver and
-       // modified slightly by Martin Samuelsson.
-
-       int mux = default_mux; /* 1 = BT866, 7 = VID1 */
-
-       GPIO(zr, 4, 1); /* Bt866 SLEEP on */
-       udelay(2);
-
-       GPIO(zr, 0, 1); /* ZR36060 /RESET on */
-       GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
-       GPIO(zr, 2, mux & 1);   /* MUX S0 */
-       GPIO(zr, 3, 0); /* /FRAME on */
-       GPIO(zr, 4, 0); /* Bt866 SLEEP off */
-       GPIO(zr, 5, mux & 2);   /* MUX S1 */
-       GPIO(zr, 6, 0); /* ? */
-       GPIO(zr, 7, mux & 4);   /* MUX S2 */
-
-}
-
-static char *
-codecid_to_modulename (u16 codecid)
-{
-       char *name = NULL;
-
-       switch (codecid) {
-       case CODEC_TYPE_ZR36060:
-               name = "zr36060";
-               break;
-       case CODEC_TYPE_ZR36050:
-               name = "zr36050";
-               break;
-       case CODEC_TYPE_ZR36016:
-               name = "zr36016";
-               break;
-       }
-
-       return name;
-}
-
-// struct tvnorm {
-//      u16 Wt, Wa, HStart, HSyncStart, Ht, Ha, VStart;
-// };
-
-static struct tvnorm f50sqpixel = { 944, 768, 83, 880, 625, 576, 16 };
-static struct tvnorm f60sqpixel = { 780, 640, 51, 716, 525, 480, 12 };
-static struct tvnorm f50ccir601 = { 864, 720, 75, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601 = { 858, 720, 57, 788, 525, 480, 16 };
-
-static struct tvnorm f50ccir601_lml33 = { 864, 720, 75+34, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601_lml33 = { 858, 720, 57+34, 788, 525, 480, 16 };
-
-/* The DC10 (57/16/50) uses VActive as HSync, so HStart must be 0 */
-static struct tvnorm f50sqpixel_dc10 = { 944, 768, 0, 880, 625, 576, 0 };
-static struct tvnorm f60sqpixel_dc10 = { 780, 640, 0, 716, 525, 480, 12 };
-
-/* FIXME: I cannot swap U and V in saa7114, so i do one
- * pixel left shift in zoran (75 -> 74)
- * (Maxim Yevtyushkin <max@linuxmedialabs.com>) */
-static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 };
-
-/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I
- * copy Maxim's left shift hack for the 6 Eyes.
- *
- * Christer's driver used the unshifted norms, though...
- * /Sam  */
-static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
-static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
-
-static const unsigned short vpx3220_addrs[] = { 0x43, 0x47, I2C_CLIENT_END };
-static const unsigned short saa7110_addrs[] = { 0x4e, 0x4f, I2C_CLIENT_END };
-static const unsigned short saa7111_addrs[] = { 0x25, 0x24, I2C_CLIENT_END };
-static const unsigned short saa7114_addrs[] = { 0x21, 0x20, I2C_CLIENT_END };
-static const unsigned short adv717x_addrs[] = { 0x6a, 0x6b, 0x2a, 0x2b, I2C_CLIENT_END };
-static const unsigned short ks0127_addrs[] = { 0x6c, 0x6d, I2C_CLIENT_END };
-static const unsigned short saa7185_addrs[] = { 0x44, I2C_CLIENT_END };
-static const unsigned short bt819_addrs[] = { 0x45, I2C_CLIENT_END };
-static const unsigned short bt856_addrs[] = { 0x44, I2C_CLIENT_END };
-static const unsigned short bt866_addrs[] = { 0x44, I2C_CLIENT_END };
-
-static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
-       {
-               .type = DC10_old,
-               .name = "DC10(old)",
-               .i2c_decoder = "vpx3220a",
-               .addrs_decoder = vpx3220_addrs,
-               .video_codec = CODEC_TYPE_ZR36050,
-               .video_vfe = CODEC_TYPE_ZR36016,
-
-               .inputs = 3,
-               .input = {
-                       { 1, "Composite" },
-                       { 2, "S-Video" },
-                       { 0, "Internal/comp" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
-               .tvn = {
-                       &f50sqpixel_dc10,
-                       &f60sqpixel_dc10,
-                       &f50sqpixel_dc10
-               },
-               .jpeg_int = 0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
-               .gpcs = { -1, 0 },
-               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10_init,
-       }, {
-               .type = DC10_new,
-               .name = "DC10(new)",
-               .i2c_decoder = "saa7110",
-               .addrs_decoder = saa7110_addrs,
-               .i2c_encoder = "adv7175",
-               .addrs_encoder = adv717x_addrs,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 3,
-               .input = {
-                               { 0, "Composite" },
-                               { 7, "S-Video" },
-                               { 5, "Internal/comp" }
-                       },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
-               .tvn = {
-                               &f50sqpixel,
-                               &f60sqpixel,
-                               &f50sqpixel},
-               .jpeg_int = ZR36057_ISR_GIRQ0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gpcs = { -1, 1},
-               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10plus_init,
-       }, {
-               .type = DC10plus,
-               .name = "DC10plus",
-               .i2c_decoder = "saa7110",
-               .addrs_decoder = saa7110_addrs,
-               .i2c_encoder = "adv7175",
-               .addrs_encoder = adv717x_addrs,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 3,
-               .input = {
-                       { 0, "Composite" },
-                       { 7, "S-Video" },
-                       { 5, "Internal/comp" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
-               .tvn = {
-                       &f50sqpixel,
-                       &f60sqpixel,
-                       &f50sqpixel
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 3, 0, 6, 1, 2, -1, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gpcs = { -1, 1 },
-               .vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10plus_init,
-       }, {
-               .type = DC30,
-               .name = "DC30",
-               .i2c_decoder = "vpx3220a",
-               .addrs_decoder = vpx3220_addrs,
-               .i2c_encoder = "adv7175",
-               .addrs_encoder = adv717x_addrs,
-               .video_codec = CODEC_TYPE_ZR36050,
-               .video_vfe = CODEC_TYPE_ZR36016,
-
-               .inputs = 3,
-               .input = {
-                       { 1, "Composite" },
-                       { 2, "S-Video" },
-                       { 0, "Internal/comp" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
-               .tvn = {
-                       &f50sqpixel_dc10,
-                       &f60sqpixel_dc10,
-                       &f50sqpixel_dc10
-               },
-               .jpeg_int = 0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
-               .gpcs = { -1, 0 },
-               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10_init,
-       }, {
-               .type = DC30plus,
-               .name = "DC30plus",
-               .i2c_decoder = "vpx3220a",
-               .addrs_decoder = vpx3220_addrs,
-               .i2c_encoder = "adv7175",
-               .addrs_encoder = adv717x_addrs,
-               .video_codec = CODEC_TYPE_ZR36050,
-               .video_vfe = CODEC_TYPE_ZR36016,
-
-               .inputs = 3,
-               .input = {
-                       { 1, "Composite" },
-                       { 2, "S-Video" },
-                       { 0, "Internal/comp" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
-               .tvn = {
-                       &f50sqpixel_dc10,
-                       &f60sqpixel_dc10,
-                       &f50sqpixel_dc10
-               },
-               .jpeg_int = 0,
-               .vsync_int = ZR36057_ISR_GIRQ1,
-               .gpio = { 2, 1, -1, 3, 7, 0, 4, 5 },
-               .gpio_pol = { 0, 0, 0, 1, 0, 0, 0, 0 },
-               .gpcs = { -1, 0 },
-               .vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gws_not_connected = 0,
-               .input_mux = 0,
-               .init = &dc10_init,
-       }, {
-               .type = LML33,
-               .name = "LML33",
-               .i2c_decoder = "bt819a",
-               .addrs_decoder = bt819_addrs,
-               .i2c_encoder = "bt856",
-               .addrs_encoder = bt856_addrs,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 2,
-               .input = {
-                       { 0, "Composite" },
-                       { 7, "S-Video" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL,
-               .tvn = {
-                       &f50ccir601_lml33,
-                       &f60ccir601_lml33,
-                       NULL
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
-               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
-               .gpcs = { 3, 1 },
-               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
-               .gws_not_connected = 1,
-               .input_mux = 0,
-               .init = &lml33_init,
-       }, {
-               .type = LML33R10,
-               .name = "LML33R10",
-               .i2c_decoder = "saa7114",
-               .addrs_decoder = saa7114_addrs,
-               .i2c_encoder = "adv7170",
-               .addrs_encoder = adv717x_addrs,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 2,
-               .input = {
-                       { 0, "Composite" },
-                       { 7, "S-Video" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL,
-               .tvn = {
-                       &f50ccir601_lm33r10,
-                       &f60ccir601_lm33r10,
-                       NULL
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, -1, 3, 5, 7, -1, -1, -1 },
-               .gpio_pol = { 0, 0, 0, 0, 1, 0, 0, 0 },
-               .gpcs = { 3, 1 },
-               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
-               .gws_not_connected = 1,
-               .input_mux = 0,
-               .init = &lml33_init,
-       }, {
-               .type = BUZ,
-               .name = "Buz",
-               .i2c_decoder = "saa7111",
-               .addrs_decoder = saa7111_addrs,
-               .i2c_encoder = "saa7185",
-               .addrs_encoder = saa7185_addrs,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 2,
-               .input = {
-                       { 3, "Composite" },
-                       { 7, "S-Video" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
-               .tvn = {
-                       &f50ccir601,
-                       &f60ccir601,
-                       &f50ccir601
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, -1, 3, -1, -1, -1, -1, -1 },
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
-               .gpcs = { 3, 1 },
-               .vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
-               .gws_not_connected = 1,
-               .input_mux = 0,
-               .init = &buz_init,
-       }, {
-               .type = AVS6EYES,
-               .name = "6-Eyes",
-               /* AverMedia chose not to brand the 6-Eyes. Thus it
-                  can't be autodetected, and requires card=x. */
-               .i2c_decoder = "ks0127",
-               .addrs_decoder = ks0127_addrs,
-               .i2c_encoder = "bt866",
-               .addrs_encoder = bt866_addrs,
-               .video_codec = CODEC_TYPE_ZR36060,
-
-               .inputs = 10,
-               .input = {
-                       { 0, "Composite 1" },
-                       { 1, "Composite 2" },
-                       { 2, "Composite 3" },
-                       { 4, "Composite 4" },
-                       { 5, "Composite 5" },
-                       { 6, "Composite 6" },
-                       { 8, "S-Video 1" },
-                       { 9, "S-Video 2" },
-                       {10, "S-Video 3" },
-                       {15, "YCbCr" }
-               },
-               .norms = V4L2_STD_NTSC|V4L2_STD_PAL,
-               .tvn = {
-                       &f50ccir601_avs6eyes,
-                       &f60ccir601_avs6eyes,
-                       NULL
-               },
-               .jpeg_int = ZR36057_ISR_GIRQ1,
-               .vsync_int = ZR36057_ISR_GIRQ0,
-               .gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
-               .gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
-               .gpcs = { 3, 1 },                       // Validity unknown /Sam
-               .vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 },  // Validity unknown /Sam
-               .gws_not_connected = 1,
-               .input_mux = 1,
-               .init = &avs6eyes_init,
-       }
-
-};
-
-/*
- * I2C functions
- */
-/* software I2C functions */
-static int
-zoran_i2c_getsda (void *data)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       return (btread(ZR36057_I2CBR) >> 1) & 1;
-}
-
-static int
-zoran_i2c_getscl (void *data)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       return btread(ZR36057_I2CBR) & 1;
-}
-
-static void
-zoran_i2c_setsda (void *data,
-                 int   state)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       if (state)
-               zr->i2cbr |= 2;
-       else
-               zr->i2cbr &= ~2;
-       btwrite(zr->i2cbr, ZR36057_I2CBR);
-}
-
-static void
-zoran_i2c_setscl (void *data,
-                 int   state)
-{
-       struct zoran *zr = (struct zoran *) data;
-
-       if (state)
-               zr->i2cbr |= 1;
-       else
-               zr->i2cbr &= ~1;
-       btwrite(zr->i2cbr, ZR36057_I2CBR);
-}
-
-static const struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
-       .setsda = zoran_i2c_setsda,
-       .setscl = zoran_i2c_setscl,
-       .getsda = zoran_i2c_getsda,
-       .getscl = zoran_i2c_getscl,
-       .udelay = 10,
-       .timeout = 100,
-};
-
-static int
-zoran_register_i2c (struct zoran *zr)
-{
-       memcpy(&zr->i2c_algo, &zoran_i2c_bit_data_template,
-              sizeof(struct i2c_algo_bit_data));
-       zr->i2c_algo.data = zr;
-       strlcpy(zr->i2c_adapter.name, ZR_DEVNAME(zr),
-               sizeof(zr->i2c_adapter.name));
-       i2c_set_adapdata(&zr->i2c_adapter, &zr->v4l2_dev);
-       zr->i2c_adapter.algo_data = &zr->i2c_algo;
-       zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
-       return i2c_bit_add_bus(&zr->i2c_adapter);
-}
-
-static void
-zoran_unregister_i2c (struct zoran *zr)
-{
-       i2c_del_adapter(&zr->i2c_adapter);
-}
-
-/* Check a zoran_params struct for correctness, insert default params */
-
-int
-zoran_check_jpg_settings (struct zoran              *zr,
-                         struct zoran_jpg_settings *settings,
-                         int try)
-{
-       int err = 0, err0 = 0;
-
-       dprintk(4,
-               KERN_DEBUG
-               "%s: %s - dec: %d, Hdcm: %d, Vdcm: %d, Tdcm: %d\n",
-               ZR_DEVNAME(zr), __func__, settings->decimation, settings->HorDcm,
-               settings->VerDcm, settings->TmpDcm);
-       dprintk(4,
-               KERN_DEBUG
-               "%s: %s - x: %d, y: %d, w: %d, y: %d\n",
-               ZR_DEVNAME(zr), __func__, settings->img_x, settings->img_y,
-               settings->img_width, settings->img_height);
-       /* Check decimation, set default values for decimation = 1, 2, 4 */
-       switch (settings->decimation) {
-       case 1:
-
-               settings->HorDcm = 1;
-               settings->VerDcm = 1;
-               settings->TmpDcm = 1;
-               settings->field_per_buff = 2;
-               settings->img_x = 0;
-               settings->img_y = 0;
-               settings->img_width = BUZ_MAX_WIDTH;
-               settings->img_height = BUZ_MAX_HEIGHT / 2;
-               break;
-       case 2:
-
-               settings->HorDcm = 2;
-               settings->VerDcm = 1;
-               settings->TmpDcm = 2;
-               settings->field_per_buff = 1;
-               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
-               settings->img_y = 0;
-               settings->img_width =
-                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
-               settings->img_height = BUZ_MAX_HEIGHT / 2;
-               break;
-       case 4:
-
-               if (zr->card.type == DC10_new) {
-                       dprintk(1,
-                               KERN_DEBUG
-                               "%s: %s - HDec by 4 is not supported on the DC10\n",
-                               ZR_DEVNAME(zr), __func__);
-                       err0++;
-                       break;
-               }
-
-               settings->HorDcm = 4;
-               settings->VerDcm = 2;
-               settings->TmpDcm = 2;
-               settings->field_per_buff = 1;
-               settings->img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
-               settings->img_y = 0;
-               settings->img_width =
-                   (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
-               settings->img_height = BUZ_MAX_HEIGHT / 2;
-               break;
-       case 0:
-
-               /* We have to check the data the user has set */
-
-               if (settings->HorDcm != 1 && settings->HorDcm != 2 &&
-                   (zr->card.type == DC10_new || settings->HorDcm != 4)) {
-                       settings->HorDcm = clamp(settings->HorDcm, 1, 2);
-                       err0++;
-               }
-               if (settings->VerDcm != 1 && settings->VerDcm != 2) {
-                       settings->VerDcm = clamp(settings->VerDcm, 1, 2);
-                       err0++;
-               }
-               if (settings->TmpDcm != 1 && settings->TmpDcm != 2) {
-                       settings->TmpDcm = clamp(settings->TmpDcm, 1, 2);
-                       err0++;
-               }
-               if (settings->field_per_buff != 1 &&
-                   settings->field_per_buff != 2) {
-                       settings->field_per_buff = clamp(settings->field_per_buff, 1, 2);
-                       err0++;
-               }
-               if (settings->img_x < 0) {
-                       settings->img_x = 0;
-                       err0++;
-               }
-               if (settings->img_y < 0) {
-                       settings->img_y = 0;
-                       err0++;
-               }
-               if (settings->img_width < 0 || settings->img_width > BUZ_MAX_WIDTH) {
-                       settings->img_width = clamp(settings->img_width, 0, (int)BUZ_MAX_WIDTH);
-                       err0++;
-               }
-               if (settings->img_height < 0 || settings->img_height > BUZ_MAX_HEIGHT / 2) {
-                       settings->img_height = clamp(settings->img_height, 0, BUZ_MAX_HEIGHT / 2);
-                       err0++;
-               }
-               if (settings->img_x + settings->img_width > BUZ_MAX_WIDTH) {
-                       settings->img_x = BUZ_MAX_WIDTH - settings->img_width;
-                       err0++;
-               }
-               if (settings->img_y + settings->img_height > BUZ_MAX_HEIGHT / 2) {
-                       settings->img_y = BUZ_MAX_HEIGHT / 2 - settings->img_height;
-                       err0++;
-               }
-               if (settings->img_width % (16 * settings->HorDcm) != 0) {
-                       settings->img_width -= settings->img_width % (16 * settings->HorDcm);
-                       if (settings->img_width == 0)
-                               settings->img_width = 16 * settings->HorDcm;
-                       err0++;
-               }
-               if (settings->img_height % (8 * settings->VerDcm) != 0) {
-                       settings->img_height -= settings->img_height % (8 * settings->VerDcm);
-                       if (settings->img_height == 0)
-                               settings->img_height = 8 * settings->VerDcm;
-                       err0++;
-               }
-
-               if (!try && err0) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - error in params for decimation = 0\n",
-                               ZR_DEVNAME(zr), __func__);
-                       err++;
-               }
-               break;
-       default:
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - decimation = %d, must be 0, 1, 2 or 4\n",
-                       ZR_DEVNAME(zr), __func__, settings->decimation);
-               err++;
-               break;
-       }
-
-       if (settings->jpg_comp.quality > 100)
-               settings->jpg_comp.quality = 100;
-       if (settings->jpg_comp.quality < 5)
-               settings->jpg_comp.quality = 5;
-       if (settings->jpg_comp.APPn < 0)
-               settings->jpg_comp.APPn = 0;
-       if (settings->jpg_comp.APPn > 15)
-               settings->jpg_comp.APPn = 15;
-       if (settings->jpg_comp.APP_len < 0)
-               settings->jpg_comp.APP_len = 0;
-       if (settings->jpg_comp.APP_len > 60)
-               settings->jpg_comp.APP_len = 60;
-       if (settings->jpg_comp.COM_len < 0)
-               settings->jpg_comp.COM_len = 0;
-       if (settings->jpg_comp.COM_len > 60)
-               settings->jpg_comp.COM_len = 60;
-       if (err)
-               return -EINVAL;
-       return 0;
-}
-
-void
-zoran_open_init_params (struct zoran *zr)
-{
-       int i;
-
-       /* User must explicitly set a window */
-       zr->overlay_settings.is_set = 0;
-       zr->overlay_mask = NULL;
-       zr->overlay_active = ZORAN_FREE;
-
-       zr->v4l_memgrab_active = 0;
-       zr->v4l_overlay_active = 0;
-       zr->v4l_grab_frame = NO_GRAB_ACTIVE;
-       zr->v4l_grab_seq = 0;
-       zr->v4l_settings.width = 192;
-       zr->v4l_settings.height = 144;
-       zr->v4l_settings.format = &zoran_formats[7];    /* YUY2 - YUV-4:2:2 packed */
-       zr->v4l_settings.bytesperline =
-           zr->v4l_settings.width *
-           ((zr->v4l_settings.format->depth + 7) / 8);
-
-       /* DMA ring stuff for V4L */
-       zr->v4l_pend_tail = 0;
-       zr->v4l_pend_head = 0;
-       zr->v4l_sync_tail = 0;
-       zr->v4l_buffers.active = ZORAN_FREE;
-       for (i = 0; i < VIDEO_MAX_FRAME; i++) {
-               zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-       }
-       zr->v4l_buffers.allocated = 0;
-
-       for (i = 0; i < BUZ_MAX_FRAME; i++) {
-               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-       }
-       zr->jpg_buffers.active = ZORAN_FREE;
-       zr->jpg_buffers.allocated = 0;
-       /* Set necessary params and call zoran_check_jpg_settings to set the defaults */
-       zr->jpg_settings.decimation = 1;
-       zr->jpg_settings.jpg_comp.quality = 50; /* default compression factor 8 */
-       if (zr->card.type != BUZ)
-               zr->jpg_settings.odd_even = 1;
-       else
-               zr->jpg_settings.odd_even = 0;
-       zr->jpg_settings.jpg_comp.APPn = 0;
-       zr->jpg_settings.jpg_comp.APP_len = 0;  /* No APPn marker */
-       memset(zr->jpg_settings.jpg_comp.APP_data, 0,
-              sizeof(zr->jpg_settings.jpg_comp.APP_data));
-       zr->jpg_settings.jpg_comp.COM_len = 0;  /* No COM marker */
-       memset(zr->jpg_settings.jpg_comp.COM_data, 0,
-              sizeof(zr->jpg_settings.jpg_comp.COM_data));
-       zr->jpg_settings.jpg_comp.jpeg_markers =
-           V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT;
-       i = zoran_check_jpg_settings(zr, &zr->jpg_settings, 0);
-       if (i)
-               dprintk(1, KERN_ERR "%s: %s internal error\n",
-                       ZR_DEVNAME(zr), __func__);
-
-       clear_interrupt_counters(zr);
-       zr->testing = 0;
-}
-
-static void __devinit
-test_interrupts (struct zoran *zr)
-{
-       DEFINE_WAIT(wait);
-       int timeout, icr;
-
-       clear_interrupt_counters(zr);
-
-       zr->testing = 1;
-       icr = btread(ZR36057_ICR);
-       btwrite(0x78000000 | ZR36057_ICR_IntPinEn, ZR36057_ICR);
-       prepare_to_wait(&zr->test_q, &wait, TASK_INTERRUPTIBLE);
-       timeout = schedule_timeout(HZ);
-       finish_wait(&zr->test_q, &wait);
-       btwrite(0, ZR36057_ICR);
-       btwrite(0x78000000, ZR36057_ISR);
-       zr->testing = 0;
-       dprintk(5, KERN_INFO "%s: Testing interrupts...\n", ZR_DEVNAME(zr));
-       if (timeout) {
-               dprintk(1, ": time spent: %d\n", 1 * HZ - timeout);
-       }
-       if (zr36067_debug > 1)
-               print_interrupts(zr);
-       btwrite(icr, ZR36057_ICR);
-}
-
-static int __devinit
-zr36057_init (struct zoran *zr)
-{
-       int j, err;
-
-       dprintk(1,
-               KERN_INFO
-               "%s: %s - initializing card[%d], zr=%p\n",
-               ZR_DEVNAME(zr), __func__, zr->id, zr);
-
-       /* default setup of all parameters which will persist between opens */
-       zr->user = 0;
-
-       init_waitqueue_head(&zr->v4l_capq);
-       init_waitqueue_head(&zr->jpg_capq);
-       init_waitqueue_head(&zr->test_q);
-       zr->jpg_buffers.allocated = 0;
-       zr->v4l_buffers.allocated = 0;
-
-       zr->vbuf_base = (void *) vidmem;
-       zr->vbuf_width = 0;
-       zr->vbuf_height = 0;
-       zr->vbuf_depth = 0;
-       zr->vbuf_bytesperline = 0;
-
-       /* Avoid nonsense settings from user for default input/norm */
-       if (default_norm < 0 || default_norm > 2)
-               default_norm = 0;
-       if (default_norm == 0) {
-               zr->norm = V4L2_STD_PAL;
-               zr->timing = zr->card.tvn[0];
-       } else if (default_norm == 1) {
-               zr->norm = V4L2_STD_NTSC;
-               zr->timing = zr->card.tvn[1];
-       } else {
-               zr->norm = V4L2_STD_SECAM;
-               zr->timing = zr->card.tvn[2];
-       }
-       if (zr->timing == NULL) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: %s - default TV standard not supported by hardware. PAL will be used.\n",
-                       ZR_DEVNAME(zr), __func__);
-               zr->norm = V4L2_STD_PAL;
-               zr->timing = zr->card.tvn[0];
-       }
-
-       if (default_input > zr->card.inputs-1) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: default_input value %d out of range (0-%d)\n",
-                       ZR_DEVNAME(zr), default_input, zr->card.inputs-1);
-               default_input = 0;
-       }
-       zr->input = default_input;
-
-       /* default setup (will be repeated at every open) */
-       zoran_open_init_params(zr);
-
-       /* allocate memory *before* doing anything to the hardware
-        * in case allocation fails */
-       zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
-       zr->video_dev = video_device_alloc();
-       if (!zr->stat_com || !zr->video_dev) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - kmalloc (STAT_COM) failed\n",
-                       ZR_DEVNAME(zr), __func__);
-               err = -ENOMEM;
-               goto exit_free;
-       }
-       for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-               zr->stat_com[j] = cpu_to_le32(1); /* mark as unavailable to zr36057 */
-       }
-
-       /*
-        *   Now add the template and register the device unit.
-        */
-       memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
-       zr->video_dev->parent = &zr->pci_dev->dev;
-       strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
-       err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
-       if (err < 0)
-               goto exit_free;
-       video_set_drvdata(zr->video_dev, zr);
-
-       zoran_init_hardware(zr);
-       if (zr36067_debug > 2)
-               detect_guest_activity(zr);
-       test_interrupts(zr);
-       if (!pass_through) {
-               decoder_call(zr, video, s_stream, 0);
-               encoder_call(zr, video, s_routing, 2, 0, 0);
-       }
-
-       zr->zoran_proc = NULL;
-       zr->initialized = 1;
-       return 0;
-
-exit_free:
-       kfree(zr->stat_com);
-       kfree(zr->video_dev);
-       return err;
-}
-
-static void __devexit zoran_remove(struct pci_dev *pdev)
-{
-       struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev);
-       struct zoran *zr = to_zoran(v4l2_dev);
-
-       if (!zr->initialized)
-               goto exit_free;
-
-       /* unregister videocodec bus */
-       if (zr->codec) {
-               struct videocodec_master *master = zr->codec->master_data;
-
-               videocodec_detach(zr->codec);
-               kfree(master);
-       }
-       if (zr->vfe) {
-               struct videocodec_master *master = zr->vfe->master_data;
-
-               videocodec_detach(zr->vfe);
-               kfree(master);
-       }
-
-       /* unregister i2c bus */
-       zoran_unregister_i2c(zr);
-       /* disable PCI bus-mastering */
-       zoran_set_pci_master(zr, 0);
-       /* put chip into reset */
-       btwrite(0, ZR36057_SPGPPCR);
-       free_irq(zr->pci_dev->irq, zr);
-       /* unmap and free memory */
-       kfree(zr->stat_com);
-       zoran_proc_cleanup(zr);
-       iounmap(zr->zr36057_mem);
-       pci_disable_device(zr->pci_dev);
-       video_unregister_device(zr->video_dev);
-exit_free:
-       v4l2_device_unregister(&zr->v4l2_dev);
-       kfree(zr);
-}
-
-void
-zoran_vdev_release (struct video_device *vdev)
-{
-       kfree(vdev);
-}
-
-static struct videocodec_master * __devinit
-zoran_setup_videocodec (struct zoran *zr,
-                       int           type)
-{
-       struct videocodec_master *m = NULL;
-
-       m = kmalloc(sizeof(struct videocodec_master), GFP_KERNEL);
-       if (!m) {
-               dprintk(1, KERN_ERR "%s: %s - no memory\n",
-                       ZR_DEVNAME(zr), __func__);
-               return m;
-       }
-
-       /* magic and type are unused for master struct. Makes sense only at
-          codec structs.
-          In the past, .type were initialized to the old V4L1 .hardware
-          value, as VID_HARDWARE_ZR36067
-        */
-       m->magic = 0L;
-       m->type = 0;
-
-       m->flags = CODEC_FLAG_ENCODER | CODEC_FLAG_DECODER;
-       strlcpy(m->name, ZR_DEVNAME(zr), sizeof(m->name));
-       m->data = zr;
-
-       switch (type)
-       {
-       case CODEC_TYPE_ZR36060:
-               m->readreg = zr36060_read;
-               m->writereg = zr36060_write;
-               m->flags |= CODEC_FLAG_JPEG | CODEC_FLAG_VFE;
-               break;
-       case CODEC_TYPE_ZR36050:
-               m->readreg = zr36050_read;
-               m->writereg = zr36050_write;
-               m->flags |= CODEC_FLAG_JPEG;
-               break;
-       case CODEC_TYPE_ZR36016:
-               m->readreg = zr36016_read;
-               m->writereg = zr36016_write;
-               m->flags |= CODEC_FLAG_VFE;
-               break;
-       }
-
-       return m;
-}
-
-static void zoran_subdev_notify(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-{
-       struct zoran *zr = to_zoran(sd->v4l2_dev);
-
-       /* Bt819 needs to reset its FIFO buffer using #FRST pin and
-          LML33 card uses GPIO(7) for that. */
-       if (cmd == BT819_FIFO_RESET_LOW)
-               GPIO(zr, 7, 0);
-       else if (cmd == BT819_FIFO_RESET_HIGH)
-               GPIO(zr, 7, 1);
-}
-
-/*
- *   Scan for a Buz card (actually for the PCI controller ZR36057),
- *   request the irq and map the io memory
- */
-static int __devinit zoran_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
-{
-       unsigned char latency, need_latency;
-       struct zoran *zr;
-       int result;
-       struct videocodec_master *master_vfe = NULL;
-       struct videocodec_master *master_codec = NULL;
-       int card_num;
-       char *codec_name, *vfe_name;
-       unsigned int nr;
-
-
-       nr = zoran_num++;
-       if (nr >= BUZ_MAX) {
-               dprintk(1, KERN_ERR "%s: driver limited to %d card(s) maximum\n",
-                       ZORAN_NAME, BUZ_MAX);
-               return -ENOENT;
-       }
-
-       zr = kzalloc(sizeof(struct zoran), GFP_KERNEL);
-       if (!zr) {
-               dprintk(1, KERN_ERR "%s: %s - kzalloc failed\n",
-                       ZORAN_NAME, __func__);
-               return -ENOMEM;
-       }
-       zr->v4l2_dev.notify = zoran_subdev_notify;
-       if (v4l2_device_register(&pdev->dev, &zr->v4l2_dev))
-               goto zr_free_mem;
-       zr->pci_dev = pdev;
-       zr->id = nr;
-       snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)), "MJPEG[%u]", zr->id);
-       spin_lock_init(&zr->spinlock);
-       mutex_init(&zr->resource_lock);
-       mutex_init(&zr->other_lock);
-       if (pci_enable_device(pdev))
-               goto zr_unreg;
-       zr->revision = zr->pci_dev->revision;
-
-       dprintk(1,
-               KERN_INFO
-               "%s: Zoran ZR360%c7 (rev %d), irq: %d, memory: 0x%08llx\n",
-               ZR_DEVNAME(zr), zr->revision < 2 ? '5' : '6', zr->revision,
-               zr->pci_dev->irq, (uint64_t)pci_resource_start(zr->pci_dev, 0));
-       if (zr->revision >= 2) {
-               dprintk(1,
-                       KERN_INFO
-                       "%s: Subsystem vendor=0x%04x id=0x%04x\n",
-                       ZR_DEVNAME(zr), zr->pci_dev->subsystem_vendor,
-                       zr->pci_dev->subsystem_device);
-       }
-
-       /* Use auto-detected card type? */
-       if (card[nr] == -1) {
-               if (zr->revision < 2) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: No card type specified, please use the card=X module parameter\n",
-                               ZR_DEVNAME(zr));
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: It is not possible to auto-detect ZR36057 based cards\n",
-                               ZR_DEVNAME(zr));
-                       goto zr_unreg;
-               }
-
-               card_num = ent->driver_data;
-               if (card_num >= NUM_CARDS) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: Unknown card, try specifying card=X module parameter\n",
-                               ZR_DEVNAME(zr));
-                       goto zr_unreg;
-               }
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: %s() - card %s detected\n",
-                       ZR_DEVNAME(zr), __func__, zoran_cards[card_num].name);
-       } else {
-               card_num = card[nr];
-               if (card_num >= NUM_CARDS || card_num < 0) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: User specified card type %d out of range (0 .. %d)\n",
-                               ZR_DEVNAME(zr), card_num, NUM_CARDS - 1);
-                       goto zr_unreg;
-               }
-       }
-
-       /* even though we make this a non pointer and thus
-        * theoretically allow for making changes to this struct
-        * on a per-individual card basis at runtime, this is
-        * strongly discouraged. This structure is intended to
-        * keep general card information, no settings or anything */
-       zr->card = zoran_cards[card_num];
-       snprintf(ZR_DEVNAME(zr), sizeof(ZR_DEVNAME(zr)),
-                "%s[%u]", zr->card.name, zr->id);
-
-       zr->zr36057_mem = pci_ioremap_bar(zr->pci_dev, 0);
-       if (!zr->zr36057_mem) {
-               dprintk(1, KERN_ERR "%s: %s() - ioremap failed\n",
-                       ZR_DEVNAME(zr), __func__);
-               goto zr_unreg;
-       }
-
-       result = request_irq(zr->pci_dev->irq, zoran_irq,
-                            IRQF_SHARED | IRQF_DISABLED, ZR_DEVNAME(zr), zr);
-       if (result < 0) {
-               if (result == -EINVAL) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - bad irq number or handler\n",
-                               ZR_DEVNAME(zr), __func__);
-               } else if (result == -EBUSY) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - IRQ %d busy, change your PnP config in BIOS\n",
-                               ZR_DEVNAME(zr), __func__, zr->pci_dev->irq);
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - can't assign irq, error code %d\n",
-                               ZR_DEVNAME(zr), __func__, result);
-               }
-               goto zr_unmap;
-       }
-
-       /* set PCI latency timer */
-       pci_read_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
-                            &latency);
-       need_latency = zr->revision > 1 ? 32 : 48;
-       if (latency != need_latency) {
-               dprintk(2, KERN_INFO "%s: Changing PCI latency from %d to %d\n",
-                       ZR_DEVNAME(zr), latency, need_latency);
-               pci_write_config_byte(zr->pci_dev, PCI_LATENCY_TIMER,
-                                     need_latency);
-       }
-
-       zr36057_restart(zr);
-       /* i2c */
-       dprintk(2, KERN_INFO "%s: Initializing i2c bus...\n",
-               ZR_DEVNAME(zr));
-
-       if (zoran_register_i2c(zr) < 0) {
-               dprintk(1, KERN_ERR "%s: %s - can't initialize i2c bus\n",
-                       ZR_DEVNAME(zr), __func__);
-               goto zr_free_irq;
-       }
-
-       zr->decoder = v4l2_i2c_new_subdev(&zr->v4l2_dev,
-               &zr->i2c_adapter, zr->card.i2c_decoder,
-               0, zr->card.addrs_decoder);
-
-       if (zr->card.i2c_encoder)
-               zr->encoder = v4l2_i2c_new_subdev(&zr->v4l2_dev,
-                       &zr->i2c_adapter, zr->card.i2c_encoder,
-                       0, zr->card.addrs_encoder);
-
-       dprintk(2,
-               KERN_INFO "%s: Initializing videocodec bus...\n",
-               ZR_DEVNAME(zr));
-
-       if (zr->card.video_codec) {
-               codec_name = codecid_to_modulename(zr->card.video_codec);
-               if (codec_name) {
-                       result = request_module(codec_name);
-                       if (result) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: failed to load modules %s: %d\n",
-                                       ZR_DEVNAME(zr), codec_name, result);
-                       }
-               }
-       }
-       if (zr->card.video_vfe) {
-               vfe_name = codecid_to_modulename(zr->card.video_vfe);
-               if (vfe_name) {
-                       result = request_module(vfe_name);
-                       if (result < 0) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: failed to load modules %s: %d\n",
-                                       ZR_DEVNAME(zr), vfe_name, result);
-                       }
-               }
-       }
-
-       /* reset JPEG codec */
-       jpeg_codec_sleep(zr, 1);
-       jpeg_codec_reset(zr);
-       /* video bus enabled */
-       /* display codec revision */
-       if (zr->card.video_codec != 0) {
-               master_codec = zoran_setup_videocodec(zr, zr->card.video_codec);
-               if (!master_codec)
-                       goto zr_unreg_i2c;
-               zr->codec = videocodec_attach(master_codec);
-               if (!zr->codec) {
-                       dprintk(1, KERN_ERR "%s: %s - no codec found\n",
-                               ZR_DEVNAME(zr), __func__);
-                       goto zr_free_codec;
-               }
-               if (zr->codec->type != zr->card.video_codec) {
-                       dprintk(1, KERN_ERR "%s: %s - wrong codec\n",
-                               ZR_DEVNAME(zr), __func__);
-                       goto zr_detach_codec;
-               }
-       }
-       if (zr->card.video_vfe != 0) {
-               master_vfe = zoran_setup_videocodec(zr, zr->card.video_vfe);
-               if (!master_vfe)
-                       goto zr_detach_codec;
-               zr->vfe = videocodec_attach(master_vfe);
-               if (!zr->vfe) {
-                       dprintk(1, KERN_ERR "%s: %s - no VFE found\n",
-                               ZR_DEVNAME(zr), __func__);
-                       goto zr_free_vfe;
-               }
-               if (zr->vfe->type != zr->card.video_vfe) {
-                       dprintk(1, KERN_ERR "%s: %s = wrong VFE\n",
-                               ZR_DEVNAME(zr), __func__);
-                       goto zr_detach_vfe;
-               }
-       }
-
-       /* take care of Natoma chipset and a revision 1 zr36057 */
-       if ((pci_pci_problems & PCIPCI_NATOMA) && zr->revision <= 1) {
-               zr->jpg_buffers.need_contiguous = 1;
-               dprintk(1, KERN_INFO
-                       "%s: ZR36057/Natoma bug, max. buffer size is 128K\n",
-                       ZR_DEVNAME(zr));
-       }
-
-       if (zr36057_init(zr) < 0)
-               goto zr_detach_vfe;
-
-       zoran_proc_init(zr);
-
-       return 0;
-
-zr_detach_vfe:
-       videocodec_detach(zr->vfe);
-zr_free_vfe:
-       kfree(master_vfe);
-zr_detach_codec:
-       videocodec_detach(zr->codec);
-zr_free_codec:
-       kfree(master_codec);
-zr_unreg_i2c:
-       zoran_unregister_i2c(zr);
-zr_free_irq:
-       btwrite(0, ZR36057_SPGPPCR);
-       free_irq(zr->pci_dev->irq, zr);
-zr_unmap:
-       iounmap(zr->zr36057_mem);
-zr_unreg:
-       v4l2_device_unregister(&zr->v4l2_dev);
-zr_free_mem:
-       kfree(zr);
-
-       return -ENODEV;
-}
-
-static struct pci_driver zoran_driver = {
-       .name = "zr36067",
-       .id_table = zr36067_pci_tbl,
-       .probe = zoran_probe,
-       .remove = __devexit_p(zoran_remove),
-};
-
-static int __init zoran_init(void)
-{
-       int res;
-
-       printk(KERN_INFO "Zoran MJPEG board driver version %s\n",
-              ZORAN_VERSION);
-
-       /* check the parameters we have been given, adjust if necessary */
-       if (v4l_nbufs < 2)
-               v4l_nbufs = 2;
-       if (v4l_nbufs > VIDEO_MAX_FRAME)
-               v4l_nbufs = VIDEO_MAX_FRAME;
-       /* The user specfies the in KB, we want them in byte
-        * (and page aligned) */
-       v4l_bufsize = PAGE_ALIGN(v4l_bufsize * 1024);
-       if (v4l_bufsize < 32768)
-               v4l_bufsize = 32768;
-       /* 2 MB is arbitrary but sufficient for the maximum possible images */
-       if (v4l_bufsize > 2048 * 1024)
-               v4l_bufsize = 2048 * 1024;
-       if (jpg_nbufs < 4)
-               jpg_nbufs = 4;
-       if (jpg_nbufs > BUZ_MAX_FRAME)
-               jpg_nbufs = BUZ_MAX_FRAME;
-       jpg_bufsize = PAGE_ALIGN(jpg_bufsize * 1024);
-       if (jpg_bufsize < 8192)
-               jpg_bufsize = 8192;
-       if (jpg_bufsize > (512 * 1024))
-               jpg_bufsize = 512 * 1024;
-       /* Use parameter for vidmem or try to find a video card */
-       if (vidmem) {
-               dprintk(1,
-                       KERN_INFO
-                       "%s: Using supplied video memory base address @ 0x%lx\n",
-                       ZORAN_NAME, vidmem);
-       }
-
-       /* some mainboards might not do PCI-PCI data transfer well */
-       if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: chipset does not support reliable PCI-PCI DMA\n",
-                       ZORAN_NAME);
-       }
-
-       res = pci_register_driver(&zoran_driver);
-       if (res) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: Unable to register ZR36057 driver\n",
-                       ZORAN_NAME);
-               return res;
-       }
-
-       return 0;
-}
-
-static void __exit zoran_exit(void)
-{
-       pci_unregister_driver(&zoran_driver);
-}
-
-module_init(zoran_init);
-module_exit(zoran_exit);
diff --git a/drivers/media/video/zoran/zoran_card.h b/drivers/media/video/zoran/zoran_card.h
deleted file mode 100644 (file)
index 4936fea..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.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.
- */
-
-#ifndef __ZORAN_CARD_H__
-#define __ZORAN_CARD_H__
-
-extern int zr36067_debug;
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (zr36067_debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* Anybody who uses more than four? */
-#define BUZ_MAX 4
-
-extern struct video_device zoran_template;
-
-extern int zoran_check_jpg_settings(struct zoran *zr,
-                                   struct zoran_jpg_settings *settings,
-                                   int try);
-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__ */
diff --git a/drivers/media/video/zoran/zoran_device.c b/drivers/media/video/zoran/zoran_device.c
deleted file mode 100644 (file)
index a4cd504..0000000
+++ /dev/null
@@ -1,1640 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles device access (PCI/I2C/codec/...)
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.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/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/spinlock.h>
-#include <linux/sem.h>
-
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-
-#include "videocodec.h"
-#include "zoran.h"
-#include "zoran_device.h"
-#include "zoran_card.h"
-
-#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \
-                  ZR36057_ISR_GIRQ1 | \
-                  ZR36057_ISR_JPEGRepIRQ )
-
-static bool 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
-                                * on TV monitor connected to the output.
-                                * However, due to absence of 75 Ohm
-                                * load on Bt819 input, there will be
-                                * some image imperfections */
-
-module_param(lml33dpath, bool, 0644);
-MODULE_PARM_DESC(lml33dpath,
-                "Use digital path capture mode (on LML33 cards)");
-
-static void
-zr36057_init_vfe (struct zoran *zr);
-
-/*
- * General Purpose I/O and Guest bus access
- */
-
-/*
- * This is a bit tricky. When a board lacks a GPIO function, the corresponding
- * GPIO bit number in the card_info structure is set to 0.
- */
-
-void
-GPIO (struct zoran *zr,
-      int           bit,
-      unsigned int  value)
-{
-       u32 reg;
-       u32 mask;
-
-       /* Make sure the bit number is legal
-        * A bit number of -1 (lacking) gives a mask of 0,
-        * making it harmless */
-       mask = (1 << (24 + bit)) & 0xff000000;
-       reg = btread(ZR36057_GPPGCR1) & ~mask;
-       if (value) {
-               reg |= mask;
-       }
-       btwrite(reg, ZR36057_GPPGCR1);
-       udelay(1);
-}
-
-/*
- * Wait til post office is no longer busy
- */
-
-int
-post_office_wait (struct zoran *zr)
-{
-       u32 por;
-
-//      while (((por = btread(ZR36057_POR)) & (ZR36057_POR_POPen | ZR36057_POR_POTime)) == ZR36057_POR_POPen) {
-       while ((por = btread(ZR36057_POR)) & ZR36057_POR_POPen) {
-               /* wait for something to happen */
-       }
-       if ((por & ZR36057_POR_POTime) && !zr->card.gws_not_connected) {
-               /* In LML33/BUZ \GWS line is not connected, so it has always timeout set */
-               dprintk(1, KERN_INFO "%s: pop timeout %08x\n", ZR_DEVNAME(zr),
-                       por);
-               return -1;
-       }
-
-       return 0;
-}
-
-int
-post_office_write (struct zoran *zr,
-                  unsigned int  guest,
-                  unsigned int  reg,
-                  unsigned int  value)
-{
-       u32 por;
-
-       por =
-           ZR36057_POR_PODir | ZR36057_POR_POTime | ((guest & 7) << 20) |
-           ((reg & 7) << 16) | (value & 0xFF);
-       btwrite(por, ZR36057_POR);
-
-       return post_office_wait(zr);
-}
-
-int
-post_office_read (struct zoran *zr,
-                 unsigned int  guest,
-                 unsigned int  reg)
-{
-       u32 por;
-
-       por = ZR36057_POR_POTime | ((guest & 7) << 20) | ((reg & 7) << 16);
-       btwrite(por, ZR36057_POR);
-       if (post_office_wait(zr) < 0) {
-               return -1;
-       }
-
-       return btread(ZR36057_POR) & 0xFF;
-}
-
-/*
- * detect guests
- */
-
-static void
-dump_guests (struct zoran *zr)
-{
-       if (zr36067_debug > 2) {
-               int i, guest[8];
-
-               for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
-                       guest[i] = post_office_read(zr, i, 0);
-               }
-
-               printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
-
-               for (i = 1; i < 8; i++) {
-                       printk(" 0x%02x", guest[i]);
-               }
-               printk("\n");
-       }
-}
-
-static inline unsigned long
-get_time (void)
-{
-       struct timeval tv;
-
-       do_gettimeofday(&tv);
-       return (1000000 * tv.tv_sec + tv.tv_usec);
-}
-
-void
-detect_guest_activity (struct zoran *zr)
-{
-       int timeout, i, j, res, guest[8], guest0[8], change[8][3];
-       unsigned long t0, t1;
-
-       dump_guests(zr);
-       printk(KERN_INFO "%s: Detecting guests activity, please wait...\n",
-              ZR_DEVNAME(zr));
-       for (i = 1; i < 8; i++) {       // Don't read jpeg codec here
-               guest0[i] = guest[i] = post_office_read(zr, i, 0);
-       }
-
-       timeout = 0;
-       j = 0;
-       t0 = get_time();
-       while (timeout < 10000) {
-               udelay(10);
-               timeout++;
-               for (i = 1; (i < 8) && (j < 8); i++) {
-                       res = post_office_read(zr, i, 0);
-                       if (res != guest[i]) {
-                               t1 = get_time();
-                               change[j][0] = (t1 - t0);
-                               t0 = t1;
-                               change[j][1] = i;
-                               change[j][2] = res;
-                               j++;
-                               guest[i] = res;
-                       }
-               }
-               if (j >= 8)
-                       break;
-       }
-       printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
-
-       for (i = 1; i < 8; i++) {
-               printk(" 0x%02x", guest0[i]);
-       }
-       printk("\n");
-       if (j == 0) {
-               printk(KERN_INFO "%s: No activity detected.\n", ZR_DEVNAME(zr));
-               return;
-       }
-       for (i = 0; i < j; i++) {
-               printk(KERN_INFO "%s: %6d: %d => 0x%02x\n", ZR_DEVNAME(zr),
-                      change[i][0], change[i][1], change[i][2]);
-       }
-}
-
-/*
- * JPEG Codec access
- */
-
-void
-jpeg_codec_sleep (struct zoran *zr,
-                 int           sleep)
-{
-       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_SLEEP], !sleep);
-       if (!sleep) {
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: jpeg_codec_sleep() - wake GPIO=0x%08x\n",
-                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
-               udelay(500);
-       } else {
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: jpeg_codec_sleep() - sleep GPIO=0x%08x\n",
-                       ZR_DEVNAME(zr), btread(ZR36057_GPPGCR1));
-               udelay(2);
-       }
-}
-
-int
-jpeg_codec_reset (struct zoran *zr)
-{
-       /* Take the codec out of sleep */
-       jpeg_codec_sleep(zr, 0);
-
-       if (zr->card.gpcs[GPCS_JPEG_RESET] != 0xff) {
-               post_office_write(zr, zr->card.gpcs[GPCS_JPEG_RESET], 0,
-                                 0);
-               udelay(2);
-       } else {
-               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 0);
-               udelay(2);
-               GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_RESET], 1);
-               udelay(2);
-       }
-
-       return 0;
-}
-
-/*
- *   Set the registers for the size we have specified. Don't bother
- *   trying to understand this without the ZR36057 manual in front of
- *   you [AC].
- *
- *   PS: The manual is free for download in .pdf format from
- *   www.zoran.com - nicely done those folks.
- */
-
-static void
-zr36057_adjust_vfe (struct zoran          *zr,
-                   enum zoran_codec_mode  mode)
-{
-       u32 reg;
-
-       switch (mode) {
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
-               reg = btread(ZR36057_VFEHCR);
-               if ((reg & (1 << 10)) && zr->card.type != LML33R10) {
-                       reg += ((1 << 10) | 1);
-               }
-               btwrite(reg, ZR36057_VFEHCR);
-               break;
-       case BUZ_MODE_MOTION_COMPRESS:
-       case BUZ_MODE_IDLE:
-       default:
-               if ((zr->norm & V4L2_STD_NTSC) ||
-                   (zr->card.type == LML33R10 &&
-                    (zr->norm & V4L2_STD_PAL)))
-                       btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
-               else
-                       btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
-               reg = btread(ZR36057_VFEHCR);
-               if (!(reg & (1 << 10)) && zr->card.type != LML33R10) {
-                       reg -= ((1 << 10) | 1);
-               }
-               btwrite(reg, ZR36057_VFEHCR);
-               break;
-       }
-}
-
-/*
- * set geometry
- */
-
-static void
-zr36057_set_vfe (struct zoran              *zr,
-                int                        video_width,
-                int                        video_height,
-                const struct zoran_format *format)
-{
-       struct tvnorm *tvn;
-       unsigned HStart, HEnd, VStart, VEnd;
-       unsigned DispMode;
-       unsigned VidWinWid, VidWinHt;
-       unsigned hcrop1, hcrop2, vcrop1, vcrop2;
-       unsigned Wa, We, Ha, He;
-       unsigned X, Y, HorDcm, VerDcm;
-       u32 reg;
-       unsigned mask_line_size;
-
-       tvn = zr->timing;
-
-       Wa = tvn->Wa;
-       Ha = tvn->Ha;
-
-       dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n",
-               ZR_DEVNAME(zr), video_width, video_height);
-
-       if (video_width < BUZ_MIN_WIDTH ||
-           video_height < BUZ_MIN_HEIGHT ||
-           video_width > Wa || video_height > Ha) {
-               dprintk(1, KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n",
-                       ZR_DEVNAME(zr), video_width, video_height);
-               return;
-       }
-
-       /**** zr36057 ****/
-
-       /* horizontal */
-       VidWinWid = video_width;
-       X = DIV_ROUND_UP(VidWinWid * 64, tvn->Wa);
-       We = (VidWinWid * 64) / X;
-       HorDcm = 64 - X;
-       hcrop1 = 2 * ((tvn->Wa - We) / 4);
-       hcrop2 = tvn->Wa - We - hcrop1;
-       HStart = tvn->HStart ? tvn->HStart : 1;
-       /* (Ronald) Original comment:
-        * "| 1 Doesn't have any effect, tested on both a DC10 and a DC10+"
-        * this is false. It inverses chroma values on the LML33R10 (so Cr
-        * suddenly is shown as Cb and reverse, really cool effect if you
-        * want to see blue faces, not useful otherwise). So don't use |1.
-        * However, the DC10 has '0' as HStart, but does need |1, so we
-        * use a dirty check...
-        */
-       HEnd = HStart + tvn->Wa - 1;
-       HStart += hcrop1;
-       HEnd -= hcrop2;
-       reg = ((HStart & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HStart)
-           | ((HEnd & ZR36057_VFEHCR_Hmask) << ZR36057_VFEHCR_HEnd);
-       if (zr->card.vfe_pol.hsync_pol)
-               reg |= ZR36057_VFEHCR_HSPol;
-       btwrite(reg, ZR36057_VFEHCR);
-
-       /* Vertical */
-       DispMode = !(video_height > BUZ_MAX_HEIGHT / 2);
-       VidWinHt = DispMode ? video_height : video_height / 2;
-       Y = DIV_ROUND_UP(VidWinHt * 64 * 2, tvn->Ha);
-       He = (VidWinHt * 64) / Y;
-       VerDcm = 64 - Y;
-       vcrop1 = (tvn->Ha / 2 - He) / 2;
-       vcrop2 = tvn->Ha / 2 - He - vcrop1;
-       VStart = tvn->VStart;
-       VEnd = VStart + tvn->Ha / 2;    // - 1; FIXME SnapShot times out with -1 in 768*576 on the DC10 - LP
-       VStart += vcrop1;
-       VEnd -= vcrop2;
-       reg = ((VStart & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VStart)
-           | ((VEnd & ZR36057_VFEVCR_Vmask) << ZR36057_VFEVCR_VEnd);
-       if (zr->card.vfe_pol.vsync_pol)
-               reg |= ZR36057_VFEVCR_VSPol;
-       btwrite(reg, ZR36057_VFEVCR);
-
-       /* scaler and pixel format */
-       reg = 0;
-       reg |= (HorDcm << ZR36057_VFESPFR_HorDcm);
-       reg |= (VerDcm << ZR36057_VFESPFR_VerDcm);
-       reg |= (DispMode << ZR36057_VFESPFR_DispMode);
-       /* RJ: I don't know, why the following has to be the opposite
-        * of the corresponding ZR36060 setting, but only this way
-        * we get the correct colors when uncompressing to the screen  */
-       //reg |= ZR36057_VFESPFR_VCLKPol; /**/
-       /* RJ: Don't know if that is needed for NTSC also */
-       if (!(zr->norm & V4L2_STD_NTSC))
-               reg |= ZR36057_VFESPFR_ExtFl;   // NEEDED!!!!!!! Wolfgang
-       reg |= ZR36057_VFESPFR_TopField;
-       if (HorDcm >= 48) {
-               reg |= 3 << ZR36057_VFESPFR_HFilter;    /* 5 tap filter */
-       } else if (HorDcm >= 32) {
-               reg |= 2 << ZR36057_VFESPFR_HFilter;    /* 4 tap filter */
-       } else if (HorDcm >= 16) {
-               reg |= 1 << ZR36057_VFESPFR_HFilter;    /* 3 tap filter */
-       }
-       reg |= format->vfespfr;
-       btwrite(reg, ZR36057_VFESPFR);
-
-       /* display configuration */
-       reg = (16 << ZR36057_VDCR_MinPix)
-           | (VidWinHt << ZR36057_VDCR_VidWinHt)
-           | (VidWinWid << ZR36057_VDCR_VidWinWid);
-       if (pci_pci_problems & PCIPCI_TRITON)
-               // || zr->revision < 1) // Revision 1 has also Triton support
-               reg &= ~ZR36057_VDCR_Triton;
-       else
-               reg |= ZR36057_VDCR_Triton;
-       btwrite(reg, ZR36057_VDCR);
-
-       /* (Ronald) don't write this if overlay_mask = NULL */
-       if (zr->overlay_mask) {
-               /* Write overlay clipping mask data, but don't enable overlay clipping */
-               /* RJ: since this makes only sense on the screen, we use
-                * zr->overlay_settings.width instead of video_width */
-
-               mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
-               reg = virt_to_bus(zr->overlay_mask);
-               btwrite(reg, ZR36057_MMTR);
-               reg = virt_to_bus(zr->overlay_mask + mask_line_size);
-               btwrite(reg, ZR36057_MMBR);
-               reg =
-                   mask_line_size - (zr->overlay_settings.width +
-                                     31) / 32;
-               if (DispMode == 0)
-                       reg += mask_line_size;
-               reg <<= ZR36057_OCR_MaskStride;
-               btwrite(reg, ZR36057_OCR);
-       }
-
-       zr36057_adjust_vfe(zr, zr->codec_mode);
-}
-
-/*
- * Switch overlay on or off
- */
-
-void
-zr36057_overlay (struct zoran *zr,
-                int           on)
-{
-       u32 reg;
-
-       if (on) {
-               /* do the necessary settings ... */
-               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);       /* switch it off first */
-
-               zr36057_set_vfe(zr,
-                               zr->overlay_settings.width,
-                               zr->overlay_settings.height,
-                               zr->overlay_settings.format);
-
-               /* Start and length of each line MUST be 4-byte aligned.
-                * This should be already checked before the call to this routine.
-                * All error messages are internal driver checking only! */
-
-               /* video display top and bottom registers */
-               reg = (long) zr->vbuf_base +
-                   zr->overlay_settings.x *
-                   ((zr->overlay_settings.format->depth + 7) / 8) +
-                   zr->overlay_settings.y *
-                   zr->vbuf_bytesperline;
-               btwrite(reg, ZR36057_VDTR);
-               if (reg & 3)
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: zr36057_overlay() - video_address not aligned\n",
-                               ZR_DEVNAME(zr));
-               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
-                       reg += zr->vbuf_bytesperline;
-               btwrite(reg, ZR36057_VDBR);
-
-               /* video stride, status, and frame grab register */
-               reg = zr->vbuf_bytesperline -
-                   zr->overlay_settings.width *
-                   ((zr->overlay_settings.format->depth + 7) / 8);
-               if (zr->overlay_settings.height > BUZ_MAX_HEIGHT / 2)
-                       reg += zr->vbuf_bytesperline;
-               if (reg & 3)
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: zr36057_overlay() - video_stride not aligned\n",
-                               ZR_DEVNAME(zr));
-               reg = (reg << ZR36057_VSSFGR_DispStride);
-               reg |= ZR36057_VSSFGR_VidOvf;   /* clear overflow status */
-               btwrite(reg, ZR36057_VSSFGR);
-
-               /* Set overlay clipping */
-               if (zr->overlay_settings.clipcount > 0)
-                       btor(ZR36057_OCR_OvlEnable, ZR36057_OCR);
-
-               /* ... and switch it on */
-               btor(ZR36057_VDCR_VidEn, ZR36057_VDCR);
-       } else {
-               /* Switch it off */
-               btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
-       }
-}
-
-/*
- * The overlay mask has one bit for each pixel on a scan line,
- *  and the maximum window size is BUZ_MAX_WIDTH * BUZ_MAX_HEIGHT pixels.
- */
-
-void write_overlay_mask(struct zoran_fh *fh, struct v4l2_clip *vp, int count)
-{
-       struct zoran *zr = fh->zr;
-       unsigned mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
-       u32 *mask;
-       int x, y, width, height;
-       unsigned i, j, k;
-
-       /* fill mask with one bits */
-       memset(fh->overlay_mask, ~0, mask_line_size * 4 * BUZ_MAX_HEIGHT);
-
-       for (i = 0; i < count; ++i) {
-               /* pick up local copy of clip */
-               x = vp[i].c.left;
-               y = vp[i].c.top;
-               width = vp[i].c.width;
-               height = vp[i].c.height;
-
-               /* trim clips that extend beyond the window */
-               if (x < 0) {
-                       width += x;
-                       x = 0;
-               }
-               if (y < 0) {
-                       height += y;
-                       y = 0;
-               }
-               if (x + width > fh->overlay_settings.width) {
-                       width = fh->overlay_settings.width - x;
-               }
-               if (y + height > fh->overlay_settings.height) {
-                       height = fh->overlay_settings.height - y;
-               }
-
-               /* ignore degenerate clips */
-               if (height <= 0) {
-                       continue;
-               }
-               if (width <= 0) {
-                       continue;
-               }
-
-               /* apply clip for each scan line */
-               for (j = 0; j < height; ++j) {
-                       /* reset bit for each pixel */
-                       /* this can be optimized later if need be */
-                       mask = fh->overlay_mask + (y + j) * mask_line_size;
-                       for (k = 0; k < width; ++k) {
-                               mask[(x + k) / 32] &=
-                                   ~((u32) 1 << (x + k) % 32);
-                       }
-               }
-       }
-}
-
-/* Enable/Disable uncompressed memory grabbing of the 36057 */
-
-void
-zr36057_set_memgrab (struct zoran *zr,
-                    int           mode)
-{
-       if (mode) {
-               /* We only check SnapShot and not FrameGrab here.  SnapShot==1
-                * means a capture is already in progress, but FrameGrab==1
-                * doesn't necessary mean that.  It's more correct to say a 1
-                * to 0 transition indicates a capture completed.  If a
-                * capture is pending when capturing is tuned off, FrameGrab
-                * will be stuck at 1 until capturing is turned back on.
-                */
-               if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot)
-                       dprintk(1,
-                               KERN_WARNING
-                               "%s: zr36057_set_memgrab(1) with SnapShot on!?\n",
-                               ZR_DEVNAME(zr));
-
-               /* switch on VSync interrupts */
-               btwrite(IRQ_MASK, ZR36057_ISR); // Clear Interrupts
-               btor(zr->card.vsync_int, ZR36057_ICR);  // SW
-
-               /* enable SnapShot */
-               btor(ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
-
-               /* Set zr36057 video front end  and enable video */
-               zr36057_set_vfe(zr, zr->v4l_settings.width,
-                               zr->v4l_settings.height,
-                               zr->v4l_settings.format);
-
-               zr->v4l_memgrab_active = 1;
-       } else {
-               /* switch off VSync interrupts */
-               btand(~zr->card.vsync_int, ZR36057_ICR);        // SW
-
-               zr->v4l_memgrab_active = 0;
-               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
-
-               /* reenable grabbing to screen if it was running */
-               if (zr->v4l_overlay_active) {
-                       zr36057_overlay(zr, 1);
-               } else {
-                       btand(~ZR36057_VDCR_VidEn, ZR36057_VDCR);
-                       btand(~ZR36057_VSSFGR_SnapShot, ZR36057_VSSFGR);
-               }
-       }
-}
-
-int
-wait_grab_pending (struct zoran *zr)
-{
-       unsigned long flags;
-
-       /* wait until all pending grabs are finished */
-
-       if (!zr->v4l_memgrab_active)
-               return 0;
-
-       wait_event_interruptible(zr->v4l_capq,
-                       (zr->v4l_pend_tail == zr->v4l_pend_head));
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-       zr36057_set_memgrab(zr, 0);
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return 0;
-}
-
-/*****************************************************************************
- *                                                                           *
- *  Set up the Buz-specific MJPEG part                                       *
- *                                                                           *
- *****************************************************************************/
-
-static inline void
-set_frame (struct zoran *zr,
-          int           val)
-{
-       GPIO(zr, zr->card.gpio[ZR_GPIO_JPEG_FRAME], val);
-}
-
-static void
-set_videobus_dir (struct zoran *zr,
-                 int           val)
-{
-       switch (zr->card.type) {
-       case LML33:
-       case LML33R10:
-               if (lml33dpath == 0)
-                       GPIO(zr, 5, val);
-               else
-                       GPIO(zr, 5, 1);
-               break;
-       default:
-               GPIO(zr, zr->card.gpio[ZR_GPIO_VID_DIR],
-                    zr->card.gpio_pol[ZR_GPIO_VID_DIR] ? !val : val);
-               break;
-       }
-}
-
-static void
-init_jpeg_queue (struct zoran *zr)
-{
-       int i;
-
-       /* re-initialize DMA ring stuff */
-       zr->jpg_que_head = 0;
-       zr->jpg_dma_head = 0;
-       zr->jpg_dma_tail = 0;
-       zr->jpg_que_tail = 0;
-       zr->jpg_seq_num = 0;
-       zr->JPEG_error = 0;
-       zr->num_errors = 0;
-       zr->jpg_err_seq = 0;
-       zr->jpg_err_shift = 0;
-       zr->jpg_queued_num = 0;
-       for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
-               zr->jpg_buffers.buffer[i].state = BUZ_STATE_USER;       /* nothing going on */
-       }
-       for (i = 0; i < BUZ_NUM_STAT_COM; i++) {
-               zr->stat_com[i] = cpu_to_le32(1);       /* mark as unavailable to zr36057 */
-       }
-}
-
-static void
-zr36057_set_jpg (struct zoran          *zr,
-                enum zoran_codec_mode  mode)
-{
-       struct tvnorm *tvn;
-       u32 reg;
-
-       tvn = zr->timing;
-
-       /* assert P_Reset, disable code transfer, deassert Active */
-       btwrite(0, ZR36057_JPC);
-
-       /* MJPEG compression mode */
-       switch (mode) {
-
-       case BUZ_MODE_MOTION_COMPRESS:
-       default:
-               reg = ZR36057_JMC_MJPGCmpMode;
-               break;
-
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               reg = ZR36057_JMC_MJPGExpMode;
-               reg |= ZR36057_JMC_SyncMstr;
-               /* RJ: The following is experimental - improves the output to screen */
-               //if(zr->jpg_settings.VFIFO_FB) reg |= ZR36057_JMC_VFIFO_FB; // No, it doesn't. SM
-               break;
-
-       case BUZ_MODE_STILL_COMPRESS:
-               reg = ZR36057_JMC_JPGCmpMode;
-               break;
-
-       case BUZ_MODE_STILL_DECOMPRESS:
-               reg = ZR36057_JMC_JPGExpMode;
-               break;
-
-       }
-       reg |= ZR36057_JMC_JPG;
-       if (zr->jpg_settings.field_per_buff == 1)
-               reg |= ZR36057_JMC_Fld_per_buff;
-       btwrite(reg, ZR36057_JMC);
-
-       /* vertical */
-       btor(ZR36057_VFEVCR_VSPol, ZR36057_VFEVCR);
-       reg = (6 << ZR36057_VSP_VsyncSize) |
-             (tvn->Ht << ZR36057_VSP_FrmTot);
-       btwrite(reg, ZR36057_VSP);
-       reg = ((zr->jpg_settings.img_y + tvn->VStart) << ZR36057_FVAP_NAY) |
-             (zr->jpg_settings.img_height << ZR36057_FVAP_PAY);
-       btwrite(reg, ZR36057_FVAP);
-
-       /* horizontal */
-       if (zr->card.vfe_pol.hsync_pol)
-               btor(ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
-       else
-               btand(~ZR36057_VFEHCR_HSPol, ZR36057_VFEHCR);
-       reg = ((tvn->HSyncStart) << ZR36057_HSP_HsyncStart) |
-             (tvn->Wt << ZR36057_HSP_LineTot);
-       btwrite(reg, ZR36057_HSP);
-       reg = ((zr->jpg_settings.img_x +
-               tvn->HStart + 4) << ZR36057_FHAP_NAX) |
-             (zr->jpg_settings.img_width << ZR36057_FHAP_PAX);
-       btwrite(reg, ZR36057_FHAP);
-
-       /* field process parameters */
-       if (zr->jpg_settings.odd_even)
-               reg = ZR36057_FPP_Odd_Even;
-       else
-               reg = 0;
-
-       btwrite(reg, ZR36057_FPP);
-
-       /* Set proper VCLK Polarity, else colors will be wrong during playback */
-       //btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
-
-       /* code base address */
-       reg = virt_to_bus(zr->stat_com);
-       btwrite(reg, ZR36057_JCBA);
-
-       /* FIFO threshold (FIFO is 160. double words) */
-       /* NOTE: decimal values here */
-       switch (mode) {
-
-       case BUZ_MODE_STILL_COMPRESS:
-       case BUZ_MODE_MOTION_COMPRESS:
-               if (zr->card.type != BUZ)
-                       reg = 140;
-               else
-                       reg = 60;
-               break;
-
-       case BUZ_MODE_STILL_DECOMPRESS:
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               reg = 20;
-               break;
-
-       default:
-               reg = 80;
-               break;
-
-       }
-       btwrite(reg, ZR36057_JCFT);
-       zr36057_adjust_vfe(zr, mode);
-
-}
-
-void
-print_interrupts (struct zoran *zr)
-{
-       int res, noerr = 0;
-
-       printk(KERN_INFO "%s: interrupts received:", ZR_DEVNAME(zr));
-       if ((res = zr->field_counter) < -1 || res > 1) {
-               printk(" FD:%d", res);
-       }
-       if ((res = zr->intr_counter_GIRQ1) != 0) {
-               printk(" GIRQ1:%d", res);
-               noerr++;
-       }
-       if ((res = zr->intr_counter_GIRQ0) != 0) {
-               printk(" GIRQ0:%d", res);
-               noerr++;
-       }
-       if ((res = zr->intr_counter_CodRepIRQ) != 0) {
-               printk(" CodRepIRQ:%d", res);
-               noerr++;
-       }
-       if ((res = zr->intr_counter_JPEGRepIRQ) != 0) {
-               printk(" JPEGRepIRQ:%d", res);
-               noerr++;
-       }
-       if (zr->JPEG_max_missed) {
-               printk(" JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
-                      zr->JPEG_min_missed);
-       }
-       if (zr->END_event_missed) {
-               printk(" ENDs missed: %d", zr->END_event_missed);
-       }
-       //if (zr->jpg_queued_num) {
-       printk(" queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
-              zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head);
-       //}
-       if (!noerr) {
-               printk(": no interrupts detected.");
-       }
-       printk("\n");
-}
-
-void
-clear_interrupt_counters (struct zoran *zr)
-{
-       zr->intr_counter_GIRQ1 = 0;
-       zr->intr_counter_GIRQ0 = 0;
-       zr->intr_counter_CodRepIRQ = 0;
-       zr->intr_counter_JPEGRepIRQ = 0;
-       zr->field_counter = 0;
-       zr->IRQ1_in = 0;
-       zr->IRQ1_out = 0;
-       zr->JPEG_in = 0;
-       zr->JPEG_out = 0;
-       zr->JPEG_0 = 0;
-       zr->JPEG_1 = 0;
-       zr->END_event_missed = 0;
-       zr->JPEG_missed = 0;
-       zr->JPEG_max_missed = 0;
-       zr->JPEG_min_missed = 0x7fffffff;
-}
-
-static u32
-count_reset_interrupt (struct zoran *zr)
-{
-       u32 isr;
-
-       if ((isr = btread(ZR36057_ISR) & 0x78000000)) {
-               if (isr & ZR36057_ISR_GIRQ1) {
-                       btwrite(ZR36057_ISR_GIRQ1, ZR36057_ISR);
-                       zr->intr_counter_GIRQ1++;
-               }
-               if (isr & ZR36057_ISR_GIRQ0) {
-                       btwrite(ZR36057_ISR_GIRQ0, ZR36057_ISR);
-                       zr->intr_counter_GIRQ0++;
-               }
-               if (isr & ZR36057_ISR_CodRepIRQ) {
-                       btwrite(ZR36057_ISR_CodRepIRQ, ZR36057_ISR);
-                       zr->intr_counter_CodRepIRQ++;
-               }
-               if (isr & ZR36057_ISR_JPEGRepIRQ) {
-                       btwrite(ZR36057_ISR_JPEGRepIRQ, ZR36057_ISR);
-                       zr->intr_counter_JPEGRepIRQ++;
-               }
-       }
-       return isr;
-}
-
-void
-jpeg_start (struct zoran *zr)
-{
-       int reg;
-
-       zr->frame_num = 0;
-
-       /* deassert P_reset, disable code transfer, deassert Active */
-       btwrite(ZR36057_JPC_P_Reset, ZR36057_JPC);
-       /* stop flushing the internal code buffer */
-       btand(~ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
-       /* enable code transfer */
-       btor(ZR36057_JPC_CodTrnsEn, ZR36057_JPC);
-
-       /* clear IRQs */
-       btwrite(IRQ_MASK, ZR36057_ISR);
-       /* enable the JPEG IRQs */
-       btwrite(zr->card.jpeg_int |
-                       ZR36057_ICR_JPEGRepIRQ |
-                       ZR36057_ICR_IntPinEn,
-               ZR36057_ICR);
-
-       set_frame(zr, 0);       // \FRAME
-
-       /* set the JPEG codec guest ID */
-       reg = (zr->card.gpcs[1] << ZR36057_JCGI_JPEGuestID) |
-              (0 << ZR36057_JCGI_JPEGuestReg);
-       btwrite(reg, ZR36057_JCGI);
-
-       if (zr->card.video_vfe == CODEC_TYPE_ZR36016 &&
-           zr->card.video_codec == CODEC_TYPE_ZR36050) {
-               /* Enable processing on the ZR36016 */
-               if (zr->vfe)
-                       zr36016_write(zr->vfe, 0, 1);
-
-               /* load the address of the GO register in the ZR36050 latch */
-               post_office_write(zr, 0, 0, 0);
-       }
-
-       /* assert Active */
-       btor(ZR36057_JPC_Active, ZR36057_JPC);
-
-       /* enable the Go generation */
-       btor(ZR36057_JMC_Go_en, ZR36057_JMC);
-       udelay(30);
-
-       set_frame(zr, 1);       // /FRAME
-
-       dprintk(3, KERN_DEBUG "%s: jpeg_start\n", ZR_DEVNAME(zr));
-}
-
-void
-zr36057_enable_jpg (struct zoran          *zr,
-                   enum zoran_codec_mode  mode)
-{
-       struct vfe_settings cap;
-       int field_size =
-           zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff;
-
-       zr->codec_mode = mode;
-
-       cap.x = zr->jpg_settings.img_x;
-       cap.y = zr->jpg_settings.img_y;
-       cap.width = zr->jpg_settings.img_width;
-       cap.height = zr->jpg_settings.img_height;
-       cap.decimation =
-           zr->jpg_settings.HorDcm | (zr->jpg_settings.VerDcm << 8);
-       cap.quality = zr->jpg_settings.jpg_comp.quality;
-
-       switch (mode) {
-
-       case BUZ_MODE_MOTION_COMPRESS: {
-               struct jpeg_app_marker app;
-               struct jpeg_com_marker com;
-
-               /* In motion compress mode, the decoder output must be enabled, and
-                * the video bus direction set to input.
-                */
-               set_videobus_dir(zr, 0);
-               decoder_call(zr, video, s_stream, 1);
-               encoder_call(zr, video, s_routing, 0, 0, 0);
-
-               /* Take the JPEG codec and the VFE out of sleep */
-               jpeg_codec_sleep(zr, 0);
-
-               /* set JPEG app/com marker */
-               app.appn = zr->jpg_settings.jpg_comp.APPn;
-               app.len = zr->jpg_settings.jpg_comp.APP_len;
-               memcpy(app.data, zr->jpg_settings.jpg_comp.APP_data, 60);
-               zr->codec->control(zr->codec, CODEC_S_JPEG_APP_DATA,
-                                  sizeof(struct jpeg_app_marker), &app);
-
-               com.len = zr->jpg_settings.jpg_comp.COM_len;
-               memcpy(com.data, zr->jpg_settings.jpg_comp.COM_data, 60);
-               zr->codec->control(zr->codec, CODEC_S_JPEG_COM_DATA,
-                                  sizeof(struct jpeg_com_marker), &com);
-
-               /* Setup the JPEG codec */
-               zr->codec->control(zr->codec, CODEC_S_JPEG_TDS_BYTE,
-                                  sizeof(int), &field_size);
-               zr->codec->set_video(zr->codec, zr->timing, &cap,
-                                    &zr->card.vfe_pol);
-               zr->codec->set_mode(zr->codec, CODEC_DO_COMPRESSION);
-
-               /* Setup the VFE */
-               if (zr->vfe) {
-                       zr->vfe->control(zr->vfe, CODEC_S_JPEG_TDS_BYTE,
-                                        sizeof(int), &field_size);
-                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
-                                          &zr->card.vfe_pol);
-                       zr->vfe->set_mode(zr->vfe, CODEC_DO_COMPRESSION);
-               }
-
-               init_jpeg_queue(zr);
-               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
-
-               clear_interrupt_counters(zr);
-               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_COMPRESS)\n",
-                       ZR_DEVNAME(zr));
-               break;
-       }
-
-       case BUZ_MODE_MOTION_DECOMPRESS:
-               /* In motion decompression mode, the decoder output must be disabled, and
-                * the video bus direction set to output.
-                */
-               decoder_call(zr, video, s_stream, 0);
-               set_videobus_dir(zr, 1);
-               encoder_call(zr, video, s_routing, 1, 0, 0);
-
-               /* Take the JPEG codec and the VFE out of sleep */
-               jpeg_codec_sleep(zr, 0);
-               /* Setup the VFE */
-               if (zr->vfe) {
-                       zr->vfe->set_video(zr->vfe, zr->timing, &cap,
-                                          &zr->card.vfe_pol);
-                       zr->vfe->set_mode(zr->vfe, CODEC_DO_EXPANSION);
-               }
-               /* Setup the JPEG codec */
-               zr->codec->set_video(zr->codec, zr->timing, &cap,
-                                    &zr->card.vfe_pol);
-               zr->codec->set_mode(zr->codec, CODEC_DO_EXPANSION);
-
-               init_jpeg_queue(zr);
-               zr36057_set_jpg(zr, mode);      // \P_Reset, ... Video param, FIFO
-
-               clear_interrupt_counters(zr);
-               dprintk(2, KERN_INFO "%s: enable_jpg(MOTION_DECOMPRESS)\n",
-                       ZR_DEVNAME(zr));
-               break;
-
-       case BUZ_MODE_IDLE:
-       default:
-               /* shut down processing */
-               btand(~(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ),
-                     ZR36057_ICR);
-               btwrite(zr->card.jpeg_int | ZR36057_ICR_JPEGRepIRQ,
-                       ZR36057_ISR);
-               btand(~ZR36057_JMC_Go_en, ZR36057_JMC); // \Go_en
-
-               msleep(50);
-
-               set_videobus_dir(zr, 0);
-               set_frame(zr, 1);       // /FRAME
-               btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);      // /CFlush
-               btwrite(0, ZR36057_JPC);        // \P_Reset,\CodTrnsEn,\Active
-               btand(~ZR36057_JMC_VFIFO_FB, ZR36057_JMC);
-               btand(~ZR36057_JMC_SyncMstr, ZR36057_JMC);
-               jpeg_codec_reset(zr);
-               jpeg_codec_sleep(zr, 1);
-               zr36057_adjust_vfe(zr, mode);
-
-               decoder_call(zr, video, s_stream, 1);
-               encoder_call(zr, video, s_routing, 0, 0, 0);
-
-               dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr));
-               break;
-
-       }
-}
-
-/* when this is called the spinlock must be held */
-void
-zoran_feed_stat_com (struct zoran *zr)
-{
-       /* move frames from pending queue to DMA */
-
-       int frame, i, max_stat_com;
-
-       max_stat_com =
-           (zr->jpg_settings.TmpDcm ==
-            1) ? BUZ_NUM_STAT_COM : (BUZ_NUM_STAT_COM >> 1);
-
-       while ((zr->jpg_dma_head - zr->jpg_dma_tail) < max_stat_com &&
-              zr->jpg_dma_head < zr->jpg_que_head) {
-
-               frame = zr->jpg_pend[zr->jpg_dma_head & BUZ_MASK_FRAME];
-               if (zr->jpg_settings.TmpDcm == 1) {
-                       /* fill 1 stat_com entry */
-                       i = (zr->jpg_dma_head -
-                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
-                               break;
-                       zr->stat_com[i] =
-                           cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
-               } else {
-                       /* fill 2 stat_com entries */
-                       i = ((zr->jpg_dma_head -
-                             zr->jpg_err_shift) & 1) * 2;
-                       if (!(zr->stat_com[i] & cpu_to_le32(1)))
-                               break;
-                       zr->stat_com[i] =
-                           cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
-                       zr->stat_com[i + 1] =
-                           cpu_to_le32(zr->jpg_buffers.buffer[frame].jpg.frag_tab_bus);
-               }
-               zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
-               zr->jpg_dma_head++;
-
-       }
-       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
-               zr->jpg_queued_num++;
-}
-
-/* when this is called the spinlock must be held */
-static void
-zoran_reap_stat_com (struct zoran *zr)
-{
-       /* move frames from DMA queue to done queue */
-
-       int i;
-       u32 stat_com;
-       unsigned int seq;
-       unsigned int dif;
-       struct zoran_buffer *buffer;
-       int frame;
-
-       /* In motion decompress we don't have a hardware frame counter,
-        * we just count the interrupts here */
-
-       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
-               zr->jpg_seq_num++;
-       }
-       while (zr->jpg_dma_tail < zr->jpg_dma_head) {
-               if (zr->jpg_settings.TmpDcm == 1)
-                       i = (zr->jpg_dma_tail -
-                            zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-               else
-                       i = ((zr->jpg_dma_tail -
-                             zr->jpg_err_shift) & 1) * 2 + 1;
-
-               stat_com = le32_to_cpu(zr->stat_com[i]);
-
-               if ((stat_com & 1) == 0) {
-                       return;
-               }
-               frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
-               buffer = &zr->jpg_buffers.buffer[frame];
-               do_gettimeofday(&buffer->bs.timestamp);
-
-               if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-                       buffer->bs.length = (stat_com & 0x7fffff) >> 1;
-
-                       /* update sequence number with the help of the counter in stat_com */
-
-                       seq = ((stat_com >> 24) + zr->jpg_err_seq) & 0xff;
-                       dif = (seq - zr->jpg_seq_num) & 0xff;
-                       zr->jpg_seq_num += dif;
-               } else {
-                       buffer->bs.length = 0;
-               }
-               buffer->bs.seq =
-                   zr->jpg_settings.TmpDcm ==
-                   2 ? (zr->jpg_seq_num >> 1) : zr->jpg_seq_num;
-               buffer->state = BUZ_STATE_DONE;
-
-               zr->jpg_dma_tail++;
-       }
-}
-
-static void zoran_restart(struct zoran *zr)
-{
-       /* Now the stat_comm buffer is ready for restart */
-       unsigned int status = 0;
-       int mode;
-
-       if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-               decoder_call(zr, video, g_input_status, &status);
-               mode = CODEC_DO_COMPRESSION;
-       } else {
-               status = V4L2_IN_ST_NO_SIGNAL;
-               mode = CODEC_DO_EXPANSION;
-       }
-       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-           !(status & V4L2_IN_ST_NO_SIGNAL)) {
-               /********** RESTART code *************/
-               jpeg_codec_reset(zr);
-               zr->codec->set_mode(zr->codec, mode);
-               zr36057_set_jpg(zr, zr->codec_mode);
-               jpeg_start(zr);
-
-               if (zr->num_errors <= 8)
-                       dprintk(2, KERN_INFO "%s: Restart\n",
-                               ZR_DEVNAME(zr));
-
-               zr->JPEG_missed = 0;
-               zr->JPEG_error = 2;
-               /********** End RESTART code ***********/
-       }
-}
-
-static void
-error_handler (struct zoran *zr,
-              u32           astat,
-              u32           stat)
-{
-       int i;
-
-       /* This is JPEG error handling part */
-       if (zr->codec_mode != BUZ_MODE_MOTION_COMPRESS &&
-           zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS) {
-               return;
-       }
-
-       if ((stat & 1) == 0 &&
-           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS &&
-           zr->jpg_dma_tail - zr->jpg_que_tail >= zr->jpg_buffers.num_buffers) {
-               /* No free buffers... */
-               zoran_reap_stat_com(zr);
-               zoran_feed_stat_com(zr);
-               wake_up_interruptible(&zr->jpg_capq);
-               zr->JPEG_missed = 0;
-               return;
-       }
-
-       if (zr->JPEG_error == 1) {
-               zoran_restart(zr);
-               return;
-       }
-
-       /*
-        * First entry: error just happened during normal operation
-        *
-        * In BUZ_MODE_MOTION_COMPRESS:
-        *
-        * Possible glitch in TV signal. In this case we should
-        * stop the codec and wait for good quality signal before
-        * restarting it to avoid further problems
-        *
-        * In BUZ_MODE_MOTION_DECOMPRESS:
-        *
-        * Bad JPEG frame: we have to mark it as processed (codec crashed
-        * and was not able to do it itself), and to remove it from queue.
-        */
-       btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
-       udelay(1);
-       stat = stat | (post_office_read(zr, 7, 0) & 3) << 8;
-       btwrite(0, ZR36057_JPC);
-       btor(ZR36057_MCTCR_CFlush, ZR36057_MCTCR);
-       jpeg_codec_reset(zr);
-       jpeg_codec_sleep(zr, 1);
-       zr->JPEG_error = 1;
-       zr->num_errors++;
-
-       /* Report error */
-       if (zr36067_debug > 1 && zr->num_errors <= 8) {
-               long frame;
-               int j;
-
-               frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME];
-               printk(KERN_ERR
-                      "%s: JPEG error stat=0x%08x(0x%08x) queue_state=%ld/%ld/%ld/%ld seq=%ld frame=%ld. Codec stopped. ",
-                      ZR_DEVNAME(zr), stat, zr->last_isr,
-                      zr->jpg_que_tail, zr->jpg_dma_tail,
-                      zr->jpg_dma_head, zr->jpg_que_head,
-                      zr->jpg_seq_num, frame);
-               printk(KERN_INFO "stat_com frames:");
-               for (j = 0; j < BUZ_NUM_STAT_COM; j++) {
-                       for (i = 0; i < zr->jpg_buffers.num_buffers; i++) {
-                               if (le32_to_cpu(zr->stat_com[j]) == zr->jpg_buffers.buffer[i].jpg.frag_tab_bus)
-                                       printk(KERN_CONT "% d->%d", j, i);
-                       }
-               }
-               printk(KERN_CONT "\n");
-       }
-       /* Find an entry in stat_com and rotate contents */
-       if (zr->jpg_settings.TmpDcm == 1)
-               i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-       else
-               i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
-       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
-               /* Mimic zr36067 operation */
-               zr->stat_com[i] |= cpu_to_le32(1);
-               if (zr->jpg_settings.TmpDcm != 1)
-                       zr->stat_com[i + 1] |= cpu_to_le32(1);
-               /* Refill */
-               zoran_reap_stat_com(zr);
-               zoran_feed_stat_com(zr);
-               wake_up_interruptible(&zr->jpg_capq);
-               /* Find an entry in stat_com again after refill */
-               if (zr->jpg_settings.TmpDcm == 1)
-                       i = (zr->jpg_dma_tail - zr->jpg_err_shift) & BUZ_MASK_STAT_COM;
-               else
-                       i = ((zr->jpg_dma_tail - zr->jpg_err_shift) & 1) * 2;
-       }
-       if (i) {
-               /* Rotate stat_comm entries to make current entry first */
-               int j;
-               __le32 bus_addr[BUZ_NUM_STAT_COM];
-
-               /* Here we are copying the stat_com array, which
-                * is already in little endian format, so
-                * no endian conversions here
-                */
-               memcpy(bus_addr, zr->stat_com, sizeof(bus_addr));
-
-               for (j = 0; j < BUZ_NUM_STAT_COM; j++)
-                       zr->stat_com[j] = bus_addr[(i + j) & BUZ_MASK_STAT_COM];
-
-               zr->jpg_err_shift += i;
-               zr->jpg_err_shift &= BUZ_MASK_STAT_COM;
-       }
-       if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)
-               zr->jpg_err_seq = zr->jpg_seq_num;      /* + 1; */
-       zoran_restart(zr);
-}
-
-irqreturn_t
-zoran_irq (int             irq,
-          void           *dev_id)
-{
-       u32 stat, astat;
-       int count;
-       struct zoran *zr;
-       unsigned long flags;
-
-       zr = dev_id;
-       count = 0;
-
-       if (zr->testing) {
-               /* Testing interrupts */
-               spin_lock_irqsave(&zr->spinlock, flags);
-               while ((stat = count_reset_interrupt(zr))) {
-                       if (count++ > 100) {
-                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: IRQ lockup while testing, isr=0x%08x, cleared int mask\n",
-                                       ZR_DEVNAME(zr), stat);
-                               wake_up_interruptible(&zr->test_q);
-                       }
-               }
-               zr->last_isr = stat;
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-               return IRQ_HANDLED;
-       }
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-       while (1) {
-               /* get/clear interrupt status bits */
-               stat = count_reset_interrupt(zr);
-               astat = stat & IRQ_MASK;
-               if (!astat) {
-                       break;
-               }
-               dprintk(4,
-                       KERN_DEBUG
-                       "zoran_irq: astat: 0x%08x, mask: 0x%08x\n",
-                       astat, btread(ZR36057_ICR));
-               if (astat & zr->card.vsync_int) {       // SW
-
-                       if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-                           zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
-                               /* count missed interrupts */
-                               zr->JPEG_missed++;
-                       }
-                       //post_office_read(zr,1,0);
-                       /* Interrupts may still happen when
-                        * zr->v4l_memgrab_active is switched off.
-                        * We simply ignore them */
-
-                       if (zr->v4l_memgrab_active) {
-                               /* A lot more checks should be here ... */
-                               if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) == 0)
-                                       dprintk(1,
-                                               KERN_WARNING
-                                               "%s: BuzIRQ with SnapShot off ???\n",
-                                               ZR_DEVNAME(zr));
-
-                               if (zr->v4l_grab_frame != NO_GRAB_ACTIVE) {
-                                       /* There is a grab on a frame going on, check if it has finished */
-                                       if ((btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_FrameGrab) == 0) {
-                                               /* it is finished, notify the user */
-
-                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].state = BUZ_STATE_DONE;
-                                               zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.seq = zr->v4l_grab_seq;
-                                               do_gettimeofday(&zr->v4l_buffers.buffer[zr->v4l_grab_frame].bs.timestamp);
-                                               zr->v4l_grab_frame = NO_GRAB_ACTIVE;
-                                               zr->v4l_pend_tail++;
-                                       }
-                               }
-
-                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE)
-                                       wake_up_interruptible(&zr->v4l_capq);
-
-                               /* Check if there is another grab queued */
-
-                               if (zr->v4l_grab_frame == NO_GRAB_ACTIVE &&
-                                   zr->v4l_pend_tail != zr->v4l_pend_head) {
-                                       int frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME];
-                                       u32 reg;
-
-                                       zr->v4l_grab_frame = frame;
-
-                                       /* Set zr36057 video front end and enable video */
-
-                                       /* Buffer address */
-
-                                       reg = zr->v4l_buffers.buffer[frame].v4l.fbuffer_bus;
-                                       btwrite(reg, ZR36057_VDTR);
-                                       if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
-                                               reg += zr->v4l_settings.bytesperline;
-                                       btwrite(reg, ZR36057_VDBR);
-
-                                       /* video stride, status, and frame grab register */
-                                       reg = 0;
-                                       if (zr->v4l_settings.height > BUZ_MAX_HEIGHT / 2)
-                                               reg += zr->v4l_settings.bytesperline;
-                                       reg = (reg << ZR36057_VSSFGR_DispStride);
-                                       reg |= ZR36057_VSSFGR_VidOvf;
-                                       reg |= ZR36057_VSSFGR_SnapShot;
-                                       reg |= ZR36057_VSSFGR_FrameGrab;
-                                       btwrite(reg, ZR36057_VSSFGR);
-
-                                       btor(ZR36057_VDCR_VidEn,
-                                            ZR36057_VDCR);
-                               }
-                       }
-
-                       /* even if we don't grab, we do want to increment
-                        * the sequence counter to see lost frames */
-                       zr->v4l_grab_seq++;
-               }
-#if (IRQ_MASK & ZR36057_ISR_CodRepIRQ)
-               if (astat & ZR36057_ISR_CodRepIRQ) {
-                       zr->intr_counter_CodRepIRQ++;
-                       IDEBUG(printk(KERN_DEBUG "%s: ZR36057_ISR_CodRepIRQ\n",
-                               ZR_DEVNAME(zr)));
-                       btand(~ZR36057_ICR_CodRepIRQ, ZR36057_ICR);
-               }
-#endif                         /* (IRQ_MASK & ZR36057_ISR_CodRepIRQ) */
-
-#if (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ)
-               if ((astat & ZR36057_ISR_JPEGRepIRQ) &&
-                   (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
-                    zr->codec_mode == BUZ_MODE_MOTION_COMPRESS)) {
-                       if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) {
-                               char sv[BUZ_NUM_STAT_COM + 1];
-                               int i;
-
-                               printk(KERN_INFO
-                                      "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n",
-                                      ZR_DEVNAME(zr), stat,
-                                      zr->jpg_settings.odd_even,
-                                      zr->jpg_settings.field_per_buff,
-                                      zr->JPEG_missed);
-
-                               for (i = 0; i < BUZ_NUM_STAT_COM; i++)
-                                       sv[i] = le32_to_cpu(zr->stat_com[i]) & 1 ? '1' : '0';
-                               sv[BUZ_NUM_STAT_COM] = 0;
-                               printk(KERN_INFO
-                                      "%s: stat_com=%s queue_state=%ld/%ld/%ld/%ld\n",
-                                      ZR_DEVNAME(zr), sv,
-                                      zr->jpg_que_tail,
-                                      zr->jpg_dma_tail,
-                                      zr->jpg_dma_head,
-                                      zr->jpg_que_head);
-                       } else {
-                               /* Get statistics */
-                               if (zr->JPEG_missed > zr->JPEG_max_missed)
-                                       zr->JPEG_max_missed = zr->JPEG_missed;
-                               if (zr->JPEG_missed < zr->JPEG_min_missed)
-                                       zr->JPEG_min_missed = zr->JPEG_missed;
-                       }
-
-                       if (zr36067_debug > 2 && zr->frame_num < 6) {
-                               int i;
-
-                               printk(KERN_INFO "%s: seq=%ld stat_com:",
-                                      ZR_DEVNAME(zr), zr->jpg_seq_num);
-                               for (i = 0; i < 4; i++) {
-                                       printk(KERN_CONT " %08x",
-                                              le32_to_cpu(zr->stat_com[i]));
-                               }
-                               printk(KERN_CONT "\n");
-                       }
-                       zr->frame_num++;
-                       zr->JPEG_missed = 0;
-                       zr->JPEG_error = 0;
-                       zoran_reap_stat_com(zr);
-                       zoran_feed_stat_com(zr);
-                       wake_up_interruptible(&zr->jpg_capq);
-               }
-#endif                         /* (IRQ_MASK & ZR36057_ISR_JPEGRepIRQ) */
-
-               /* DATERR, too many fields missed, error processing */
-               if ((astat & zr->card.jpeg_int) ||
-                   zr->JPEG_missed > 25 ||
-                   zr->JPEG_error == 1 ||
-                   ((zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) &&
-                    (zr->frame_num && (zr->JPEG_missed > zr->jpg_settings.field_per_buff)))) {
-                       error_handler(zr, astat, stat);
-               }
-
-               count++;
-               if (count > 10) {
-                       dprintk(2, KERN_WARNING "%s: irq loop %d\n",
-                               ZR_DEVNAME(zr), count);
-                       if (count > 20) {
-                               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-                               dprintk(2,
-                                       KERN_ERR
-                                       "%s: IRQ lockup, cleared int mask\n",
-                                       ZR_DEVNAME(zr));
-                               break;
-                       }
-               }
-               zr->last_isr = stat;
-       }
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return IRQ_HANDLED;
-}
-
-void
-zoran_set_pci_master (struct zoran *zr,
-                     int           set_master)
-{
-       if (set_master) {
-               pci_set_master(zr->pci_dev);
-       } else {
-               u16 command;
-
-               pci_read_config_word(zr->pci_dev, PCI_COMMAND, &command);
-               command &= ~PCI_COMMAND_MASTER;
-               pci_write_config_word(zr->pci_dev, PCI_COMMAND, command);
-       }
-}
-
-void
-zoran_init_hardware (struct zoran *zr)
-{
-       /* Enable bus-mastering */
-       zoran_set_pci_master(zr, 1);
-
-       /* Initialize the board */
-       if (zr->card.init) {
-               zr->card.init(zr);
-       }
-
-       decoder_call(zr, core, init, 0);
-       decoder_call(zr, core, s_std, zr->norm);
-       decoder_call(zr, video, s_routing,
-               zr->card.input[zr->input].muxsel, 0, 0);
-
-       encoder_call(zr, core, init, 0);
-       encoder_call(zr, video, s_std_output, zr->norm);
-       encoder_call(zr, video, s_routing, 0, 0, 0);
-
-       /* toggle JPEG codec sleep to sync PLL */
-       jpeg_codec_sleep(zr, 1);
-       jpeg_codec_sleep(zr, 0);
-
-       /* set individual interrupt enables (without GIRQ1)
-        * but don't global enable until zoran_open() */
-
-       //btwrite(IRQ_MASK & ~ZR36057_ISR_GIRQ1, ZR36057_ICR);  // SW
-       // It looks like using only JPEGRepIRQEn is not always reliable,
-       // may be when JPEG codec crashes it won't generate IRQ? So,
-        /*CP*/                 //        btwrite(IRQ_MASK, ZR36057_ICR); // Enable Vsync interrupts too. SM    WHY ? LP
-           zr36057_init_vfe(zr);
-
-       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-
-       btwrite(IRQ_MASK, ZR36057_ISR); // Clears interrupts
-}
-
-void
-zr36057_restart (struct zoran *zr)
-{
-       btwrite(0, ZR36057_SPGPPCR);
-       mdelay(1);
-       btor(ZR36057_SPGPPCR_SoftReset, ZR36057_SPGPPCR);
-       mdelay(1);
-
-       /* assert P_Reset */
-       btwrite(0, ZR36057_JPC);
-       /* set up GPIO direction - all output */
-       btwrite(ZR36057_SPGPPCR_SoftReset | 0, ZR36057_SPGPPCR);
-
-       /* set up GPIO pins and guest bus timing */
-       btwrite((0x81 << 24) | 0x8888, ZR36057_GPPGCR1);
-}
-
-/*
- * initialize video front end
- */
-
-static void
-zr36057_init_vfe (struct zoran *zr)
-{
-       u32 reg;
-
-       reg = btread(ZR36057_VFESPFR);
-       reg |= ZR36057_VFESPFR_LittleEndian;
-       reg &= ~ZR36057_VFESPFR_VCLKPol;
-       reg |= ZR36057_VFESPFR_ExtFl;
-       reg |= ZR36057_VFESPFR_TopField;
-       btwrite(reg, ZR36057_VFESPFR);
-       reg = btread(ZR36057_VDCR);
-       if (pci_pci_problems & PCIPCI_TRITON)
-               // || zr->revision < 1) // Revision 1 has also Triton support
-               reg &= ~ZR36057_VDCR_Triton;
-       else
-               reg |= ZR36057_VDCR_Triton;
-       btwrite(reg, ZR36057_VDCR);
-}
diff --git a/drivers/media/video/zoran/zoran_device.h b/drivers/media/video/zoran/zoran_device.h
deleted file mode 100644 (file)
index 07f2c23..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.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.
- */
-
-#ifndef __ZORAN_DEVICE_H__
-#define __ZORAN_DEVICE_H__
-
-/* general purpose I/O */
-extern void GPIO(struct zoran *zr,
-                int bit,
-                unsigned int value);
-
-/* codec (or actually: guest bus) access */
-extern int post_office_wait(struct zoran *zr);
-extern int post_office_write(struct zoran *zr,
-                            unsigned guest,
-                            unsigned reg,
-                            unsigned value);
-extern int post_office_read(struct zoran *zr,
-                           unsigned guest,
-                           unsigned reg);
-
-extern void detect_guest_activity(struct zoran *zr);
-
-extern void jpeg_codec_sleep(struct zoran *zr,
-                            int sleep);
-extern int jpeg_codec_reset(struct zoran *zr);
-
-/* zr360x7 access to raw capture */
-extern void zr36057_overlay(struct zoran *zr,
-                           int on);
-extern void write_overlay_mask(struct zoran_fh *fh,
-                              struct v4l2_clip *vp,
-                              int count);
-extern void zr36057_set_memgrab(struct zoran *zr,
-                               int mode);
-extern int wait_grab_pending(struct zoran *zr);
-
-/* interrupts */
-extern void print_interrupts(struct zoran *zr);
-extern void clear_interrupt_counters(struct zoran *zr);
-extern irqreturn_t zoran_irq(int irq, void *dev_id);
-
-/* JPEG codec access */
-extern void jpeg_start(struct zoran *zr);
-extern void zr36057_enable_jpg(struct zoran *zr,
-                              enum zoran_codec_mode mode);
-extern void zoran_feed_stat_com(struct zoran *zr);
-
-/* general */
-extern void zoran_set_pci_master(struct zoran *zr,
-                                int set_master);
-extern void zoran_init_hardware(struct zoran *zr);
-extern void zr36057_restart(struct zoran *zr);
-
-extern const struct zoran_format zoran_formats[];
-
-extern int v4l_nbufs;
-extern int v4l_bufsize;
-extern int jpg_nbufs;
-extern int jpg_bufsize;
-extern int pass_through;
-
-/* i2c */
-#define decoder_call(zr, o, f, args...) \
-       v4l2_subdev_call(zr->decoder, o, f, ##args)
-#define encoder_call(zr, o, f, args...) \
-       v4l2_subdev_call(zr->encoder, o, f, ##args)
-
-#endif                         /* __ZORAN_DEVICE_H__ */
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c
deleted file mode 100644 (file)
index c6ccdeb..0000000
+++ /dev/null
@@ -1,3090 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net>
- *
- * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com>
- *
- * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net>
- *
- * Based on
- *
- * Miro DC10 driver
- * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
- *
- * Iomega Buz driver version 1.0
- * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
- *
- * buz.0.0.3
- * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
- *
- * bttv - Bt848 frame grabber driver
- * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
- *                        & Marcus Metzler (mocm@thp.uni-koeln.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.
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include <linux/spinlock.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include "videocodec.h"
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/proc_fs.h>
-
-#include <linux/mutex.h>
-#include "zoran.h"
-#include "zoran_device.h"
-#include "zoran_card.h"
-
-
-const struct zoran_format zoran_formats[] = {
-       {
-               .name = "15-bit RGB LE",
-               .fourcc = V4L2_PIX_FMT_RGB555,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 15,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif|
-                          ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "15-bit RGB BE",
-               .fourcc = V4L2_PIX_FMT_RGB555X,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 15,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif,
-       }, {
-               .name = "16-bit RGB LE",
-               .fourcc = V4L2_PIX_FMT_RGB565,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif|
-                          ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "16-bit RGB BE",
-               .fourcc = V4L2_PIX_FMT_RGB565X,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif,
-       }, {
-               .name = "24-bit RGB",
-               .fourcc = V4L2_PIX_FMT_BGR24,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 24,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24,
-       }, {
-               .name = "32-bit RGB LE",
-               .fourcc = V4L2_PIX_FMT_BGR32,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 32,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "32-bit RGB BE",
-               .fourcc = V4L2_PIX_FMT_RGB32,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .depth = 32,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_RGB888,
-       }, {
-               .name = "4:2:2, packed, YUYV",
-               .fourcc = V4L2_PIX_FMT_YUYV,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_YUV422,
-       }, {
-               .name = "4:2:2, packed, UYVY",
-               .fourcc = V4L2_PIX_FMT_UYVY,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-               .depth = 16,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_OVERLAY,
-               .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian,
-       }, {
-               .name = "Hardware-encoded Motion-JPEG",
-               .fourcc = V4L2_PIX_FMT_MJPEG,
-               .colorspace = V4L2_COLORSPACE_SMPTE170M,
-               .depth = 0,
-               .flags = ZORAN_FORMAT_CAPTURE |
-                        ZORAN_FORMAT_PLAYBACK |
-                        ZORAN_FORMAT_COMPRESSED,
-       }
-};
-#define NUM_FORMATS ARRAY_SIZE(zoran_formats)
-
-       /* small helper function for calculating buffersizes for v4l2
-        * we calculate the nearest higher power-of-two, which
-        * will be the recommended buffersize */
-static __u32
-zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings)
-{
-       __u8 div = settings->VerDcm * settings->HorDcm * settings->TmpDcm;
-       __u32 num = (1024 * 512) / (div);
-       __u32 result = 2;
-
-       num--;
-       while (num) {
-               num >>= 1;
-               result <<= 1;
-       }
-
-       if (result > jpg_bufsize)
-               return jpg_bufsize;
-       if (result < 8192)
-               return 8192;
-       return result;
-}
-
-/* forward references */
-static void v4l_fbuffer_free(struct zoran_fh *fh);
-static void jpg_fbuffer_free(struct zoran_fh *fh);
-
-/* Set mapping mode */
-static void map_mode_raw(struct zoran_fh *fh)
-{
-       fh->map_mode = ZORAN_MAP_MODE_RAW;
-       fh->buffers.buffer_size = v4l_bufsize;
-       fh->buffers.num_buffers = v4l_nbufs;
-}
-static void map_mode_jpg(struct zoran_fh *fh, int play)
-{
-       fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC;
-       fh->buffers.buffer_size = jpg_bufsize;
-       fh->buffers.num_buffers = jpg_nbufs;
-}
-static inline const char *mode_name(enum zoran_map_mode mode)
-{
-       return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG";
-}
-
-/*
- *   Allocate the V4L grab buffers
- *
- *   These have to be pysically contiguous.
- */
-
-static int v4l_fbuffer_alloc(struct zoran_fh *fh)
-{
-       struct zoran *zr = fh->zr;
-       int i, off;
-       unsigned char *mem;
-
-       for (i = 0; i < fh->buffers.num_buffers; i++) {
-               if (fh->buffers.buffer[i].v4l.fbuffer)
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: %s - buffer %d already allocated!?\n",
-                               ZR_DEVNAME(zr), __func__, i);
-
-               //udelay(20);
-               mem = kmalloc(fh->buffers.buffer_size,
-                             GFP_KERNEL | __GFP_NOWARN);
-               if (!mem) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - kmalloc for V4L buf %d failed\n",
-                               ZR_DEVNAME(zr), __func__, i);
-                       v4l_fbuffer_free(fh);
-                       return -ENOBUFS;
-               }
-               fh->buffers.buffer[i].v4l.fbuffer = mem;
-               fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
-               fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
-               for (off = 0; off < fh->buffers.buffer_size;
-                    off += PAGE_SIZE)
-                       SetPageReserved(virt_to_page(mem + off));
-               dprintk(4,
-                       KERN_INFO
-                       "%s: %s - V4L frame %d mem 0x%lx (bus: 0x%llx)\n",
-                       ZR_DEVNAME(zr), __func__, i, (unsigned long) mem,
-                       (unsigned long long)virt_to_bus(mem));
-       }
-
-       fh->buffers.allocated = 1;
-
-       return 0;
-}
-
-/* free the V4L grab buffers */
-static void v4l_fbuffer_free(struct zoran_fh *fh)
-{
-       struct zoran *zr = fh->zr;
-       int i, off;
-       unsigned char *mem;
-
-       dprintk(4, KERN_INFO "%s: %s\n", ZR_DEVNAME(zr), __func__);
-
-       for (i = 0; i < fh->buffers.num_buffers; i++) {
-               if (!fh->buffers.buffer[i].v4l.fbuffer)
-                       continue;
-
-               mem = fh->buffers.buffer[i].v4l.fbuffer;
-               for (off = 0; off < fh->buffers.buffer_size;
-                    off += PAGE_SIZE)
-                       ClearPageReserved(virt_to_page(mem + off));
-               kfree(fh->buffers.buffer[i].v4l.fbuffer);
-               fh->buffers.buffer[i].v4l.fbuffer = NULL;
-       }
-
-       fh->buffers.allocated = 0;
-}
-
-/*
- *   Allocate the MJPEG grab buffers.
- *
- *   If a Natoma chipset is present and this is a revision 1 zr36057,
- *   each MJPEG buffer needs to be physically contiguous.
- *   (RJ: This statement is from Dave Perks' original driver,
- *   I could never check it because I have a zr36067)
- *
- *   RJ: The contents grab buffers needs never be accessed in the driver.
- *       Therefore there is no need to allocate them with vmalloc in order
- *       to get a contiguous virtual memory space.
- *       I don't understand why many other drivers first allocate them with
- *       vmalloc (which uses internally also get_zeroed_page, but delivers you
- *       virtual addresses) and then again have to make a lot of efforts
- *       to get the physical address.
- *
- *   Ben Capper:
- *       On big-endian architectures (such as ppc) some extra steps
- *       are needed. When reading and writing to the stat_com array
- *       and fragment buffers, the device expects to see little-
- *       endian values. The use of cpu_to_le32() and le32_to_cpu()
- *       in this function (and one or two others in zoran_device.c)
- *       ensure that these values are always stored in little-endian
- *       form, regardless of architecture. The zr36057 does Very Bad
- *       Things on big endian architectures if the stat_com array
- *       and fragment buffers are not little-endian.
- */
-
-static int jpg_fbuffer_alloc(struct zoran_fh *fh)
-{
-       struct zoran *zr = fh->zr;
-       int i, j, off;
-       u8 *mem;
-
-       for (i = 0; i < fh->buffers.num_buffers; i++) {
-               if (fh->buffers.buffer[i].jpg.frag_tab)
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: %s - buffer %d already allocated!?\n",
-                               ZR_DEVNAME(zr), __func__, i);
-
-               /* Allocate fragment table for this buffer */
-
-               mem = (void *)get_zeroed_page(GFP_KERNEL);
-               if (!mem) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - get_zeroed_page (frag_tab) failed for buffer %d\n",
-                               ZR_DEVNAME(zr), __func__, i);
-                       jpg_fbuffer_free(fh);
-                       return -ENOBUFS;
-               }
-               fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem;
-               fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem);
-
-               if (fh->buffers.need_contiguous) {
-                       mem = kmalloc(fh->buffers.buffer_size, GFP_KERNEL);
-                       if (mem == NULL) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: %s - kmalloc failed for buffer %d\n",
-                                       ZR_DEVNAME(zr), __func__, i);
-                               jpg_fbuffer_free(fh);
-                               return -ENOBUFS;
-                       }
-                       fh->buffers.buffer[i].jpg.frag_tab[0] =
-                               cpu_to_le32(virt_to_bus(mem));
-                       fh->buffers.buffer[i].jpg.frag_tab[1] =
-                               cpu_to_le32((fh->buffers.buffer_size >> 1) | 1);
-                       for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
-                               SetPageReserved(virt_to_page(mem + off));
-               } else {
-                       /* jpg_bufsize is already page aligned */
-                       for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
-                               mem = (void *)get_zeroed_page(GFP_KERNEL);
-                               if (mem == NULL) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: %s - get_zeroed_page failed for buffer %d\n",
-                                               ZR_DEVNAME(zr), __func__, i);
-                                       jpg_fbuffer_free(fh);
-                                       return -ENOBUFS;
-                               }
-
-                               fh->buffers.buffer[i].jpg.frag_tab[2 * j] =
-                                       cpu_to_le32(virt_to_bus(mem));
-                               fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] =
-                                       cpu_to_le32((PAGE_SIZE >> 2) << 1);
-                               SetPageReserved(virt_to_page(mem));
-                       }
-
-                       fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1);
-               }
-       }
-
-       dprintk(4,
-               KERN_DEBUG "%s: %s - %d KB allocated\n",
-               ZR_DEVNAME(zr), __func__,
-               (fh->buffers.num_buffers * fh->buffers.buffer_size) >> 10);
-
-       fh->buffers.allocated = 1;
-
-       return 0;
-}
-
-/* free the MJPEG grab buffers */
-static void jpg_fbuffer_free(struct zoran_fh *fh)
-{
-       struct zoran *zr = fh->zr;
-       int i, j, off;
-       unsigned char *mem;
-       __le32 frag_tab;
-       struct zoran_buffer *buffer;
-
-       dprintk(4, KERN_DEBUG "%s: %s\n", ZR_DEVNAME(zr), __func__);
-
-       for (i = 0, buffer = &fh->buffers.buffer[0];
-            i < fh->buffers.num_buffers; i++, buffer++) {
-               if (!buffer->jpg.frag_tab)
-                       continue;
-
-               if (fh->buffers.need_contiguous) {
-                       frag_tab = buffer->jpg.frag_tab[0];
-
-                       if (frag_tab) {
-                               mem = bus_to_virt(le32_to_cpu(frag_tab));
-                               for (off = 0; off < fh->buffers.buffer_size; off += PAGE_SIZE)
-                                       ClearPageReserved(virt_to_page(mem + off));
-                               kfree(mem);
-                               buffer->jpg.frag_tab[0] = 0;
-                               buffer->jpg.frag_tab[1] = 0;
-                       }
-               } else {
-                       for (j = 0; j < fh->buffers.buffer_size / PAGE_SIZE; j++) {
-                               frag_tab = buffer->jpg.frag_tab[2 * j];
-
-                               if (!frag_tab)
-                                       break;
-                               ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab))));
-                               free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab)));
-                               buffer->jpg.frag_tab[2 * j] = 0;
-                               buffer->jpg.frag_tab[2 * j + 1] = 0;
-                       }
-               }
-
-               free_page((unsigned long)buffer->jpg.frag_tab);
-               buffer->jpg.frag_tab = NULL;
-       }
-
-       fh->buffers.allocated = 0;
-}
-
-/*
- *   V4L Buffer grabbing
- */
-
-static int
-zoran_v4l_set_format (struct zoran_fh           *fh,
-                     int                        width,
-                     int                        height,
-                     const struct zoran_format *format)
-{
-       struct zoran *zr = fh->zr;
-       int bpp;
-
-       /* Check size and format of the grab wanted */
-
-       if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||
-           height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - wrong frame size (%dx%d)\n",
-                       ZR_DEVNAME(zr), __func__, width, height);
-               return -EINVAL;
-       }
-
-       bpp = (format->depth + 7) / 8;
-
-       /* Check against available buffer size */
-       if (height * width * bpp > fh->buffers.buffer_size) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - video buffer size (%d kB) is too small\n",
-                       ZR_DEVNAME(zr), __func__, fh->buffers.buffer_size >> 10);
-               return -EINVAL;
-       }
-
-       /* The video front end needs 4-byte alinged line sizes */
-
-       if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - wrong frame alignment\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       fh->v4l_settings.width = width;
-       fh->v4l_settings.height = height;
-       fh->v4l_settings.format = format;
-       fh->v4l_settings.bytesperline = bpp * fh->v4l_settings.width;
-
-       return 0;
-}
-
-static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num)
-{
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-       int res = 0;
-
-       if (!fh->buffers.allocated) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - buffers not yet allocated\n",
-                       ZR_DEVNAME(zr), __func__);
-               res = -ENOMEM;
-       }
-
-       /* No grabbing outside the buffer range! */
-       if (num >= fh->buffers.num_buffers || num < 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - buffer %d is out of range\n",
-                       ZR_DEVNAME(zr), __func__, num);
-               res = -EINVAL;
-       }
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       if (fh->buffers.active == ZORAN_FREE) {
-               if (zr->v4l_buffers.active == ZORAN_FREE) {
-                       zr->v4l_buffers = fh->buffers;
-                       fh->buffers.active = ZORAN_ACTIVE;
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - another session is already capturing\n",
-                               ZR_DEVNAME(zr), __func__);
-                       res = -EBUSY;
-               }
-       }
-
-       /* make sure a grab isn't going on currently with this buffer */
-       if (!res) {
-               switch (zr->v4l_buffers.buffer[num].state) {
-               default:
-               case BUZ_STATE_PEND:
-                       if (zr->v4l_buffers.active == ZORAN_FREE) {
-                               fh->buffers.active = ZORAN_FREE;
-                               zr->v4l_buffers.allocated = 0;
-                       }
-                       res = -EBUSY;   /* what are you doing? */
-                       break;
-               case BUZ_STATE_DONE:
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: %s - queueing buffer %d in state DONE!?\n",
-                               ZR_DEVNAME(zr), __func__, num);
-               case BUZ_STATE_USER:
-                       /* since there is at least one unused buffer there's room for at least
-                        * one more pend[] entry */
-                       zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num;
-                       zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
-                       zr->v4l_buffers.buffer[num].bs.length =
-                           fh->v4l_settings.bytesperline *
-                           zr->v4l_settings.height;
-                       fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num];
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       if (!res && zr->v4l_buffers.active == ZORAN_FREE)
-               zr->v4l_buffers.active = fh->buffers.active;
-
-       return res;
-}
-
-/*
- * Sync on a V4L buffer
- */
-
-static int v4l_sync(struct zoran_fh *fh, int frame)
-{
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-
-       if (fh->buffers.active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - no grab active for this session\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       /* check passed-in frame number */
-       if (frame >= fh->buffers.num_buffers || frame < 0) {
-               dprintk(1,
-                       KERN_ERR "%s: %s - frame %d is invalid\n",
-                       ZR_DEVNAME(zr), __func__, frame);
-               return -EINVAL;
-       }
-
-       /* Check if is buffer was queued at all */
-       if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - attempt to sync on a buffer which was not queued?\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EPROTO;
-       }
-
-       /* wait on this buffer to get ready */
-       if (!wait_event_interruptible_timeout(zr->v4l_capq,
-               (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10*HZ))
-               return -ETIME;
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       /* buffer should now be in BUZ_STATE_DONE */
-       if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
-               dprintk(2,
-                       KERN_ERR "%s: %s - internal state error\n",
-                       ZR_DEVNAME(zr), __func__);
-
-       zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
-       fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       /* Check if streaming capture has finished */
-       if (zr->v4l_pend_tail == zr->v4l_pend_head) {
-               zr36057_set_memgrab(zr, 0);
-               if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
-                       fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE;
-                       zr->v4l_buffers.allocated = 0;
-               }
-       }
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return 0;
-}
-
-/*
- *   Queue a MJPEG buffer for capture/playback
- */
-
-static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num,
-                                enum zoran_codec_mode mode)
-{
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-       int res = 0;
-
-       /* Check if buffers are allocated */
-       if (!fh->buffers.allocated) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - buffers not yet allocated\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -ENOMEM;
-       }
-
-       /* No grabbing outside the buffer range! */
-       if (num >= fh->buffers.num_buffers || num < 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - buffer %d out of range\n",
-                       ZR_DEVNAME(zr), __func__, num);
-               return -EINVAL;
-       }
-
-       /* what is the codec mode right now? */
-       if (zr->codec_mode == BUZ_MODE_IDLE) {
-               zr->jpg_settings = fh->jpg_settings;
-       } else if (zr->codec_mode != mode) {
-               /* wrong codec mode active - invalid */
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - codec in wrong mode\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       if (fh->buffers.active == ZORAN_FREE) {
-               if (zr->jpg_buffers.active == ZORAN_FREE) {
-                       zr->jpg_buffers = fh->buffers;
-                       fh->buffers.active = ZORAN_ACTIVE;
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - another session is already capturing\n",
-                               ZR_DEVNAME(zr), __func__);
-                       res = -EBUSY;
-               }
-       }
-
-       if (!res && zr->codec_mode == BUZ_MODE_IDLE) {
-               /* Ok load up the jpeg codec */
-               zr36057_enable_jpg(zr, mode);
-       }
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       if (!res) {
-               switch (zr->jpg_buffers.buffer[num].state) {
-               case BUZ_STATE_DONE:
-                       dprintk(2,
-                               KERN_WARNING
-                               "%s: %s - queing frame in BUZ_STATE_DONE state!?\n",
-                               ZR_DEVNAME(zr), __func__);
-               case BUZ_STATE_USER:
-                       /* since there is at least one unused buffer there's room for at
-                        *least one more pend[] entry */
-                       zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num;
-                       zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
-                       fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num];
-                       zoran_feed_stat_com(zr);
-                       break;
-               default:
-               case BUZ_STATE_DMA:
-               case BUZ_STATE_PEND:
-                       if (zr->jpg_buffers.active == ZORAN_FREE) {
-                               fh->buffers.active = ZORAN_FREE;
-                               zr->jpg_buffers.allocated = 0;
-                       }
-                       res = -EBUSY;   /* what are you doing? */
-                       break;
-               }
-       }
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       if (!res && zr->jpg_buffers.active == ZORAN_FREE)
-               zr->jpg_buffers.active = fh->buffers.active;
-
-       return res;
-}
-
-static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode)
-{
-       struct zoran *zr = fh->zr;
-       int res = 0;
-
-       /* Does the user want to stop streaming? */
-       if (frame < 0) {
-               if (zr->codec_mode == mode) {
-                       if (fh->buffers.active == ZORAN_FREE) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: %s(-1) - session not active\n",
-                                       ZR_DEVNAME(zr), __func__);
-                               return -EINVAL;
-                       }
-                       fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE;
-                       zr->jpg_buffers.allocated = 0;
-                       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-                       return 0;
-               } else {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - stop streaming but not in streaming mode\n",
-                               ZR_DEVNAME(zr), __func__);
-                       return -EINVAL;
-               }
-       }
-
-       if ((res = zoran_jpg_queue_frame(fh, frame, mode)))
-               return res;
-
-       /* Start the jpeg codec when the first frame is queued  */
-       if (!res && zr->jpg_que_head == 1)
-               jpeg_start(zr);
-
-       return res;
-}
-
-/*
- *   Sync on a MJPEG buffer
- */
-
-static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
-{
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-       int frame;
-
-       if (fh->buffers.active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - capture is not currently active\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-       if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
-           zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - codec not in streaming mode\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-       if (!wait_event_interruptible_timeout(zr->jpg_capq,
-                       (zr->jpg_que_tail != zr->jpg_dma_tail ||
-                        zr->jpg_dma_tail == zr->jpg_dma_head),
-                       10*HZ)) {
-               int isr;
-
-               btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
-               udelay(1);
-               zr->codec->control(zr->codec, CODEC_G_STATUS,
-                                          sizeof(isr), &isr);
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - timeout: codec isr=0x%02x\n",
-                       ZR_DEVNAME(zr), __func__, isr);
-
-               return -ETIME;
-
-       }
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       spin_lock_irqsave(&zr->spinlock, flags);
-
-       if (zr->jpg_dma_tail != zr->jpg_dma_head)
-               frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME];
-       else
-               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
-       /* buffer should now be in BUZ_STATE_DONE */
-       if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
-               dprintk(2,
-                       KERN_ERR "%s: %s - internal state error\n",
-                       ZR_DEVNAME(zr), __func__);
-
-       *bs = zr->jpg_buffers.buffer[frame].bs;
-       bs->frame = frame;
-       zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
-       fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
-
-       spin_unlock_irqrestore(&zr->spinlock, flags);
-
-       return 0;
-}
-
-static void zoran_open_init_session(struct zoran_fh *fh)
-{
-       int i;
-       struct zoran *zr = fh->zr;
-
-       /* Per default, map the V4L Buffers */
-       map_mode_raw(fh);
-
-       /* take over the card's current settings */
-       fh->overlay_settings = zr->overlay_settings;
-       fh->overlay_settings.is_set = 0;
-       fh->overlay_settings.format = zr->overlay_settings.format;
-       fh->overlay_active = ZORAN_FREE;
-
-       /* v4l settings */
-       fh->v4l_settings = zr->v4l_settings;
-       /* jpg settings */
-       fh->jpg_settings = zr->jpg_settings;
-
-       /* buffers */
-       memset(&fh->buffers, 0, sizeof(fh->buffers));
-       for (i = 0; i < MAX_FRAME; i++) {
-               fh->buffers.buffer[i].state = BUZ_STATE_USER;   /* nothing going on */
-               fh->buffers.buffer[i].bs.frame = i;
-       }
-       fh->buffers.allocated = 0;
-       fh->buffers.active = ZORAN_FREE;
-}
-
-static void zoran_close_end_session(struct zoran_fh *fh)
-{
-       struct zoran *zr = fh->zr;
-
-       /* overlay */
-       if (fh->overlay_active != ZORAN_FREE) {
-               fh->overlay_active = zr->overlay_active = ZORAN_FREE;
-               zr->v4l_overlay_active = 0;
-               if (!zr->v4l_memgrab_active)
-                       zr36057_overlay(zr, 0);
-               zr->overlay_mask = NULL;
-       }
-
-       if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
-               /* v4l capture */
-               if (fh->buffers.active != ZORAN_FREE) {
-                       unsigned long flags;
-
-                       spin_lock_irqsave(&zr->spinlock, flags);
-                       zr36057_set_memgrab(zr, 0);
-                       zr->v4l_buffers.allocated = 0;
-                       zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
-                       spin_unlock_irqrestore(&zr->spinlock, flags);
-               }
-
-               /* v4l buffers */
-               if (fh->buffers.allocated)
-                       v4l_fbuffer_free(fh);
-       } else {
-               /* jpg capture */
-               if (fh->buffers.active != ZORAN_FREE) {
-                       zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-                       zr->jpg_buffers.allocated = 0;
-                       zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
-               }
-
-               /* jpg buffers */
-               if (fh->buffers.allocated)
-                       jpg_fbuffer_free(fh);
-       }
-}
-
-/*
- *   Open a zoran card. Right now the flags stuff is just playing
- */
-
-static int zoran_open(struct file *file)
-{
-       struct zoran *zr = video_drvdata(file);
-       struct zoran_fh *fh;
-       int res, first_open = 0;
-
-       dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(-)=%d\n",
-               ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user + 1);
-
-       mutex_lock(&zr->other_lock);
-
-       if (zr->user >= 2048) {
-               dprintk(1, KERN_ERR "%s: too many users (%d) on device\n",
-                       ZR_DEVNAME(zr), zr->user);
-               res = -EBUSY;
-               goto fail_unlock;
-       }
-
-       /* now, create the open()-specific file_ops struct */
-       fh = kzalloc(sizeof(struct zoran_fh), GFP_KERNEL);
-       if (!fh) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - allocation of zoran_fh failed\n",
-                       ZR_DEVNAME(zr), __func__);
-               res = -ENOMEM;
-               goto fail_unlock;
-       }
-       /* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
-        * on norm-change! */
-       fh->overlay_mask =
-           kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
-       if (!fh->overlay_mask) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - allocation of overlay_mask failed\n",
-                       ZR_DEVNAME(zr), __func__);
-               res = -ENOMEM;
-               goto fail_fh;
-       }
-
-       if (zr->user++ == 0)
-               first_open = 1;
-
-       /*mutex_unlock(&zr->resource_lock);*/
-
-       /* default setup - TODO: look at flags */
-       if (first_open) {       /* First device open */
-               zr36057_restart(zr);
-               zoran_open_init_params(zr);
-               zoran_init_hardware(zr);
-
-               btor(ZR36057_ICR_IntPinEn, ZR36057_ICR);
-       }
-
-       /* set file_ops stuff */
-       file->private_data = fh;
-       fh->zr = zr;
-       zoran_open_init_session(fh);
-       mutex_unlock(&zr->other_lock);
-
-       return 0;
-
-fail_fh:
-       kfree(fh);
-fail_unlock:
-       mutex_unlock(&zr->other_lock);
-
-       dprintk(2, KERN_INFO "%s: open failed (%d), users(-)=%d\n",
-               ZR_DEVNAME(zr), res, zr->user);
-
-       return res;
-}
-
-static int
-zoran_close(struct file  *file)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-
-       dprintk(2, KERN_INFO "%s: %s(%s, pid=[%d]), users(+)=%d\n",
-               ZR_DEVNAME(zr), __func__, current->comm, task_pid_nr(current), zr->user - 1);
-
-       /* kernel locks (fs/device.c), so don't do that ourselves
-        * (prevents deadlocks) */
-       mutex_lock(&zr->other_lock);
-
-       zoran_close_end_session(fh);
-
-       if (zr->user-- == 1) {  /* Last process */
-               /* Clean up JPEG process */
-               wake_up_interruptible(&zr->jpg_capq);
-               zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
-               zr->jpg_buffers.allocated = 0;
-               zr->jpg_buffers.active = ZORAN_FREE;
-
-               /* disable interrupts */
-               btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-
-               if (zr36067_debug > 1)
-                       print_interrupts(zr);
-
-               /* Overlay off */
-               zr->v4l_overlay_active = 0;
-               zr36057_overlay(zr, 0);
-               zr->overlay_mask = NULL;
-
-               /* capture off */
-               wake_up_interruptible(&zr->v4l_capq);
-               zr36057_set_memgrab(zr, 0);
-               zr->v4l_buffers.allocated = 0;
-               zr->v4l_buffers.active = ZORAN_FREE;
-               zoran_set_pci_master(zr, 0);
-
-               if (!pass_through) {    /* Switch to color bar */
-                       decoder_call(zr, video, s_stream, 0);
-                       encoder_call(zr, video, s_routing, 2, 0, 0);
-               }
-       }
-       mutex_unlock(&zr->other_lock);
-
-       file->private_data = NULL;
-       kfree(fh->overlay_mask);
-       kfree(fh);
-
-       dprintk(4, KERN_INFO "%s: %s done\n", ZR_DEVNAME(zr), __func__);
-
-       return 0;
-}
-
-
-static ssize_t
-zoran_read (struct file *file,
-           char        __user *data,
-           size_t       count,
-           loff_t      *ppos)
-{
-       /* we simply don't support read() (yet)... */
-
-       return -EINVAL;
-}
-
-static ssize_t
-zoran_write (struct file *file,
-            const char  __user *data,
-            size_t       count,
-            loff_t      *ppos)
-{
-       /* ...and the same goes for write() */
-
-       return -EINVAL;
-}
-
-static int setup_fbuffer(struct zoran_fh *fh,
-              void                      *base,
-              const struct zoran_format *fmt,
-              int                        width,
-              int                        height,
-              int                        bytesperline)
-{
-       struct zoran *zr = fh->zr;
-
-       /* (Ronald) v4l/v4l2 guidelines */
-       if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       /* Don't allow frame buffer overlay if PCI or AGP is buggy, or on
-          ALi Magik (that needs very low latency while the card needs a
-          higher value always) */
-
-       if (pci_pci_problems & (PCIPCI_FAIL | PCIAGP_FAIL | PCIPCI_ALIMAGIK))
-               return -ENXIO;
-
-       /* we need a bytesperline value, even if not given */
-       if (!bytesperline)
-               bytesperline = width * ((fmt->depth + 7) & ~7) / 8;
-
-#if 0
-       if (zr->overlay_active) {
-               /* dzjee... stupid users... don't even bother to turn off
-                * overlay before changing the memory location...
-                * normally, we would return errors here. However, one of
-                * the tools that does this is... xawtv! and since xawtv
-                * is used by +/- 99% of the users, we'd rather be user-
-                * friendly and silently do as if nothing went wrong */
-               dprintk(3,
-                       KERN_ERR
-                       "%s: %s - forced overlay turnoff because framebuffer changed\n",
-                       ZR_DEVNAME(zr), __func__);
-               zr36057_overlay(zr, 0);
-       }
-#endif
-
-       if (!(fmt->flags & ZORAN_FORMAT_OVERLAY)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - no valid overlay format given\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-       if (height <= 0 || width <= 0 || bytesperline <= 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - invalid height/width/bpl value (%d|%d|%d)\n",
-                       ZR_DEVNAME(zr), __func__, width, height, bytesperline);
-               return -EINVAL;
-       }
-       if (bytesperline & 3) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - bytesperline (%d) must be 4-byte aligned\n",
-                       ZR_DEVNAME(zr), __func__, bytesperline);
-               return -EINVAL;
-       }
-
-       zr->vbuf_base = (void *) ((unsigned long) base & ~3);
-       zr->vbuf_height = height;
-       zr->vbuf_width = width;
-       zr->vbuf_depth = fmt->depth;
-       zr->overlay_settings.format = fmt;
-       zr->vbuf_bytesperline = bytesperline;
-
-       /* The user should set new window parameters */
-       zr->overlay_settings.is_set = 0;
-
-       return 0;
-}
-
-
-static int setup_window(struct zoran_fh *fh,
-                       int x,
-                       int y,
-                       int width,
-                       int height,
-                       struct v4l2_clip __user *clips,
-                       unsigned int clipcount,
-                       void __user *bitmap)
-{
-       struct zoran *zr = fh->zr;
-       struct v4l2_clip *vcp = NULL;
-       int on, end;
-
-
-       if (!zr->vbuf_base) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - frame buffer has to be set first\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       if (!fh->overlay_settings.format) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - no overlay format set\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       if (clipcount > 2048) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - invalid clipcount\n",
-                        ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       /*
-        * The video front end needs 4-byte alinged line sizes, we correct that
-        * silently here if necessary
-        */
-       if (zr->vbuf_depth == 15 || zr->vbuf_depth == 16) {
-               end = (x + width) & ~1; /* round down */
-               x = (x + 1) & ~1;       /* round up */
-               width = end - x;
-       }
-
-       if (zr->vbuf_depth == 24) {
-               end = (x + width) & ~3; /* round down */
-               x = (x + 3) & ~3;       /* round up */
-               width = end - x;
-       }
-
-       if (width > BUZ_MAX_WIDTH)
-               width = BUZ_MAX_WIDTH;
-       if (height > BUZ_MAX_HEIGHT)
-               height = BUZ_MAX_HEIGHT;
-
-       /* Check for invalid parameters */
-       if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||
-           width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - width = %d or height = %d invalid\n",
-                       ZR_DEVNAME(zr), __func__, width, height);
-               return -EINVAL;
-       }
-
-       fh->overlay_settings.x = x;
-       fh->overlay_settings.y = y;
-       fh->overlay_settings.width = width;
-       fh->overlay_settings.height = height;
-       fh->overlay_settings.clipcount = clipcount;
-
-       /*
-        * If an overlay is running, we have to switch it off
-        * and switch it on again in order to get the new settings in effect.
-        *
-        * We also want to avoid that the overlay mask is written
-        * when an overlay is running.
-        */
-
-       on = zr->v4l_overlay_active && !zr->v4l_memgrab_active &&
-           zr->overlay_active != ZORAN_FREE &&
-           fh->overlay_active != ZORAN_FREE;
-       if (on)
-               zr36057_overlay(zr, 0);
-
-       /*
-        *   Write the overlay mask if clips are wanted.
-        *   We prefer a bitmap.
-        */
-       if (bitmap) {
-               /* fake value - it just means we want clips */
-               fh->overlay_settings.clipcount = 1;
-
-               if (copy_from_user(fh->overlay_mask, bitmap,
-                                  (width * height + 7) / 8)) {
-                       return -EFAULT;
-               }
-       } else if (clipcount) {
-               /* write our own bitmap from the clips */
-               vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4));
-               if (vcp == NULL) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - Alloc of clip mask failed\n",
-                               ZR_DEVNAME(zr), __func__);
-                       return -ENOMEM;
-               }
-               if (copy_from_user
-                   (vcp, clips, sizeof(struct v4l2_clip) * clipcount)) {
-                       vfree(vcp);
-                       return -EFAULT;
-               }
-               write_overlay_mask(fh, vcp, clipcount);
-               vfree(vcp);
-       }
-
-       fh->overlay_settings.is_set = 1;
-       if (fh->overlay_active != ZORAN_FREE &&
-           zr->overlay_active != ZORAN_FREE)
-               zr->overlay_settings = fh->overlay_settings;
-
-       if (on)
-               zr36057_overlay(zr, 1);
-
-       /* Make sure the changes come into effect */
-       return wait_grab_pending(zr);
-}
-
-static int setup_overlay(struct zoran_fh *fh, int on)
-{
-       struct zoran *zr = fh->zr;
-
-       /* If there is nothing to do, return immediately */
-       if ((on && fh->overlay_active != ZORAN_FREE) ||
-           (!on && fh->overlay_active == ZORAN_FREE))
-               return 0;
-
-       /* check whether we're touching someone else's overlay */
-       if (on && zr->overlay_active != ZORAN_FREE &&
-           fh->overlay_active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - overlay is already active for another session\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EBUSY;
-       }
-       if (!on && zr->overlay_active != ZORAN_FREE &&
-           fh->overlay_active == ZORAN_FREE) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - you cannot cancel someone else's session\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EPERM;
-       }
-
-       if (on == 0) {
-               zr->overlay_active = fh->overlay_active = ZORAN_FREE;
-               zr->v4l_overlay_active = 0;
-               /* When a grab is running, the video simply
-                * won't be switched on any more */
-               if (!zr->v4l_memgrab_active)
-                       zr36057_overlay(zr, 0);
-               zr->overlay_mask = NULL;
-       } else {
-               if (!zr->vbuf_base || !fh->overlay_settings.is_set) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - buffer or window not set\n",
-                               ZR_DEVNAME(zr), __func__);
-                       return -EINVAL;
-               }
-               if (!fh->overlay_settings.format) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - no overlay format set\n",
-                               ZR_DEVNAME(zr), __func__);
-                       return -EINVAL;
-               }
-               zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
-               zr->v4l_overlay_active = 1;
-               zr->overlay_mask = fh->overlay_mask;
-               zr->overlay_settings = fh->overlay_settings;
-               if (!zr->v4l_memgrab_active)
-                       zr36057_overlay(zr, 1);
-               /* When a grab is running, the video will be
-                * switched on when grab is finished */
-       }
-
-       /* Make sure the changes come into effect */
-       return wait_grab_pending(zr);
-}
-
-/* get the status of a buffer in the clients buffer queue */
-static int zoran_v4l2_buffer_status(struct zoran_fh *fh,
-                                   struct v4l2_buffer *buf, int num)
-{
-       struct zoran *zr = fh->zr;
-       unsigned long flags;
-
-       buf->flags = V4L2_BUF_FLAG_MAPPED;
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:
-               /* check range */
-               if (num < 0 || num >= fh->buffers.num_buffers ||
-                   !fh->buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - wrong number or buffers not allocated\n",
-                               ZR_DEVNAME(zr), __func__);
-                       return -EINVAL;
-               }
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: %s() - raw active=%c, buffer %d: state=%c, map=%c\n",
-                       ZR_DEVNAME(zr), __func__,
-                       "FAL"[fh->buffers.active], num,
-                       "UPMD"[zr->v4l_buffers.buffer[num].state],
-                       fh->buffers.buffer[num].map ? 'Y' : 'N');
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-
-               buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               buf->length = fh->buffers.buffer_size;
-
-               /* get buffer */
-               buf->bytesused = fh->buffers.buffer[num].bs.length;
-               if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
-                   fh->buffers.buffer[num].state == BUZ_STATE_USER) {
-                       buf->sequence = fh->buffers.buffer[num].bs.seq;
-                       buf->flags |= V4L2_BUF_FLAG_DONE;
-                       buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
-               } else {
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               }
-
-               if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2)
-                       buf->field = V4L2_FIELD_TOP;
-               else
-                       buf->field = V4L2_FIELD_INTERLACED;
-
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-
-               /* check range */
-               if (num < 0 || num >= fh->buffers.num_buffers ||
-                   !fh->buffers.allocated) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - wrong number or buffers not allocated\n",
-                               ZR_DEVNAME(zr), __func__);
-                       return -EINVAL;
-               }
-
-               buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
-                             V4L2_BUF_TYPE_VIDEO_CAPTURE :
-                             V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               buf->length = fh->buffers.buffer_size;
-
-               /* these variables are only written after frame has been captured */
-               if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
-                   fh->buffers.buffer[num].state == BUZ_STATE_USER) {
-                       buf->sequence = fh->buffers.buffer[num].bs.seq;
-                       buf->timestamp = fh->buffers.buffer[num].bs.timestamp;
-                       buf->bytesused = fh->buffers.buffer[num].bs.length;
-                       buf->flags |= V4L2_BUF_FLAG_DONE;
-               } else {
-                       buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               }
-
-               /* which fields are these? */
-               if (fh->jpg_settings.TmpDcm != 1)
-                       buf->field = fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
-               else
-                       buf->field = fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
-
-               break;
-
-       default:
-
-               dprintk(5,
-                       KERN_ERR
-                       "%s: %s - invalid buffer type|map_mode (%d|%d)\n",
-                       ZR_DEVNAME(zr), __func__, buf->type, fh->map_mode);
-               return -EINVAL;
-       }
-
-       buf->memory = V4L2_MEMORY_MMAP;
-       buf->index = num;
-       buf->m.offset = buf->length * num;
-
-       return 0;
-}
-
-static int
-zoran_set_norm (struct zoran *zr,
-               v4l2_std_id norm)
-{
-       int on;
-
-       if (zr->v4l_buffers.active != ZORAN_FREE ||
-           zr->jpg_buffers.active != ZORAN_FREE) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: %s called while in playback/capture mode\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EBUSY;
-       }
-
-       if (!(norm & zr->card.norms)) {
-               dprintk(1,
-                       KERN_ERR "%s: %s - unsupported norm %llx\n",
-                       ZR_DEVNAME(zr), __func__, norm);
-               return -EINVAL;
-       }
-
-       if (norm == V4L2_STD_ALL) {
-               unsigned int status = 0;
-               v4l2_std_id std = 0;
-
-               decoder_call(zr, video, querystd, &std);
-               decoder_call(zr, core, s_std, std);
-
-               /* let changes come into effect */
-               ssleep(2);
-
-               decoder_call(zr, video, g_input_status, &status);
-               if (status & V4L2_IN_ST_NO_SIGNAL) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s - no norm detected\n",
-                               ZR_DEVNAME(zr), __func__);
-                       /* reset norm */
-                       decoder_call(zr, core, s_std, zr->norm);
-                       return -EIO;
-               }
-
-               norm = std;
-       }
-       if (norm & V4L2_STD_SECAM)
-               zr->timing = zr->card.tvn[2];
-       else if (norm & V4L2_STD_NTSC)
-               zr->timing = zr->card.tvn[1];
-       else
-               zr->timing = zr->card.tvn[0];
-
-       /* We switch overlay off and on since a change in the
-        * norm needs different VFE settings */
-       on = zr->overlay_active && !zr->v4l_memgrab_active;
-       if (on)
-               zr36057_overlay(zr, 0);
-
-       decoder_call(zr, core, s_std, norm);
-       encoder_call(zr, video, s_std_output, norm);
-
-       if (on)
-               zr36057_overlay(zr, 1);
-
-       /* Make sure the changes come into effect */
-       zr->norm = norm;
-
-       return 0;
-}
-
-static int
-zoran_set_input (struct zoran *zr,
-                int           input)
-{
-       if (input == zr->input) {
-               return 0;
-       }
-
-       if (zr->v4l_buffers.active != ZORAN_FREE ||
-           zr->jpg_buffers.active != ZORAN_FREE) {
-               dprintk(1,
-                       KERN_WARNING
-                       "%s: %s called while in playback/capture mode\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EBUSY;
-       }
-
-       if (input < 0 || input >= zr->card.inputs) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - unnsupported input %d\n",
-                       ZR_DEVNAME(zr), __func__, input);
-               return -EINVAL;
-       }
-
-       zr->input = input;
-
-       decoder_call(zr, video, s_routing,
-                       zr->card.input[input].muxsel, 0, 0);
-
-       return 0;
-}
-
-/*
- *   ioctl routine
- */
-
-static int zoran_querycap(struct file *file, void *__fh, struct v4l2_capability *cap)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       memset(cap, 0, sizeof(*cap));
-       strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
-       strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-                pci_name(zr->pci_dev));
-       cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
-                           V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
-       return 0;
-}
-
-static int zoran_enum_fmt(struct zoran *zr, struct v4l2_fmtdesc *fmt, int flag)
-{
-       unsigned int num, i;
-
-       for (num = i = 0; i < NUM_FORMATS; i++) {
-               if (zoran_formats[i].flags & flag && num++ == fmt->index) {
-                       strncpy(fmt->description, zoran_formats[i].name,
-                               sizeof(fmt->description) - 1);
-                       /* fmt struct pre-zeroed, so adding '\0' not needed */
-                       fmt->pixelformat = zoran_formats[i].fourcc;
-                       if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
-                               fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-                       return 0;
-               }
-       }
-       return -EINVAL;
-}
-
-static int zoran_enum_fmt_vid_cap(struct file *file, void *__fh,
-                                           struct v4l2_fmtdesc *f)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       return zoran_enum_fmt(zr, f, ZORAN_FORMAT_CAPTURE);
-}
-
-static int zoran_enum_fmt_vid_out(struct file *file, void *__fh,
-                                           struct v4l2_fmtdesc *f)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       return zoran_enum_fmt(zr, f, ZORAN_FORMAT_PLAYBACK);
-}
-
-static int zoran_enum_fmt_vid_overlay(struct file *file, void *__fh,
-                                           struct v4l2_fmtdesc *f)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       return zoran_enum_fmt(zr, f, ZORAN_FORMAT_OVERLAY);
-}
-
-static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       mutex_lock(&zr->resource_lock);
-
-       fmt->fmt.pix.width = fh->jpg_settings.img_width / fh->jpg_settings.HorDcm;
-       fmt->fmt.pix.height = fh->jpg_settings.img_height * 2 /
-               (fh->jpg_settings.VerDcm * fh->jpg_settings.TmpDcm);
-       fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-       fmt->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
-       if (fh->jpg_settings.TmpDcm == 1)
-               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
-       else
-               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
-       fmt->fmt.pix.bytesperline = 0;
-       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       mutex_unlock(&zr->resource_lock);
-       return 0;
-}
-
-static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       if (fh->map_mode != ZORAN_MAP_MODE_RAW)
-               return zoran_g_fmt_vid_out(file, fh, fmt);
-
-       mutex_lock(&zr->resource_lock);
-       fmt->fmt.pix.width = fh->v4l_settings.width;
-       fmt->fmt.pix.height = fh->v4l_settings.height;
-       fmt->fmt.pix.sizeimage = fh->v4l_settings.bytesperline *
-                                       fh->v4l_settings.height;
-       fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc;
-       fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
-       fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
-       if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2))
-               fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       else
-               fmt->fmt.pix.field = V4L2_FIELD_TOP;
-       mutex_unlock(&zr->resource_lock);
-       return 0;
-}
-
-static int zoran_g_fmt_vid_overlay(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       mutex_lock(&zr->resource_lock);
-
-       fmt->fmt.win.w.left = fh->overlay_settings.x;
-       fmt->fmt.win.w.top = fh->overlay_settings.y;
-       fmt->fmt.win.w.width = fh->overlay_settings.width;
-       fmt->fmt.win.w.height = fh->overlay_settings.height;
-       if (fh->overlay_settings.width * 2 > BUZ_MAX_HEIGHT)
-               fmt->fmt.win.field = V4L2_FIELD_INTERLACED;
-       else
-               fmt->fmt.win.field = V4L2_FIELD_TOP;
-
-       mutex_unlock(&zr->resource_lock);
-       return 0;
-}
-
-static int zoran_try_fmt_vid_overlay(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       mutex_lock(&zr->resource_lock);
-
-       if (fmt->fmt.win.w.width > BUZ_MAX_WIDTH)
-               fmt->fmt.win.w.width = BUZ_MAX_WIDTH;
-       if (fmt->fmt.win.w.width < BUZ_MIN_WIDTH)
-               fmt->fmt.win.w.width = BUZ_MIN_WIDTH;
-       if (fmt->fmt.win.w.height > BUZ_MAX_HEIGHT)
-               fmt->fmt.win.w.height = BUZ_MAX_HEIGHT;
-       if (fmt->fmt.win.w.height < BUZ_MIN_HEIGHT)
-               fmt->fmt.win.w.height = BUZ_MIN_HEIGHT;
-
-       mutex_unlock(&zr->resource_lock);
-       return 0;
-}
-
-static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       struct zoran_jpg_settings settings;
-       int res = 0;
-
-       if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
-               return -EINVAL;
-
-       mutex_lock(&zr->resource_lock);
-       settings = fh->jpg_settings;
-
-       /* we actually need to set 'real' parameters now */
-       if ((fmt->fmt.pix.height * 2) > BUZ_MAX_HEIGHT)
-               settings.TmpDcm = 1;
-       else
-               settings.TmpDcm = 2;
-       settings.decimation = 0;
-       if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2)
-               settings.VerDcm = 2;
-       else
-               settings.VerDcm = 1;
-       if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4)
-               settings.HorDcm = 4;
-       else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2)
-               settings.HorDcm = 2;
-       else
-               settings.HorDcm = 1;
-       if (settings.TmpDcm == 1)
-               settings.field_per_buff = 2;
-       else
-               settings.field_per_buff = 1;
-
-       if (settings.HorDcm > 1) {
-               settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
-               settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
-       } else {
-               settings.img_x = 0;
-               settings.img_width = BUZ_MAX_WIDTH;
-       }
-
-       /* check */
-       res = zoran_check_jpg_settings(zr, &settings, 1);
-       if (res)
-               goto tryfmt_unlock_and_return;
-
-       /* tell the user what we actually did */
-       fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
-       fmt->fmt.pix.height = settings.img_height * 2 /
-               (settings.TmpDcm * settings.VerDcm);
-       if (settings.TmpDcm == 1)
-               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
-       else
-               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
-
-       fmt->fmt.pix.sizeimage = zoran_v4l2_calc_bufsize(&settings);
-       fmt->fmt.pix.bytesperline = 0;
-       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-tryfmt_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int bpp;
-       int i;
-
-       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
-               return zoran_try_fmt_vid_out(file, fh, fmt);
-
-       mutex_lock(&zr->resource_lock);
-
-       for (i = 0; i < NUM_FORMATS; i++)
-               if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
-                       break;
-
-       if (i == NUM_FORMATS) {
-               mutex_unlock(&zr->resource_lock);
-               return -EINVAL;
-       }
-
-       bpp = DIV_ROUND_UP(zoran_formats[i].depth, 8);
-       v4l_bound_align_image(
-               &fmt->fmt.pix.width, BUZ_MIN_WIDTH, BUZ_MAX_WIDTH, bpp == 2 ? 1 : 2,
-               &fmt->fmt.pix.height, BUZ_MIN_HEIGHT, BUZ_MAX_HEIGHT, 0, 0);
-       mutex_unlock(&zr->resource_lock);
-
-       return 0;
-}
-
-static int zoran_s_fmt_vid_overlay(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res;
-
-       dprintk(3, "x=%d, y=%d, w=%d, h=%d, cnt=%d, map=0x%p\n",
-                       fmt->fmt.win.w.left, fmt->fmt.win.w.top,
-                       fmt->fmt.win.w.width,
-                       fmt->fmt.win.w.height,
-                       fmt->fmt.win.clipcount,
-                       fmt->fmt.win.bitmap);
-       mutex_lock(&zr->resource_lock);
-       res = setup_window(fh, fmt->fmt.win.w.left, fmt->fmt.win.w.top,
-                          fmt->fmt.win.w.width, fmt->fmt.win.w.height,
-                          (struct v4l2_clip __user *)fmt->fmt.win.clips,
-                          fmt->fmt.win.clipcount, fmt->fmt.win.bitmap);
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       __le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
-       struct zoran_jpg_settings settings;
-       int res = 0;
-
-       dprintk(3, "size=%dx%d, fmt=0x%x (%4.4s)\n",
-                       fmt->fmt.pix.width, fmt->fmt.pix.height,
-                       fmt->fmt.pix.pixelformat,
-                       (char *) &printformat);
-       if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
-               return -EINVAL;
-
-       mutex_lock(&zr->resource_lock);
-
-       if (fh->buffers.allocated) {
-               dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
-                       ZR_DEVNAME(zr));
-               res = -EBUSY;
-               goto sfmtjpg_unlock_and_return;
-       }
-
-       settings = fh->jpg_settings;
-
-       /* we actually need to set 'real' parameters now */
-       if (fmt->fmt.pix.height * 2 > BUZ_MAX_HEIGHT)
-               settings.TmpDcm = 1;
-       else
-               settings.TmpDcm = 2;
-       settings.decimation = 0;
-       if (fmt->fmt.pix.height <= fh->jpg_settings.img_height / 2)
-               settings.VerDcm = 2;
-       else
-               settings.VerDcm = 1;
-       if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 4)
-               settings.HorDcm = 4;
-       else if (fmt->fmt.pix.width <= fh->jpg_settings.img_width / 2)
-               settings.HorDcm = 2;
-       else
-               settings.HorDcm = 1;
-       if (settings.TmpDcm == 1)
-               settings.field_per_buff = 2;
-       else
-               settings.field_per_buff = 1;
-
-       if (settings.HorDcm > 1) {
-               settings.img_x = (BUZ_MAX_WIDTH == 720) ? 8 : 0;
-               settings.img_width = (BUZ_MAX_WIDTH == 720) ? 704 : BUZ_MAX_WIDTH;
-       } else {
-               settings.img_x = 0;
-               settings.img_width = BUZ_MAX_WIDTH;
-       }
-
-       /* check */
-       res = zoran_check_jpg_settings(zr, &settings, 0);
-       if (res)
-               goto sfmtjpg_unlock_and_return;
-
-       /* it's ok, so set them */
-       fh->jpg_settings = settings;
-
-       map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
-       fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-
-       /* tell the user what we actually did */
-       fmt->fmt.pix.width = settings.img_width / settings.HorDcm;
-       fmt->fmt.pix.height = settings.img_height * 2 /
-               (settings.TmpDcm * settings.VerDcm);
-       if (settings.TmpDcm == 1)
-               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT);
-       else
-               fmt->fmt.pix.field = (fh->jpg_settings.odd_even ?
-                               V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM);
-       fmt->fmt.pix.bytesperline = 0;
-       fmt->fmt.pix.sizeimage = fh->buffers.buffer_size;
-       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-sfmtjpg_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
-                                       struct v4l2_format *fmt)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int i;
-       int res = 0;
-
-       if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
-               return zoran_s_fmt_vid_out(file, fh, fmt);
-
-       for (i = 0; i < NUM_FORMATS; i++)
-               if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc)
-                       break;
-       if (i == NUM_FORMATS) {
-               dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x\n",
-                       ZR_DEVNAME(zr), fmt->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       mutex_lock(&zr->resource_lock);
-
-       if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) ||
-           fh->buffers.active != ZORAN_FREE) {
-               dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - cannot change capture mode\n",
-                               ZR_DEVNAME(zr));
-               res = -EBUSY;
-               goto sfmtv4l_unlock_and_return;
-       }
-       if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
-               fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
-       if (fmt->fmt.pix.width > BUZ_MAX_WIDTH)
-               fmt->fmt.pix.width = BUZ_MAX_WIDTH;
-
-       map_mode_raw(fh);
-
-       res = zoran_v4l_set_format(fh, fmt->fmt.pix.width, fmt->fmt.pix.height,
-                                  &zoran_formats[i]);
-       if (res)
-               goto sfmtv4l_unlock_and_return;
-
-       /* tell the user the results/missing stuff */
-       fmt->fmt.pix.bytesperline = fh->v4l_settings.bytesperline;
-       fmt->fmt.pix.sizeimage = fh->v4l_settings.height * fh->v4l_settings.bytesperline;
-       fmt->fmt.pix.colorspace = fh->v4l_settings.format->colorspace;
-       if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2))
-               fmt->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       else
-               fmt->fmt.pix.field = V4L2_FIELD_TOP;
-
-sfmtv4l_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_g_fbuf(struct file *file, void *__fh,
-               struct v4l2_framebuffer *fb)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       memset(fb, 0, sizeof(*fb));
-       mutex_lock(&zr->resource_lock);
-       fb->base = zr->vbuf_base;
-       fb->fmt.width = zr->vbuf_width;
-       fb->fmt.height = zr->vbuf_height;
-       if (zr->overlay_settings.format)
-               fb->fmt.pixelformat = fh->overlay_settings.format->fourcc;
-       fb->fmt.bytesperline = zr->vbuf_bytesperline;
-       mutex_unlock(&zr->resource_lock);
-       fb->fmt.colorspace = V4L2_COLORSPACE_SRGB;
-       fb->fmt.field = V4L2_FIELD_INTERLACED;
-       fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-
-       return 0;
-}
-
-static int zoran_s_fbuf(struct file *file, void *__fh,
-               struct v4l2_framebuffer *fb)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int i, res = 0;
-       __le32 printformat = __cpu_to_le32(fb->fmt.pixelformat);
-
-       for (i = 0; i < NUM_FORMATS; i++)
-               if (zoran_formats[i].fourcc == fb->fmt.pixelformat)
-                       break;
-       if (i == NUM_FORMATS) {
-               dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n",
-                       ZR_DEVNAME(zr), fb->fmt.pixelformat,
-                       (char *)&printformat);
-               return -EINVAL;
-       }
-
-       mutex_lock(&zr->resource_lock);
-       res = setup_fbuffer(fh, fb->base, &zoran_formats[i], fb->fmt.width,
-                           fb->fmt.height, fb->fmt.bytesperline);
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_overlay(struct file *file, void *__fh, unsigned int on)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res;
-
-       mutex_lock(&zr->resource_lock);
-       res = setup_overlay(fh, on);
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type);
-
-static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0;
-
-       if (req->memory != V4L2_MEMORY_MMAP) {
-               dprintk(2,
-                               KERN_ERR
-                               "%s: only MEMORY_MMAP capture is supported, not %d\n",
-                               ZR_DEVNAME(zr), req->memory);
-               return -EINVAL;
-       }
-
-       if (req->count == 0)
-               return zoran_streamoff(file, fh, req->type);
-
-       mutex_lock(&zr->resource_lock);
-       if (fh->buffers.allocated) {
-               dprintk(2,
-                               KERN_ERR
-                               "%s: VIDIOC_REQBUFS - buffers already allocated\n",
-                               ZR_DEVNAME(zr));
-               res = -EBUSY;
-               goto v4l2reqbuf_unlock_and_return;
-       }
-
-       if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
-           req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               /* control user input */
-               if (req->count < 2)
-                       req->count = 2;
-               if (req->count > v4l_nbufs)
-                       req->count = v4l_nbufs;
-
-               /* The next mmap will map the V4L buffers */
-               map_mode_raw(fh);
-               fh->buffers.num_buffers = req->count;
-
-               if (v4l_fbuffer_alloc(fh)) {
-                       res = -ENOMEM;
-                       goto v4l2reqbuf_unlock_and_return;
-               }
-       } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
-                  fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-               /* we need to calculate size ourselves now */
-               if (req->count < 4)
-                       req->count = 4;
-               if (req->count > jpg_nbufs)
-                       req->count = jpg_nbufs;
-
-               /* The next mmap will map the MJPEG buffers */
-               map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
-               fh->buffers.num_buffers = req->count;
-               fh->buffers.buffer_size = zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-
-               if (jpg_fbuffer_alloc(fh)) {
-                       res = -ENOMEM;
-                       goto v4l2reqbuf_unlock_and_return;
-               }
-       } else {
-               dprintk(1,
-                               KERN_ERR
-                               "%s: VIDIOC_REQBUFS - unknown type %d\n",
-                               ZR_DEVNAME(zr), req->type);
-               res = -EINVAL;
-               goto v4l2reqbuf_unlock_and_return;
-       }
-v4l2reqbuf_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res;
-
-       mutex_lock(&zr->resource_lock);
-       res = zoran_v4l2_buffer_status(fh, buf, buf->index);
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0, codec_mode, buf_type;
-
-       mutex_lock(&zr->resource_lock);
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:
-               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       dprintk(1, KERN_ERR
-                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                       res = -EINVAL;
-                       goto qbuf_unlock_and_return;
-               }
-
-               res = zoran_v4l_queue_frame(fh, buf->index);
-               if (res)
-                       goto qbuf_unlock_and_return;
-               if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED)
-                       zr36057_set_memgrab(zr, 1);
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-               if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
-                       buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-                       codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
-               } else {
-                       buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                       codec_mode = BUZ_MODE_MOTION_COMPRESS;
-               }
-
-               if (buf->type != buf_type) {
-                       dprintk(1, KERN_ERR
-                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                       res = -EINVAL;
-                       goto qbuf_unlock_and_return;
-               }
-
-               res = zoran_jpg_queue_frame(fh, buf->index, codec_mode);
-               if (res != 0)
-                       goto qbuf_unlock_and_return;
-               if (zr->codec_mode == BUZ_MODE_IDLE &&
-                   fh->buffers.active == ZORAN_LOCKED)
-                       zr36057_enable_jpg(zr, codec_mode);
-
-               break;
-
-       default:
-               dprintk(1, KERN_ERR
-                       "%s: VIDIOC_QBUF - unsupported type %d\n",
-                       ZR_DEVNAME(zr), buf->type);
-               res = -EINVAL;
-               break;
-       }
-qbuf_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0, buf_type, num = -1;        /* compiler borks here (?) */
-
-       mutex_lock(&zr->resource_lock);
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:
-               if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       dprintk(1, KERN_ERR
-                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                       res = -EINVAL;
-                       goto dqbuf_unlock_and_return;
-               }
-
-               num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
-               if (file->f_flags & O_NONBLOCK &&
-                   zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) {
-                       res = -EAGAIN;
-                       goto dqbuf_unlock_and_return;
-               }
-               res = v4l_sync(fh, num);
-               if (res)
-                       goto dqbuf_unlock_and_return;
-               zr->v4l_sync_tail++;
-               res = zoran_v4l2_buffer_status(fh, buf, num);
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-       {
-               struct zoran_sync bs;
-
-               if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
-                       buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               else
-                       buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-               if (buf->type != buf_type) {
-                       dprintk(1, KERN_ERR
-                               "%s: VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
-                               ZR_DEVNAME(zr), buf->type, fh->map_mode);
-                       res = -EINVAL;
-                       goto dqbuf_unlock_and_return;
-               }
-
-               num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
-               if (file->f_flags & O_NONBLOCK &&
-                   zr->jpg_buffers.buffer[num].state != BUZ_STATE_DONE) {
-                       res = -EAGAIN;
-                       goto dqbuf_unlock_and_return;
-               }
-               bs.frame = 0; /* suppress compiler warning */
-               res = jpg_sync(fh, &bs);
-               if (res)
-                       goto dqbuf_unlock_and_return;
-               res = zoran_v4l2_buffer_status(fh, buf, bs.frame);
-               break;
-       }
-
-       default:
-               dprintk(1, KERN_ERR
-                       "%s: VIDIOC_DQBUF - unsupported type %d\n",
-                       ZR_DEVNAME(zr), buf->type);
-               res = -EINVAL;
-               break;
-       }
-dqbuf_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0;
-
-       mutex_lock(&zr->resource_lock);
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:        /* raw capture */
-               if (zr->v4l_buffers.active != ZORAN_ACTIVE ||
-                   fh->buffers.active != ZORAN_ACTIVE) {
-                       res = -EBUSY;
-                       goto strmon_unlock_and_return;
-               }
-
-               zr->v4l_buffers.active = fh->buffers.active = ZORAN_LOCKED;
-               zr->v4l_settings = fh->v4l_settings;
-
-               zr->v4l_sync_tail = zr->v4l_pend_tail;
-               if (!zr->v4l_memgrab_active &&
-                   zr->v4l_pend_head != zr->v4l_pend_tail) {
-                       zr36057_set_memgrab(zr, 1);
-               }
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-               /* what is the codec mode right now? */
-               if (zr->jpg_buffers.active != ZORAN_ACTIVE ||
-                   fh->buffers.active != ZORAN_ACTIVE) {
-                       res = -EBUSY;
-                       goto strmon_unlock_and_return;
-               }
-
-               zr->jpg_buffers.active = fh->buffers.active = ZORAN_LOCKED;
-
-               if (zr->jpg_que_head != zr->jpg_que_tail) {
-                       /* Start the jpeg codec when the first frame is queued  */
-                       jpeg_start(zr);
-               }
-               break;
-
-       default:
-               dprintk(1,
-                       KERN_ERR
-                       "%s: VIDIOC_STREAMON - invalid map mode %d\n",
-                       ZR_DEVNAME(zr), fh->map_mode);
-               res = -EINVAL;
-               break;
-       }
-strmon_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int i, res = 0;
-       unsigned long flags;
-
-       mutex_lock(&zr->resource_lock);
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:        /* raw capture */
-               if (fh->buffers.active == ZORAN_FREE &&
-                   zr->v4l_buffers.active != ZORAN_FREE) {
-                       res = -EPERM;   /* stay off other's settings! */
-                       goto strmoff_unlock_and_return;
-               }
-               if (zr->v4l_buffers.active == ZORAN_FREE)
-                       goto strmoff_unlock_and_return;
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               /* unload capture */
-               if (zr->v4l_memgrab_active) {
-
-                       zr36057_set_memgrab(zr, 0);
-               }
-
-               for (i = 0; i < fh->buffers.num_buffers; i++)
-                       zr->v4l_buffers.buffer[i].state = BUZ_STATE_USER;
-               fh->buffers = zr->v4l_buffers;
-
-               zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
-
-               zr->v4l_grab_seq = 0;
-               zr->v4l_pend_head = zr->v4l_pend_tail = 0;
-               zr->v4l_sync_tail = 0;
-
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-               if (fh->buffers.active == ZORAN_FREE &&
-                   zr->jpg_buffers.active != ZORAN_FREE) {
-                       res = -EPERM;   /* stay off other's settings! */
-                       goto strmoff_unlock_and_return;
-               }
-               if (zr->jpg_buffers.active == ZORAN_FREE)
-                       goto strmoff_unlock_and_return;
-
-               res = jpg_qbuf(fh, -1,
-                            (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
-                            BUZ_MODE_MOTION_COMPRESS :
-                            BUZ_MODE_MOTION_DECOMPRESS);
-               if (res)
-                       goto strmoff_unlock_and_return;
-               break;
-       default:
-               dprintk(1, KERN_ERR
-                       "%s: VIDIOC_STREAMOFF - invalid map mode %d\n",
-                       ZR_DEVNAME(zr), fh->map_mode);
-               res = -EINVAL;
-               break;
-       }
-strmoff_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_queryctrl(struct file *file, void *__fh,
-                                       struct v4l2_queryctrl *ctrl)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       /* we only support hue/saturation/contrast/brightness */
-       if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-           ctrl->id > V4L2_CID_HUE)
-               return -EINVAL;
-
-       decoder_call(zr, core, queryctrl, ctrl);
-
-       return 0;
-}
-
-static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       /* we only support hue/saturation/contrast/brightness */
-       if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-           ctrl->id > V4L2_CID_HUE)
-               return -EINVAL;
-
-       mutex_lock(&zr->resource_lock);
-       decoder_call(zr, core, g_ctrl, ctrl);
-       mutex_unlock(&zr->resource_lock);
-
-       return 0;
-}
-
-static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       /* we only support hue/saturation/contrast/brightness */
-       if (ctrl->id < V4L2_CID_BRIGHTNESS ||
-           ctrl->id > V4L2_CID_HUE)
-               return -EINVAL;
-
-       mutex_lock(&zr->resource_lock);
-       decoder_call(zr, core, s_ctrl, ctrl);
-       mutex_unlock(&zr->resource_lock);
-
-       return 0;
-}
-
-static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       mutex_lock(&zr->resource_lock);
-       *std = zr->norm;
-       mutex_unlock(&zr->resource_lock);
-       return 0;
-}
-
-static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0;
-
-       mutex_lock(&zr->resource_lock);
-       res = zoran_set_norm(zr, *std);
-       if (res)
-               goto sstd_unlock_and_return;
-
-       res = wait_grab_pending(zr);
-sstd_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_enum_input(struct file *file, void *__fh,
-                                struct v4l2_input *inp)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       if (inp->index >= zr->card.inputs)
-               return -EINVAL;
-
-       strncpy(inp->name, zr->card.input[inp->index].name,
-               sizeof(inp->name) - 1);
-       inp->type = V4L2_INPUT_TYPE_CAMERA;
-       inp->std = V4L2_STD_ALL;
-
-       /* Get status of video decoder */
-       mutex_lock(&zr->resource_lock);
-       decoder_call(zr, video, g_input_status, &inp->status);
-       mutex_unlock(&zr->resource_lock);
-       return 0;
-}
-
-static int zoran_g_input(struct file *file, void *__fh, unsigned int *input)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-
-       mutex_lock(&zr->resource_lock);
-       *input = zr->input;
-       mutex_unlock(&zr->resource_lock);
-
-       return 0;
-}
-
-static int zoran_s_input(struct file *file, void *__fh, unsigned int input)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res;
-
-       mutex_lock(&zr->resource_lock);
-       res = zoran_set_input(zr, input);
-       if (res)
-               goto sinput_unlock_and_return;
-
-       /* Make sure the changes come into effect */
-       res = wait_grab_pending(zr);
-sinput_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_enum_output(struct file *file, void *__fh,
-                                 struct v4l2_output *outp)
-{
-       if (outp->index != 0)
-               return -EINVAL;
-
-       outp->index = 0;
-       outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-       strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
-
-       return 0;
-}
-
-static int zoran_g_output(struct file *file, void *__fh, unsigned int *output)
-{
-       *output = 0;
-
-       return 0;
-}
-
-static int zoran_s_output(struct file *file, void *__fh, unsigned int output)
-{
-       if (output != 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-/* cropping (sub-frame capture) */
-static int zoran_cropcap(struct file *file, void *__fh,
-                                       struct v4l2_cropcap *cropcap)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int type = cropcap->type, res = 0;
-
-       memset(cropcap, 0, sizeof(*cropcap));
-       cropcap->type = type;
-
-       mutex_lock(&zr->resource_lock);
-
-       if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-            fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-               dprintk(1, KERN_ERR
-                       "%s: VIDIOC_CROPCAP - subcapture only supported for compressed capture\n",
-                       ZR_DEVNAME(zr));
-               res = -EINVAL;
-               goto cropcap_unlock_and_return;
-       }
-
-       cropcap->bounds.top = cropcap->bounds.left = 0;
-       cropcap->bounds.width = BUZ_MAX_WIDTH;
-       cropcap->bounds.height = BUZ_MAX_HEIGHT;
-       cropcap->defrect.top = cropcap->defrect.left = 0;
-       cropcap->defrect.width = BUZ_MIN_WIDTH;
-       cropcap->defrect.height = BUZ_MIN_HEIGHT;
-cropcap_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_g_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int type = crop->type, res = 0;
-
-       memset(crop, 0, sizeof(*crop));
-       crop->type = type;
-
-       mutex_lock(&zr->resource_lock);
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-            fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
-                       ZR_DEVNAME(zr));
-               res = -EINVAL;
-               goto gcrop_unlock_and_return;
-       }
-
-       crop->c.top = fh->jpg_settings.img_y;
-       crop->c.left = fh->jpg_settings.img_x;
-       crop->c.width = fh->jpg_settings.img_width;
-       crop->c.height = fh->jpg_settings.img_height;
-
-gcrop_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0;
-       struct zoran_jpg_settings settings;
-
-       settings = fh->jpg_settings;
-
-       mutex_lock(&zr->resource_lock);
-
-       if (fh->buffers.allocated) {
-               dprintk(1, KERN_ERR
-                       "%s: VIDIOC_S_CROP - cannot change settings while active\n",
-                       ZR_DEVNAME(zr));
-               res = -EBUSY;
-               goto scrop_unlock_and_return;
-       }
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-            fh->map_mode == ZORAN_MAP_MODE_RAW)) {
-               dprintk(1, KERN_ERR
-                       "%s: VIDIOC_G_CROP - subcapture only supported for compressed capture\n",
-                       ZR_DEVNAME(zr));
-               res = -EINVAL;
-               goto scrop_unlock_and_return;
-       }
-
-       /* move into a form that we understand */
-       settings.img_x = crop->c.left;
-       settings.img_y = crop->c.top;
-       settings.img_width = crop->c.width;
-       settings.img_height = crop->c.height;
-
-       /* check validity */
-       res = zoran_check_jpg_settings(zr, &settings, 0);
-       if (res)
-               goto scrop_unlock_and_return;
-
-       /* accept */
-       fh->jpg_settings = settings;
-
-scrop_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-       return res;
-}
-
-static int zoran_g_jpegcomp(struct file *file, void *__fh,
-                                       struct v4l2_jpegcompression *params)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       memset(params, 0, sizeof(*params));
-
-       mutex_lock(&zr->resource_lock);
-
-       params->quality = fh->jpg_settings.jpg_comp.quality;
-       params->APPn = fh->jpg_settings.jpg_comp.APPn;
-       memcpy(params->APP_data,
-              fh->jpg_settings.jpg_comp.APP_data,
-              fh->jpg_settings.jpg_comp.APP_len);
-       params->APP_len = fh->jpg_settings.jpg_comp.APP_len;
-       memcpy(params->COM_data,
-              fh->jpg_settings.jpg_comp.COM_data,
-              fh->jpg_settings.jpg_comp.COM_len);
-       params->COM_len = fh->jpg_settings.jpg_comp.COM_len;
-       params->jpeg_markers =
-           fh->jpg_settings.jpg_comp.jpeg_markers;
-
-       mutex_unlock(&zr->resource_lock);
-
-       return 0;
-}
-
-static int zoran_s_jpegcomp(struct file *file, void *__fh,
-                                       struct v4l2_jpegcompression *params)
-{
-       struct zoran_fh *fh = __fh;
-       struct zoran *zr = fh->zr;
-       int res = 0;
-       struct zoran_jpg_settings settings;
-
-       settings = fh->jpg_settings;
-
-       settings.jpg_comp = *params;
-
-       mutex_lock(&zr->resource_lock);
-
-       if (fh->buffers.active != ZORAN_FREE) {
-               dprintk(1, KERN_WARNING
-                       "%s: VIDIOC_S_JPEGCOMP called while in playback/capture mode\n",
-                       ZR_DEVNAME(zr));
-               res = -EBUSY;
-               goto sjpegc_unlock_and_return;
-       }
-
-       res = zoran_check_jpg_settings(zr, &settings, 0);
-       if (res)
-               goto sjpegc_unlock_and_return;
-       if (!fh->buffers.allocated)
-               fh->buffers.buffer_size =
-                       zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-       fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
-sjpegc_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static unsigned int
-zoran_poll (struct file *file,
-           poll_table  *wait)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int res = 0, frame;
-       unsigned long flags;
-
-       /* we should check whether buffers are ready to be synced on
-        * (w/o waits - O_NONBLOCK) here
-        * if ready for read (sync), return POLLIN|POLLRDNORM,
-        * if ready for write (sync), return POLLOUT|POLLWRNORM,
-        * if error, return POLLERR,
-        * if no buffers queued or so, return POLLNVAL
-        */
-
-       mutex_lock(&zr->resource_lock);
-
-       switch (fh->map_mode) {
-       case ZORAN_MAP_MODE_RAW:
-               poll_wait(file, &zr->v4l_capq, wait);
-               frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n",
-                       ZR_DEVNAME(zr), __func__,
-                       "FAL"[fh->buffers.active], zr->v4l_sync_tail,
-                       "UPMD"[zr->v4l_buffers.buffer[frame].state],
-                       zr->v4l_pend_tail, zr->v4l_pend_head);
-               /* Process is the one capturing? */
-               if (fh->buffers.active != ZORAN_FREE &&
-                   /* Buffer ready to DQBUF? */
-                   zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE)
-                       res = POLLIN | POLLRDNORM;
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-
-               break;
-
-       case ZORAN_MAP_MODE_JPG_REC:
-       case ZORAN_MAP_MODE_JPG_PLAY:
-               poll_wait(file, &zr->jpg_capq, wait);
-               frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
-               spin_lock_irqsave(&zr->spinlock, flags);
-               dprintk(3,
-                       KERN_DEBUG
-                       "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n",
-                       ZR_DEVNAME(zr), __func__,
-                       "FAL"[fh->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);
-               if (fh->buffers.active != ZORAN_FREE &&
-                   zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) {
-                       if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC)
-                               res = POLLIN | POLLRDNORM;
-                       else
-                               res = POLLOUT | POLLWRNORM;
-               }
-               spin_unlock_irqrestore(&zr->spinlock, flags);
-
-               break;
-
-       default:
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - internal error, unknown map_mode=%d\n",
-                       ZR_DEVNAME(zr), __func__, fh->map_mode);
-               res = POLLNVAL;
-       }
-
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-
-/*
- * This maps the buffers to user space.
- *
- * Depending on the state of fh->map_mode
- * the V4L or the MJPEG buffers are mapped
- * per buffer or all together
- *
- * Note that we need to connect to some
- * unmap signal event to unmap the de-allocate
- * the buffer accordingly (zoran_vm_close())
- */
-
-static void
-zoran_vm_open (struct vm_area_struct *vma)
-{
-       struct zoran_mapping *map = vma->vm_private_data;
-
-       map->count++;
-}
-
-static void
-zoran_vm_close (struct vm_area_struct *vma)
-{
-       struct zoran_mapping *map = vma->vm_private_data;
-       struct zoran_fh *fh = map->fh;
-       struct zoran *zr = fh->zr;
-       int i;
-
-       if (--map->count > 0)
-               return;
-
-       dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
-               __func__, mode_name(fh->map_mode));
-
-       for (i = 0; i < fh->buffers.num_buffers; i++) {
-               if (fh->buffers.buffer[i].map == map)
-                       fh->buffers.buffer[i].map = NULL;
-       }
-       kfree(map);
-
-       /* Any buffers still mapped? */
-       for (i = 0; i < fh->buffers.num_buffers; i++)
-               if (fh->buffers.buffer[i].map)
-                       return;
-
-       dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
-               __func__, mode_name(fh->map_mode));
-
-       mutex_lock(&zr->resource_lock);
-
-       if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
-               if (fh->buffers.active != ZORAN_FREE) {
-                       unsigned long flags;
-
-                       spin_lock_irqsave(&zr->spinlock, flags);
-                       zr36057_set_memgrab(zr, 0);
-                       zr->v4l_buffers.allocated = 0;
-                       zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
-                       spin_unlock_irqrestore(&zr->spinlock, flags);
-               }
-               v4l_fbuffer_free(fh);
-       } else {
-               if (fh->buffers.active != ZORAN_FREE) {
-                       jpg_qbuf(fh, -1, zr->codec_mode);
-                       zr->jpg_buffers.allocated = 0;
-                       zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
-               }
-               jpg_fbuffer_free(fh);
-       }
-
-       mutex_unlock(&zr->resource_lock);
-}
-
-static const struct vm_operations_struct zoran_vm_ops = {
-       .open = zoran_vm_open,
-       .close = zoran_vm_close,
-};
-
-static int
-zoran_mmap (struct file           *file,
-           struct vm_area_struct *vma)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       unsigned long size = (vma->vm_end - vma->vm_start);
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       int i, j;
-       unsigned long page, start = vma->vm_start, todo, pos, fraglen;
-       int first, last;
-       struct zoran_mapping *map;
-       int res = 0;
-
-       dprintk(3,
-               KERN_INFO "%s: %s(%s) of 0x%08lx-0x%08lx (size=%lu)\n",
-               ZR_DEVNAME(zr), __func__,
-               mode_name(fh->map_mode), vma->vm_start, vma->vm_end, size);
-
-       if (!(vma->vm_flags & VM_SHARED) || !(vma->vm_flags & VM_READ) ||
-           !(vma->vm_flags & VM_WRITE)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s - no MAP_SHARED/PROT_{READ,WRITE} given\n",
-                       ZR_DEVNAME(zr), __func__);
-               return -EINVAL;
-       }
-
-       mutex_lock(&zr->resource_lock);
-
-       if (!fh->buffers.allocated) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s(%s) - buffers not yet allocated\n",
-                       ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode));
-               res = -ENOMEM;
-               goto mmap_unlock_and_return;
-       }
-
-       first = offset / fh->buffers.buffer_size;
-       last = first - 1 + size / fh->buffers.buffer_size;
-       if (offset % fh->buffers.buffer_size != 0 ||
-           size % fh->buffers.buffer_size != 0 || first < 0 ||
-           last < 0 || first >= fh->buffers.num_buffers ||
-           last >= fh->buffers.buffer_size) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: %s(%s) - offset=%lu or size=%lu invalid for bufsize=%d and numbufs=%d\n",
-                       ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), offset, size,
-                       fh->buffers.buffer_size,
-                       fh->buffers.num_buffers);
-               res = -EINVAL;
-               goto mmap_unlock_and_return;
-       }
-
-       /* Check if any buffers are already mapped */
-       for (i = first; i <= last; i++) {
-               if (fh->buffers.buffer[i].map) {
-                       dprintk(1,
-                               KERN_ERR
-                               "%s: %s(%s) - buffer %d already mapped\n",
-                               ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode), i);
-                       res = -EBUSY;
-                       goto mmap_unlock_and_return;
-               }
-       }
-
-       /* map these buffers */
-       map = kmalloc(sizeof(struct zoran_mapping), GFP_KERNEL);
-       if (!map) {
-               res = -ENOMEM;
-               goto mmap_unlock_and_return;
-       }
-       map->fh = fh;
-       map->count = 1;
-
-       vma->vm_ops = &zoran_vm_ops;
-       vma->vm_flags |= VM_DONTEXPAND;
-       vma->vm_private_data = map;
-
-       if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
-               for (i = first; i <= last; i++) {
-                       todo = size;
-                       if (todo > fh->buffers.buffer_size)
-                               todo = fh->buffers.buffer_size;
-                       page = fh->buffers.buffer[i].v4l.fbuffer_phys;
-                       if (remap_pfn_range(vma, start, page >> PAGE_SHIFT,
-                                                       todo, PAGE_SHARED)) {
-                               dprintk(1,
-                                       KERN_ERR
-                                       "%s: %s(V4L) - remap_pfn_range failed\n",
-                                       ZR_DEVNAME(zr), __func__);
-                               res = -EAGAIN;
-                               goto mmap_unlock_and_return;
-                       }
-                       size -= todo;
-                       start += todo;
-                       fh->buffers.buffer[i].map = map;
-                       if (size == 0)
-                               break;
-               }
-       } else {
-               for (i = first; i <= last; i++) {
-                       for (j = 0;
-                            j < fh->buffers.buffer_size / PAGE_SIZE;
-                            j++) {
-                               fraglen =
-                                   (le32_to_cpu(fh->buffers.buffer[i].jpg.
-                                    frag_tab[2 * j + 1]) & ~1) << 1;
-                               todo = size;
-                               if (todo > fraglen)
-                                       todo = fraglen;
-                               pos =
-                                   le32_to_cpu(fh->buffers.
-                                   buffer[i].jpg.frag_tab[2 * j]);
-                               /* should just be pos on i386 */
-                               page = virt_to_phys(bus_to_virt(pos))
-                                                               >> PAGE_SHIFT;
-                               if (remap_pfn_range(vma, start, page,
-                                                       todo, PAGE_SHARED)) {
-                                       dprintk(1,
-                                               KERN_ERR
-                                               "%s: %s(V4L) - remap_pfn_range failed\n",
-                                               ZR_DEVNAME(zr), __func__);
-                                       res = -EAGAIN;
-                                       goto mmap_unlock_and_return;
-                               }
-                               size -= todo;
-                               start += todo;
-                               if (size == 0)
-                                       break;
-                               if (le32_to_cpu(fh->buffers.buffer[i].jpg.
-                                   frag_tab[2 * j + 1]) & 1)
-                                       break;  /* was last fragment */
-                       }
-                       fh->buffers.buffer[i].map = map;
-                       if (size == 0)
-                               break;
-
-               }
-       }
-
-mmap_unlock_and_return:
-       mutex_unlock(&zr->resource_lock);
-
-       return res;
-}
-
-static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
-       .vidioc_querycap                    = zoran_querycap,
-       .vidioc_cropcap                     = zoran_cropcap,
-       .vidioc_s_crop                      = zoran_s_crop,
-       .vidioc_g_crop                      = zoran_g_crop,
-       .vidioc_enum_input                  = zoran_enum_input,
-       .vidioc_g_input                     = zoran_g_input,
-       .vidioc_s_input                     = zoran_s_input,
-       .vidioc_enum_output                 = zoran_enum_output,
-       .vidioc_g_output                    = zoran_g_output,
-       .vidioc_s_output                    = zoran_s_output,
-       .vidioc_g_fbuf                      = zoran_g_fbuf,
-       .vidioc_s_fbuf                      = zoran_s_fbuf,
-       .vidioc_g_std                       = zoran_g_std,
-       .vidioc_s_std                       = zoran_s_std,
-       .vidioc_g_jpegcomp                  = zoran_g_jpegcomp,
-       .vidioc_s_jpegcomp                  = zoran_s_jpegcomp,
-       .vidioc_overlay                     = zoran_overlay,
-       .vidioc_reqbufs                     = zoran_reqbufs,
-       .vidioc_querybuf                    = zoran_querybuf,
-       .vidioc_qbuf                        = zoran_qbuf,
-       .vidioc_dqbuf                       = zoran_dqbuf,
-       .vidioc_streamon                    = zoran_streamon,
-       .vidioc_streamoff                   = zoran_streamoff,
-       .vidioc_enum_fmt_vid_cap            = zoran_enum_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_out            = zoran_enum_fmt_vid_out,
-       .vidioc_enum_fmt_vid_overlay        = zoran_enum_fmt_vid_overlay,
-       .vidioc_g_fmt_vid_cap               = zoran_g_fmt_vid_cap,
-       .vidioc_g_fmt_vid_out               = zoran_g_fmt_vid_out,
-       .vidioc_g_fmt_vid_overlay           = zoran_g_fmt_vid_overlay,
-       .vidioc_s_fmt_vid_cap               = zoran_s_fmt_vid_cap,
-       .vidioc_s_fmt_vid_out               = zoran_s_fmt_vid_out,
-       .vidioc_s_fmt_vid_overlay           = zoran_s_fmt_vid_overlay,
-       .vidioc_try_fmt_vid_cap             = zoran_try_fmt_vid_cap,
-       .vidioc_try_fmt_vid_out             = zoran_try_fmt_vid_out,
-       .vidioc_try_fmt_vid_overlay         = zoran_try_fmt_vid_overlay,
-       .vidioc_queryctrl                   = zoran_queryctrl,
-       .vidioc_s_ctrl                      = zoran_s_ctrl,
-       .vidioc_g_ctrl                      = zoran_g_ctrl,
-};
-
-/* please use zr->resource_lock consistently and kill this wrapper */
-static long zoran_ioctl(struct file *file, unsigned int cmd,
-                       unsigned long arg)
-{
-       struct zoran_fh *fh = file->private_data;
-       struct zoran *zr = fh->zr;
-       int ret;
-
-       mutex_lock(&zr->other_lock);
-       ret = video_ioctl2(file, cmd, arg);
-       mutex_unlock(&zr->other_lock);
-
-       return ret;
-}
-
-static const struct v4l2_file_operations zoran_fops = {
-       .owner = THIS_MODULE,
-       .open = zoran_open,
-       .release = zoran_close,
-       .unlocked_ioctl = zoran_ioctl,
-       .read = zoran_read,
-       .write = zoran_write,
-       .mmap = zoran_mmap,
-       .poll = zoran_poll,
-};
-
-struct video_device zoran_template __devinitdata = {
-       .name = ZORAN_NAME,
-       .fops = &zoran_fops,
-       .ioctl_ops = &zoran_ioctl_ops,
-       .release = &zoran_vdev_release,
-       .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
-};
-
diff --git a/drivers/media/video/zoran/zoran_procfs.c b/drivers/media/video/zoran/zoran_procfs.c
deleted file mode 100644 (file)
index f1423b7..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles the procFS entries (/proc/ZORAN[%d])
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.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/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/videodev2.h>
-#include <linux/spinlock.h>
-#include <linux/sem.h>
-#include <linux/seq_file.h>
-
-#include <linux/ctype.h>
-#include <linux/poll.h>
-#include <asm/io.h>
-
-#include "videocodec.h"
-#include "zoran.h"
-#include "zoran_procfs.h"
-#include "zoran_card.h"
-
-#ifdef CONFIG_PROC_FS
-struct procfs_params_zr36067 {
-       char *name;
-       short reg;
-       u32 mask;
-       short bit;
-};
-
-static const struct procfs_params_zr36067 zr67[] = {
-       {"HSPol", 0x000, 1, 30},
-       {"HStart", 0x000, 0x3ff, 10},
-       {"HEnd", 0x000, 0x3ff, 0},
-
-       {"VSPol", 0x004, 1, 30},
-       {"VStart", 0x004, 0x3ff, 10},
-       {"VEnd", 0x004, 0x3ff, 0},
-
-       {"ExtFl", 0x008, 1, 26},
-       {"TopField", 0x008, 1, 25},
-       {"VCLKPol", 0x008, 1, 24},
-       {"DupFld", 0x008, 1, 20},
-       {"LittleEndian", 0x008, 1, 0},
-
-       {"HsyncStart", 0x10c, 0xffff, 16},
-       {"LineTot", 0x10c, 0xffff, 0},
-
-       {"NAX", 0x110, 0xffff, 16},
-       {"PAX", 0x110, 0xffff, 0},
-
-       {"NAY", 0x114, 0xffff, 16},
-       {"PAY", 0x114, 0xffff, 0},
-
-       /* {"",,,}, */
-
-       {NULL, 0, 0, 0},
-};
-
-static void
-setparam (struct zoran *zr,
-         char         *name,
-         char         *sval)
-{
-       int i = 0, reg0, reg, val;
-
-       while (zr67[i].name != NULL) {
-               if (!strncmp(name, zr67[i].name, strlen(zr67[i].name))) {
-                       reg = reg0 = btread(zr67[i].reg);
-                       reg &= ~(zr67[i].mask << zr67[i].bit);
-                       if (!isdigit(sval[0]))
-                               break;
-                       val = simple_strtoul(sval, NULL, 0);
-                       if ((val & ~zr67[i].mask))
-                               break;
-                       reg |= (val & zr67[i].mask) << zr67[i].bit;
-                       dprintk(4,
-                               KERN_INFO
-                               "%s: setparam: setting ZR36067 register 0x%03x: 0x%08x=>0x%08x %s=%d\n",
-                               ZR_DEVNAME(zr), zr67[i].reg, reg0, reg,
-                               zr67[i].name, val);
-                       btwrite(reg, zr67[i].reg);
-                       break;
-               }
-               i++;
-       }
-}
-
-static int zoran_show(struct seq_file *p, void *v)
-{
-       struct zoran *zr = p->private;
-       int i;
-
-       seq_printf(p, "ZR36067 registers:\n");
-       for (i = 0; i < 0x130; i += 16)
-               seq_printf(p, "%03X %08X  %08X  %08X  %08X \n", i,
-                          btread(i), btread(i+4), btread(i+8), btread(i+12));
-       return 0;
-}
-
-static int zoran_open(struct inode *inode, struct file *file)
-{
-       struct zoran *data = PDE(inode)->data;
-       return single_open(file, zoran_show, data);
-}
-
-static ssize_t zoran_write(struct file *file, const char __user *buffer,
-                       size_t count, loff_t *ppos)
-{
-       struct zoran *zr = PDE(file->f_path.dentry->d_inode)->data;
-       char *string, *sp;
-       char *line, *ldelim, *varname, *svar, *tdelim;
-
-       if (count > 32768)      /* Stupidity filter */
-               return -EINVAL;
-
-       string = sp = vmalloc(count + 1);
-       if (!string) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: write_proc: can not allocate memory\n",
-                       ZR_DEVNAME(zr));
-               return -ENOMEM;
-       }
-       if (copy_from_user(string, buffer, count)) {
-               vfree (string);
-               return -EFAULT;
-       }
-       string[count] = 0;
-       dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
-               ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
-       ldelim = " \t\n";
-       tdelim = "=";
-       line = strpbrk(sp, ldelim);
-       while (line) {
-               *line = 0;
-               svar = strpbrk(sp, tdelim);
-               if (svar) {
-                       *svar = 0;
-                       varname = sp;
-                       svar++;
-                       setparam(zr, varname, svar);
-               }
-               sp = line + 1;
-               line = strpbrk(sp, ldelim);
-       }
-       vfree(string);
-
-       return count;
-}
-
-static const struct file_operations zoran_operations = {
-       .owner          = THIS_MODULE,
-       .open           = zoran_open,
-       .read           = seq_read,
-       .write          = zoran_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-#endif
-
-int
-zoran_proc_init (struct zoran *zr)
-{
-#ifdef CONFIG_PROC_FS
-       char name[8];
-
-       snprintf(name, 7, "zoran%d", zr->id);
-       zr->zoran_proc = proc_create_data(name, 0, NULL, &zoran_operations, zr);
-       if (zr->zoran_proc != NULL) {
-               dprintk(2,
-                       KERN_INFO
-                       "%s: procfs entry /proc/%s allocated. data=%p\n",
-                       ZR_DEVNAME(zr), name, zr->zoran_proc->data);
-       } else {
-               dprintk(1, KERN_ERR "%s: Unable to initialise /proc/%s\n",
-                       ZR_DEVNAME(zr), name);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-void
-zoran_proc_cleanup (struct zoran *zr)
-{
-#ifdef CONFIG_PROC_FS
-       char name[8];
-
-       snprintf(name, 7, "zoran%d", zr->id);
-       if (zr->zoran_proc)
-               remove_proc_entry(name, NULL);
-       zr->zoran_proc = NULL;
-#endif
-}
diff --git a/drivers/media/video/zoran/zoran_procfs.h b/drivers/media/video/zoran/zoran_procfs.h
deleted file mode 100644 (file)
index f2d5b1b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Zoran zr36057/zr36067 PCI controller driver, for the
- * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux
- * Media Labs LML33/LML33R10.
- *
- * This part handles card-specific data and detection
- *
- * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
- *
- * Currently maintained by:
- *   Ronald Bultje    <rbultje@ronald.bitfreak.net>
- *   Laurent Pinchart <laurent.pinchart@skynet.be>
- *   Mailinglist      <mjpeg-users@lists.sf.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.
- */
-
-#ifndef __ZORAN_PROCFS_H__
-#define __ZORAN_PROCFS_H__
-
-extern int zoran_proc_init(struct zoran *zr);
-extern void zoran_proc_cleanup(struct zoran *zr);
-
-#endif                         /* __ZORAN_PROCFS_H__ */
diff --git a/drivers/media/video/zoran/zr36016.c b/drivers/media/video/zoran/zr36016.c
deleted file mode 100644 (file)
index b87ddba..0000000
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Zoran ZR36016 basic configuration functions
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36016.c,v 1.1.2.14 2003/08/20 19:46:55 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 ZR016_VERSION "v0.7"
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-/* I/O commands, error codes */
-#include <asm/io.h>
-
-/* v4l  API */
-
-/* headerfile of this module */
-#include "zr36016.h"
-
-/* codec io API */
-#include "videocodec.h"
-
-/* it doesn't make sense to have more than 20 or so,
-  just to prevent some unwanted loops */
-#define MAX_CODECS 20
-
-/* amount of chips attached via this driver */
-static int zr36016_codecs;
-
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* =========================================================================
-   Local hardware I/O functions:
-
-   read/write via codec layer (registers are located in the master device)
-   ========================================================================= */
-
-/* read and write functions */
-static u8
-zr36016_read (struct zr36016 *ptr,
-             u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->readreg)
-               value =
-                   (ptr->codec->master_data->
-                    readreg(ptr->codec, reg)) & 0xFF;
-       else
-               dprintk(1,
-                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
-                       ptr->name);
-
-       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
-               value);
-
-       return value;
-}
-
-static void
-zr36016_write (struct zr36016 *ptr,
-              u16             reg,
-              u8              value)
-{
-       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
-               reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg) {
-               ptr->codec->master_data->writereg(ptr->codec, reg, value);
-       } else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written!\n",
-                       ptr->name);
-}
-
-/* indirect read and write functions */
-/* the 016 supports auto-addr-increment, but
- * writing it all time cost not much and is safer... */
-static u8
-zr36016_readi (struct zr36016 *ptr,
-              u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if ((ptr->codec->master_data->writereg) &&
-           (ptr->codec->master_data->readreg)) {
-               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
-               value = (ptr->codec->master_data->readreg(ptr->codec, ZR016_IDATA)) & 0xFF;     // DATA
-       } else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing read (i)!\n",
-                       ptr->name);
-
-       dprintk(4, "%s: reading indirect from 0x%04x: %02x\n", ptr->name,
-               reg, value);
-       return value;
-}
-
-static void
-zr36016_writei (struct zr36016 *ptr,
-               u16             reg,
-               u8              value)
-{
-       dprintk(4, "%s: writing indirect 0x%02x to 0x%04x\n", ptr->name,
-               value, reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg) {
-               ptr->codec->master_data->writereg(ptr->codec, ZR016_IADDR, reg & 0x0F); // ADDR
-               ptr->codec->master_data->writereg(ptr->codec, ZR016_IDATA, value & 0x0FF);      // DATA
-       } else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written (i)!\n",
-                       ptr->name);
-}
-
-/* =========================================================================
-   Local helper function:
-
-   version read
-   ========================================================================= */
-
-/* version kept in datastructure */
-static u8
-zr36016_read_version (struct zr36016 *ptr)
-{
-       ptr->version = zr36016_read(ptr, 0) >> 4;
-       return ptr->version;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   basic test of "connectivity", writes/reads to/from PAX-Lo register
-   ========================================================================= */
-
-static int
-zr36016_basic_test (struct zr36016 *ptr)
-{
-       if (debug) {
-               int i;
-               zr36016_writei(ptr, ZR016I_PAX_LO, 0x55);
-               dprintk(1, KERN_INFO "%s: registers: ", ptr->name);
-               for (i = 0; i <= 0x0b; i++)
-                       dprintk(1, "%02x ", zr36016_readi(ptr, i));
-               dprintk(1, "\n");
-       }
-       // for testing just write 0, then the default value to a register and read
-       // it back in both cases
-       zr36016_writei(ptr, ZR016I_PAX_LO, 0x00);
-       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to vfe processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-       zr36016_writei(ptr, ZR016I_PAX_LO, 0x0d0);
-       if (zr36016_readi(ptr, ZR016I_PAX_LO) != 0x0d0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to vfe processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-       // we allow version numbers from 0-3, should be enough, though
-       zr36016_read_version(ptr);
-       if (ptr->version & 0x0c) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, suspicious version %d found...\n",
-                       ptr->name, ptr->version);
-               return -ENXIO;
-       }
-
-       return 0;               /* looks good! */
-}
-
-/* =========================================================================
-   Local helper function:
-
-   simple loop for pushing the init datasets - NO USE --
-   ========================================================================= */
-
-#if 0
-static int zr36016_pushit (struct zr36016 *ptr,
-                          u16             startreg,
-                          u16             len,
-                          const char     *data)
-{
-       int i=0;
-
-       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n",
-               ptr->name, startreg,len);
-       while (i<len) {
-               zr36016_writei(ptr, startreg++,  data[i++]);
-       }
-
-       return i;
-}
-#endif
-
-/* =========================================================================
-   Basic datasets & init:
-
-   //TODO//
-   ========================================================================= */
-
-// needed offset values          PAL NTSC SECAM
-static const int zr016_xoff[] = { 20, 20, 20 };
-static const int zr016_yoff[] = { 8, 9, 7 };
-
-static void
-zr36016_init (struct zr36016 *ptr)
-{
-       // stop any processing
-       zr36016_write(ptr, ZR016_GOSTOP, 0);
-
-       // mode setup (yuv422 in and out, compression/expansuon due to mode)
-       zr36016_write(ptr, ZR016_MODE,
-                     ZR016_YUV422 | ZR016_YUV422_YUV422 |
-                     (ptr->mode == CODEC_DO_COMPRESSION ?
-                      ZR016_COMPRESSION : ZR016_EXPANSION));
-
-       // misc setup
-       zr36016_writei(ptr, ZR016I_SETUP1,
-                      (ptr->xdec ? (ZR016_HRFL | ZR016_HORZ) : 0) |
-                      (ptr->ydec ? ZR016_VERT : 0) | ZR016_CNTI);
-       zr36016_writei(ptr, ZR016I_SETUP2, ZR016_CCIR);
-
-       // Window setup
-       // (no extra offset for now, norm defines offset, default width height)
-       zr36016_writei(ptr, ZR016I_PAX_HI, ptr->width >> 8);
-       zr36016_writei(ptr, ZR016I_PAX_LO, ptr->width & 0xFF);
-       zr36016_writei(ptr, ZR016I_PAY_HI, ptr->height >> 8);
-       zr36016_writei(ptr, ZR016I_PAY_LO, ptr->height & 0xFF);
-       zr36016_writei(ptr, ZR016I_NAX_HI, ptr->xoff >> 8);
-       zr36016_writei(ptr, ZR016I_NAX_LO, ptr->xoff & 0xFF);
-       zr36016_writei(ptr, ZR016I_NAY_HI, ptr->yoff >> 8);
-       zr36016_writei(ptr, ZR016I_NAY_LO, ptr->yoff & 0xFF);
-
-       /* shall we continue now, please? */
-       zr36016_write(ptr, ZR016_GOSTOP, 1);
-}
-
-/* =========================================================================
-   CODEC API FUNCTIONS
-
-   this functions are accessed by the master via the API structure
-   ========================================================================= */
-
-/* set compression/expansion mode and launches codec -
-   this should be the last call from the master before starting processing */
-static int
-zr36016_set_mode (struct videocodec *codec,
-                 int                mode)
-{
-       struct zr36016 *ptr = (struct zr36016 *) codec->data;
-
-       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
-
-       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
-               return -EINVAL;
-
-       ptr->mode = mode;
-       zr36016_init(ptr);
-
-       return 0;
-}
-
-/* set picture size */
-static int
-zr36016_set_video (struct videocodec   *codec,
-                  struct tvnorm       *norm,
-                  struct vfe_settings *cap,
-                  struct vfe_polarity *pol)
-{
-       struct zr36016 *ptr = (struct zr36016 *) codec->data;
-
-       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n",
-               ptr->name, norm->HStart, norm->VStart,
-               cap->x, cap->y, cap->width, cap->height,
-               cap->decimation);
-
-       /* if () return -EINVAL;
-        * trust the master driver that it knows what it does - so
-        * we allow invalid startx/y for now ... */
-       ptr->width = cap->width;
-       ptr->height = cap->height;
-       /* (Ronald) This is ugly. zoran_device.c, line 387
-        * already mentions what happens if HStart is even
-        * (blue faces, etc., cr/cb inversed). There's probably
-        * some good reason why HStart is 0 instead of 1, so I'm
-        * leaving it to this for now, but really... This can be
-        * done a lot simpler */
-       ptr->xoff = (norm->HStart ? norm->HStart : 1) + cap->x;
-       /* Something to note here (I don't understand it), setting
-        * VStart too high will cause the codec to 'not work'. I
-        * really don't get it. values of 16 (VStart) already break
-        * it here. Just '0' seems to work. More testing needed! */
-       ptr->yoff = norm->VStart + cap->y;
-       /* (Ronald) dzjeeh, can't this thing do hor_decimation = 4? */
-       ptr->xdec = ((cap->decimation & 0xff) == 1) ? 0 : 1;
-       ptr->ydec = (((cap->decimation >> 8) & 0xff) == 1) ? 0 : 1;
-
-       return 0;
-}
-
-/* additional control functions */
-static int
-zr36016_control (struct videocodec *codec,
-                int                type,
-                int                size,
-                void              *data)
-{
-       struct zr36016 *ptr = (struct zr36016 *) codec->data;
-       int *ival = (int *) data;
-
-       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
-               size);
-
-       switch (type) {
-       case CODEC_G_STATUS:    /* get last status - we don't know it ... */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = 0;
-               break;
-
-       case CODEC_G_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = 0;
-               break;
-
-       case CODEC_S_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               if (*ival != 0)
-                       return -EINVAL;
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_G_VFE:
-       case CODEC_S_VFE:
-               return 0;
-
-       case CODEC_S_MMAP:
-               /* not available, give an error */
-               return -ENXIO;
-
-       default:
-               return -EINVAL;
-       }
-
-       return size;
-}
-
-/* =========================================================================
-   Exit and unregister function:
-
-   Deinitializes Zoran's JPEG processor
-   ========================================================================= */
-
-static int
-zr36016_unset (struct videocodec *codec)
-{
-       struct zr36016 *ptr = codec->data;
-
-       if (ptr) {
-               /* do wee need some codec deinit here, too ???? */
-
-               dprintk(1, "%s: finished codec #%d\n", ptr->name,
-                       ptr->num);
-               kfree(ptr);
-               codec->data = NULL;
-
-               zr36016_codecs--;
-               return 0;
-       }
-
-       return -EFAULT;
-}
-
-/* =========================================================================
-   Setup and registry function:
-
-   Initializes Zoran's JPEG processor
-
-   Also sets pixel size, average code size, mode (compr./decompr.)
-   (the given size is determined by the processor with the video interface)
-   ========================================================================= */
-
-static int
-zr36016_setup (struct videocodec *codec)
-{
-       struct zr36016 *ptr;
-       int res;
-
-       dprintk(2, "zr36016: initializing VFE subsystem #%d.\n",
-               zr36016_codecs);
-
-       if (zr36016_codecs == MAX_CODECS) {
-               dprintk(1,
-                       KERN_ERR "zr36016: Can't attach more codecs!\n");
-               return -ENOSPC;
-       }
-       //mem structure init
-       codec->data = ptr = kzalloc(sizeof(struct zr36016), GFP_KERNEL);
-       if (NULL == ptr) {
-               dprintk(1, KERN_ERR "zr36016: Can't get enough memory!\n");
-               return -ENOMEM;
-       }
-
-       snprintf(ptr->name, sizeof(ptr->name), "zr36016[%d]",
-                zr36016_codecs);
-       ptr->num = zr36016_codecs++;
-       ptr->codec = codec;
-
-       //testing
-       res = zr36016_basic_test(ptr);
-       if (res < 0) {
-               zr36016_unset(codec);
-               return res;
-       }
-       //final setup
-       ptr->mode = CODEC_DO_COMPRESSION;
-       ptr->width = 768;
-       ptr->height = 288;
-       ptr->xdec = 1;
-       ptr->ydec = 0;
-       zr36016_init(ptr);
-
-       dprintk(1, KERN_INFO "%s: codec v%d attached and running\n",
-               ptr->name, ptr->version);
-
-       return 0;
-}
-
-static const struct videocodec zr36016_codec = {
-       .owner = THIS_MODULE,
-       .name = "zr36016",
-       .magic = 0L,            // magic not used
-       .flags =
-           CODEC_FLAG_HARDWARE | CODEC_FLAG_VFE | CODEC_FLAG_ENCODER |
-           CODEC_FLAG_DECODER,
-       .type = CODEC_TYPE_ZR36016,
-       .setup = zr36016_setup, // functionality
-       .unset = zr36016_unset,
-       .set_mode = zr36016_set_mode,
-       .set_video = zr36016_set_video,
-       .control = zr36016_control,
-       // others are not used
-};
-
-/* =========================================================================
-   HOOK IN DRIVER AS KERNEL MODULE
-   ========================================================================= */
-
-static int __init
-zr36016_init_module (void)
-{
-       //dprintk(1, "ZR36016 driver %s\n",ZR016_VERSION);
-       zr36016_codecs = 0;
-       return videocodec_register(&zr36016_codec);
-}
-
-static void __exit
-zr36016_cleanup_module (void)
-{
-       if (zr36016_codecs) {
-               dprintk(1,
-                       "zr36016: something's wrong - %d codecs left somehow.\n",
-                       zr36016_codecs);
-       }
-       videocodec_unregister(&zr36016_codec);
-}
-
-module_init(zr36016_init_module);
-module_exit(zr36016_cleanup_module);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Driver module for ZR36016 video frontends "
-                  ZR016_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/zr36016.h b/drivers/media/video/zoran/zr36016.h
deleted file mode 100644 (file)
index 8c79229..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Zoran ZR36016 basic configuration functions - header file
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36016.h,v 1.1.2.3 2003/01/14 21:18:07 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 ZR36016_H
-#define ZR36016_H
-
-/* data stored for each zoran jpeg codec chip */
-struct zr36016 {
-       char name[32];
-       int num;
-       /* io datastructure */
-       struct videocodec *codec;
-       // coder status
-       __u8 version;
-       // actual coder setup
-       int mode;
-
-       __u16 xoff;
-       __u16 yoff;
-       __u16 width;
-       __u16 height;
-       __u16 xdec;
-       __u16 ydec;
-};
-
-/* direct  register addresses */
-#define ZR016_GOSTOP      0x00
-#define ZR016_MODE        0x01
-#define ZR016_IADDR       0x02
-#define ZR016_IDATA       0x03
-
-/* indirect  register addresses */
-#define ZR016I_SETUP1     0x00
-#define ZR016I_SETUP2     0x01
-#define ZR016I_NAX_LO     0x02
-#define ZR016I_NAX_HI     0x03
-#define ZR016I_PAX_LO     0x04
-#define ZR016I_PAX_HI     0x05
-#define ZR016I_NAY_LO     0x06
-#define ZR016I_NAY_HI     0x07
-#define ZR016I_PAY_LO     0x08
-#define ZR016I_PAY_HI     0x09
-#define ZR016I_NOL_LO     0x0a
-#define ZR016I_NOL_HI     0x0b
-
-/* possible values for mode register */
-#define ZR016_RGB444_YUV444  0x00
-#define ZR016_RGB444_YUV422  0x01
-#define ZR016_RGB444_YUV411  0x02
-#define ZR016_RGB444_Y400    0x03
-#define ZR016_RGB444_RGB444  0x04
-#define ZR016_YUV444_YUV444  0x08
-#define ZR016_YUV444_YUV422  0x09
-#define ZR016_YUV444_YUV411  0x0a
-#define ZR016_YUV444_Y400    0x0b
-#define ZR016_YUV444_RGB444  0x0c
-#define ZR016_YUV422_YUV422  0x11
-#define ZR016_YUV422_YUV411  0x12
-#define ZR016_YUV422_Y400    0x13
-#define ZR016_YUV411_YUV411  0x16
-#define ZR016_YUV411_Y400    0x17
-#define ZR016_4444_4444      0x19
-#define ZR016_100_100        0x1b
-
-#define ZR016_RGB444         0x00
-#define ZR016_YUV444         0x20
-#define ZR016_YUV422         0x40
-
-#define ZR016_COMPRESSION    0x80
-#define ZR016_EXPANSION      0x80
-
-/* possible values for setup 1 register */
-#define ZR016_CKRT           0x80
-#define ZR016_VERT           0x40
-#define ZR016_HORZ           0x20
-#define ZR016_HRFL           0x10
-#define ZR016_DSFL           0x08
-#define ZR016_SBFL           0x04
-#define ZR016_RSTR           0x02
-#define ZR016_CNTI           0x01
-
-/* possible values for setup 2 register */
-#define ZR016_SYEN           0x40
-#define ZR016_CCIR           0x04
-#define ZR016_SIGN           0x02
-#define ZR016_YMCS           0x01
-
-#endif                         /*fndef ZR36016_H */
diff --git a/drivers/media/video/zoran/zr36050.c b/drivers/media/video/zoran/zr36050.c
deleted file mode 100644 (file)
index e198560..0000000
+++ /dev/null
@@ -1,900 +0,0 @@
-/*
- * Zoran ZR36050 basic configuration functions
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36050.c,v 1.1.2.11 2003/08/03 14:54:53 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 ZR050_VERSION "v0.7.1"
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-/* I/O commands, error codes */
-#include <asm/io.h>
-
-/* headerfile of this module */
-#include "zr36050.h"
-
-/* codec io API */
-#include "videocodec.h"
-
-/* it doesn't make sense to have more than 20 or so,
-  just to prevent some unwanted loops */
-#define MAX_CODECS 20
-
-/* amount of chips attached via this driver */
-static int zr36050_codecs;
-
-/* debugging is available via module parameter */
-static int debug;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* =========================================================================
-   Local hardware I/O functions:
-
-   read/write via codec layer (registers are located in the master device)
-   ========================================================================= */
-
-/* read and write functions */
-static u8
-zr36050_read (struct zr36050 *ptr,
-             u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->readreg)
-               value = (ptr->codec->master_data->readreg(ptr->codec,
-                                                         reg)) & 0xFF;
-       else
-               dprintk(1,
-                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
-                       ptr->name);
-
-       dprintk(4, "%s: reading from 0x%04x: %02x\n", ptr->name, reg,
-               value);
-
-       return value;
-}
-
-static void
-zr36050_write (struct zr36050 *ptr,
-              u16             reg,
-              u8              value)
-{
-       dprintk(4, "%s: writing 0x%02x to 0x%04x\n", ptr->name, value,
-               reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg)
-               ptr->codec->master_data->writereg(ptr->codec, reg, value);
-       else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written!\n",
-                       ptr->name);
-}
-
-/* =========================================================================
-   Local helper function:
-
-   status read
-   ========================================================================= */
-
-/* status is kept in datastructure */
-static u8
-zr36050_read_status1 (struct zr36050 *ptr)
-{
-       ptr->status1 = zr36050_read(ptr, ZR050_STATUS_1);
-
-       zr36050_read(ptr, 0);
-       return ptr->status1;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   scale factor read
-   ========================================================================= */
-
-/* scale factor is kept in datastructure */
-static u16
-zr36050_read_scalefactor (struct zr36050 *ptr)
-{
-       ptr->scalefact = (zr36050_read(ptr, ZR050_SF_HI) << 8) |
-                        (zr36050_read(ptr, ZR050_SF_LO) & 0xFF);
-
-       /* leave 0 selected for an eventually GO from master */
-       zr36050_read(ptr, 0);
-       return ptr->scalefact;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   wait if codec is ready to proceed (end of processing) or time is over
-   ========================================================================= */
-
-static void
-zr36050_wait_end (struct zr36050 *ptr)
-{
-       int i = 0;
-
-       while (!(zr36050_read_status1(ptr) & 0x4)) {
-               udelay(1);
-               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
-                       dprintk(1,
-                               "%s: timeout at wait_end (last status: 0x%02x)\n",
-                               ptr->name, ptr->status1);
-                       break;
-               }
-       }
-}
-
-/* =========================================================================
-   Local helper function:
-
-   basic test of "connectivity", writes/reads to/from memory the SOF marker
-   ========================================================================= */
-
-static int
-zr36050_basic_test (struct zr36050 *ptr)
-{
-       zr36050_write(ptr, ZR050_SOF_IDX, 0x00);
-       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0x00);
-       if ((zr36050_read(ptr, ZR050_SOF_IDX) |
-            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0x0000) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to jpeg processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-       zr36050_write(ptr, ZR050_SOF_IDX, 0xff);
-       zr36050_write(ptr, ZR050_SOF_IDX + 1, 0xc0);
-       if (((zr36050_read(ptr, ZR050_SOF_IDX) << 8) |
-            zr36050_read(ptr, ZR050_SOF_IDX + 1)) != 0xffc0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to jpeg processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-
-       zr36050_wait_end(ptr);
-       if ((ptr->status1 & 0x4) == 0) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, jpeg processor failed (end flag)!\n",
-                       ptr->name);
-               return -EBUSY;
-       }
-
-       return 0;               /* looks good! */
-}
-
-/* =========================================================================
-   Local helper function:
-
-   simple loop for pushing the init datasets
-   ========================================================================= */
-
-static int
-zr36050_pushit (struct zr36050 *ptr,
-               u16             startreg,
-               u16             len,
-               const char     *data)
-{
-       int i = 0;
-
-       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
-               startreg, len);
-       while (i < len) {
-               zr36050_write(ptr, startreg++, data[i++]);
-       }
-
-       return i;
-}
-
-/* =========================================================================
-   Basic datasets:
-
-   jpeg baseline setup data (you find it on lots places in internet, or just
-   extract it from any regular .jpg image...)
-
-   Could be variable, but until it's not needed it they are just fixed to save
-   memory. Otherwise expand zr36050 structure with arrays, push the values to
-   it and initialize from there, as e.g. the linux zr36057/60 driver does it.
-   ========================================================================= */
-
-static const char zr36050_dqt[0x86] = {
-       0xff, 0xdb,             //Marker: DQT
-       0x00, 0x84,             //Length: 2*65+2
-       0x00,                   //Pq,Tq first table
-       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-       0x01,                   //Pq,Tq second table
-       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
-};
-
-static const char zr36050_dht[0x1a4] = {
-       0xff, 0xc4,             //Marker: DHT
-       0x01, 0xa2,             //Length: 2*AC, 2*DC
-       0x00,                   //DC first table
-       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x01,                   //DC second table
-       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x10,                   //AC first table
-       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
-       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
-       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
-       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
-       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
-       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
-       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
-       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
-       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
-       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-       0xF8, 0xF9, 0xFA,
-       0x11,                   //AC second table
-       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
-       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
-       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
-       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
-       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
-       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
-       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
-       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
-       0xF9, 0xFA
-};
-
-/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
-#define NO_OF_COMPONENTS          0x3  //Y,U,V
-#define BASELINE_PRECISION        0x8  //MCU size (?)
-static const char zr36050_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
-static const char zr36050_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
-static const char zr36050_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
-
-/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
-static const char zr36050_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
-static const char zr36050_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
-
-/* =========================================================================
-   Local helper functions:
-
-   calculation and setup of parameter-dependent JPEG baseline segments
-   (needed for compression only)
-   ========================================================================= */
-
-/* ------------------------------------------------------------------------- */
-
-/* SOF (start of frame) segment depends on width, height and sampling ratio
-                        of each color component */
-
-static int
-zr36050_set_sof (struct zr36050 *ptr)
-{
-       char sof_data[34];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
-               ptr->width, ptr->height, NO_OF_COMPONENTS);
-       sof_data[0] = 0xff;
-       sof_data[1] = 0xc0;
-       sof_data[2] = 0x00;
-       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
-       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36050
-       sof_data[5] = (ptr->height) >> 8;
-       sof_data[6] = (ptr->height) & 0xff;
-       sof_data[7] = (ptr->width) >> 8;
-       sof_data[8] = (ptr->width) & 0xff;
-       sof_data[9] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sof_data[10 + (i * 3)] = i;     // index identifier
-               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) | (ptr->v_samp_ratio[i]);  // sampling ratios
-               sof_data[12 + (i * 3)] = zr36050_tq[i]; // Q table selection
-       }
-       return zr36050_pushit(ptr, ZR050_SOF_IDX,
-                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* SOS (start of scan) segment depends on the used scan components
-                       of each color component */
-
-static int
-zr36050_set_sos (struct zr36050 *ptr)
-{
-       char sos_data[16];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOS\n", ptr->name);
-       sos_data[0] = 0xff;
-       sos_data[1] = 0xda;
-       sos_data[2] = 0x00;
-       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
-       sos_data[4] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sos_data[5 + (i * 2)] = i;      // index
-               sos_data[6 + (i * 2)] = (zr36050_td[i] << 4) | zr36050_ta[i];   // AC/DC tbl.sel.
-       }
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3F;
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
-       return zr36050_pushit(ptr, ZR050_SOS1_IDX,
-                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
-                             sos_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* DRI (define restart interval) */
-
-static int
-zr36050_set_dri (struct zr36050 *ptr)
-{
-       char dri_data[6];       // max. size of register set
-
-       dprintk(3, "%s: write DRI\n", ptr->name);
-       dri_data[0] = 0xff;
-       dri_data[1] = 0xdd;
-       dri_data[2] = 0x00;
-       dri_data[3] = 0x04;
-       dri_data[4] = ptr->dri >> 8;
-       dri_data[5] = ptr->dri & 0xff;
-       return zr36050_pushit(ptr, ZR050_DRI_IDX, 6, dri_data);
-}
-
-/* =========================================================================
-   Setup function:
-
-   Setup compression/decompression of Zoran's JPEG processor
-   ( see also zoran 36050 manual )
-
-   ... sorry for the spaghetti code ...
-   ========================================================================= */
-static void
-zr36050_init (struct zr36050 *ptr)
-{
-       int sum = 0;
-       long bitcnt, tmp;
-
-       if (ptr->mode == CODEC_DO_COMPRESSION) {
-               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
-
-               /* 050 communicates with 057 in master mode */
-               zr36050_write(ptr, ZR050_HARDWARE, ZR050_HW_MSTR);
-
-               /* encoding table preload for compression */
-               zr36050_write(ptr, ZR050_MODE,
-                             ZR050_MO_COMP | ZR050_MO_TLM);
-               zr36050_write(ptr, ZR050_OPTIONS, 0);
-
-               /* disable all IRQs */
-               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
-               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
-
-               /* volume control settings */
-               /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/
-               zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8);
-               zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff);
-
-               zr36050_write(ptr, ZR050_AF_HI, 0xff);
-               zr36050_write(ptr, ZR050_AF_M, 0xff);
-               zr36050_write(ptr, ZR050_AF_LO, 0xff);
-
-               /* setup the variable jpeg tables */
-               sum += zr36050_set_sof(ptr);
-               sum += zr36050_set_sos(ptr);
-               sum += zr36050_set_dri(ptr);
-
-               /* setup the fixed jpeg tables - maybe variable, though -
-                * (see table init section above) */
-               dprintk(3, "%s: write DQT, DHT, APP\n", ptr->name);
-               sum += zr36050_pushit(ptr, ZR050_DQT_IDX,
-                                     sizeof(zr36050_dqt), zr36050_dqt);
-               sum += zr36050_pushit(ptr, ZR050_DHT_IDX,
-                                     sizeof(zr36050_dht), zr36050_dht);
-               zr36050_write(ptr, ZR050_APP_IDX, 0xff);
-               zr36050_write(ptr, ZR050_APP_IDX + 1, 0xe0 + ptr->app.appn);
-               zr36050_write(ptr, ZR050_APP_IDX + 2, 0x00);
-               zr36050_write(ptr, ZR050_APP_IDX + 3, ptr->app.len + 2);
-               sum += zr36050_pushit(ptr, ZR050_APP_IDX + 4, 60,
-                                     ptr->app.data) + 4;
-               zr36050_write(ptr, ZR050_COM_IDX, 0xff);
-               zr36050_write(ptr, ZR050_COM_IDX + 1, 0xfe);
-               zr36050_write(ptr, ZR050_COM_IDX + 2, 0x00);
-               zr36050_write(ptr, ZR050_COM_IDX + 3, ptr->com.len + 2);
-               sum += zr36050_pushit(ptr, ZR050_COM_IDX + 4, 60,
-                                     ptr->com.data) + 4;
-
-               /* do the internal huffman table preload */
-               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
-
-               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
-               zr36050_wait_end(ptr);
-               dprintk(2, "%s: Status after table preload: 0x%02x\n",
-                       ptr->name, ptr->status1);
-
-               if ((ptr->status1 & 0x4) == 0) {
-                       dprintk(1, KERN_ERR "%s: init aborted!\n",
-                               ptr->name);
-                       return; // something is wrong, its timed out!!!!
-               }
-
-               /* setup misc. data for compression (target code sizes) */
-
-               /* size of compressed code to reach without header data */
-               sum = ptr->real_code_vol - sum;
-               bitcnt = sum << 3;      /* need the size in bits */
-
-               tmp = bitcnt >> 16;
-               dprintk(3,
-                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
-                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
-               zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36050_write(ptr, ZR050_TCV_NET_ML, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_NET_LO, tmp & 0xff);
-
-               bitcnt -= bitcnt >> 7;  // bits without stuffing
-               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
-
-               tmp = bitcnt >> 16;
-               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
-                       ptr->name, bitcnt, tmp);
-               zr36050_write(ptr, ZR050_TCV_DATA_HI, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_DATA_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36050_write(ptr, ZR050_TCV_DATA_ML, tmp >> 8);
-               zr36050_write(ptr, ZR050_TCV_DATA_LO, tmp & 0xff);
-
-               /* compression setup with or without bitrate control */
-               zr36050_write(ptr, ZR050_MODE,
-                             ZR050_MO_COMP | ZR050_MO_PASS2 |
-                             (ptr->bitrate_ctrl ? ZR050_MO_BRC : 0));
-
-               /* this headers seem to deliver "valid AVI" jpeg frames */
-               zr36050_write(ptr, ZR050_MARKERS_EN,
-                             ZR050_ME_DQT | ZR050_ME_DHT |
-                             ((ptr->app.len > 0) ? ZR050_ME_APP : 0) |
-                             ((ptr->com.len > 0) ? ZR050_ME_COM : 0));
-       } else {
-               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
-
-               /* 050 communicates with 055 in master mode */
-               zr36050_write(ptr, ZR050_HARDWARE,
-                             ZR050_HW_MSTR | ZR050_HW_CFIS_2_CLK);
-
-               /* encoding table preload */
-               zr36050_write(ptr, ZR050_MODE, ZR050_MO_TLM);
-
-               /* disable all IRQs */
-               zr36050_write(ptr, ZR050_INT_REQ_0, 0);
-               zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1
-
-               dprintk(3, "%s: write DHT\n", ptr->name);
-               zr36050_pushit(ptr, ZR050_DHT_IDX, sizeof(zr36050_dht),
-                              zr36050_dht);
-
-               /* do the internal huffman table preload */
-               zr36050_write(ptr, ZR050_MARKERS_EN, ZR050_ME_DHTI);
-
-               zr36050_write(ptr, ZR050_GO, 1);        // launch codec
-               zr36050_wait_end(ptr);
-               dprintk(2, "%s: Status after table preload: 0x%02x\n",
-                       ptr->name, ptr->status1);
-
-               if ((ptr->status1 & 0x4) == 0) {
-                       dprintk(1, KERN_ERR "%s: init aborted!\n",
-                               ptr->name);
-                       return; // something is wrong, its timed out!!!!
-               }
-
-               /* setup misc. data for expansion */
-               zr36050_write(ptr, ZR050_MODE, 0);
-               zr36050_write(ptr, ZR050_MARKERS_EN, 0);
-       }
-
-       /* adr on selected, to allow GO from master */
-       zr36050_read(ptr, 0);
-}
-
-/* =========================================================================
-   CODEC API FUNCTIONS
-
-   this functions are accessed by the master via the API structure
-   ========================================================================= */
-
-/* set compression/expansion mode and launches codec -
-   this should be the last call from the master before starting processing */
-static int
-zr36050_set_mode (struct videocodec *codec,
-                 int                mode)
-{
-       struct zr36050 *ptr = (struct zr36050 *) codec->data;
-
-       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
-
-       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
-               return -EINVAL;
-
-       ptr->mode = mode;
-       zr36050_init(ptr);
-
-       return 0;
-}
-
-/* set picture size (norm is ignored as the codec doesn't know about it) */
-static int
-zr36050_set_video (struct videocodec   *codec,
-                  struct tvnorm       *norm,
-                  struct vfe_settings *cap,
-                  struct vfe_polarity *pol)
-{
-       struct zr36050 *ptr = (struct zr36050 *) codec->data;
-       int size;
-
-       dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n",
-               ptr->name, norm->HStart, norm->VStart,
-               cap->x, cap->y, cap->width, cap->height,
-               cap->decimation, cap->quality);
-       /* if () return -EINVAL;
-        * trust the master driver that it knows what it does - so
-        * we allow invalid startx/y and norm for now ... */
-       ptr->width = cap->width / (cap->decimation & 0xff);
-       ptr->height = cap->height / ((cap->decimation >> 8) & 0xff);
-
-       /* (KM) JPEG quality */
-       size = ptr->width * ptr->height;
-       size *= 16; /* size in bits */
-       /* apply quality setting */
-       size = size * cap->quality / 200;
-
-       /* Minimum: 1kb */
-       if (size < 8192)
-               size = 8192;
-       /* Maximum: 7/8 of code buffer */
-       if (size > ptr->total_code_vol * 7)
-               size = ptr->total_code_vol * 7;
-
-       ptr->real_code_vol = size >> 3; /* in bytes */
-
-       /* Set max_block_vol here (previously in zr36050_init, moved
-        * here for consistency with zr36060 code */
-       zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);
-
-       return 0;
-}
-
-/* additional control functions */
-static int
-zr36050_control (struct videocodec *codec,
-                int                type,
-                int                size,
-                void              *data)
-{
-       struct zr36050 *ptr = (struct zr36050 *) codec->data;
-       int *ival = (int *) data;
-
-       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
-               size);
-
-       switch (type) {
-       case CODEC_G_STATUS:    /* get last status */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               zr36050_read_status1(ptr);
-               *ival = ptr->status1;
-               break;
-
-       case CODEC_G_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = CODEC_MODE_BJPG;
-               break;
-
-       case CODEC_S_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               if (*ival != CODEC_MODE_BJPG)
-                       return -EINVAL;
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_G_VFE:
-       case CODEC_S_VFE:
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_S_MMAP:
-               /* not available, give an error */
-               return -ENXIO;
-
-       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = ptr->total_code_vol;
-               break;
-
-       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->total_code_vol = *ival;
-               /* (Kieran Morrissey)
-                * code copied from zr36060.c to ensure proper bitrate */
-               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
-               break;
-
-       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = zr36050_read_scalefactor(ptr);
-               break;
-
-       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->scalefact = *ival;
-               break;
-
-       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               *app = ptr->app;
-               break;
-       }
-
-       case CODEC_S_JPEG_APP_DATA: {    /* set appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               ptr->app = *app;
-               break;
-       }
-
-       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               *com = ptr->com;
-               break;
-       }
-
-       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               ptr->com = *com;
-               break;
-       }
-
-       default:
-               return -EINVAL;
-       }
-
-       return size;
-}
-
-/* =========================================================================
-   Exit and unregister function:
-
-   Deinitializes Zoran's JPEG processor
-   ========================================================================= */
-
-static int
-zr36050_unset (struct videocodec *codec)
-{
-       struct zr36050 *ptr = codec->data;
-
-       if (ptr) {
-               /* do wee need some codec deinit here, too ???? */
-
-               dprintk(1, "%s: finished codec #%d\n", ptr->name,
-                       ptr->num);
-               kfree(ptr);
-               codec->data = NULL;
-
-               zr36050_codecs--;
-               return 0;
-       }
-
-       return -EFAULT;
-}
-
-/* =========================================================================
-   Setup and registry function:
-
-   Initializes Zoran's JPEG processor
-
-   Also sets pixel size, average code size, mode (compr./decompr.)
-   (the given size is determined by the processor with the video interface)
-   ========================================================================= */
-
-static int
-zr36050_setup (struct videocodec *codec)
-{
-       struct zr36050 *ptr;
-       int res;
-
-       dprintk(2, "zr36050: initializing MJPEG subsystem #%d.\n",
-               zr36050_codecs);
-
-       if (zr36050_codecs == MAX_CODECS) {
-               dprintk(1,
-                       KERN_ERR "zr36050: Can't attach more codecs!\n");
-               return -ENOSPC;
-       }
-       //mem structure init
-       codec->data = ptr = kzalloc(sizeof(struct zr36050), GFP_KERNEL);
-       if (NULL == ptr) {
-               dprintk(1, KERN_ERR "zr36050: Can't get enough memory!\n");
-               return -ENOMEM;
-       }
-
-       snprintf(ptr->name, sizeof(ptr->name), "zr36050[%d]",
-                zr36050_codecs);
-       ptr->num = zr36050_codecs++;
-       ptr->codec = codec;
-
-       //testing
-       res = zr36050_basic_test(ptr);
-       if (res < 0) {
-               zr36050_unset(codec);
-               return res;
-       }
-       //final setup
-       memcpy(ptr->h_samp_ratio, zr36050_decimation_h, 8);
-       memcpy(ptr->v_samp_ratio, zr36050_decimation_v, 8);
-
-       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
-                                * (what is the difference?) */
-       ptr->mode = CODEC_DO_COMPRESSION;
-       ptr->width = 384;
-       ptr->height = 288;
-       ptr->total_code_vol = 16000;
-       ptr->max_block_vol = 240;
-       ptr->scalefact = 0x100;
-       ptr->dri = 1;
-
-       /* no app/com marker by default */
-       ptr->app.appn = 0;
-       ptr->app.len = 0;
-       ptr->com.len = 0;
-
-       zr36050_init(ptr);
-
-       dprintk(1, KERN_INFO "%s: codec attached and running\n",
-               ptr->name);
-
-       return 0;
-}
-
-static const struct videocodec zr36050_codec = {
-       .owner = THIS_MODULE,
-       .name = "zr36050",
-       .magic = 0L,            // magic not used
-       .flags =
-           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
-           CODEC_FLAG_DECODER,
-       .type = CODEC_TYPE_ZR36050,
-       .setup = zr36050_setup, // functionality
-       .unset = zr36050_unset,
-       .set_mode = zr36050_set_mode,
-       .set_video = zr36050_set_video,
-       .control = zr36050_control,
-       // others are not used
-};
-
-/* =========================================================================
-   HOOK IN DRIVER AS KERNEL MODULE
-   ========================================================================= */
-
-static int __init
-zr36050_init_module (void)
-{
-       //dprintk(1, "ZR36050 driver %s\n",ZR050_VERSION);
-       zr36050_codecs = 0;
-       return videocodec_register(&zr36050_codec);
-}
-
-static void __exit
-zr36050_cleanup_module (void)
-{
-       if (zr36050_codecs) {
-               dprintk(1,
-                       "zr36050: something's wrong - %d codecs left somehow.\n",
-                       zr36050_codecs);
-       }
-       videocodec_unregister(&zr36050_codec);
-}
-
-module_init(zr36050_init_module);
-module_exit(zr36050_cleanup_module);
-
-MODULE_AUTHOR("Wolfgang Scherr <scherr@net4you.at>");
-MODULE_DESCRIPTION("Driver module for ZR36050 jpeg processors "
-                  ZR050_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/zr36050.h b/drivers/media/video/zoran/zr36050.h
deleted file mode 100644 (file)
index 9f52f0c..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Zoran ZR36050 basic configuration functions - header file
- *
- * Copyright (C) 2001 Wolfgang Scherr <scherr@net4you.at>
- *
- * $Id: zr36050.h,v 1.1.2.2 2003/01/14 21:18:22 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 ZR36050_H
-#define ZR36050_H
-
-#include "videocodec.h"
-
-/* data stored for each zoran jpeg codec chip */
-struct zr36050 {
-       char name[32];
-       int num;
-       /* io datastructure */
-       struct videocodec *codec;
-       // last coder status
-       __u8 status1;
-       // actual coder setup
-       int mode;
-
-       __u16 width;
-       __u16 height;
-
-       __u16 bitrate_ctrl;
-
-       __u32 total_code_vol;
-       __u32 real_code_vol;
-       __u16 max_block_vol;
-
-       __u8 h_samp_ratio[8];
-       __u8 v_samp_ratio[8];
-       __u16 scalefact;
-       __u16 dri;
-
-       /* com/app marker */
-       struct jpeg_com_marker com;
-       struct jpeg_app_marker app;
-};
-
-/* zr36050 register addresses */
-#define ZR050_GO                  0x000
-#define ZR050_HARDWARE            0x002
-#define ZR050_MODE                0x003
-#define ZR050_OPTIONS             0x004
-#define ZR050_MBCV                0x005
-#define ZR050_MARKERS_EN          0x006
-#define ZR050_INT_REQ_0           0x007
-#define ZR050_INT_REQ_1           0x008
-#define ZR050_TCV_NET_HI          0x009
-#define ZR050_TCV_NET_MH          0x00a
-#define ZR050_TCV_NET_ML          0x00b
-#define ZR050_TCV_NET_LO          0x00c
-#define ZR050_TCV_DATA_HI         0x00d
-#define ZR050_TCV_DATA_MH         0x00e
-#define ZR050_TCV_DATA_ML         0x00f
-#define ZR050_TCV_DATA_LO         0x010
-#define ZR050_SF_HI               0x011
-#define ZR050_SF_LO               0x012
-#define ZR050_AF_HI               0x013
-#define ZR050_AF_M                0x014
-#define ZR050_AF_LO               0x015
-#define ZR050_ACV_HI              0x016
-#define ZR050_ACV_MH              0x017
-#define ZR050_ACV_ML              0x018
-#define ZR050_ACV_LO              0x019
-#define ZR050_ACT_HI              0x01a
-#define ZR050_ACT_MH              0x01b
-#define ZR050_ACT_ML              0x01c
-#define ZR050_ACT_LO              0x01d
-#define ZR050_ACV_TRUN_HI         0x01e
-#define ZR050_ACV_TRUN_MH         0x01f
-#define ZR050_ACV_TRUN_ML         0x020
-#define ZR050_ACV_TRUN_LO         0x021
-#define ZR050_STATUS_0            0x02e
-#define ZR050_STATUS_1            0x02f
-
-#define ZR050_SOF_IDX             0x040
-#define ZR050_SOS1_IDX            0x07a
-#define ZR050_SOS2_IDX            0x08a
-#define ZR050_SOS3_IDX            0x09a
-#define ZR050_SOS4_IDX            0x0aa
-#define ZR050_DRI_IDX             0x0c0
-#define ZR050_DNL_IDX             0x0c6
-#define ZR050_DQT_IDX             0x0cc
-#define ZR050_DHT_IDX             0x1d4
-#define ZR050_APP_IDX             0x380
-#define ZR050_COM_IDX             0x3c0
-
-/* zr36050 hardware register bits */
-
-#define ZR050_HW_BSWD                0x80
-#define ZR050_HW_MSTR                0x40
-#define ZR050_HW_DMA                 0x20
-#define ZR050_HW_CFIS_1_CLK          0x00
-#define ZR050_HW_CFIS_2_CLK          0x04
-#define ZR050_HW_CFIS_3_CLK          0x08
-#define ZR050_HW_CFIS_4_CLK          0x0C
-#define ZR050_HW_CFIS_5_CLK          0x10
-#define ZR050_HW_CFIS_6_CLK          0x14
-#define ZR050_HW_CFIS_7_CLK          0x18
-#define ZR050_HW_CFIS_8_CLK          0x1C
-#define ZR050_HW_BELE                0x01
-
-/* zr36050 mode register bits */
-
-#define ZR050_MO_COMP                0x80
-#define ZR050_MO_COMP                0x80
-#define ZR050_MO_ATP                 0x40
-#define ZR050_MO_PASS2               0x20
-#define ZR050_MO_TLM                 0x10
-#define ZR050_MO_DCONLY              0x08
-#define ZR050_MO_BRC                 0x04
-
-#define ZR050_MO_ATP                 0x40
-#define ZR050_MO_PASS2               0x20
-#define ZR050_MO_TLM                 0x10
-#define ZR050_MO_DCONLY              0x08
-
-/* zr36050 option register bits */
-
-#define ZR050_OP_NSCN_1              0x00
-#define ZR050_OP_NSCN_2              0x20
-#define ZR050_OP_NSCN_3              0x40
-#define ZR050_OP_NSCN_4              0x60
-#define ZR050_OP_NSCN_5              0x80
-#define ZR050_OP_NSCN_6              0xA0
-#define ZR050_OP_NSCN_7              0xC0
-#define ZR050_OP_NSCN_8              0xE0
-#define ZR050_OP_OVF                 0x10
-
-
-/* zr36050 markers-enable register bits */
-
-#define ZR050_ME_APP                 0x80
-#define ZR050_ME_COM                 0x40
-#define ZR050_ME_DRI                 0x20
-#define ZR050_ME_DQT                 0x10
-#define ZR050_ME_DHT                 0x08
-#define ZR050_ME_DNL                 0x04
-#define ZR050_ME_DQTI                0x02
-#define ZR050_ME_DHTI                0x01
-
-/* zr36050 status0/1 register bit masks */
-
-#define ZR050_ST_RST_MASK            0x20
-#define ZR050_ST_SOF_MASK            0x02
-#define ZR050_ST_SOS_MASK            0x02
-#define ZR050_ST_DATRDY_MASK         0x80
-#define ZR050_ST_MRKDET_MASK         0x40
-#define ZR050_ST_RFM_MASK            0x10
-#define ZR050_ST_RFD_MASK            0x08
-#define ZR050_ST_END_MASK            0x04
-#define ZR050_ST_TCVOVF_MASK         0x02
-#define ZR050_ST_DATOVF_MASK         0x01
-
-/* pixel component idx */
-
-#define ZR050_Y_COMPONENT         0
-#define ZR050_U_COMPONENT         1
-#define ZR050_V_COMPONENT         2
-
-#endif                         /*fndef ZR36050_H */
diff --git a/drivers/media/video/zoran/zr36057.h b/drivers/media/video/zoran/zr36057.h
deleted file mode 100644 (file)
index 54c9362..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * zr36057.h - zr36057 register offsets
- *
- * Copyright (C) 1998 Dave Perks <dperks@ibm.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.
- */
-
-#ifndef _ZR36057_H_
-#define _ZR36057_H_
-
-
-/* Zoran ZR36057 registers */
-
-#define ZR36057_VFEHCR          0x000  /* Video Front End, Horizontal Configuration Register */
-#define ZR36057_VFEHCR_HSPol            (1<<30)
-#define ZR36057_VFEHCR_HStart           10
-#define ZR36057_VFEHCR_HEnd            0
-#define ZR36057_VFEHCR_Hmask           0x3ff
-
-#define ZR36057_VFEVCR          0x004  /* Video Front End, Vertical Configuration Register */
-#define ZR36057_VFEVCR_VSPol            (1<<30)
-#define ZR36057_VFEVCR_VStart           10
-#define ZR36057_VFEVCR_VEnd            0
-#define ZR36057_VFEVCR_Vmask           0x3ff
-
-#define ZR36057_VFESPFR         0x008  /* Video Front End, Scaler and Pixel Format Register */
-#define ZR36057_VFESPFR_ExtFl           (1<<26)
-#define ZR36057_VFESPFR_TopField        (1<<25)
-#define ZR36057_VFESPFR_VCLKPol         (1<<24)
-#define ZR36057_VFESPFR_HFilter         21
-#define ZR36057_VFESPFR_HorDcm          14
-#define ZR36057_VFESPFR_VerDcm          8
-#define ZR36057_VFESPFR_DispMode        6
-#define ZR36057_VFESPFR_YUV422          (0<<3)
-#define ZR36057_VFESPFR_RGB888          (1<<3)
-#define ZR36057_VFESPFR_RGB565          (2<<3)
-#define ZR36057_VFESPFR_RGB555          (3<<3)
-#define ZR36057_VFESPFR_ErrDif          (1<<2)
-#define ZR36057_VFESPFR_Pack24          (1<<1)
-#define ZR36057_VFESPFR_LittleEndian    (1<<0)
-
-#define ZR36057_VDTR            0x00c  /* Video Display "Top" Register */
-
-#define ZR36057_VDBR            0x010  /* Video Display "Bottom" Register */
-
-#define ZR36057_VSSFGR          0x014  /* Video Stride, Status, and Frame Grab Register */
-#define ZR36057_VSSFGR_DispStride       16
-#define ZR36057_VSSFGR_VidOvf           (1<<8)
-#define ZR36057_VSSFGR_SnapShot         (1<<1)
-#define ZR36057_VSSFGR_FrameGrab        (1<<0)
-
-#define ZR36057_VDCR            0x018  /* Video Display Configuration Register */
-#define ZR36057_VDCR_VidEn              (1<<31)
-#define ZR36057_VDCR_MinPix             24
-#define ZR36057_VDCR_Triton             (1<<24)
-#define ZR36057_VDCR_VidWinHt           12
-#define ZR36057_VDCR_VidWinWid          0
-
-#define ZR36057_MMTR            0x01c  /* Masking Map "Top" Register */
-
-#define ZR36057_MMBR            0x020  /* Masking Map "Bottom" Register */
-
-#define ZR36057_OCR             0x024  /* Overlay Control Register */
-#define ZR36057_OCR_OvlEnable           (1 << 15)
-#define ZR36057_OCR_MaskStride          0
-
-#define ZR36057_SPGPPCR         0x028  /* System, PCI, and General Purpose Pins Control Register */
-#define ZR36057_SPGPPCR_SoftReset      (1<<24)
-
-#define ZR36057_GPPGCR1         0x02c  /* General Purpose Pins and GuestBus Control Register (1) */
-
-#define ZR36057_MCSAR           0x030  /* MPEG Code Source Address Register */
-
-#define ZR36057_MCTCR           0x034  /* MPEG Code Transfer Control Register */
-#define ZR36057_MCTCR_CodTime           (1 << 30)
-#define ZR36057_MCTCR_CEmpty            (1 << 29)
-#define ZR36057_MCTCR_CFlush            (1 << 28)
-#define ZR36057_MCTCR_CodGuestID       20
-#define ZR36057_MCTCR_CodGuestReg      16
-
-#define ZR36057_MCMPR           0x038  /* MPEG Code Memory Pointer Register */
-
-#define ZR36057_ISR             0x03c  /* Interrupt Status Register */
-#define ZR36057_ISR_GIRQ1               (1<<30)
-#define ZR36057_ISR_GIRQ0               (1<<29)
-#define ZR36057_ISR_CodRepIRQ           (1<<28)
-#define ZR36057_ISR_JPEGRepIRQ          (1<<27)
-
-#define ZR36057_ICR             0x040  /* Interrupt Control Register */
-#define ZR36057_ICR_GIRQ1               (1<<30)
-#define ZR36057_ICR_GIRQ0               (1<<29)
-#define ZR36057_ICR_CodRepIRQ           (1<<28)
-#define ZR36057_ICR_JPEGRepIRQ          (1<<27)
-#define ZR36057_ICR_IntPinEn            (1<<24)
-
-#define ZR36057_I2CBR           0x044  /* I2C Bus Register */
-#define ZR36057_I2CBR_SDA              (1<<1)
-#define ZR36057_I2CBR_SCL              (1<<0)
-
-#define ZR36057_JMC             0x100  /* JPEG Mode and Control */
-#define ZR36057_JMC_JPG                 (1 << 31)
-#define ZR36057_JMC_JPGExpMode          (0 << 29)
-#define ZR36057_JMC_JPGCmpMode          (1 << 29)
-#define ZR36057_JMC_MJPGExpMode         (2 << 29)
-#define ZR36057_JMC_MJPGCmpMode         (3 << 29)
-#define ZR36057_JMC_RTBUSY_FB           (1 << 6)
-#define ZR36057_JMC_Go_en               (1 << 5)
-#define ZR36057_JMC_SyncMstr            (1 << 4)
-#define ZR36057_JMC_Fld_per_buff        (1 << 3)
-#define ZR36057_JMC_VFIFO_FB            (1 << 2)
-#define ZR36057_JMC_CFIFO_FB            (1 << 1)
-#define ZR36057_JMC_Stll_LitEndian      (1 << 0)
-
-#define ZR36057_JPC             0x104  /* JPEG Process Control */
-#define ZR36057_JPC_P_Reset             (1 << 7)
-#define ZR36057_JPC_CodTrnsEn           (1 << 5)
-#define ZR36057_JPC_Active              (1 << 0)
-
-#define ZR36057_VSP             0x108  /* Vertical Sync Parameters */
-#define ZR36057_VSP_VsyncSize           16
-#define ZR36057_VSP_FrmTot              0
-
-#define ZR36057_HSP             0x10c  /* Horizontal Sync Parameters */
-#define ZR36057_HSP_HsyncStart          16
-#define ZR36057_HSP_LineTot             0
-
-#define ZR36057_FHAP            0x110  /* Field Horizontal Active Portion */
-#define ZR36057_FHAP_NAX                16
-#define ZR36057_FHAP_PAX                0
-
-#define ZR36057_FVAP            0x114  /* Field Vertical Active Portion */
-#define ZR36057_FVAP_NAY                16
-#define ZR36057_FVAP_PAY                0
-
-#define ZR36057_FPP             0x118  /* Field Process Parameters */
-#define ZR36057_FPP_Odd_Even            (1 << 0)
-
-#define ZR36057_JCBA            0x11c  /* JPEG Code Base Address */
-
-#define ZR36057_JCFT            0x120  /* JPEG Code FIFO Threshold */
-
-#define ZR36057_JCGI            0x124  /* JPEG Codec Guest ID */
-#define ZR36057_JCGI_JPEGuestID         4
-#define ZR36057_JCGI_JPEGuestReg        0
-
-#define ZR36057_GCR2            0x12c  /* GuestBus Control Register (2) */
-
-#define ZR36057_POR             0x200  /* Post Office Register */
-#define ZR36057_POR_POPen               (1<<25)
-#define ZR36057_POR_POTime              (1<<24)
-#define ZR36057_POR_PODir               (1<<23)
-
-#define ZR36057_STR             0x300  /* "Still" Transfer Register */
-
-#endif
diff --git a/drivers/media/video/zoran/zr36060.c b/drivers/media/video/zoran/zr36060.c
deleted file mode 100644 (file)
index f08546f..0000000
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- * Zoran ZR36060 basic configuration functions
- *
- * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * $Id: zr36060.c,v 1.1.2.22 2003/05/06 09:35:36 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 ZR060_VERSION "v0.7"
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <linux/types.h>
-#include <linux/wait.h>
-
-/* I/O commands, error codes */
-#include <asm/io.h>
-
-/* headerfile of this module */
-#include "zr36060.h"
-
-/* codec io API */
-#include "videocodec.h"
-
-/* it doesn't make sense to have more than 20 or so,
-  just to prevent some unwanted loops */
-#define MAX_CODECS 20
-
-/* amount of chips attached via this driver */
-static int zr36060_codecs;
-
-static bool 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;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0-4)");
-
-#define dprintk(num, format, args...) \
-       do { \
-               if (debug >= num) \
-                       printk(format, ##args); \
-       } while (0)
-
-/* =========================================================================
-   Local hardware I/O functions:
-
-   read/write via codec layer (registers are located in the master device)
-   ========================================================================= */
-
-/* read and write functions */
-static u8
-zr36060_read (struct zr36060 *ptr,
-             u16             reg)
-{
-       u8 value = 0;
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->readreg)
-               value = (ptr->codec->master_data->readreg(ptr->codec,
-                                                         reg)) & 0xff;
-       else
-               dprintk(1,
-                       KERN_ERR "%s: invalid I/O setup, nothing read!\n",
-                       ptr->name);
-
-       //dprintk(4, "%s: reading from 0x%04x: %02x\n",ptr->name,reg,value);
-
-       return value;
-}
-
-static void
-zr36060_write(struct zr36060 *ptr,
-             u16             reg,
-             u8              value)
-{
-       //dprintk(4, "%s: writing 0x%02x to 0x%04x\n",ptr->name,value,reg);
-       dprintk(4, "0x%02x @0x%04x\n", value, reg);
-
-       // just in case something is wrong...
-       if (ptr->codec->master_data->writereg)
-               ptr->codec->master_data->writereg(ptr->codec, reg, value);
-       else
-               dprintk(1,
-                       KERN_ERR
-                       "%s: invalid I/O setup, nothing written!\n",
-                       ptr->name);
-}
-
-/* =========================================================================
-   Local helper function:
-
-   status read
-   ========================================================================= */
-
-/* status is kept in datastructure */
-static u8
-zr36060_read_status (struct zr36060 *ptr)
-{
-       ptr->status = zr36060_read(ptr, ZR060_CFSR);
-
-       zr36060_read(ptr, 0);
-       return ptr->status;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   scale factor read
-   ========================================================================= */
-
-/* scale factor is kept in datastructure */
-static u16
-zr36060_read_scalefactor (struct zr36060 *ptr)
-{
-       ptr->scalefact = (zr36060_read(ptr, ZR060_SF_HI) << 8) |
-                        (zr36060_read(ptr, ZR060_SF_LO) & 0xFF);
-
-       /* leave 0 selected for an eventually GO from master */
-       zr36060_read(ptr, 0);
-       return ptr->scalefact;
-}
-
-/* =========================================================================
-   Local helper function:
-
-   wait if codec is ready to proceed (end of processing) or time is over
-   ========================================================================= */
-
-static void
-zr36060_wait_end (struct zr36060 *ptr)
-{
-       int i = 0;
-
-       while (zr36060_read_status(ptr) & ZR060_CFSR_Busy) {
-               udelay(1);
-               if (i++ > 200000) {     // 200ms, there is for sure something wrong!!!
-                       dprintk(1,
-                               "%s: timeout at wait_end (last status: 0x%02x)\n",
-                               ptr->name, ptr->status);
-                       break;
-               }
-       }
-}
-
-/* =========================================================================
-   Local helper function:
-
-   basic test of "connectivity", writes/reads to/from memory the SOF marker
-   ========================================================================= */
-
-static int
-zr36060_basic_test (struct zr36060 *ptr)
-{
-       if ((zr36060_read(ptr, ZR060_IDR_DEV) != 0x33) &&
-           (zr36060_read(ptr, ZR060_IDR_REV) != 0x01)) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, can't connect to jpeg processor!\n",
-                       ptr->name);
-               return -ENXIO;
-       }
-
-       zr36060_wait_end(ptr);
-       if (ptr->status & ZR060_CFSR_Busy) {
-               dprintk(1,
-                       KERN_ERR
-                       "%s: attach failed, jpeg processor failed (end flag)!\n",
-                       ptr->name);
-               return -EBUSY;
-       }
-
-       return 0;               /* looks good! */
-}
-
-/* =========================================================================
-   Local helper function:
-
-   simple loop for pushing the init datasets
-   ========================================================================= */
-
-static int
-zr36060_pushit (struct zr36060 *ptr,
-               u16             startreg,
-               u16             len,
-               const char     *data)
-{
-       int i = 0;
-
-       dprintk(4, "%s: write data block to 0x%04x (len=%d)\n", ptr->name,
-               startreg, len);
-       while (i < len) {
-               zr36060_write(ptr, startreg++, data[i++]);
-       }
-
-       return i;
-}
-
-/* =========================================================================
-   Basic datasets:
-
-   jpeg baseline setup data (you find it on lots places in internet, or just
-   extract it from any regular .jpg image...)
-
-   Could be variable, but until it's not needed it they are just fixed to save
-   memory. Otherwise expand zr36060 structure with arrays, push the values to
-   it and initialize from there, as e.g. the linux zr36057/60 driver does it.
-   ========================================================================= */
-
-static const char zr36060_dqt[0x86] = {
-       0xff, 0xdb,             //Marker: DQT
-       0x00, 0x84,             //Length: 2*65+2
-       0x00,                   //Pq,Tq first table
-       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-       0x01,                   //Pq,Tq second table
-       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
-};
-
-static const char zr36060_dht[0x1a4] = {
-       0xff, 0xc4,             //Marker: DHT
-       0x01, 0xa2,             //Length: 2*AC, 2*DC
-       0x00,                   //DC first table
-       0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x01,                   //DC second table
-       0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
-       0x10,                   //AC first table
-       0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
-       0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
-       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11,
-       0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-       0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1,
-       0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24,
-       0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17,
-       0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-       0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-       0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
-       0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
-       0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
-       0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
-       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
-       0xF8, 0xF9, 0xFA,
-       0x11,                   //AC second table
-       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-       0x07, 0x05, 0x04, 0x04, 0x00, 0x01,
-       0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
-       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-       0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62,
-       0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25,
-       0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A,
-       0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-       0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-       0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-       0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
-       0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8,
-       0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
-       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
-       0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
-       0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
-       0xF9, 0xFA
-};
-
-/* jpeg baseline setup, this is just fixed in this driver (YUV pictures) */
-#define NO_OF_COMPONENTS          0x3  //Y,U,V
-#define BASELINE_PRECISION        0x8  //MCU size (?)
-static const char zr36060_tq[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's QT
-static const char zr36060_td[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's DC
-static const char zr36060_ta[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };  //table idx's AC
-
-/* horizontal 422 decimation setup (maybe we support 411 or so later, too) */
-static const char zr36060_decimation_h[8] = { 2, 1, 1, 0, 0, 0, 0, 0 };
-static const char zr36060_decimation_v[8] = { 1, 1, 1, 0, 0, 0, 0, 0 };
-
-/* =========================================================================
-   Local helper functions:
-
-   calculation and setup of parameter-dependent JPEG baseline segments
-   (needed for compression only)
-   ========================================================================= */
-
-/* ------------------------------------------------------------------------- */
-
-/* SOF (start of frame) segment depends on width, height and sampling ratio
-                        of each color component */
-
-static int
-zr36060_set_sof (struct zr36060 *ptr)
-{
-       char sof_data[34];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOF (%dx%d, %d components)\n", ptr->name,
-               ptr->width, ptr->height, NO_OF_COMPONENTS);
-       sof_data[0] = 0xff;
-       sof_data[1] = 0xc0;
-       sof_data[2] = 0x00;
-       sof_data[3] = (3 * NO_OF_COMPONENTS) + 8;
-       sof_data[4] = BASELINE_PRECISION;       // only '8' possible with zr36060
-       sof_data[5] = (ptr->height) >> 8;
-       sof_data[6] = (ptr->height) & 0xff;
-       sof_data[7] = (ptr->width) >> 8;
-       sof_data[8] = (ptr->width) & 0xff;
-       sof_data[9] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sof_data[10 + (i * 3)] = i;     // index identifier
-               sof_data[11 + (i * 3)] = (ptr->h_samp_ratio[i] << 4) |
-                                        (ptr->v_samp_ratio[i]); // sampling ratios
-               sof_data[12 + (i * 3)] = zr36060_tq[i]; // Q table selection
-       }
-       return zr36060_pushit(ptr, ZR060_SOF_IDX,
-                             (3 * NO_OF_COMPONENTS) + 10, sof_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* SOS (start of scan) segment depends on the used scan components
-                       of each color component */
-
-static int
-zr36060_set_sos (struct zr36060 *ptr)
-{
-       char sos_data[16];      // max. size of register set
-       int i;
-
-       dprintk(3, "%s: write SOS\n", ptr->name);
-       sos_data[0] = 0xff;
-       sos_data[1] = 0xda;
-       sos_data[2] = 0x00;
-       sos_data[3] = 2 + 1 + (2 * NO_OF_COMPONENTS) + 3;
-       sos_data[4] = NO_OF_COMPONENTS;
-       for (i = 0; i < NO_OF_COMPONENTS; i++) {
-               sos_data[5 + (i * 2)] = i;      // index
-               sos_data[6 + (i * 2)] = (zr36060_td[i] << 4) |
-                                       zr36060_ta[i]; // AC/DC tbl.sel.
-       }
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 2] = 00;      // scan start
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 3] = 0x3f;
-       sos_data[2 + 1 + (2 * NO_OF_COMPONENTS) + 4] = 00;
-       return zr36060_pushit(ptr, ZR060_SOS_IDX,
-                             4 + 1 + (2 * NO_OF_COMPONENTS) + 3,
-                             sos_data);
-}
-
-/* ------------------------------------------------------------------------- */
-
-/* DRI (define restart interval) */
-
-static int
-zr36060_set_dri (struct zr36060 *ptr)
-{
-       char dri_data[6];       // max. size of register set
-
-       dprintk(3, "%s: write DRI\n", ptr->name);
-       dri_data[0] = 0xff;
-       dri_data[1] = 0xdd;
-       dri_data[2] = 0x00;
-       dri_data[3] = 0x04;
-       dri_data[4] = (ptr->dri) >> 8;
-       dri_data[5] = (ptr->dri) & 0xff;
-       return zr36060_pushit(ptr, ZR060_DRI_IDX, 6, dri_data);
-}
-
-/* =========================================================================
-   Setup function:
-
-   Setup compression/decompression of Zoran's JPEG processor
-   ( see also zoran 36060 manual )
-
-   ... sorry for the spaghetti code ...
-   ========================================================================= */
-static void
-zr36060_init (struct zr36060 *ptr)
-{
-       int sum = 0;
-       long bitcnt, tmp;
-
-       if (ptr->mode == CODEC_DO_COMPRESSION) {
-               dprintk(2, "%s: COMPRESSION SETUP\n", ptr->name);
-
-               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
-
-               /* 060 communicates with 067 in master mode */
-               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
-
-               /* Compression with or without variable scale factor */
-               /*FIXME: What about ptr->bitrate_ctrl? */
-               zr36060_write(ptr, ZR060_CMR,
-                             ZR060_CMR_Comp | ZR060_CMR_Pass2 |
-                             ZR060_CMR_BRB);
-
-               /* Must be zero */
-               zr36060_write(ptr, ZR060_MBZ, 0x00);
-               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
-               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
-
-               /* Disable all IRQs - no DataErr means autoreset */
-               zr36060_write(ptr, ZR060_IMR, 0);
-
-               /* volume control settings */
-               zr36060_write(ptr, ZR060_SF_HI, ptr->scalefact >> 8);
-               zr36060_write(ptr, ZR060_SF_LO, ptr->scalefact & 0xff);
-
-               zr36060_write(ptr, ZR060_AF_HI, 0xff);
-               zr36060_write(ptr, ZR060_AF_M, 0xff);
-               zr36060_write(ptr, ZR060_AF_LO, 0xff);
-
-               /* setup the variable jpeg tables */
-               sum += zr36060_set_sof(ptr);
-               sum += zr36060_set_sos(ptr);
-               sum += zr36060_set_dri(ptr);
-
-               /* setup the fixed jpeg tables - maybe variable, though -
-                * (see table init section above) */
-               sum +=
-                   zr36060_pushit(ptr, ZR060_DQT_IDX, sizeof(zr36060_dqt),
-                                  zr36060_dqt);
-               sum +=
-                   zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
-                                  zr36060_dht);
-               zr36060_write(ptr, ZR060_APP_IDX, 0xff);
-               zr36060_write(ptr, ZR060_APP_IDX + 1, 0xe0 + ptr->app.appn);
-               zr36060_write(ptr, ZR060_APP_IDX + 2, 0x00);
-               zr36060_write(ptr, ZR060_APP_IDX + 3, ptr->app.len + 2);
-               sum += zr36060_pushit(ptr, ZR060_APP_IDX + 4, 60,
-                                     ptr->app.data) + 4;
-               zr36060_write(ptr, ZR060_COM_IDX, 0xff);
-               zr36060_write(ptr, ZR060_COM_IDX + 1, 0xfe);
-               zr36060_write(ptr, ZR060_COM_IDX + 2, 0x00);
-               zr36060_write(ptr, ZR060_COM_IDX + 3, ptr->com.len + 2);
-               sum += zr36060_pushit(ptr, ZR060_COM_IDX + 4, 60,
-                                     ptr->com.data) + 4;
-
-               /* setup misc. data for compression (target code sizes) */
-
-               /* size of compressed code to reach without header data */
-               sum = ptr->real_code_vol - sum;
-               bitcnt = sum << 3;      /* need the size in bits */
-
-               tmp = bitcnt >> 16;
-               dprintk(3,
-                       "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n",
-                       ptr->name, sum, ptr->real_code_vol, bitcnt, tmp);
-               zr36060_write(ptr, ZR060_TCV_NET_HI, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_NET_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36060_write(ptr, ZR060_TCV_NET_ML, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_NET_LO, tmp & 0xff);
-
-               bitcnt -= bitcnt >> 7;  // bits without stuffing
-               bitcnt -= ((bitcnt * 5) >> 6);  // bits without eob
-
-               tmp = bitcnt >> 16;
-               dprintk(3, "%s: code: nettobit=%ld, highnettobits=%ld\n",
-                       ptr->name, bitcnt, tmp);
-               zr36060_write(ptr, ZR060_TCV_DATA_HI, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_DATA_MH, tmp & 0xff);
-               tmp = bitcnt & 0xffff;
-               zr36060_write(ptr, ZR060_TCV_DATA_ML, tmp >> 8);
-               zr36060_write(ptr, ZR060_TCV_DATA_LO, tmp & 0xff);
-
-               /* JPEG markers to be included in the compressed stream */
-               zr36060_write(ptr, ZR060_MER,
-                             ZR060_MER_DQT | ZR060_MER_DHT |
-                             ((ptr->com.len > 0) ? ZR060_MER_Com : 0) |
-                             ((ptr->app.len > 0) ? ZR060_MER_App : 0));
-
-               /* Setup the Video Frontend */
-               /* Limit pixel range to 16..235 as per CCIR-601 */
-               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
-
-       } else {
-               dprintk(2, "%s: EXPANSION SETUP\n", ptr->name);
-
-               zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
-
-               /* 060 communicates with 067 in master mode */
-               zr36060_write(ptr, ZR060_CIR, ZR060_CIR_CodeMstr);
-
-               /* Decompression */
-               zr36060_write(ptr, ZR060_CMR, 0);
-
-               /* Must be zero */
-               zr36060_write(ptr, ZR060_MBZ, 0x00);
-               zr36060_write(ptr, ZR060_TCR_HI, 0x00);
-               zr36060_write(ptr, ZR060_TCR_LO, 0x00);
-
-               /* Disable all IRQs - no DataErr means autoreset */
-               zr36060_write(ptr, ZR060_IMR, 0);
-
-               /* setup misc. data for expansion */
-               zr36060_write(ptr, ZR060_MER, 0);
-
-               /* setup the fixed jpeg tables - maybe variable, though -
-                * (see table init section above) */
-               zr36060_pushit(ptr, ZR060_DHT_IDX, sizeof(zr36060_dht),
-                              zr36060_dht);
-
-               /* Setup the Video Frontend */
-               //zr36060_write(ptr, ZR060_VCR, ZR060_VCR_FIExt);
-               //this doesn't seem right and doesn't work...
-               zr36060_write(ptr, ZR060_VCR, ZR060_VCR_Range);
-       }
-
-       /* Load the tables */
-       zr36060_write(ptr, ZR060_LOAD,
-                     ZR060_LOAD_SyncRst | ZR060_LOAD_Load);
-       zr36060_wait_end(ptr);
-       dprintk(2, "%s: Status after table preload: 0x%02x\n", ptr->name,
-               ptr->status);
-
-       if (ptr->status & ZR060_CFSR_Busy) {
-               dprintk(1, KERN_ERR "%s: init aborted!\n", ptr->name);
-               return;         // something is wrong, its timed out!!!!
-       }
-}
-
-/* =========================================================================
-   CODEC API FUNCTIONS
-
-   this functions are accessed by the master via the API structure
-   ========================================================================= */
-
-/* set compression/expansion mode and launches codec -
-   this should be the last call from the master before starting processing */
-static int
-zr36060_set_mode (struct videocodec *codec,
-                 int                mode)
-{
-       struct zr36060 *ptr = (struct zr36060 *) codec->data;
-
-       dprintk(2, "%s: set_mode %d call\n", ptr->name, mode);
-
-       if ((mode != CODEC_DO_EXPANSION) && (mode != CODEC_DO_COMPRESSION))
-               return -EINVAL;
-
-       ptr->mode = mode;
-       zr36060_init(ptr);
-
-       return 0;
-}
-
-/* set picture size (norm is ignored as the codec doesn't know about it) */
-static int
-zr36060_set_video (struct videocodec   *codec,
-                  struct tvnorm       *norm,
-                  struct vfe_settings *cap,
-                  struct vfe_polarity *pol)
-{
-       struct zr36060 *ptr = (struct zr36060 *) codec->data;
-       u32 reg;
-       int size;
-
-       dprintk(2, "%s: set_video %d/%d-%dx%d (%%%d) call\n", ptr->name,
-               cap->x, cap->y, cap->width, cap->height, cap->decimation);
-
-       /* if () return -EINVAL;
-        * trust the master driver that it knows what it does - so
-        * we allow invalid startx/y and norm for now ... */
-       ptr->width = cap->width / (cap->decimation & 0xff);
-       ptr->height = cap->height / (cap->decimation >> 8);
-
-       zr36060_write(ptr, ZR060_LOAD, ZR060_LOAD_SyncRst);
-
-       /* Note that VSPol/HSPol bits in zr36060 have the opposite
-        * meaning of their zr360x7 counterparts with the same names
-        * N.b. for VSPol this is only true if FIVEdge = 0 (default,
-        * left unchanged here - in accordance with datasheet).
-       */
-       reg = (!pol->vsync_pol ? ZR060_VPR_VSPol : 0)
-           | (!pol->hsync_pol ? ZR060_VPR_HSPol : 0)
-           | (pol->field_pol ? ZR060_VPR_FIPol : 0)
-           | (pol->blank_pol ? ZR060_VPR_BLPol : 0)
-           | (pol->subimg_pol ? ZR060_VPR_SImgPol : 0)
-           | (pol->poe_pol ? ZR060_VPR_PoePol : 0)
-           | (pol->pvalid_pol ? ZR060_VPR_PValPol : 0)
-           | (pol->vclk_pol ? ZR060_VPR_VCLKPol : 0);
-       zr36060_write(ptr, ZR060_VPR, reg);
-
-       reg = 0;
-       switch (cap->decimation & 0xff) {
-       default:
-       case 1:
-               break;
-
-       case 2:
-               reg |= ZR060_SR_HScale2;
-               break;
-
-       case 4:
-               reg |= ZR060_SR_HScale4;
-               break;
-       }
-
-       switch (cap->decimation >> 8) {
-       default:
-       case 1:
-               break;
-
-       case 2:
-               reg |= ZR060_SR_VScale;
-               break;
-       }
-       zr36060_write(ptr, ZR060_SR, reg);
-
-       zr36060_write(ptr, ZR060_BCR_Y, 0x00);
-       zr36060_write(ptr, ZR060_BCR_U, 0x80);
-       zr36060_write(ptr, ZR060_BCR_V, 0x80);
-
-       /* sync generator */
-
-       reg = norm->Ht - 1;     /* Vtotal */
-       zr36060_write(ptr, ZR060_SGR_VTOTAL_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_VTOTAL_LO, (reg >> 0) & 0xff);
-
-       reg = norm->Wt - 1;     /* Htotal */
-       zr36060_write(ptr, ZR060_SGR_HTOTAL_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_HTOTAL_LO, (reg >> 0) & 0xff);
-
-       reg = 6 - 1;            /* VsyncSize */
-       zr36060_write(ptr, ZR060_SGR_VSYNC, reg);
-
-       //reg   = 30 - 1;               /* HsyncSize */
-///*CP*/        reg = (zr->params.norm == 1 ? 57 : 68);
-       reg = 68;
-       zr36060_write(ptr, ZR060_SGR_HSYNC, reg);
-
-       reg = norm->VStart - 1; /* BVstart */
-       zr36060_write(ptr, ZR060_SGR_BVSTART, reg);
-
-       reg += norm->Ha / 2;    /* BVend */
-       zr36060_write(ptr, ZR060_SGR_BVEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_BVEND_LO, (reg >> 0) & 0xff);
-
-       reg = norm->HStart - 1; /* BHstart */
-       zr36060_write(ptr, ZR060_SGR_BHSTART, reg);
-
-       reg += norm->Wa;        /* BHend */
-       zr36060_write(ptr, ZR060_SGR_BHEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SGR_BHEND_LO, (reg >> 0) & 0xff);
-
-       /* active area */
-       reg = cap->y + norm->VStart;    /* Vstart */
-       zr36060_write(ptr, ZR060_AAR_VSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_VSTART_LO, (reg >> 0) & 0xff);
-
-       reg += cap->height;     /* Vend */
-       zr36060_write(ptr, ZR060_AAR_VEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_VEND_LO, (reg >> 0) & 0xff);
-
-       reg = cap->x + norm->HStart;    /* Hstart */
-       zr36060_write(ptr, ZR060_AAR_HSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_HSTART_LO, (reg >> 0) & 0xff);
-
-       reg += cap->width;      /* Hend */
-       zr36060_write(ptr, ZR060_AAR_HEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_AAR_HEND_LO, (reg >> 0) & 0xff);
-
-       /* subimage area */
-       reg = norm->VStart - 4; /* SVstart */
-       zr36060_write(ptr, ZR060_SWR_VSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_VSTART_LO, (reg >> 0) & 0xff);
-
-       reg += norm->Ha / 2 + 8;        /* SVend */
-       zr36060_write(ptr, ZR060_SWR_VEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_VEND_LO, (reg >> 0) & 0xff);
-
-       reg = norm->HStart /*+ 64 */  - 4;      /* SHstart */
-       zr36060_write(ptr, ZR060_SWR_HSTART_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_HSTART_LO, (reg >> 0) & 0xff);
-
-       reg += norm->Wa + 8;    /* SHend */
-       zr36060_write(ptr, ZR060_SWR_HEND_HI, (reg >> 8) & 0xff);
-       zr36060_write(ptr, ZR060_SWR_HEND_LO, (reg >> 0) & 0xff);
-
-       size = ptr->width * ptr->height;
-       /* Target compressed field size in bits: */
-       size = size * 16;       /* uncompressed size in bits */
-       /* (Ronald) by default, quality = 100 is a compression
-        * ratio 1:2. Setting low_bitrate (insmod option) sets
-        * it to 1:4 (instead of 1:2, zr36060 max) as limit because the
-        * buz can't handle more at decimation=1... Use low_bitrate if
-        * you have a Buz, unless you know what you're doing */
-       size = size * cap->quality / (low_bitrate ? 400 : 200);
-       /* Lower limit (arbitrary, 1 KB) */
-       if (size < 8192)
-               size = 8192;
-       /* Upper limit: 7/8 of the code buffers */
-       if (size > ptr->total_code_vol * 7)
-               size = ptr->total_code_vol * 7;
-
-       ptr->real_code_vol = size >> 3; /* in bytes */
-
-       /* the MBCVR is the *maximum* block volume, according to the
-        * JPEG ISO specs, this shouldn't be used, since that allows
-        * for the best encoding quality. So set it to it's max value */
-       reg = ptr->max_block_vol;
-       zr36060_write(ptr, ZR060_MBCVR, reg);
-
-       return 0;
-}
-
-/* additional control functions */
-static int
-zr36060_control (struct videocodec *codec,
-                int                type,
-                int                size,
-                void              *data)
-{
-       struct zr36060 *ptr = (struct zr36060 *) codec->data;
-       int *ival = (int *) data;
-
-       dprintk(2, "%s: control %d call with %d byte\n", ptr->name, type,
-               size);
-
-       switch (type) {
-       case CODEC_G_STATUS:    /* get last status */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               zr36060_read_status(ptr);
-               *ival = ptr->status;
-               break;
-
-       case CODEC_G_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = CODEC_MODE_BJPG;
-               break;
-
-       case CODEC_S_CODEC_MODE:
-               if (size != sizeof(int))
-                       return -EFAULT;
-               if (*ival != CODEC_MODE_BJPG)
-                       return -EINVAL;
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_G_VFE:
-       case CODEC_S_VFE:
-               /* not needed, do nothing */
-               return 0;
-
-       case CODEC_S_MMAP:
-               /* not available, give an error */
-               return -ENXIO;
-
-       case CODEC_G_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = ptr->total_code_vol;
-               break;
-
-       case CODEC_S_JPEG_TDS_BYTE:     /* get target volume in byte */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->total_code_vol = *ival;
-               ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
-               break;
-
-       case CODEC_G_JPEG_SCALE:        /* get scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               *ival = zr36060_read_scalefactor(ptr);
-               break;
-
-       case CODEC_S_JPEG_SCALE:        /* set scaling factor */
-               if (size != sizeof(int))
-                       return -EFAULT;
-               ptr->scalefact = *ival;
-               break;
-
-       case CODEC_G_JPEG_APP_DATA: {   /* get appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               *app = ptr->app;
-               break;
-       }
-
-       case CODEC_S_JPEG_APP_DATA: {   /* set appn marker data */
-               struct jpeg_app_marker *app = data;
-
-               if (size != sizeof(struct jpeg_app_marker))
-                       return -EFAULT;
-
-               ptr->app = *app;
-               break;
-       }
-
-       case CODEC_G_JPEG_COM_DATA: {   /* get comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               *com = ptr->com;
-               break;
-       }
-
-       case CODEC_S_JPEG_COM_DATA: {   /* set comment marker data */
-               struct jpeg_com_marker *com = data;
-
-               if (size != sizeof(struct jpeg_com_marker))
-                       return -EFAULT;
-
-               ptr->com = *com;
-               break;
-       }
-
-       default:
-               return -EINVAL;
-       }
-
-       return size;
-}
-
-/* =========================================================================
-   Exit and unregister function:
-
-   Deinitializes Zoran's JPEG processor
-   ========================================================================= */
-
-static int
-zr36060_unset (struct videocodec *codec)
-{
-       struct zr36060 *ptr = codec->data;
-
-       if (ptr) {
-               /* do wee need some codec deinit here, too ???? */
-
-               dprintk(1, "%s: finished codec #%d\n", ptr->name,
-                       ptr->num);
-               kfree(ptr);
-               codec->data = NULL;
-
-               zr36060_codecs--;
-               return 0;
-       }
-
-       return -EFAULT;
-}
-
-/* =========================================================================
-   Setup and registry function:
-
-   Initializes Zoran's JPEG processor
-
-   Also sets pixel size, average code size, mode (compr./decompr.)
-   (the given size is determined by the processor with the video interface)
-   ========================================================================= */
-
-static int
-zr36060_setup (struct videocodec *codec)
-{
-       struct zr36060 *ptr;
-       int res;
-
-       dprintk(2, "zr36060: initializing MJPEG subsystem #%d.\n",
-               zr36060_codecs);
-
-       if (zr36060_codecs == MAX_CODECS) {
-               dprintk(1,
-                       KERN_ERR "zr36060: Can't attach more codecs!\n");
-               return -ENOSPC;
-       }
-       //mem structure init
-       codec->data = ptr = kzalloc(sizeof(struct zr36060), GFP_KERNEL);
-       if (NULL == ptr) {
-               dprintk(1, KERN_ERR "zr36060: Can't get enough memory!\n");
-               return -ENOMEM;
-       }
-
-       snprintf(ptr->name, sizeof(ptr->name), "zr36060[%d]",
-                zr36060_codecs);
-       ptr->num = zr36060_codecs++;
-       ptr->codec = codec;
-
-       //testing
-       res = zr36060_basic_test(ptr);
-       if (res < 0) {
-               zr36060_unset(codec);
-               return res;
-       }
-       //final setup
-       memcpy(ptr->h_samp_ratio, zr36060_decimation_h, 8);
-       memcpy(ptr->v_samp_ratio, zr36060_decimation_v, 8);
-
-       ptr->bitrate_ctrl = 0;  /* 0 or 1 - fixed file size flag
-                                * (what is the difference?) */
-       ptr->mode = CODEC_DO_COMPRESSION;
-       ptr->width = 384;
-       ptr->height = 288;
-       ptr->total_code_vol = 16000;    /* CHECKME */
-       ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3;
-       ptr->max_block_vol = 240;       /* CHECKME, was 120 is 240 */
-       ptr->scalefact = 0x100;
-       ptr->dri = 1;           /* CHECKME, was 8 is 1 */
-
-       /* by default, no COM or APP markers - app should set those */
-       ptr->com.len = 0;
-       ptr->app.appn = 0;
-       ptr->app.len = 0;
-
-       zr36060_init(ptr);
-
-       dprintk(1, KERN_INFO "%s: codec attached and running\n",
-               ptr->name);
-
-       return 0;
-}
-
-static const struct videocodec zr36060_codec = {
-       .owner = THIS_MODULE,
-       .name = "zr36060",
-       .magic = 0L,            // magic not used
-       .flags =
-           CODEC_FLAG_JPEG | CODEC_FLAG_HARDWARE | CODEC_FLAG_ENCODER |
-           CODEC_FLAG_DECODER | CODEC_FLAG_VFE,
-       .type = CODEC_TYPE_ZR36060,
-       .setup = zr36060_setup, // functionality
-       .unset = zr36060_unset,
-       .set_mode = zr36060_set_mode,
-       .set_video = zr36060_set_video,
-       .control = zr36060_control,
-       // others are not used
-};
-
-/* =========================================================================
-   HOOK IN DRIVER AS KERNEL MODULE
-   ========================================================================= */
-
-static int __init
-zr36060_init_module (void)
-{
-       //dprintk(1, "zr36060 driver %s\n",ZR060_VERSION);
-       zr36060_codecs = 0;
-       return videocodec_register(&zr36060_codec);
-}
-
-static void __exit
-zr36060_cleanup_module (void)
-{
-       if (zr36060_codecs) {
-               dprintk(1,
-                       "zr36060: something's wrong - %d codecs left somehow.\n",
-                       zr36060_codecs);
-       }
-
-       /* however, we can't just stay alive */
-       videocodec_unregister(&zr36060_codec);
-}
-
-module_init(zr36060_init_module);
-module_exit(zr36060_cleanup_module);
-
-MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@skynet.be>");
-MODULE_DESCRIPTION("Driver module for ZR36060 jpeg processors "
-                  ZR060_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/zoran/zr36060.h b/drivers/media/video/zoran/zr36060.h
deleted file mode 100644 (file)
index 914ffa4..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Zoran ZR36060 basic configuration functions - header file
- *
- * Copyright (C) 2002 Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * $Id: zr36060.h,v 1.1.1.1.2.3 2003/01/14 21:18:47 rbultje Exp $
- *
- * ------------------------------------------------------------------------
- *
- * 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 ZR36060_H
-#define ZR36060_H
-
-#include "videocodec.h"
-
-/* data stored for each zoran jpeg codec chip */
-struct zr36060 {
-       char name[32];
-       int num;
-       /* io datastructure */
-       struct videocodec *codec;
-       // last coder status
-       __u8 status;
-       // actual coder setup
-       int mode;
-
-       __u16 width;
-       __u16 height;
-
-       __u16 bitrate_ctrl;
-
-       __u32 total_code_vol;
-       __u32 real_code_vol;
-       __u16 max_block_vol;
-
-       __u8 h_samp_ratio[8];
-       __u8 v_samp_ratio[8];
-       __u16 scalefact;
-       __u16 dri;
-
-       /* app/com marker data */
-       struct jpeg_app_marker app;
-       struct jpeg_com_marker com;
-};
-
-/* ZR36060 register addresses */
-#define ZR060_LOAD                     0x000
-#define ZR060_CFSR                     0x001
-#define ZR060_CIR                      0x002
-#define ZR060_CMR                      0x003
-#define ZR060_MBZ                      0x004
-#define ZR060_MBCVR                    0x005
-#define ZR060_MER                      0x006
-#define ZR060_IMR                      0x007
-#define ZR060_ISR                      0x008
-#define ZR060_TCV_NET_HI               0x009
-#define ZR060_TCV_NET_MH               0x00a
-#define ZR060_TCV_NET_ML               0x00b
-#define ZR060_TCV_NET_LO               0x00c
-#define ZR060_TCV_DATA_HI              0x00d
-#define ZR060_TCV_DATA_MH              0x00e
-#define ZR060_TCV_DATA_ML              0x00f
-#define ZR060_TCV_DATA_LO              0x010
-#define ZR060_SF_HI                    0x011
-#define ZR060_SF_LO                    0x012
-#define ZR060_AF_HI                    0x013
-#define ZR060_AF_M                     0x014
-#define ZR060_AF_LO                    0x015
-#define ZR060_ACV_HI                   0x016
-#define ZR060_ACV_MH                   0x017
-#define ZR060_ACV_ML                   0x018
-#define ZR060_ACV_LO                   0x019
-#define ZR060_ACT_HI                   0x01a
-#define ZR060_ACT_MH                   0x01b
-#define ZR060_ACT_ML                   0x01c
-#define ZR060_ACT_LO                   0x01d
-#define ZR060_ACV_TRUN_HI              0x01e
-#define ZR060_ACV_TRUN_MH              0x01f
-#define ZR060_ACV_TRUN_ML              0x020
-#define ZR060_ACV_TRUN_LO              0x021
-#define ZR060_IDR_DEV                  0x022
-#define ZR060_IDR_REV                  0x023
-#define ZR060_TCR_HI                   0x024
-#define ZR060_TCR_LO                   0x025
-#define ZR060_VCR                      0x030
-#define ZR060_VPR                      0x031
-#define ZR060_SR                       0x032
-#define ZR060_BCR_Y                    0x033
-#define ZR060_BCR_U                    0x034
-#define ZR060_BCR_V                    0x035
-#define ZR060_SGR_VTOTAL_HI            0x036
-#define ZR060_SGR_VTOTAL_LO            0x037
-#define ZR060_SGR_HTOTAL_HI            0x038
-#define ZR060_SGR_HTOTAL_LO            0x039
-#define ZR060_SGR_VSYNC                        0x03a
-#define ZR060_SGR_HSYNC                        0x03b
-#define ZR060_SGR_BVSTART              0x03c
-#define ZR060_SGR_BHSTART              0x03d
-#define ZR060_SGR_BVEND_HI             0x03e
-#define ZR060_SGR_BVEND_LO             0x03f
-#define ZR060_SGR_BHEND_HI             0x040
-#define ZR060_SGR_BHEND_LO             0x041
-#define ZR060_AAR_VSTART_HI            0x042
-#define ZR060_AAR_VSTART_LO            0x043
-#define ZR060_AAR_VEND_HI              0x044
-#define ZR060_AAR_VEND_LO              0x045
-#define ZR060_AAR_HSTART_HI            0x046
-#define ZR060_AAR_HSTART_LO            0x047
-#define ZR060_AAR_HEND_HI              0x048
-#define ZR060_AAR_HEND_LO              0x049
-#define ZR060_SWR_VSTART_HI            0x04a
-#define ZR060_SWR_VSTART_LO            0x04b
-#define ZR060_SWR_VEND_HI              0x04c
-#define ZR060_SWR_VEND_LO              0x04d
-#define ZR060_SWR_HSTART_HI            0x04e
-#define ZR060_SWR_HSTART_LO            0x04f
-#define ZR060_SWR_HEND_HI              0x050
-#define ZR060_SWR_HEND_LO              0x051
-
-#define ZR060_SOF_IDX                  0x060
-#define ZR060_SOS_IDX                  0x07a
-#define ZR060_DRI_IDX                  0x0c0
-#define ZR060_DQT_IDX                  0x0cc
-#define ZR060_DHT_IDX                  0x1d4
-#define ZR060_APP_IDX                  0x380
-#define ZR060_COM_IDX                  0x3c0
-
-/* ZR36060 LOAD register bits */
-
-#define ZR060_LOAD_Load                        (1 << 7)
-#define ZR060_LOAD_SyncRst             (1 << 0)
-
-/* ZR36060 Code FIFO Status register bits */
-
-#define ZR060_CFSR_Busy                        (1 << 7)
-#define ZR060_CFSR_CBusy               (1 << 2)
-#define ZR060_CFSR_CFIFO               (3 << 0)
-
-/* ZR36060 Code Interface register */
-
-#define ZR060_CIR_Code16               (1 << 7)
-#define ZR060_CIR_Endian               (1 << 6)
-#define ZR060_CIR_CFIS                 (1 << 2)
-#define ZR060_CIR_CodeMstr             (1 << 0)
-
-/* ZR36060 Codec Mode register */
-
-#define ZR060_CMR_Comp                 (1 << 7)
-#define ZR060_CMR_ATP                  (1 << 6)
-#define ZR060_CMR_Pass2                        (1 << 5)
-#define ZR060_CMR_TLM                  (1 << 4)
-#define ZR060_CMR_BRB                  (1 << 2)
-#define ZR060_CMR_FSF                  (1 << 1)
-
-/* ZR36060 Markers Enable register */
-
-#define ZR060_MER_App                  (1 << 7)
-#define ZR060_MER_Com                  (1 << 6)
-#define ZR060_MER_DRI                  (1 << 5)
-#define ZR060_MER_DQT                  (1 << 4)
-#define ZR060_MER_DHT                  (1 << 3)
-
-/* ZR36060 Interrupt Mask register */
-
-#define ZR060_IMR_EOAV                 (1 << 3)
-#define ZR060_IMR_EOI                  (1 << 2)
-#define ZR060_IMR_End                  (1 << 1)
-#define ZR060_IMR_DataErr              (1 << 0)
-
-/* ZR36060 Interrupt Status register */
-
-#define ZR060_ISR_ProCnt               (3 << 6)
-#define ZR060_ISR_EOAV                 (1 << 3)
-#define ZR060_ISR_EOI                  (1 << 2)
-#define ZR060_ISR_End                  (1 << 1)
-#define ZR060_ISR_DataErr              (1 << 0)
-
-/* ZR36060 Video Control register */
-
-#define ZR060_VCR_Video8               (1 << 7)
-#define ZR060_VCR_Range                        (1 << 6)
-#define ZR060_VCR_FIDet                        (1 << 3)
-#define ZR060_VCR_FIVedge              (1 << 2)
-#define ZR060_VCR_FIExt                        (1 << 1)
-#define ZR060_VCR_SyncMstr             (1 << 0)
-
-/* ZR36060 Video Polarity register */
-
-#define ZR060_VPR_VCLKPol              (1 << 7)
-#define ZR060_VPR_PValPol              (1 << 6)
-#define ZR060_VPR_PoePol               (1 << 5)
-#define ZR060_VPR_SImgPol              (1 << 4)
-#define ZR060_VPR_BLPol                        (1 << 3)
-#define ZR060_VPR_FIPol                        (1 << 2)
-#define ZR060_VPR_HSPol                        (1 << 1)
-#define ZR060_VPR_VSPol                        (1 << 0)
-
-/* ZR36060 Scaling register */
-
-#define ZR060_SR_VScale                        (1 << 2)
-#define ZR060_SR_HScale2               (1 << 0)
-#define ZR060_SR_HScale4               (2 << 0)
-
-#endif                         /*fndef ZR36060_H */